diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c86ef826c9..d6def6d1a69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,18 +19,24 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - The CSL preview styles now also support displaying data from cross references entries that are linked via the `crossref` field [#7378](https://github.com/JabRef/jabref/issues/7378) - We made the Search button in Web Search wider. We also skewed the panel titles to the left [#8397](https://github.com/JabRef/jabref/issues/8397) - We introduced a preference to disable fulltext indexing [#8468](https://github.com/JabRef/jabref/issues/8468) +- When exporting entries, the encoding is always UTF-8 +- When embedding BibTeX data into a PDF, the encoding is always UTF-8 ### Fixed - We fixed an issue wehre long article numbers in the `pages` field would cause an exception and preventing the citation style to display [#8381](https://github.com/JabRef/jabref/issues/8381), [citeproc-java](https://github.com/michel-kraemer/citeproc-java/issues/114) +- We fixed an issue where online links in the file field were not detected correctly and could produce an exception [#8150](https://github.com/JabRef/jabref/issues/8510) - We fixed an issue where an exception could occur when saving the preferences [#7614](https://github.com/JabRef/jabref/issues/7614) - We fixed an issue where "Copy DOI url" in the right-click menu of the Entry List would just copy the DOI and not the DOI url. [#8389](https://github.com/JabRef/jabref/issues/8389) - We fixed an issue where opening the console from the drop-down menu would cause an exception. [#8466](https://github.com/JabRef/jabref/issues/8466) +- We fixed an issue when reading non-UTF-8 encoded. When no encoding header is present, the encoding is now detected from the file content (and the preference option is disregarded) [#8417](https://github.com/JabRef/jabref/issues/8417) - We fixed an issue where pasting a URL was replacing + signs by spaces making the URL unreachable. [#8448](https://github.com/JabRef/jabref/issues/8448) +- We fixed an issue where creating subsidiary files from aux files created with some versions of biblatex would produce incorrect results. [#8513](https://github.com/JabRef/jabref/issues/8513) ### Removed - We removed the option to copy CSL Citation styles data as `XSL_FO`, `ASCIIDOC`, and `RTF` as these have not been working since a long time and are no longer supported in the external library used for processing the styles [#7378](https://github.com/JabRef/jabref/issues/7378) +- We removed the option to configure the default encoding. The default encoding is now hard-coded to the modern UTF-8 encoding. @@ -54,6 +60,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - We moved the search box in preview preferences closer to the available citation styles list. [#8370](https://github.com/JabRef/jabref/pull/8370) - Changing the preference to show the preview panel as a separate tab now has effect without restarting JabRef. [#8370](https://github.com/JabRef/jabref/pull/8370) - We enabled switching themes in JabRef without the need to restart JabRef. [#7335](https://github.com/JabRef/jabref/pull/7335) +- We added support for the field `day`, `rights`, `coverage` and `language` when reading XMP data in Dublin Core format. [#8491](https://github.com/JabRef/jabref/issues/8491) ### Fixed diff --git a/build.gradle b/build.gradle index 09f12be3eae..e31c898adc6 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,8 @@ -import groovy.json.JsonSlurper import org.gradle.internal.os.OperatingSystem import org.jabref.build.JournalAbbreviationConverter import org.jabref.build.xjc.XjcPlugin import org.jabref.build.xjc.XjcTask -// to update the gradle wrapper, execute -// ./gradlew wrapper --gradle-version=6.0 --distribution-type=bin - plugins { id 'application' @@ -123,6 +119,7 @@ dependencies { implementation 'com.h2database:h2-mvstore:2.1.210' implementation group: 'org.apache.tika', name: 'tika-core', version: '2.3.0' + implementation 'com.ibm.icu:icu4j-charset:70.1' // required for reading write-protected PDFs - see https://github.com/JabRef/jabref/pull/942#issuecomment-209252635 implementation 'org.bouncycastle:bcprov-jdk15on:1.70' @@ -218,7 +215,7 @@ dependencies { testImplementation "org.testfx:testfx-junit5:4.0.17-alpha-SNAPSHOT" testImplementation "org.hamcrest:hamcrest-library:2.2" - checkstyle 'com.puppycrawl.tools:checkstyle:9.3' + checkstyle 'com.puppycrawl.tools:checkstyle:10.0' // xjc needs the runtime as well for the ant task, otherwise it fails xjc group: 'org.glassfish.jaxb', name: 'jaxb-xjc', version: '3.0.2' xjc group: 'org.glassfish.jaxb', name: 'jaxb-runtime', version: '3.0.2' diff --git a/crowdin.yml b/crowdin.yml index 1ec4fb7a69c..90c30e89519 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -4,6 +4,5 @@ files: languages_mapping: two_letters_code: pt-BR: pt_BR - id: in zh-CN: zh_CN zh-TW: zh_TW diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 9d7234fb089..f875ffff259 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -21,4 +21,10 @@ * [Readings on Coding](readings-on-coding/README.md) * [Readings on JavaFX](readings-on-coding/javafx.md) * [Useful development tooling](readings-on-coding/tools.md) - +* [The OpenOffice/LibreOffice panel](openoffice/README.md) + * [Overview](openoffice/overview.md) + * [Order of appearance of citation groups](openoffice/order-of-appearance.md) + * [Problems](openoffice/problems.md) + * [Code reorganization](openoffice/code-reorganization.md) + * [About `OOError`, `OOResult` and `OOVoidResult`](openoffice/ooresult-ooerror.md) + * [Alternatives to using OOResult and OOVoidResult in OOBibBase](openoffice/ooresult-alternatives.md) diff --git a/docs/getting-into-the-code/code-howtos.md b/docs/getting-into-the-code/code-howtos.md index 42f96fc958f..6759b6a38d8 100644 --- a/docs/getting-into-the-code/code-howtos.md +++ b/docs/getting-into-the-code/code-howtos.md @@ -18,7 +18,7 @@ Please read [https://github.com/cxxr/better-java](https://github.com/cxxr/better Principles: -* All Exceptions we throw should be or extend `JabRefException`; This is especially important if the message stored in the Exception should be shown to the user. `JabRefException` has already implemented the `getLocalizedMessage()` method which should be used for such cases \(see details below!\). +* All exceptions we throw should be or extend `JabRefException`; This is especially important if the message stored in the Exception should be shown to the user. `JabRefException` has already implemented the `getLocalizedMessage()` method which should be used for such cases \(see details below!\). * Catch and wrap all API exceptions \(such as `IOExceptions`\) and rethrow them * Example: @@ -119,7 +119,8 @@ If you want to catch the event you'll have to register your listener class with ## Logging -JabRef uses the logging facade [SLF4j](https://www.slf4j.org/). All log messages are passed internally to [log4j2](https://logging.apache.org/log4j/2.x/) which handles any filtering, formatting and writing of log messages. +JabRef uses the logging facade [SLF4j](https://www.slf4j.org/). +All log messages are passed internally to [tinylog](https://tinylog.org/v2/) which handles any filtering, formatting and writing of log messages. * Obtaining a logger for a class: @@ -137,6 +138,11 @@ JabRef uses the logging facade [SLF4j](https://www.slf4j.org/). All log messages ``` * SLF4J also support parameterized logging, e.g. if you want to print out multiple arguments in a log statement use a pair of curly braces. [Examples](https://www.slf4j.org/faq.html#logging_performance) +* When running tests, `tinylog-test.properties` is used. It is located under `src/test/resources`. + As default, only `info` is logged. + When developing, it makes sense to use `debug` as log level. + One can change the log level per class using the pattern `level@class=debug` is set to `debug`. + In the `.properties` file, this is done for `org.jabref.model.entry.BibEntry`. ## Using Localization correctly diff --git a/docs/openoffice/README.md b/docs/openoffice/README.md new file mode 100644 index 00000000000..5587cc8291e --- /dev/null +++ b/docs/openoffice/README.md @@ -0,0 +1 @@ +# OpenOffice/LibreOffice integration diff --git a/docs/openoffice/code-reorganization.md b/docs/openoffice/code-reorganization.md new file mode 100644 index 00000000000..a9d45418690 --- /dev/null +++ b/docs/openoffice/code-reorganization.md @@ -0,0 +1,188 @@ + +# Code reorganization + +Why + +- Separate backend +- Separate GUI code (dialogs) and logic +- Data is now organized around `Citation`, `CitationGroup` instead of arrays for citation group + fields, and arrays of arrays for citation fields. + Also take `citationKey` as the central data unit, this is what we start with: unresolved `citationKeys` + do not stop processing. Although we cannot sort them by author and year, we can still emit a marker + that acts as a placeholder and shows the user the problematic key. + +## Result + +### Layers + +![Layers](layers-v1.svg) + +### By directories + +- `model` + - `util` : general utilities + - (`OOPair`, `OOTuple3`) collect two or three objects without creating a new class + - `OOResult` : while an Optional.empty can comunicate failure, it cannot provide details. + `OOResult` allows an arbitrary error object to be provided in case of failure. + - `OOVoidResult` : for functions returning no result on success, only diagnostics on failure. + - `OOListUtil`: some utilities working on List + - `uno` : helpers for various tasks via UNO. + These are conceptually independent of JabRef code and logic. + - `ootext` : to separate decisions on the format of references and citation marks from + the actual insertion into the document, the earlier method + [OOUtil.insertOOFormattedTextAtCurrentLocation](https://github.com/JabRef/jabref/blob/475b2989ffa8ec61c3327c62ed8f694149f83220/src/main/java/org/jabref/logic/openoffice/OOUtil.java#L112) + was extended to handle new tags that describe actions earlier done in code. + - This became [OOTextIntoOO.write](https://github.com/antalk2/jabref/blob/122d5133fa6c7b44245c5ba5600d398775718664/src/main/java/org/jabref/model/openoffice/ootext/OOTextIntoOO.java#L149) + - `(change)` Now all output to the document goes through this, not only those from Layout. This allows the citation markers and `jstyle:Title` to use these tags. + - This allows some backward-compatible extensions to jstyle. + `(change)` [Added](https://github.com/antalk2/jabref/blob/122d5133fa6c7b44245c5ba5600d398775718664/src/main/java/org/jabref/logic/openoffice/style/OOBibStyle.java#L92) + some extra keywords, in `{prefix}_MARKUP_BEFORE`, `{prefix}_MARKUP_AFTER` pairs to allow bracketing some parts of citation marks with text and/or open/close tag pairs. + - [OOFormat](https://github.com/antalk2/jabref/blob/improve-reversibility-rebased-03/src/main/java/org/jabref/model/openoffice/ootext/OOFormat.java) + contains helpers to create the appropriate tags + - [OOText](https://github.com/antalk2/jabref/blob/improve-reversibility-rebased-03/src/main/java/org/jabref/model/openoffice/ootext/OOText.java) formalizes + the distinction from `String`. I did not change `String` to `OOText` in old code, (in particular in OOStyle). + - `rangesort` : ordering objects that have an `XTextRange`, optionally with an extra integer to break ties. + - `RangeSort.partitionAndSortRanges` : since `XTextRangeCompare` can only compare `XTextRange` values in + the same `XText`, we partition them accordingly and only sort within each partiion. + - `RangeSortable` (interface), `RangeSortEntry` (implements) : + When we replace `XTextRange` of citation marks in footnotes with the range of the footnote mark, + multiple citation marks may be mapped to the same location. To preserve the order between these, + `RangeSortable` allows this order to be indicated by returning appropriate indices from `getIndexInPosition` + - `RangeSortVisual` : sort in top-to-bottom left-to-right order. + Needs a functional `XTextViewCursor`. + Works on `RangeSortable` values. + - `FunctionalTextViewCursor` : helper to get a functional `XTextViewCursor` (cannot always) + - `RangeOverlapWithin` : check for overlaps within a set of `XTextRange` values. Probably O(n*log(n)). Used for all-to-all check of protected ranges. + - `RangeOverlapBetween` : check for overlaps between two sets of `XTextRange` values. Assumes one set is small. O(n*k). + Used for checking if the cursor is in a protected range. + - `backend` : interfaces to be provided by backends. + May change as new backends may need different APIs. + - `style` : data structures and interfaces used while going from ordered list of citation groups + to formatted citation markers and bibliography. Does not communicate with the document. Too long to fit here, starting a new section. + +## model/style + +At the core, + +- we have `Citation` values + - represented in the document by their `citationKey` + - each may have a `pageInfo` +- A citation group (`CitationGroup`) has + - a list of citations (`citationsInStorageOrder`) + - an identifier `CitationGroupId cgid` + - this allows to refer to the group + - also used to associate the group to its citation markers location (outside the style part, + in [Backend](https://github.com/antalk2/jabref/blob/fed0952cbdaf7a76bcb09b3db5ac48f34f5ca388/src/main/java/org/jabref/logic/openoffice/backend/Backend52.java#L46)) + - `OODataModel dataModel` is here, in order to handle old (Jabref5.2) structure where pageInfo belonged to + CitationGroup not Citation + - `referenceMarkNameForLinking` is optional: can be used to crosslink to the citation marker + from the bibliography. +- `CitationGroups` represents the collection of citation groups. +Processing starts with creating a `CitationGroups` instance from the data stored in the document. + +- `CitedKey` represents a cited source, with ordered backreferences (using `CitationPath`) to the correponding +citations. + +- `CitedKeys` is just an order-preserving collection of `CitedKeys` that also supports lookup by +`citationKey`. While producing citation markers, we also create a corresponding `CitedKeys` +instance, and store it in `CitationGroups.bibliography`. This is already sorted, its entries have +`uniqueLetter` or `number` assigned, but not converted to markup yet. + +Common processing steps: + +- We need `globalOrder` for the citation groups (provided externally) +`CitationGroups.setGlobalOrder()` +- We need to look up each citationKey in the bibliography databases: + - `CitationGroups.lookupCitations` collects the cited keys, + looks up each, then distributes the results to the citations. + Uses a temporary `CitedKeys` instance, based on unsorted citations and citation groups. +- `CitationGroups.imposeLocalOrder` fills `localOrder` in each `CitationGroup` + +- Now we have order of appearance for the citations (`globalOrder` and `localOrder`). + We can create a `CitedKeys` instance (`bibliography`) according to this order. + +- For citations numbered in order of first appearance we number the sources and distribute the numbers +to the corresponding citations. +- For citations numbered in order of bibliography, we sort the bibliography, number, distribute. + +- For author-year citations we have to decide on the letters `uniqueLetter` used to distinguish +sources. This needs order of first appearance of the sources and recognizing clashing citation markers. +This is done in logic, in [`OOProcessAuthorYearMarkers.createUniqueLetters()`](https://github.com/antalk2/jabref/blob/122d5133fa6c7b44245c5ba5600d398775718664/src/main/java/org/jabref/logic/openoffice/style/OOProcessAuthorYearMarkers.java#L49) +- We also mark first appearance of each source ([`setIsFirstAppearanceOfSourceInCitations`](https://github.com/antalk2/jabref/blob/fed0952cbdaf7a76bcb09b3db5ac48f34f5ca388/src/main/java/org/jabref/logic/openoffice/style/OOProcessAuthorYearMarkers.java#L146)) + +The entry point for this processing is: [`OOProcess.produceCitationMarkers`](https://github.com/antalk2/jabref/blob/fed0952cbdaf7a76bcb09b3db5ac48f34f5ca388/src/main/java/org/jabref/logic/openoffice/style/OOProcess.java#L69). +It fills + +- each `CitationGroup.citationMarker` +- `CitationGroups.bibliography` + - From bibliography `OOFormatBibliography.formatBibliography()` creates an `OOText` + ready to be written to the document. + + +## logic/style + +- `StyleLoader` : not changed (knows about default styles) Used by GUI +- `OOPreFormatter` : LaTeX code to unicode and OOText tags. (not changed) +- `OOBibStyle` : is mostly concerned by loading/parsing jstyle files and presenting its pieces +to the rest. Originally it also contains code to format numeric and author-year citation markers. + - Details of their new implementations are in + [`OOBibStyleGetNumCitationMarker`](https://github.com/antalk2/jabref/blob/improve-reversibility-rebased-03/src/main/java/org/jabref/logic/openoffice/style/OOBibStyleGetNumCitationMarker.java) and + [`OOBibStyleGetCitationMarker`](https://github.com/antalk2/jabref/blob/improve-reversibility-rebased-03/src/main/java/org/jabref/logic/openoffice/style/OOBibStyleGetCitationMarker.java) + - The new implementations + - support pageInfo for each citation + - support unresolved citations + - instead of `List` and (`List` plus arrays and database) they expect + more self-contained entries `List`, `List`. + - We have distinct methods for `getNormalizedCitationMarker(CitationMarkerNormEntry)` and + `getNumCitationMarkerForBibliography(CitationMarkerNumericBibEntry)`. + - The corresponding interfaces in model/style: + - `CitationMarkerNumericEntry` + - `CitationMarkerEntry` + - `CitationMarkerNumericBibEntry` + - `CitationMarkerNormEntry` + describe their expected input entries. +- [`OOProcess.produceCitationMarkers`](https://github.com/antalk2/jabref/blob/fed0952cbdaf7a76bcb09b3db5ac48f34f5ca388/src/main/java/org/jabref/logic/openoffice/style/OOProcess.java#L69) +is the main entry point for style application. Calls to specific implementations +in `OOProcessCitationKeyMarkers`, `OOProcessNumericMarkers` and `OOProcessAuthorYearMarkers` +according to jstyle flags. + +## logic/backend + +Details of encoding and retrieving data stored in a document as well as +the citation maker locations. Also contains dataModel-dependent code +(which could probably be moved out once the datamodel is settled). + +Creating and finding the bibliography (providing a cursor to write at) should be here too. +These are currently in `UpdateBibliography` + +## logic/frontend + +- `OOFrontend` : has a `Backend` and `CitationGroups` + - Its constructor creates a backend, reads data from the document and creates a CitationGroups instance. + - provides functionality that requires both access to the document and the CitationGroups instance +- `RangeForOverlapCheck` used in `OOFrontend` +- `UpdateBibliography` : Create, find and update the bibliography in the document using output from + `produceCitationMarkers()` +- `UpdateCitationMarkers` create `CitationGroup`, update citation markers using output from + `produceCitationMarkers()` + + +## logic/action + +GUI-independent part of implementations of GUI actions. + +## gui + +- `OOError` : common error messages and dialog titles + - adds `title` to `Jabrefexception` + - converts from some common exception types using type-specific message + - contains some dialog messages that do not correspond to exceptions + +- `OOBibBase2` : most activity was moved out from here to parts discussed above. + - connecting / selecting a document moved to `OOBibBaseConnect` + - the rest connects higher parts of the GUI to actions in logic + - does argument and precondition checking + - catches all exceptions + - shows error and warning dialogs + - adds `enterUndoContext`, `leaveUndoContext` around action code + diff --git a/docs/openoffice/layers-v1.svg b/docs/openoffice/layers-v1.svg new file mode 100644 index 00000000000..f9b8239d504 --- /dev/null +++ b/docs/openoffice/layers-v1.svg @@ -0,0 +1,915 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + document content (UNO) + + frontend + + actions + + OOBibBase2 + + backend + + style + + OOTextIntoOO + + rangesort + data in doc, ranges + order ranges + fill ranges + markup text + XTextDocument + Backend, CitationGroups + + + + GUI: + BibEntry, BibDatabase, OOBibStyle + provides input in terms of these types + + provides connection to doc + Cite, Update, Merge, Separate, Manage, Export + Connect + Load Style + Create OOFrontend instance + Catch exceptions, Undo + Forward requests to actions + Check preconditions + + locations + citation keys + pageInfo + citation type + + + lookup, localOrder, number, + uniqueLetter, sort bibliography, + format citationMarkers, + format bibliography + + + or visually + within XText + + checkRangeOverlaps, checkRangeOverlapsWithCursor + connects the parts below + getVisuallySortedCitationGroups, imposeGlobalOrder + UpdateCitationMarkers, UpdateBibliography + lock screen refresh + GUI-independent part of actions + + + diff --git a/docs/openoffice/ooresult-alternatives.md b/docs/openoffice/ooresult-alternatives.md new file mode 100644 index 00000000000..27d5dbb7e11 --- /dev/null +++ b/docs/openoffice/ooresult-alternatives.md @@ -0,0 +1,505 @@ + +# Alternatives to `OOResult` during precondition checking in `OOBibBase` + +(Talk about ADRs prompted me to think about alternatives to what I used.) + +Situation: + +- some tests return no data, only report problems +- we may need to get some resources that might not be available + (for example: connection to a document, a functional textview cursor) +- some test depend on these resources + + +One strategy could be to use a single try-catch around the whole body, +then showing a message based on the type of exceptions thrown. + +## [base case] + +```java +try { + A a = f(); + B b = g(a); + realAction(a,b); +} catch (FirstExceptionType ex) { + showDialog( title, messageForFirstExceptionType(ex) ); +} catch (SecondExceptionType ex) { + showDialog( title, messageForSecondExceptionType(ex) ); +} catch (Exception ex) { + showDialog( title, messageForOtherExceptions(ex) ); +} +``` + +This our base case. + +It is not clear from the code, nor within the catch branches (unless +we start looking into stack traces) which call (`f()`, `g(a)` or +`realAction(a,b)`) resulted in the exception. This limits the +specificity of the message and makes it hard to think about the "why" +can we get this exception here? + +## Catch around each call? + +A more detailed strategy would be to try-catch around each call. +In case we need a result from the call, this means either increasingly indented +code (try-in-try). + +```java +try { + A a = f(); + try { + B b = g(a); + try { + realAction(ab); + } catch (...){ + showDialog(); + } + } catch (G ex) { + showDialog(title, ex); // title describes which GUI action we are in + } +} catch (F ex) { + // could an F be thrown in g? + showDialog( title, ex ); +} +``` + +or (declare and fill later) + +```java +A a = null; +try { + a = f(); +} catch (F ex) { + showDialog(title, ex); + return; +} +B b = null; +try { + b = g(a); +} catch (G ex) { + showDialog(title, ex); + return; +} +try { + realAction(ab); +} catch (...){ + showDialog(); +} +``` + +In either case, the code becomes littered with exception handling code. + +## Catch in wrappers? + +We might push the try-catch into its own function. +If the wrapper is called multiple times, this may reduce duplication of the +catch-and-assign-message part. + +We can show an error dialog here: `title` carries some information +from the caller, the exeption caught brings some from below. + +We still need to notify the action handler (the caller) about +failure. Since we have shown the dialog, we do not need to provide a +message. + +### Notify caller with `Optional` result + +With `Optional` we get something like this: + +#### [dialog in wrap, return Optional] + +```java +Optional wrap_f(String title) { + try { + return Optional.of(f()); + } catch (F ex) { + showDialog(title, ex); + return Optional.empty(); + } +} + +Optional wrap_g(String title, A a) { + try { + return Optional.of(g(a)); + } catch (G ex) { + showDialog(title, ex); + return Optional.empty(); + } +} +``` + +and use it like this: + +```java +Optional a = wrap_f(title); +if (a.isEmpty()) { return; } + +Optional b = wrap_g(title, a.get()); +if (b.isEmpty()) { return; } + +try { + realAction(a.get(), b.get()); +} catch (...) { +} +``` + +This looks fairly regular. + +If `g` did not need `a`, we could simplify to + +```java +Optional a = wrap_f(title); +Optional b = wrap_g(title); +if (a.isEmpty() || b.isEmpty()) { return; } + +try { + realAction(a.get(), b.get()); +} catch (...) { +} +``` + +### Notify caller with `Result` result + +With `Result` we get something like this: + +#### [dialog in wrap, return OOResult] + +```java +OOResult wrap_f() { + try { + return OOResult.ok(f()); + } catch (F ex) { + return OOResult.error(OOError.from(ex)); + } catch (F2 ex) { + String message = "..."; + return OOResult.error(new OOError(message, ex)); // [1] + } +} +// [1] : this OOError constructor (explicit message but no title) is missing + +Optional wrap_g(A a) { + try { + return OOResult.ok(g(a)); + } catch (G ex) { + return OOResult.error(OOError.from(ex)); + } +} +``` + +and use it like this: + +```java +OOResult a = wrap_f(); +if (testDialog(title, a)) { // [1] + return; +} + +// [1] needs boolean testDialog(String title, OOResultLike... a); +// where OOResultLike is an interface with `OOVoidResult asVoidResult()` +// and is implemented by OOResult and OOVoidResult + +OOResult b = wrap_g(a.get()); +if (testDialog(title, b)) { return; } // (checkstyle makes this 3 lines) + +try { + realAction(a.get(), b.get()); +} catch (...) { +} +``` + +If `g` did not need `a`, we could simplify to + +```java +Optional a = wrap_f(); +Optional b = wrap_g(); +if (testDialog(title, a, b)) { // a single dialog can show both messages + return; +} + +try { + realAction(a.get(), b.get()); +} catch (...) { +} +``` + +### Notify caller by throwing an exception + +Or we can throw an exception to notify the caller. + +To simplify code in the caller, I assume we are using an exception +type not used elsewhere, but shared by all precondition checks. + +#### [dialog in wrap, PreconditionException] + +```java +A wrap_f(String title) throws PreconditionException { + try { + return f(); + } catch (F ex) { + showDialog(title, ex) + throw new PreconditionException(); + } +} + +B wrap_g(String title, A a) throws PreconditionException { + try { + return g(a); + } catch (G ex) { + showDialog(title, ex); + throw new PreconditionException(); + } +} +``` + +use + +```java +try { + A a = wrap_f(title); + B b = wrap_g(title, a); + try { + realAction(a, b); + } catch (...) { + showDialog(...) + } +} catch( PreconditionException ) { + // Only precondition checks get us here. + return; +} +``` + +or (since PreconditionException is not thrown from realAction) + +```java +try { + A a = wrap_f(title); + B b = wrap_g(title, a); + realAction(a, b); +} catch (...) { + // Only realAction gets us here + showDialog(...) +} catch( PreconditionException ) { + // Only precondition checks get us here. + return; +} +``` + +or (separate try-catch for preconditions and realAction) + +```java +A a = null; +B b = null; +try { + a = wrap_f(title); + b = wrap_g(title, a); +} catch( PreconditionException ) { + return; +} +try { + realAction(a, b); +} catch (...) { +} +``` + +or to reduce passing around the title part: + +#### [PreconditionException, dialog in catch] + +```java +A wrap_f() throws PreconditionException { + try { + return f(); + } catch (F ex) { + throw new PreconditionException(message, ex); + } +} + +B wrap_g(A a) throws PreconditionException { + try { + return g(a); + } catch (G ex) { + throw new PreconditionException(message, ex); + } +} +``` + +use + +```java +try { + A a = wrap_f(); + B b = wrap_g(a); + try { + realAction(a, b); + } catch (...) { + showDialog(...); + } +} catch(PreconditionException ex) { + showDialog(title, ex.message ); + return; +} +``` + +or + +```java +try { + A a = wrap_f(); + B b = wrap_g(a); + realAction(a, b); +} catch (...) { + showDialog(...); +} catch(PreconditionException ex) { + showDialog(title, ex.message ); + return; +} +``` + + +## Push associating the message further down + +As [the developers guide](https://jabref.readthedocs.io/en/latest/getting-into-the-code/code-howtos/#throwing-and-catching-exceptions) +suggest, we could "Catch and wrap all API exceptions" and rethrow them +as a `JabRefException` or some exception derived from it. In this case the try-catch part goes even further down, and +in principle we could just + +```java +try { + A a = f(); + B b = g(a); + realAction(a, b); +} catch(JabRefException ex) { + showDialog(title, ex.message ); + return; +} +``` + +Constraints: + +- conversion to `JabRefException` cannot be done in `model` (since JabRefException is in `logic`) +- `JabRefException` expects a localized message. Or we need to remember +which `JabRefException` instances are localized and which need to be caught +for localizing the message. +- At the bottom we usually have very little information on higher level +contexts: at a failure like `NoSuchProperty` we cannot tell which set +of properties did we look in and why. +For messages originating too deeply, we might want to override or extend the message anyway. +- for each exeption we might want to handle programmatically, we need a variant based +on `JabRefException` + +So we might end up: + +```java +try { + A a = f(); + B b = g(a); + realAction(a, b); +} catch(FDerivedFromJabRefException ex) { + showDialog(title, messageForF ); +} catch(GDerivedFromJabRefException ex) { + showDialog(title, messageForG ); +} catch(JabRefException ex) { + showDialog(title, ex.message ); +} catch(Exception ex) { // [1] + showDialog(title, ex.message, ex ); + // [1] does "never catch Exception or Throwable" apply at this point? + // Probably should not: we are promising not to throw. +} +``` + +which looks very similar to the original version. + +This again loses the information: can `GDerivedFromJabRefException` +come from `realAction` or `f` or not? This is because we have pushed +down the last catch/throw indefinitely (eliminating `wrap_f`) into a +depth, where we cannot necessarily assign an appropriate message. + +To a lesser extent this also happens in `wrap_f`: it only knows about +the action that called it what we provide (`title` or nothing). It knows +the precondition it checks: probably an optimal location to assign a message. + +**Summary**: going from top to bottom, we move to increasingly more local context, +our knowledge shifts towards the "in which part of the code did we have a problem" +and away from the high level ("which action"). + +One natural point to meet information from these to levels +is the top level of action handlers. For precondition checking code +a wrapper around code elsewhere may be considered. +Using such wrappers may reduce duplication if called in multiple actions. + +We still have to signal failure to the action handler: the options considered +above were using an `Optional` and throwing an exception with the appropriate message. + +The more promising variants were + +- **[dialog in wrap, return Optional]** + `Optional wrap_f(String title)` (showDialog inside) + - pro: explicit return in caller + - con: explicit return in caller (boilerplate) + - con: passing in the title is repeated + - would be 'pro' if we wanted title to vary within an action + +- **[PreconditionException, dialog in catch]** + `A wrap_f() throws PreconditionException` + (with `showDialog` under `catch(PreconditionException ex)`) + - con: hidden control flow + - pro: no repeated `if(){return}` boilerplate + - pro: title used only once + +### [using OOResult] + +```java +final String title = "Could not insert citation"; + +OOResult odoc = getXTextDocument(); +if (testDialog(title, + odoc, + styleIsRequired(style), + selectedBibEntryIsRequired(entries, OOError::noEntriesSelectedForCitation))) { + return; +} +XTextDocument doc = odoc.get(); + +OOResult ofr = getFrontend(doc); +if (testDialog(title, ofr)) { + return; +} +OOFrontend fr = ofr.get(); + +OOResult cursor = getUserCursorForTextInsertion(doc); +if (testDialog(title, cursor)) { + return; +} +... +``` + + +### [using PreconditionException, dialog in catch] + +```java +final String title = "Could not insert citation"; + +try { + XTextDocument doc = getXTextDocument(); + styleIsRequired(style); + selectedBibEntryIsRequired(entries, OOError::noEntriesSelectedForCitation); + OOFrontend fr = getFrontend(doc); + XTextCursor cursor = getUserCursorForTextInsertion(doc); + ... +} catch (PreconditionException ex) { + showDialog(title, ex); +} catch (...) { +} +``` + +I would suggest using the latter, + +- probably using `OOError` for `PreconditionException` + - In this case `OOError` being in `gui` becomes an asset: we can be sure + code in `logic` cannot throw it. +- We lose the capability to collect mmessages in a single dialog (we + stop processing at the first problem). +- The division between precondition checking (only throws + PreconditionException) and `realAction`becomes invisible in the + action code. + diff --git a/docs/openoffice/ooresult-ooerror.md b/docs/openoffice/ooresult-ooerror.md new file mode 100644 index 00000000000..867ee55d009 --- /dev/null +++ b/docs/openoffice/ooresult-ooerror.md @@ -0,0 +1,232 @@ +# About `OOError`, `OOResult` and `OOVoidResult` + +## Context + +### Relieve GUI panel code + +On the question of where should we catch exceptions in relation to GUI +code it was suggested (Jonatan Asketorp +[here](https://github.com/koppor/jabref/pull/496#discussion_r629695493), "most +of them (all?) should be handled latest in the ViewModel.") that +catching them early could help simplifying the higher levels. + +### Same messages in different contexts + +Some types of exceptions are caught in *different GUI actions*, often +resulting in basically the same error dialog, possibly only differing in +the indicated context (which GUI action). + +Problems found during *precondition checking* (for example: do we have +a connection to a document) and error conditions (for example: lost +connection to a document during an action) can overlap. + +### OOBibBase as a precondition and exception handling layer + +Since most of the code originally in `OOBibBase` was moved to `logic` and +almost all GUI actions go through `OOBibBase`, it seemed a good location +to collect precondition checking and exception handling code. + +Note: some of the precondition checking still needs to stay in `OpenOfficePanel`: +for example to provide a list of selected `BibEntry` instances, it needs to go through some steps +from `frame.getCurrentLibraryTab()` to `(!entries.isEmpty() && checkThatEntriesHaveKeys(entries))` + +To avoid `OOBibBase` depending on the higher level `OpenOfficePanel` +message texts needed in `OOBibBase` were moved from `OpenOfficePanel` to `OOError`. +(Others stayed, but could be moved if that seems worthwile) + +## OOError + +- `OOError` is a collection of data used in error dialogs. + - It is a `JabRefException` with an added field: `localizedTitle` + - It can store: a dialog title, a localized message (optionally a non-localized message as well) and a `Throwable` + - I used it in `OOBibBase` as a unified format for errors to be shown in an error dialog. + - Static constructors in `OOError` provide uniform translation from some exception types to + `OOError` with the corresponding localized messages: + `public static OOError from(SomeException ex)` + There is also `public static OOError fromMisc(Exception ex)` for exception types + not handled individually. (It has a different name, to avoid ambiguity) + + - Another set of contructors provide messages for some preconditions. + For example `public static OOError noDataBaseIsOpenForCiting()` + +Some questions: + +- Should we use static data instead of static methods for the precondition-related messages? + - pro: why create a new instance for each error? + - con: `OOError.setTitle()` currently just sets `this.localizedTitle` and returns `this`. + For static instances this would modify a shared resource unless we create a new copy in `setTitle`. + However `setTitle` can be called repeatedly on the same object: as we bubble up, we can be more specific + about the context. + +- Should we remove title from `OOError`? + - pro: we almost always override its original value + - con: may need to duplicate the title in different files (preconditions for an action in OpenOfficePanel + and in OOBibBase) + +- Should we include `OOError.showErrorDialog` ? + - pro: since it was intended *for* error dialogs, it is nice to provide this. + - con: the reference to `DialogService` forces it to `gui`, thus it cannot be used in `logic` or `model` + +- Should we use `JabRefException` as base? + - pro: `JabRefException` is mentioned as the standard form of errors in the developers guide. + [All Exceptions we throw should be or extend JabRefException](https://jabref.readthedocs.io/en/latest/getting-into-the-code/code-howtos/#throwing-and-catching-exceptions) + - against: `JabRefException` is in `logic` cannot be used in model. + (Could this be resolved by moving `JabRefException` to `model`?) + +## OOResult + +During precondition checking + +1. some tests return no data, only report problems +2. we may need to get some resources that might not be available + (for example: connection to a document, a functional textview cursor) +3. some test depend on these resources + +While concentrating on these and on "do not throw exceptions here" +... using a [Result type](https://en.wikipedia.org/wiki/Result_type) as a return +value from precondition checking code seemed a good fit: + +- Instead of throwing an exception, we can return some data describing the problem. +- Conceptually it is a data structure that either holds the result (of a computation) or and error value. +- It can be considered as an extended `Optional`, that can provide details on "why empty"? +- It can be considered as an alternative to throwing an exception: we return an `error` instead. +- Methods throwing checked exceptions cannot be used with for example `List.map`. + Methods returning a Result could. + +- `Result` shares the problem (with any other solutions) that in a +function several types of errors may occur, but we can only return a +single error type. Java solves this using checked exceptions being all +descendants of Exception. (Also adds try/catch/catch to select cases +based on the exceptions type, and some checking against forgotten +cases of checked exception types) + +In `OOBibBase` I used `OOError` as the unified error type: it can +store error messages and wrap exceptions. It contains everything we need +for an error dialog. On the other hand it does not support programmatic +dissection. + +### Implementation + +Unlike `Optional` and `List`, `Result` (in the sense used here) did not get into +java standard libraries. There are some implementations of this idea for java on the net: + +- [bgerstle/result-java](https://github.com/bgerstle/result-java/) +- [MrKloan/result-type](https://github.com/MrKloan/result-type) +- [david-bakin](https://gist.github.com/david-bakin/35d55daeeaee1eb71cea) +- [vavr-try](https://www.baeldung.com/vavr-try) + +Generics allow an implementation built around + +```java +class OOResult { + private final Optional result; + private final Optional error; +} +``` + +with an assumption that at any time exactly one of `result` and `error` is present. + +> `class X { boolean isOK; Object data; }` expresses this assumption more directly, +> (but omits the relation between the type parameters `` and the type in `data`) + +- Since `OOResult` encodes the state `isOK` in `result.isPresent()` (and equivalently in `errror.isEmpty()`), + we cannot allow construction of instances where both values are `isEmpty`. + In particular, `OOResult.ok(null)` and `OOResult.error(null)` are not + allowed: it would make the state `isOK` ambiguous. + It would also break the similarity to `Optional` to allow both `isEmpty` and `isOK` to be true. + +- Not allowing null, has a consequence on `OOResult` + According to + [baeldung.com/java-void-type](https://www.baeldung.com/java-void-type), + the only possible value for `Void` is `null` which we excluded. + + `OOResult.ok(null)` would look strange: in this case we need + `ok()` without arguments. + +To solve this problem, I introduced + +```java +class OOVoidResult { + private final Optional error; + ... +} +``` + +with methods on the error side similar to those in `OOError`, and +`OOVoidResult.ok()` to construct the success case with no data. + +### The relation between `Optional` and `OOVoidResult` + +- Both `Optional` and `OOVoidResult` can store 0 or 1 values, + in this respect they are equivalent + + - Actually, `OOVoidResult` is just a wrapper around an `Optional` + +- In terms of communication to human readers when used, their + connotation in respect to success and failure is the opposite: + + - `Optional.empty()` normally suggests failure, `OOVoidResult.ok()` mean success. + - `Optional.of(something)` probably means success, `OOVoidResult.error(something)` indicates failure. + - `OOVoidResult` is "the other half" (the failure branch) of `OOResult` + + - its content is accessed through `getError`, `mapError`, `ifError`, not `get`, `map`, `ifPresent` + +`OOVoidResult` allows + +- a clear distinction between success and failure when + calls to "get" something that might not be available (`Optional`) and + calls to precondition checking where we can only get reasons for failure + (`OOVoidResult`) + appear together. + Using `Optional` for both is possible, but is more error-prone. + +- it also allows using uniform verbs (`isError`, `getError`, + `ifError`, return `OO{Void}Result.error`) for "we have a problem" + when + + - checking preconditions (`OOVoidResult`) is mixed with + - "I need an X" orelse "we have a problem" (`OOResult`) + +- at a functions head: + + - `OOVoidResult function()` says: no result, but may get an error message + - `Optional function()` says: a `String` result or nothing. + +**Summary**: technically could use `Optional` for both situation, but it would be less precise, +leaving more room for confusion and bugs. `OOVoidResult` forces use of `getError` instead of `get`, +and `isError` or `isOk` instead of `isPresent`or `isEmpty`. + +## What does OOResult buy us? + + +The promise of `Result` is that we can avoid throwing exceptions and +return errors instead. This allows the caller to handle these latter +as data, for example may summarize / collect them for example into a single +message dialog. + +Handling the result needs some code in the caller. If we only needed checks that +return only errors (not results), the code could look like this (with possibly more tests listed): + +```java +OOResult odoc = getXTextDocument(); +if (testDialog(title, + odoc, + styleIsRequired(style), + selectedBibEntryIsRequired(entries, OOError::noEntriesSelectedForCitation))) { + return; +} +``` + +with a reasonably small footstep. + +Dependencies of tests on earlier results complicates this: now we repeat the + +```java +if (testDialog(title, + ...)) { + return; +} +``` + +part several times. + diff --git a/docs/openoffice/order-of-appearance.md b/docs/openoffice/order-of-appearance.md new file mode 100644 index 00000000000..e43009b9f93 --- /dev/null +++ b/docs/openoffice/order-of-appearance.md @@ -0,0 +1,118 @@ + +# Order of appearance of citation groups (`globalOrder`) + +The order of appearance of citations is decided on +two levels: + +1. their order within each citation group (`localOrder`), and +2. the order of the citation +groups that appear as citation markers in the text (`globalOrder`). + +This page is about the latter: how to decide the order of appearance (numbering sequence) of a set +of citation markers? + +## Conceptually + +In a continuous text it is easy: take the textual order of citation markers. + +In the presence of figures, tables, footnotes/endnotes possibly far from the location they are +referred to in the text or wrapped around with text it becomes less obvious what is the correct +order. + +Examples: + +- References in footnotes: are they *after* the page content, or number them as if they appeared at + the footnote mark? (JabRef does the latter) +- A figure with references in its caption. Text may flow on either or both sides. + Where should we insert these in the sequence? +- In a two-column layout, a text frame or figure mostly, but not fully in the second column: shall + we consider it part of the second column? + + +## Technically + + +In LibreOffice, a document has a main text that supports the +[XText](https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1text_1_1XText.html) +interface. +This allows several types of +[XTextContent](https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1text_1_1XTextContent.html) +to be inserted. + +- Some of these allow text inside with further insertions. + +### Anchors + +- Many, but not all XTextContent types support getting a "technical" insertion point or text range + through [getAnchor](https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1text_1_1XTextContent.html#ae82a8b42f6b2578549b68b4483a877d3). +- In Libreoffice positioning both a frame and its anchor seems hard: moving the frame tends to also + move the anchor. +- Consequence: producing an order of appearance for the citation groups based solely on `getAnchor` + calls may be impossible. + + - Allowing or requiring the user to insert "logical anchors" for frames and other "floating" parts + might help to alleviate these problems. + +### Sorting within a `Text` + +The text ranges occupied by the citation markers support the +[XTextRange](https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1text_1_1XTextRange.html) +interface. + +- These provide access to the XText they are contained in. +- The [Text](https://api.libreoffice.org/docs/idl/ref/servicecom_1_1sun_1_1star_1_1text_1_1Text.html) service +may support (optional) the [XTextRangeCompare](https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1text_1_1XTextRangeCompare.html) +interface, that allows two XTextRange values to be compared if both belong to this `Text` + +### Visual ordering + +- The cursor used by the user is available as an + [XTextViewCursor](https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1text_1_1XTextViewCursor.html) +- If we can get it and can set its position in the document to each XTextRange to be sorted, and ask its + [getPosition](https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1text_1_1XTextViewCursor.html#a9b2bafd342ef75b5d504a9313dbb1389) + to provide coordinates "relative to the top left position of the first page of the document.", + then we can sort by these coordinates in top-to-bottom left-to-right order. +- Note: in some cases, for example when the cursor is in a comment (as in + `Libreoffice:[menu:Insert]/[Comment]`), the XTextViewCursor is not available (I know of no way to + get it). +- In some other cases, for example when an image is selected, the XTextViewCursor we normally receive is not 'functional': +we cannot position it for getting coordinates for the citation marks. +The [FunctionalTextViewCursor](https://github.com/antalk2/jabref/blob/improve-reversibility-rebased-03/src/main/java/org/jabref/model/openoffice/rangesort/FunctionalTextViewCursor.java) +class can solve this case by accessing and manipulating the cursor through [XSelectionSupplier](https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1view_1_1XSelectionSupplier.html) + +Consequences of getting these visual coordinates and using them to order the citation markers + +- allows uniform handling of the markers. Works in footnotes, tables, frames (apparently anywhere) +- requires moving the user visible cursor to each position and with [screen + refresh](https://github.com/antalk2/jabref/blob/improve-reversibility-rebased-03/src/main/java/org/jabref/model/openoffice/uno/UnoScreenRefresh.java) + enabled. + `(problem)` This results in some user-visible flashing and scrolling around in the document view. +- The expression "relative to the top left position of the first page of the document" is + understood literally, "as on the screen". + `(problem)` Showing pages side by side or using a two-column layout + will result in markers in the top half of the second column or page to be sorted before those on the bottom + of the first column of the first page. + + +## JabRef + +Jabref uses the following steps for sorting sorting citation markers (providing `globalOrder`): + +1. the textranges of citation marks in footnotes are replaced by the textranges of the footnote + marks. +2. get the positions (coordinates) of these marks +3. sort in top-to-botton left-to-right order + + +`(problem)` In JabRef5.2 the positions of citation marks within the same footnote become +indistinguishable, thus their order after sorting may differ from their order in the footnote text. +This caused problems for + +1. numbering order + `(solved)` by keeping track of the order-in-footnote of citation markers during sorting using + [getIndexInPosition](https://github.com/antalk2/jabref/blob/122d5133fa6c7b44245c5ba5600d398775718664/src/main/java/org/jabref/model/openoffice/rangesort/RangeSortable.java#L21)) +2. `click:Merge`: It examines *consecutive* pairs of citation groups if they can be merged. Wrong +order may result in not discovering some mergeable pairs or attempting to merge in wrong order. +`(solved)` by not using visual order, only XTextRangeCompare-based order within each XText +[here](https://github.com/antalk2/jabref/blob/122d5133fa6c7b44245c5ba5600d398775718664/src/main/java/org/jabref/logic/openoffice/action/EditMerge.java#L325)) + diff --git a/docs/openoffice/overview.md b/docs/openoffice/overview.md new file mode 100644 index 00000000000..f3a6ed251f6 --- /dev/null +++ b/docs/openoffice/overview.md @@ -0,0 +1,297 @@ + +# Overview + +This is a partial overview of the OpenOffice/LibreOffice panel and the +code behind. + +- To access the panel: `JabRef:/[menu:View]/[OpenOffice/LibreOffice]` +- The user documentation is at +[https://docs.jabref.org/cite/openofficeintegration](https://docs.jabref.org/cite/openofficeintegration) + + +I am going to refer to OpenOffice Writer and LibreOffice Writer as +LibreOffice or LO: their UNO APIs are still mostly identical, but I +only tested with LibreOffice and differences do exist. + +## Subject + +- What is stored in a document, how. +- Generating citation markers and bibliography + - (excluding the bibliography entries, which is delegated to the layout module) + + +## The purpose of the panel + +- Allow the user to insert **citations** in a LibreOffice writer document. +- Automatically format these according to some prescribed style as **citation markers**. +- Generate a **bibliography**, also formatted according to the style. + - The bibliography consists of a title (e.g. "References") and a sorted list + of formatted bibliography entries, possibly prefixed with a marker (e.g. "[1]") +- It also allows some related activities: connect to a document, select a style, group ("Merge") the + citations for nicer output, ungroup ("Separate") them to move or delete them individually, + edit ("Manage") their page-info parts, and collect the database entries of cited sources + to a new database. + +## Citation types + +Citations (actually citation groups, see below) have three types +depending on how the citation marker is intended to appear in the +text: + +- **Parenthesized**: "(Smith, 2000)" +- **In-text**: "Smith (2000)" +- **Invisible**: no visible citation mark. + - An invisible citation mark lets the user to use any form for the citation + by taking control (and responsibility) back from the style. + - Like the other two citation types, they have a location in the document. + - In the bibliography these behave as the other two citation types. + - In LibreOffice (`LibreOffice:[Ctrl-F8]` or`LibreOffice:[menu:View]/[Field Shadings]`) + shows reference marks with gray background. Invisible citation marks appear as a thin gray rectangle. + +- These citation types correspond to `\citep{Smith2000}`, + `\citet{Smith2000}` in + [natbib](http://tug.ctan.org/macros/latex/contrib/natbib/natnotes.pdf) + and `\nocite{Smith2000}`. I will use `\citep`, `\citet` and `\citen` in "LaTeX pseudocode" below. + +## PageInfo + +The citations can be augmented with a string detailing which part +of a document is cited, for example "page 11" or "chapter 2". + +Sample citation markers (with LaTeX pseudocode): + +- `\citep[page 11]{Smith2000}` "(Smith, 2000; page 11)" +- `\citet[page 11]{Smith2000}` "Smith (2000; page 11)" +- `\citen[page 11]{Smith2000}` "" + +- This string is referred to as **`pageInfo`** in the code. +- In the GUI the labels "Cite special", "Extra information + (e.g. page number)" are used. + +## Citation groups + +Citations can be grouped. + +A group of parenthesized citations share the parentheses around, like this: + "(Smith, 2000; Jones 2001)". + +- Examples with pseudocode: + - `\citep{Smith2000,Jones2001}` "(Smith, 2000; Jones 2001)" + - `\citet{Smith2000,Jones2001}` "Smith (2000); Jones (2001)" + - `\citen{Smith2000,Jones2001}` "" + +From the user's point of view, citation groups can be created by + +1. Selecting multiple entries in a bibliography database, then + - `[click:Cite]` or + - `[click:Cite in-text]` or + - `[click:Cite special]` or + - `[click:Insert empty citation]` in the panel. + + This method allows any of the citation types to be used. + +2. `[click:Merge citations]` finds all sets of consecutive citations in the text and + replaces each with a group. + - `(change)` The new code only merges consecutive [parenthesized](https://github.com/antalk2/jabref/blob/122d5133fa6c7b44245c5ba5600d398775718664/src/main/java/org/jabref/logic/openoffice/action/EditMerge.java#L183) citations. + - This is inconsistent with the solution used in `[click:Cite]` + - My impression is that + - groups of in-text or invisible citations are probably not useful + - mixed groups are even less. However, with a numbered style + there is no visual difference between parenthesized and in-text + citations, the user may be left wondering why did merge not work. + - One way out could be to merge as a "parenthesized" + group. But then users switching between styles get a + surprise, we have unexpectedly overridden their choice. + - I would prefer a visible log-like warning that does not require + a click to close and lets me see multiple warnings. + Could the main window have such an area at the bottom? + - Starting with JabRef 5.3 there is also `[click:Separate citations]` + that breaks all groups to single citations. + - This allows + - deleting individual citations + - moving individual citations around (between citation groups) + - (copy does not work) + - (Moving a citation within a group has no effect on the final output + due to sorting of citations within groups. See [Sorting within a citation group](#localOrder)) + +In order to manage single citations and groups uniformly, we +consider each citation in the document to belong to a citation +group, even if it means a group containing a single citation. + +Citation groups correspond to citation markers in the document. The latter is empty for invisible +citation groups. When creating the citation markers, the citations in the group +are processed together. + +# Citation styles + +The details of how to format the bibliography and the citation markers are described in a text file. + +- These normally use `.jstyle` extension, and I will refer to them as jstyle files. +- See the [User documentation](https://docs.jabref.org/cite/openofficeintegration#the-style-file) + for details. +- I will refer to keywords in jstyle files as `jstyle:keyword` below. + + +Four major types citation of styles can be described by a jstyle. + +- (1) `jstyle:BibTeXKeyCitations` + + - The citation markers show the citationKey. + - It is not fully implemented + - does not produce markers before the bibliography entries + - does not show pageInfo + - It is not advertised in the [User documentation](https://docs.jabref.org/cite/openofficeintegration#the-style-file). + - Its intended purpose may be + + - (likely) a proper style, with "[Smith2000]" style citation markers + - (possibly) a style for "draft mode" that + - can avoid lookup of citation markers in the database when only the + citation markers are updated + - can produce unique citation markers trivially (only needs local information) + - makes the citation keys visible to the user + - can work without knowing the order of appearance of citation groups + - In case we expect to handle larger documents, a "draft mode" + minimizing work during `[click:Cite]` may be useful. + +- There are two types of numbered (`jstyle:IsNumberEntries`) citation styles: + + - (2) Citations numbered in order of first appearance (`jstyle:IsSortByPosition`) + - (3) Citations numbered according to their order in the sorted bibliography + +- (4) Author-year styles + +# Sorting + +## Sorting te bibliography + +The bibliography is sorted in (author, year, title) order + +- except for `jstyle:IsSortByPosition`, that uses the order of first + appearance of the cited sources. + +## Ordering the citations + +The order of appearance of citations (as considered during numbering and adding letters after the +year to ensure that citation markers uniquely identify sources in the bibliography) is decided on +two levels. + +1. Their order within each citation group (`localOrder`), and +2. the order of the citation groups (citation markers) in the text (`globalOrder`). + +### Sorting within a citation group (`localOrder`) + +The order of citations within a citation group is controlled by +`jstyle:MultiCiteChronological`. + +- true asks for (year, author, title) ordering, +- false for (author, year, title). +- (There is no option for "in the order provided by the user"). + + +For author-year citation styles this ordering is used directly. + +- The (author, year, title) order promotes discovering citations + sharing authors and year and emitting them in a shorter form. For + example as "(Smith 2000a,b)". + +For numbered styles, the citations within a group are sorted again +during generation of the citation marker, now by the numbers +themselves. The result of this sorting is not saved, only affects the citation marker. + +- Series of consecutive number are replaced with ranges: for example "[1-5; 11]" + +### Order of the citation groups (`globalOrder`) + +The location of each citation group in the document is provided by the +user. In a text with no insets, footnotes, figures etc. this directly +provides the order. In the presence of these, it becomes more +complicated, see [Order of appearance of +citation groups](order-of-appearance.md). + +### Order of the citations + +- `globalOrder` and `localOrder` together provide the order of appearance of + citations +- This also provides the order of first appearance of the cited sources. + + First appearance order of sources is used + - in `jstyle:IsSortByPosition` numbered styles + - in author-year styles: first appearance of "Smith200a" + should precede that of "Smith200b". + To achieve this, the sources get the letters + according the order of their first appearance. + - This seems to contradict the statement "The bibliography is + sorted in (author, year, title) order" above. + It does not. As of JabRef 5.3 both are true. + Consequence: in the references + Smith2000b may precede Smith2000a. + ([reported](https://github.com/JabRef/jabref/issues/7805)) + - Some author-year citation styles prescribe a higher threshold on + the number of authors for switching to "FirstAuthor et al." form + (`jstyle:MaxAuthors`) at the first citation of a source + (`jstyle:MaxAuthorsFirst`) + + +# What is stored in a document (JabRef5.2) + +- Each group of citations has a reference mark. + + (Reference marks are shown in LibreOffice in Navigator, under "References". + To show the Navigator: `LibreOffice:[menu:View]/[Navigator]` or `LibreOffice:[key:F5]`) + + Its purposes: + + 1. The text range of the reference mark tells where to write or update the citation mark. + 2. The name of the reference mark + + - Lets us select only those reference marks that belong to us + - Encodes the citation type + - Contains the list of citation keys that belong to this group + - It may contain an extra number, to make the name unique in the document + - Format: `"JR_cite{number}_{type}_{citationKeys}"`, where + - `{number}` is either empty or an unsigned integer (it can be zero) to make the name unique + - `{type}` is 1, 2, or 3 for parenthesized, in-text and invisible + - `{citationKeys}` contains the comma-separated list of citation keys + - Examples: + - `JR_cite_1_Smith2000` (empty number part, parenthesized, single citation) + - `JR_cite0_2_Smith2000,Jones2001` (number part is 0, in-text, two citations) + - `JR_cite1_3_Smith2000,Jones2001` (number part is 1, invisible, two citations) + +- Each group of citations may have an associated pageInfo. + + - In LibreOffice, these can be found at + `LibreOffice:/[menu:File]/[Properties]/[Custom Properties]` + - The property names are identical to the name of the reference mark + corresponding to the citation group. + - JabRef 5.2 never cleans up these, they are left around. + `(problem)` New citations may "pick up" these unexpectedly. + +- The bibliography, if not found, is created at the end of the document. + - The location and extent of the bibliography is the content of the Section named `"JR_bib"`. + (In LibreOffice Sections are listed in the Navigator panel, under "Sections") + - JabRef 5.2 also creates a bookmark named `"JR_bib_end"`, but does + not use it. During bibliography update it attempts to create it again without + removing the old bookmark. The result is a new bookmark, with a number appended to its name + (by LibreOffice, to ensure unique names of bookmarks). + - [Correction in new code](https://github.com/antalk2/jabref/blob/122d5133fa6c7b44245c5ba5600d398775718664/src/main/java/org/jabref/logic/openoffice/frontend/UpdateBibliography.java#L147): + remove the old before creating the new. + +# How does it interact with the document? + +- "stateless" + JabRef is only loosely coupled to the document. + Between two GUI actions it does not receive any information from LibreOffice. + It cannot distinguish between the user changing a single character in the document or rewriting everything. + +- Access data + - During a `[click:cite]` or `[click:Update]` we need the reference mark names. + - Get all reference mark names + - Filter (only ours) + - Parse: gives citation type (for the group), citation keys + - Access/store pageInfo: based on reference mark name and property name being equal + - Creating a citation group: (`[click:cite]`) + - Creates a reference mark at the cursor, with a name as described above. +- Update (refreshing citation markers and bibliography): + - citation markers: the content of the reference mark + - bibliography: the content of the Section (in LibreOffice sense) + named `"JR_bib"`. diff --git a/docs/openoffice/problems.md b/docs/openoffice/problems.md new file mode 100644 index 00000000000..c23b39a7d25 --- /dev/null +++ b/docs/openoffice/problems.md @@ -0,0 +1,97 @@ +# Problems in JabRef 5.2 + +## pageInfo should belong to citations, not citation groups + +- Creating `[click:Separate]` revealed + a `(problem)`: pageInfo strings are conceptually associated with + citations, but the implementation associates them to citation groups. + The number of available + pageInfo slots changes during`[click:Merge]` and `[click:Separate]` while the number of citations + remains fixed. + - The proposed solution was to change the association. + - Not only reference marks (citation groups) need unique identifiers, but also citations. + Possible encoding for reference mark names: + `JR_cite{type}_{number1}_{citationKey1},{number2}_{citationKey2}` + where `{type}` encodes the citation type (for the group), `{citationKey1}` is made unique by choosing an appropriate number for `{number1}` + This would allow + `JR_cite_{number1}_{citationKey1}` to be used as a property name for storing the pageInfo. + + Changes required to + - reference mark search, name generation and parsing + - name generation and parsing for properties storing pageInfo values + - in-memory representation + - JabRef 5.2 does not collect pageInfo values, accesses only when needed. + So it would be change to code accessing them. + - The proposed representation does collect, to allow separation of getting from the document + and processing + - insertion of pageInfo into citation markers: JabRef 5.2 injects a single pageInfo before the closing parenthesis, + now we need to handle several values + - `[click:Manage citations]` should work on citations, not citation groups. + + +## Backend + +The choice of how do we represent the data and the citation marks in the document has consequences +on usability. + +Reference marks have some features that make it easy to mess up citations in a document + +- They are **not visible** by default, the user is not aware of their boundaries +(`LO:[key:Ctrl-F8]`, `LO:[View]/[Field shadings]` helps) + +- They are **not atomic**: + - the user can edit the content. This will be lost on `[click:Update]` + If an `As character` or `To character` anchor is inserted, the corresponding frame or footnote is deleted. + - by pressing Enter within, the user can break a reference mark into two parts. + The second part is now outside the reference mark: `[click:Update]` will leave it as is, and replace the first part + with the full text for the citation mark. + - If the space separating to citation marks is deleted, the user cannot reliably type between the + marks. + The text typed usually becomes part of one of the marks. No visual clue as to which one. + Note: `[click:Merge]` then `[click:Separate]` adds a single space between. The user can + position the cursor before or after it. In either case the cursor is on a boundary: it is not + clear if it is in or out of a reference mark. + Special case: a reference mark at the start or end of a paragraph: the cursor is usually considered to be within at the coresponding edge. +- (good) They can be moved (Ctrl-X,Ctrl-V) +- They cannot be copied. (Ctrl-C, Ctrl-V) copies the text without the reference mark. +- Reference marks are lost if the document is saved as docx. + +- I know of no way to insert text into an empty text range denoted by a reference mark + - JabRef 5.3 recreates the reference mark (using [insertReferenceMark](https://github.com/JabRef/jabref/blob/475b2989ffa8ec61c3327c62ed8f694149f83220/src/main/java/org/jabref/gui/openoffice/OOBibBase.java#L1072)) + [here](https://github.com/JabRef/jabref/blob/475b2989ffa8ec61c3327c62ed8f694149f83220/src/main/java/org/jabref/gui/openoffice/OOBibBase.java#L706) + - `(change)` I preferred to (try to) avoid this: + [NamedRangeReferenceMark.nrGetFillCursor](https://github.com/antalk2/jabref/blob/122d5133fa6c7b44245c5ba5600d398775718664/src/main/java/org/jabref/logic/openoffice/backend/NamedRangeReferenceMark.java#L225) + returns a cursor between two invisible + spaces, to provide the caller a location it can safely write some text. [NamedRangeReferenceMark.nrCleanFillCursor](https://github.com/antalk2/jabref/blob/122d5133fa6c7b44245c5ba5600d398775718664/src/main/java/org/jabref/logic/openoffice/backend/NamedRangeReferenceMark.java#L432) + removes these invisible spaces unless the content would become empty or a single character. By + keeping the content at least two characters, we avoid the ambiguity at the edges: a cursor + positioned between two characters inside is always within the reference mark. (At the edges it + may or may not be inside.) + +- `(change)` `[click:Cite]` at reference mark edges: [safeInsertSpacesBetweenReferenceMarks](https://github.com/antalk2/jabref/blob/122d5133fa6c7b44245c5ba5600d398775718664/src/main/java/org/jabref/logic/openoffice/backend/NamedRangeReferenceMark.java#L67) ensures the we are not inside, by starting two new paragraphs, inserting two spaces between them, then removing the new paragraph marks. +- `(change)` [guiActionInsertEntry](https://github.com/antalk2/jabref/blob/122d5133fa6c7b44245c5ba5600d398775718664/src/main/java/org/jabref/gui/openoffice/OOBibBase2.java#L624) +checks if the cursor is in a citation mark or the bibliography. + +- `(change)` `[click:Update]` does an [exhaustive check](https://github.com/antalk2/jabref/blob/122d5133fa6c7b44245c5ba5600d398775718664/src/main/java/org/jabref/gui/openoffice/OOBibBase2.java#L927) +for overlaps between protected ranges (citation marks and bibliography). This can become slow if there are many citations. + + +It would be nice if we could have a backend with better properties. We probably need multiple +backends for different purposes. This would be made easier if the backend were separated from the +rest of the code. This would be the purpose of +[logic/openoffice/backend](https://github.com/antalk2/jabref/tree/improve-reversibility-rebased-03/src/main/java/org/jabref/logic/openoffice/backend). + +## Undo + +- JabRef 5.3 does not collect the effects of GUI actions on the document into larger Undo actions. +This makes the Undo functionality of LO impractial. +- `(change)` collect the effects of GUI actions into large chunks: now a GUI action can be undone +with a single click. + - except the effect on pageInfo: that is stored at the document level and is not restored by Undo. + +## Block screen refresh + +- LibreOffice has support in [XModel](https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1frame_1_1XModel.html#a7b7d36374033ee9210ec0ac5c1a90d9f) +to "suspend some notifications to the controllers which are used for display updates." + +- `(change)` Now we are using this facility. diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 39910a08fac..043d325694c 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -91,6 +91,7 @@ requires org.apache.tika.core; requires pdfbox; requires xmpbox; + requires com.ibm.icu; requires flexmark; requires flexmark.ext.gfm.strikethrough; @@ -104,5 +105,4 @@ requires com.fasterxml.jackson.dataformat.yaml; requires com.fasterxml.jackson.datatype.jsr310; requires net.harawata.appdirs; - } diff --git a/src/main/java/org/jabref/cli/ArgumentProcessor.java b/src/main/java/org/jabref/cli/ArgumentProcessor.java index adbf9be7f42..681b9155a30 100644 --- a/src/main/java/org/jabref/cli/ArgumentProcessor.java +++ b/src/main/java/org/jabref/cli/ArgumentProcessor.java @@ -1,7 +1,7 @@ package org.jabref.cli; import java.io.IOException; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -236,7 +236,6 @@ private List processArguments() { if (!loaded.isEmpty()) { writeMetadatatoPdf(loaded, cli.getWriteMetadatatoPdf(), - preferencesService.getGeneralPreferences().getDefaultEncoding(), preferencesService.getXmpPreferences(), preferencesService.getFilePreferences(), preferencesService.getGeneralPreferences().getDefaultBibDatabaseMode(), @@ -271,7 +270,7 @@ private List processArguments() { return loaded; } - private void writeMetadatatoPdf(List loaded, String filesAndCitekeys, Charset encoding, XmpPreferences xmpPreferences, FilePreferences filePreferences, BibDatabaseMode databaseMode, BibEntryTypesManager entryTypesManager, FieldWriterPreferences fieldWriterPreferences, boolean writeXMP, boolean embeddBibfile) { + private void writeMetadatatoPdf(List loaded, String filesAndCitekeys, XmpPreferences xmpPreferences, FilePreferences filePreferences, BibDatabaseMode databaseMode, BibEntryTypesManager entryTypesManager, FieldWriterPreferences fieldWriterPreferences, boolean writeXMP, boolean embeddBibfile) { if (loaded.isEmpty()) { LOGGER.error("The write xmp option depends on a valid import option."); return; @@ -285,7 +284,7 @@ private void writeMetadatatoPdf(List loaded, String filesAndCiteke if ("all".equals(filesAndCitekeys)) { for (BibEntry entry : dataBase.getEntries()) { - writeMetadatatoPDFsOfEntry(databaseContext, entry.getCitationKey().orElse(""), entry, encoding, filePreferences, xmpPdfExporter, embeddedBibFilePdfExporter, writeXMP, embeddBibfile); + writeMetadatatoPDFsOfEntry(databaseContext, entry.getCitationKey().orElse(""), entry, filePreferences, xmpPdfExporter, embeddedBibFilePdfExporter, writeXMP, embeddBibfile); } return; } @@ -300,22 +299,22 @@ private void writeMetadatatoPdf(List loaded, String filesAndCiteke } } - writeMetadatatoPdfByCitekey(databaseContext, dataBase, citeKeys, encoding, filePreferences, xmpPdfExporter, embeddedBibFilePdfExporter, writeXMP, embeddBibfile); - writeMetadatatoPdfByFileNames(databaseContext, dataBase, pdfs, encoding, filePreferences, xmpPdfExporter, embeddedBibFilePdfExporter, writeXMP, embeddBibfile); + writeMetadatatoPdfByCitekey(databaseContext, dataBase, citeKeys, filePreferences, xmpPdfExporter, embeddedBibFilePdfExporter, writeXMP, embeddBibfile); + writeMetadatatoPdfByFileNames(databaseContext, dataBase, pdfs, filePreferences, xmpPdfExporter, embeddedBibFilePdfExporter, writeXMP, embeddBibfile); } - private void writeMetadatatoPDFsOfEntry(BibDatabaseContext databaseContext, String citeKey, BibEntry entry, Charset encoding, FilePreferences filePreferences, XmpPdfExporter xmpPdfExporter, EmbeddedBibFilePdfExporter embeddedBibFilePdfExporter, boolean writeXMP, boolean embeddBibfile) { + private void writeMetadatatoPDFsOfEntry(BibDatabaseContext databaseContext, String citeKey, BibEntry entry, FilePreferences filePreferences, XmpPdfExporter xmpPdfExporter, EmbeddedBibFilePdfExporter embeddedBibFilePdfExporter, boolean writeXMP, boolean embeddBibfile) { try { if (writeXMP) { - if (xmpPdfExporter.exportToAllFilesOfEntry(databaseContext, encoding, filePreferences, entry, List.of(entry))) { + if (xmpPdfExporter.exportToAllFilesOfEntry(databaseContext, filePreferences, entry, List.of(entry))) { System.out.printf("Successfully written XMP metadata on at least one linked file of %s%n", citeKey); } else { System.err.printf("Cannot write XMP metadata on any linked files of %s. Make sure there is at least one linked file and the path is correct.%n", citeKey); } } if (embeddBibfile) { - if (embeddedBibFilePdfExporter.exportToAllFilesOfEntry(databaseContext, encoding, filePreferences, entry, List.of(entry))) { + if (embeddedBibFilePdfExporter.exportToAllFilesOfEntry(databaseContext, filePreferences, entry, List.of(entry))) { System.out.printf("Successfully embedded metadata on at least one linked file of %s%n", citeKey); } else { System.out.printf("Cannot embedd metadata on any linked files of %s. Make sure there is at least one linked file and the path is correct.%n", citeKey); @@ -326,7 +325,7 @@ private void writeMetadatatoPDFsOfEntry(BibDatabaseContext databaseContext, Stri } } - private void writeMetadatatoPdfByCitekey(BibDatabaseContext databaseContext, BibDatabase dataBase, Vector citeKeys, Charset encoding, FilePreferences filePreferences, XmpPdfExporter xmpPdfExporter, EmbeddedBibFilePdfExporter embeddedBibFilePdfExporter, boolean writeXMP, boolean embeddBibfile) { + private void writeMetadatatoPdfByCitekey(BibDatabaseContext databaseContext, BibDatabase dataBase, Vector citeKeys, FilePreferences filePreferences, XmpPdfExporter xmpPdfExporter, EmbeddedBibFilePdfExporter embeddedBibFilePdfExporter, boolean writeXMP, boolean embeddBibfile) { for (String citeKey : citeKeys) { List bibEntryList = dataBase.getEntriesByCitationKey(citeKey); if (bibEntryList.isEmpty()) { @@ -334,12 +333,12 @@ private void writeMetadatatoPdfByCitekey(BibDatabaseContext databaseContext, Bib continue; } for (BibEntry entry : bibEntryList) { - writeMetadatatoPDFsOfEntry(databaseContext, citeKey, entry, encoding, filePreferences, xmpPdfExporter, embeddedBibFilePdfExporter, writeXMP, embeddBibfile); + writeMetadatatoPDFsOfEntry(databaseContext, citeKey, entry, filePreferences, xmpPdfExporter, embeddedBibFilePdfExporter, writeXMP, embeddBibfile); } } } - private void writeMetadatatoPdfByFileNames(BibDatabaseContext databaseContext, BibDatabase dataBase, Vector fileNames, Charset encoding, FilePreferences filePreferences, XmpPdfExporter xmpPdfExporter, EmbeddedBibFilePdfExporter embeddedBibFilePdfExporter, boolean writeXMP, boolean embeddBibfile) { + private void writeMetadatatoPdfByFileNames(BibDatabaseContext databaseContext, BibDatabase dataBase, Vector fileNames, FilePreferences filePreferences, XmpPdfExporter xmpPdfExporter, EmbeddedBibFilePdfExporter embeddedBibFilePdfExporter, boolean writeXMP, boolean embeddBibfile) { for (String fileName : fileNames) { Path filePath = Path.of(fileName); if (!filePath.isAbsolute()) { @@ -348,14 +347,14 @@ private void writeMetadatatoPdfByFileNames(BibDatabaseContext databaseContext, B if (Files.exists(filePath)) { try { if (writeXMP) { - if (xmpPdfExporter.exportToFileByPath(databaseContext, dataBase, encoding, filePreferences, filePath)) { + if (xmpPdfExporter.exportToFileByPath(databaseContext, dataBase, filePreferences, filePath)) { System.out.printf("Successfully written XMP metadata of at least one entry to %s%n", fileName); } else { System.out.printf("File %s is not linked to any entry in database.%n", fileName); } } if (embeddBibfile) { - if (embeddedBibFilePdfExporter.exportToFileByPath(databaseContext, dataBase, encoding, filePreferences, filePath)) { + if (embeddedBibFilePdfExporter.exportToFileByPath(databaseContext, dataBase, filePreferences, filePath)) { System.out.printf("Successfully embedded XMP metadata of at least one entry to %s%n", fileName); } else { System.out.printf("File %s is not linked to any entry in database.%n", fileName); @@ -410,9 +409,7 @@ private boolean exportMatches(List loaded) { // We have an TemplateExporter instance: try { System.out.println(Localization.lang("Exporting") + ": " + data[1]); - exporter.get().export(databaseContext, Path.of(data[1]), - databaseContext.getMetaData().getEncoding().orElse(preferencesService.getGeneralPreferences().getDefaultEncoding()), - matches); + exporter.get().export(databaseContext, Path.of(data[1]), matches); } catch (Exception ex) { System.err.println(Localization.lang("Could not export file") + " '" + data[1] + "': " + Throwables.getStackTraceAsString(ex)); @@ -455,7 +452,6 @@ private List importAndOpenFiles() { try { pr = OpenDatabase.loadDatabase( Path.of(aLeftOver), - preferencesService.getGeneralPreferences(), preferencesService.getImportFormatPreferences(), Globals.getFileUpdateMonitor()); } catch (IOException ex) { @@ -530,7 +526,7 @@ private void saveDatabase(BibDatabase newBase, String subName) { System.out.println(Localization.lang("Saving") + ": " + subName); GeneralPreferences generalPreferences = preferencesService.getGeneralPreferences(); SavePreferences savePreferences = preferencesService.getSavePreferences(); - AtomicFileWriter fileWriter = new AtomicFileWriter(Path.of(subName), generalPreferences.getDefaultEncoding()); + AtomicFileWriter fileWriter = new AtomicFileWriter(Path.of(subName), StandardCharsets.UTF_8); BibWriter bibWriter = new BibWriter(fileWriter, OS.NEWLINE); BibDatabaseWriter databaseWriter = new BibtexDatabaseWriter(bibWriter, generalPreferences, savePreferences, Globals.entryTypesManager); databaseWriter.saveDatabase(new BibDatabaseContext(newBase)); @@ -538,10 +534,7 @@ private void saveDatabase(BibDatabase newBase, String subName) { // Show just a warning message if encoding did not work for all characters: if (fileWriter.hasEncodingProblems()) { System.err.println(Localization.lang("Warning") + ": " - + Localization.lang( - "The chosen encoding '%0' could not encode the following characters:", - generalPreferences.getDefaultEncoding().displayName()) - + " " + fileWriter.getEncodingProblems()); + + Localization.lang("UTF-8 could not be used to encode the following characters: %0", fileWriter.getEncodingProblems())); } } catch (IOException ex) { System.err.println(Localization.lang("Could not save file.") + "\n" + ex.getLocalizedMessage()); @@ -581,8 +574,6 @@ private void exportFile(List loaded, String[] data) { // We have an exporter: try { exporter.get().export(pr.getDatabaseContext(), Path.of(data[0]), - pr.getDatabaseContext().getMetaData().getEncoding() - .orElse(preferencesService.getGeneralPreferences().getDefaultEncoding()), pr.getDatabaseContext().getDatabase().getEntries()); } catch (Exception ex) { System.err.println(Localization.lang("Could not export file") + " '" + data[0] + "': " diff --git a/src/main/java/org/jabref/gui/JabRefFrame.java b/src/main/java/org/jabref/gui/JabRefFrame.java index 4d6d09ab0f7..3d774c3eab1 100644 --- a/src/main/java/org/jabref/gui/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/JabRefFrame.java @@ -826,7 +826,7 @@ private MenuBar createMenu() { new SeparatorMenuItem(), - factory.createMenuItem(StandardActions.WRITE_METADATA_TO_PDF, new WriteMetadataToPdfAction(stateManager, prefs.getGeneralPreferences().getDefaultBibDatabaseMode(), Globals.entryTypesManager, prefs.getFieldWriterPreferences(), dialogService, taskExecutor, prefs.getFilePreferences(), prefs.getXmpPreferences(), prefs.getGeneralPreferences().getDefaultEncoding())), + factory.createMenuItem(StandardActions.WRITE_METADATA_TO_PDF, new WriteMetadataToPdfAction(stateManager, prefs.getGeneralPreferences().getDefaultBibDatabaseMode(), Globals.entryTypesManager, prefs.getFieldWriterPreferences(), dialogService, taskExecutor, prefs.getFilePreferences(), prefs.getXmpPreferences())), factory.createMenuItem(StandardActions.COPY_LINKED_FILES, new CopyFilesAction(dialogService, prefs, stateManager)), new SeparatorMenuItem(), diff --git a/src/main/java/org/jabref/gui/JabRefGUI.java b/src/main/java/org/jabref/gui/JabRefGUI.java index c4d82316ae0..b6ec8fd0b49 100644 --- a/src/main/java/org/jabref/gui/JabRefGUI.java +++ b/src/main/java/org/jabref/gui/JabRefGUI.java @@ -279,7 +279,6 @@ private void openLastEditedDatabases() { try { parsedDatabase = OpenDatabase.loadDatabase( dbFile, - preferencesService.getGeneralPreferences(), preferencesService.getImportFormatPreferences(), Globals.getFileUpdateMonitor()); } catch (IOException ex) { diff --git a/src/main/java/org/jabref/gui/collab/ChangeScanner.java b/src/main/java/org/jabref/gui/collab/ChangeScanner.java index cf76d3b7c41..f19f406e18f 100644 --- a/src/main/java/org/jabref/gui/collab/ChangeScanner.java +++ b/src/main/java/org/jabref/gui/collab/ChangeScanner.java @@ -55,7 +55,7 @@ public List scanForChanges() { // Important: apply all post-load actions ImportFormatPreferences importFormatPreferences = preferencesService.getImportFormatPreferences(); GeneralPreferences generalPreferences = preferencesService.getGeneralPreferences(); - ParserResult result = OpenDatabase.loadDatabase(database.getDatabasePath().get(), generalPreferences, importFormatPreferences, new DummyFileUpdateMonitor()); + ParserResult result = OpenDatabase.loadDatabase(database.getDatabasePath().get(), importFormatPreferences, new DummyFileUpdateMonitor()); BibDatabaseContext databaseOnDisk = result.getDatabaseContext(); // Start looking at changes. diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java index 1b8cd4b4846..187328a02cd 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java @@ -370,8 +370,7 @@ private void setupToolBar() { preferencesService.getImporterPreferences(), preferencesService.getImportFormatPreferences(), preferencesService.getFilePreferences(), - databaseContext, - preferencesService.getGeneralPreferences().getDefaultEncoding()); + databaseContext); for (EntryBasedFetcher fetcher : entryBasedFetchers) { MenuItem fetcherMenuItem = new MenuItem(fetcher.getName()); if (fetcher instanceof PdfMergeMetadataImporter.EntryBasedFetcherWrapper) { @@ -383,8 +382,7 @@ private void setupToolBar() { preferencesService.getImporterPreferences(), preferencesService.getImportFormatPreferences(), preferencesService.getFilePreferences(), - databaseContext, - preferencesService.getGeneralPreferences().getDefaultEncoding()); + databaseContext); fetchAndMerge(pdfMergeMetadataImporter); }); } else { diff --git a/src/main/java/org/jabref/gui/exporter/ExportCommand.java b/src/main/java/org/jabref/gui/exporter/ExportCommand.java index 4511c7107ac..9d49e62652e 100644 --- a/src/main/java/org/jabref/gui/exporter/ExportCommand.java +++ b/src/main/java/org/jabref/gui/exporter/ExportCommand.java @@ -118,10 +118,6 @@ private void export(Path file, FileChooser.ExtensionFilter selectedExtensionFilt .wrap(() -> { format.export(stateManager.getActiveDatabase().get(), file, - stateManager.getActiveDatabase().get() - .getMetaData() - .getEncoding() - .orElse(preferences.getGeneralPreferences().getDefaultEncoding()), finEntries); return null; // can not use BackgroundTask.wrap(Runnable) because Runnable.run() can't throw Exceptions }) diff --git a/src/main/java/org/jabref/gui/exporter/ExportToClipboardAction.java b/src/main/java/org/jabref/gui/exporter/ExportToClipboardAction.java index 80247e2c335..3407c25c153 100644 --- a/src/main/java/org/jabref/gui/exporter/ExportToClipboardAction.java +++ b/src/main/java/org/jabref/gui/exporter/ExportToClipboardAction.java @@ -1,14 +1,11 @@ package org.jabref.gui.exporter; -import java.io.BufferedReader; import java.io.IOException; -import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Comparator; import java.util.List; -import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -26,7 +23,6 @@ import org.jabref.logic.exporter.ExporterFactory; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.FileType; -import org.jabref.logic.util.OS; import org.jabref.logic.util.StandardFileType; import org.jabref.model.entry.BibEntry; import org.jabref.preferences.PreferencesService; @@ -124,14 +120,10 @@ private ExportResult exportToClipboard(Exporter exporter) throws Exception { // Write to file: exporter.export(stateManager.getActiveDatabase().get(), tmp, - stateManager.getActiveDatabase().get() - .getMetaData() - .getEncoding() - .orElse(preferences.getGeneralPreferences().getDefaultEncoding()), entries); // Read the file and put the contents on the clipboard: - return new ExportResult(readFileToString(tmp), exporter.getFileType()); + return new ExportResult(Files.readString(tmp), exporter.getFileType()); } finally { // Clean up: if ((tmp != null) && Files.exists(tmp)) { @@ -160,18 +152,6 @@ private void setContentToClipboard(ExportResult result) { dialogService.notify(Localization.lang("Entries exported to clipboard") + ": " + entries.size()); } - private String readFileToString(Path tmp) throws IOException { - Charset defaultEncoding = Objects.requireNonNull(preferences.getGeneralPreferences().getDefaultEncoding()); - try (BufferedReader reader = Files.newBufferedReader(tmp, stateManager.getActiveDatabase() - .map(db -> db.getMetaData() - .getEncoding() - .orElse(defaultEncoding)) - .orElse(defaultEncoding))) { - return reader.lines().collect(Collectors.joining(OS.NEWLINE)); - } - } - private record ExportResult(String content, FileType fileType) { - } } diff --git a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java index 8dcc142e81f..5197bf64d30 100644 --- a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java +++ b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java @@ -2,6 +2,7 @@ import java.io.IOException; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.nio.charset.UnsupportedCharsetException; import java.nio.file.Files; import java.nio.file.Path; @@ -92,7 +93,7 @@ public boolean saveAs(Path file) { public void saveSelectedAsPlain() { askForSavePath().ifPresent(path -> { try { - saveDatabase(path, true, preferences.getGeneralPreferences().getDefaultEncoding(), SavePreferences.DatabaseSaveType.PLAIN_BIBTEX); + saveDatabase(path, true, StandardCharsets.UTF_8, SavePreferences.DatabaseSaveType.PLAIN_BIBTEX); frame.getFileHistory().newFile(path); dialogService.notify(Localization.lang("Saved selected to '%0'.", path.toString())); } catch (SaveException ex) { @@ -203,7 +204,7 @@ private boolean save(Path targetPath, SaveDatabaseMode mode) { Charset encoding = libraryTab.getBibDatabaseContext() .getMetaData() .getEncoding() - .orElse(preferences.getGeneralPreferences().getDefaultEncoding()); + .orElse(StandardCharsets.UTF_8); // Make sure to remember which encoding we used. libraryTab.getBibDatabaseContext().getMetaData().setEncoding(encoding, ChangePropagation.DO_NOT_POST_EVENT); diff --git a/src/main/java/org/jabref/gui/exporter/WriteMetadataToPdfAction.java b/src/main/java/org/jabref/gui/exporter/WriteMetadataToPdfAction.java index 2e72706e0ba..4043dde2b46 100644 --- a/src/main/java/org/jabref/gui/exporter/WriteMetadataToPdfAction.java +++ b/src/main/java/org/jabref/gui/exporter/WriteMetadataToPdfAction.java @@ -1,6 +1,5 @@ package org.jabref.gui.exporter; -import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.util.Collection; @@ -50,7 +49,6 @@ public class WriteMetadataToPdfAction extends SimpleCommand { private final FilePreferences filePreferences; private final XmpPreferences xmpPreferences; private final EmbeddedBibFilePdfExporter embeddedBibExporter; - private final Charset encoding; private OptionsDialog optionsDialog; @@ -62,13 +60,12 @@ public class WriteMetadataToPdfAction extends SimpleCommand { private int entriesChanged; private int errors; - public WriteMetadataToPdfAction(StateManager stateManager, BibDatabaseMode databaseMode, BibEntryTypesManager entryTypesManager, FieldWriterPreferences fieldWriterPreferences, DialogService dialogService, TaskExecutor taskExecutor, FilePreferences filePreferences, XmpPreferences xmpPreferences, Charset encoding) { + public WriteMetadataToPdfAction(StateManager stateManager, BibDatabaseMode databaseMode, BibEntryTypesManager entryTypesManager, FieldWriterPreferences fieldWriterPreferences, DialogService dialogService, TaskExecutor taskExecutor, FilePreferences filePreferences, XmpPreferences xmpPreferences) { this.stateManager = stateManager; this.dialogService = dialogService; this.taskExecutor = taskExecutor; this.filePreferences = filePreferences; this.xmpPreferences = xmpPreferences; - this.encoding = encoding; this.embeddedBibExporter = new EmbeddedBibFilePdfExporter(databaseMode, entryTypesManager, fieldWriterPreferences); this.executable.bind(needsDatabase(stateManager)); @@ -191,12 +188,12 @@ private void writeMetadata() { String.valueOf(entriesChanged), String.valueOf(skipped), String.valueOf(errors))); } + /** + * This writes both XMP data and embeddeds the .bib file + */ private void writeMetadataToFile(Path file, BibEntry entry, BibDatabaseContext databaseContext, BibDatabase database) throws Exception { - // XMP XmpUtilWriter.writeXmp(file, entry, database, xmpPreferences); - - // Embedded Bib File - embeddedBibExporter.exportToFileByPath(databaseContext, database, encoding, filePreferences, file); + embeddedBibExporter.exportToFileByPath(databaseContext, database, filePreferences, file); } class OptionsDialog extends FXDialog { diff --git a/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java b/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java index 50f27f6bb5e..63523c76d9b 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java +++ b/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java @@ -428,7 +428,7 @@ public void writeMetadataToPdf() { XmpUtilWriter.writeXmp(file.get(), entry, databaseContext.getDatabase(), preferences.getXmpPreferences()); EmbeddedBibFilePdfExporter embeddedBibExporter = new EmbeddedBibFilePdfExporter(preferences.getGeneralPreferences().getDefaultBibDatabaseMode(), Globals.entryTypesManager, preferences.getFieldWriterPreferences()); - embeddedBibExporter.exportToFileByPath(databaseContext, databaseContext.getDatabase(), preferences.getGeneralPreferences().getDefaultEncoding(), preferences.getFilePreferences(), file.get()); + embeddedBibExporter.exportToFileByPath(databaseContext, databaseContext.getDatabase(), preferences.getFilePreferences(), file.get()); } catch (IOException | TransformerException ex) { // TODO: Print error message // Localization.lang("Error while writing") + " '" + file.toString() + "': " + ex; @@ -584,7 +584,7 @@ public void parsePdfMetadataAndShowMergeDialog() { private Supplier wrapImporterToSupplier(Importer importer, Path filePath) { return () -> { try { - ParserResult parserResult = importer.importDatabase(filePath, preferences.getGeneralPreferences().getDefaultEncoding()); + ParserResult parserResult = importer.importDatabase(filePath); if (parserResult.isInvalid() || parserResult.isEmpty() || !parserResult.getDatabase().hasEntries()) { return null; } diff --git a/src/main/java/org/jabref/gui/importer/ImportAction.java b/src/main/java/org/jabref/gui/importer/ImportAction.java index a4eeea9e99a..aa63222685e 100644 --- a/src/main/java/org/jabref/gui/importer/ImportAction.java +++ b/src/main/java/org/jabref/gui/importer/ImportAction.java @@ -132,7 +132,7 @@ private List doImport(List files) frame.getDialogService().notify(Localization.lang("Importing in %0 format", importer.get().getName()) + "..."); }); // Specific importer: - ParserResult pr = importer.get().importDatabase(filename, prefs.getGeneralPreferences().getDefaultEncoding()); + ParserResult pr = importer.get().importDatabase(filename); imports.add(new ImportFormatReader.UnknownFormatImport(importer.get().getName(), pr)); } } catch (ImportException | IOException e) { diff --git a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java index c79bc929950..c4336bd6374 100644 --- a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java +++ b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java @@ -41,7 +41,8 @@ // The action concerned with opening an existing database. public class OpenDatabaseAction extends SimpleCommand { - public static final Logger LOGGER = LoggerFactory.getLogger(OpenDatabaseAction.class); + private static final Logger LOGGER = LoggerFactory.getLogger(OpenDatabaseAction.class); + // List of actions that may need to be called after opening the file. Such as // upgrade actions etc. that may depend on the JabRef version that wrote the file: private static final List POST_OPEN_ACTIONS = Arrays.asList( @@ -198,7 +199,6 @@ private ParserResult loadDatabase(Path file) throws Exception { ParserResult result; try { result = OpenDatabase.loadDatabase(fileToLoad, - preferencesService.getGeneralPreferences(), preferencesService.getImportFormatPreferences(), Globals.getFileUpdateMonitor()); } catch (IOException e) { diff --git a/src/main/java/org/jabref/gui/integrity/IntegrityCheckAction.java b/src/main/java/org/jabref/gui/integrity/IntegrityCheckAction.java index e0bda0f8d33..809a2020c78 100644 --- a/src/main/java/org/jabref/gui/integrity/IntegrityCheckAction.java +++ b/src/main/java/org/jabref/gui/integrity/IntegrityCheckAction.java @@ -42,7 +42,6 @@ public void execute() { IntegrityCheck check = new IntegrityCheck(database, Globals.prefs.getFilePreferences(), Globals.prefs.getCitationKeyPatternPreferences(), - Globals.prefs.getGeneralPreferences().getDefaultEncoding(), Globals.journalAbbreviationRepository, Globals.prefs.getEntryEditorPreferences().shouldAllowIntegerEditionBibtex()); diff --git a/src/main/java/org/jabref/gui/libraryproperties/general/GeneralPropertiesViewModel.java b/src/main/java/org/jabref/gui/libraryproperties/general/GeneralPropertiesViewModel.java index 9fbdf98c565..65dc1d0b9ef 100644 --- a/src/main/java/org/jabref/gui/libraryproperties/general/GeneralPropertiesViewModel.java +++ b/src/main/java/org/jabref/gui/libraryproperties/general/GeneralPropertiesViewModel.java @@ -1,6 +1,7 @@ package org.jabref.gui.libraryproperties.general; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.nio.file.Path; import javax.swing.undo.UndoManager; @@ -62,7 +63,7 @@ public void setValues() { boolean isShared = (databaseContext.getLocation() == DatabaseLocation.SHARED); encodingDisableProperty.setValue(isShared); // the encoding of shared database is always UTF-8 - selectedEncodingProperty.setValue(metaData.getEncoding().orElse(preferencesService.getGeneralPreferences().getDefaultEncoding())); + selectedEncodingProperty.setValue(metaData.getEncoding().orElse(StandardCharsets.UTF_8)); selectedDatabaseModeProperty.setValue(metaData.getMode().orElse(BibDatabaseMode.BIBLATEX)); generalFileDirectoryProperty.setValue(metaData.getDefaultFileDirectory().orElse("").trim()); userSpecificFileDirectoryProperty.setValue(metaData.getUserFileDirectory(preferencesService.getFilePreferences().getUser()).orElse("").trim()); diff --git a/src/main/java/org/jabref/gui/openoffice/AdvancedCiteDialogView.java b/src/main/java/org/jabref/gui/openoffice/AdvancedCiteDialogView.java index f11e8ab90ae..e30eec67c3d 100644 --- a/src/main/java/org/jabref/gui/openoffice/AdvancedCiteDialogView.java +++ b/src/main/java/org/jabref/gui/openoffice/AdvancedCiteDialogView.java @@ -24,6 +24,7 @@ public AdvancedCiteDialogView() { ViewLoader.view(this) .load() .setAsDialogPane(this); + setResultConverter(btn -> { if (btn == ButtonType.OK) { return viewModel; diff --git a/src/main/java/org/jabref/gui/openoffice/BibEntryNotFoundException.java b/src/main/java/org/jabref/gui/openoffice/BibEntryNotFoundException.java deleted file mode 100644 index b3db5f8f9e7..00000000000 --- a/src/main/java/org/jabref/gui/openoffice/BibEntryNotFoundException.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.jabref.gui.openoffice; - -class BibEntryNotFoundException extends Exception { - - private final String citationKey; - - public BibEntryNotFoundException(String citationKey, String message) { - super(message); - - this.citationKey = citationKey; - } - - public String getCitationKey() { - return citationKey; - } -} diff --git a/src/main/java/org/jabref/gui/openoffice/ConnectionLostException.java b/src/main/java/org/jabref/gui/openoffice/ConnectionLostException.java deleted file mode 100644 index df0264be0de..00000000000 --- a/src/main/java/org/jabref/gui/openoffice/ConnectionLostException.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.jabref.gui.openoffice; - -/** - * This exception is used to indicate that connection to OpenOffice has been lost. - */ -class ConnectionLostException extends RuntimeException { - - public ConnectionLostException(String msg) { - super(msg); - } -} diff --git a/src/main/java/org/jabref/gui/openoffice/DetectOpenOfficeInstallation.java b/src/main/java/org/jabref/gui/openoffice/DetectOpenOfficeInstallation.java index 8141d5c7141..719cdd4b870 100644 --- a/src/main/java/org/jabref/gui/openoffice/DetectOpenOfficeInstallation.java +++ b/src/main/java/org/jabref/gui/openoffice/DetectOpenOfficeInstallation.java @@ -21,18 +21,18 @@ */ public class DetectOpenOfficeInstallation { - private final OpenOfficePreferences ooPrefs; + private final OpenOfficePreferences openOfficePreferences; private final DialogService dialogService; private final PreferencesService preferencesService; public DetectOpenOfficeInstallation(PreferencesService preferencesService, DialogService dialogService) { this.preferencesService = preferencesService; this.dialogService = dialogService; - this.ooPrefs = preferencesService.getOpenOfficePreferences(); + this.openOfficePreferences = preferencesService.getOpenOfficePreferences(); } public boolean isExecutablePathDefined() { - return checkAutoDetectedPaths(ooPrefs); + return checkAutoDetectedPaths(openOfficePreferences); } public Optional selectInstallationPath() { @@ -71,8 +71,8 @@ public boolean setOpenOfficePreferences(Path installDir) { } if (execPath.isPresent()) { - ooPrefs.setExecutablePath(execPath.get().toString()); - preferencesService.setOpenOfficePreferences(ooPrefs); + openOfficePreferences.setExecutablePath(execPath.get().toString()); + preferencesService.setOpenOfficePreferences(openOfficePreferences); return true; } @@ -88,12 +88,11 @@ public Optional chooseAmongInstallations(List installDirs) { return Optional.of(installDirs.get(0).toAbsolutePath()); } - String content = Localization.lang("Found more than one OpenOffice/LibreOffice executable.") - + "\n" + Localization.lang("Please choose which one to connect to:"); - - Optional selectedPath = dialogService.showChoiceDialogAndWait(Localization.lang("Choose OpenOffice/LibreOffice executable"), - content, Localization.lang("Use selected instance"), installDirs); - - return selectedPath; + return dialogService.showChoiceDialogAndWait( + Localization.lang("Choose OpenOffice/LibreOffice executable"), + Localization.lang("Found more than one OpenOffice/LibreOffice executable.") + "\n" + + Localization.lang("Please choose which one to connect to:"), + Localization.lang("Use selected instance"), + installDirs); } } diff --git a/src/main/java/org/jabref/gui/openoffice/ManageCitationsDialogView.java b/src/main/java/org/jabref/gui/openoffice/ManageCitationsDialogView.java index a312a4ef375..d954dc55667 100644 --- a/src/main/java/org/jabref/gui/openoffice/ManageCitationsDialogView.java +++ b/src/main/java/org/jabref/gui/openoffice/ManageCitationsDialogView.java @@ -19,9 +19,6 @@ import org.jabref.model.strings.StringUtil; import com.airhacks.afterburner.views.ViewLoader; -import com.sun.star.beans.UnknownPropertyException; -import com.sun.star.container.NoSuchElementException; -import com.sun.star.lang.WrappedTargetException; public class ManageCitationsDialogView extends BaseDialog { @@ -56,7 +53,7 @@ public ManageCitationsDialogView(OOBibBase ooBase) { } @FXML - private void initialize() throws NoSuchElementException, WrappedTargetException, UnknownPropertyException { + private void initialize() { viewModel = new ManageCitationsDialogViewModel(ooBase, dialogService); @@ -70,9 +67,8 @@ private void initialize() throws NoSuchElementException, WrappedTargetException, citationsTableView.itemsProperty().bindBidirectional(viewModel.citationsProperty()); - extraInfo.setOnEditCommit((CellEditEvent cell) -> { - cell.getRowValue().setExtraInfo(cell.getNewValue()); - }); + extraInfo.setOnEditCommit((CellEditEvent cell) -> + cell.getRowValue().setExtraInfo(cell.getNewValue())); extraInfo.setCellFactory(TextFieldTableCell.forTableColumn()); } @@ -87,7 +83,13 @@ private Node getText(String citationContext) { inBetweenText.setStyle("-fx-font-weight: bold"); Text endText = new Text(end); - FlowPane flow = new FlowPane(startText, inBetweenText, endText); - return flow; + return new FlowPane(startText, inBetweenText, endText); + } + + public boolean isOkToShowThisDialog() { + if (viewModel == null || viewModel.failedToGetCitationEntries) { + return false; + } + return true; } } diff --git a/src/main/java/org/jabref/gui/openoffice/ManageCitationsDialogViewModel.java b/src/main/java/org/jabref/gui/openoffice/ManageCitationsDialogViewModel.java index 40cee65036f..697212fde54 100644 --- a/src/main/java/org/jabref/gui/openoffice/ManageCitationsDialogViewModel.java +++ b/src/main/java/org/jabref/gui/openoffice/ManageCitationsDialogViewModel.java @@ -9,59 +9,34 @@ import javafx.collections.FXCollections; import org.jabref.gui.DialogService; -import org.jabref.logic.l10n.Localization; import org.jabref.model.openoffice.CitationEntry; -import com.sun.star.beans.IllegalTypeException; -import com.sun.star.beans.NotRemoveableException; -import com.sun.star.beans.PropertyExistException; -import com.sun.star.beans.UnknownPropertyException; -import com.sun.star.container.NoSuchElementException; -import com.sun.star.container.XNameAccess; -import com.sun.star.lang.IllegalArgumentException; -import com.sun.star.lang.WrappedTargetException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class ManageCitationsDialogViewModel { - private static final Logger LOGGER = LoggerFactory.getLogger(ManageCitationsDialogViewModel.class); - + public final boolean failedToGetCitationEntries; private final ListProperty citations = new SimpleListProperty<>(FXCollections.observableArrayList()); private final OOBibBase ooBase; private final DialogService dialogService; - public ManageCitationsDialogViewModel(OOBibBase ooBase, DialogService dialogService) throws NoSuchElementException, WrappedTargetException, UnknownPropertyException { + public ManageCitationsDialogViewModel(OOBibBase ooBase, DialogService dialogService) { this.ooBase = ooBase; this.dialogService = dialogService; - XNameAccess nameAccess = ooBase.getReferenceMarks(); - List names = ooBase.getJabRefReferenceMarks(nameAccess); - for (String name : names) { - - CitationEntry entry = new CitationEntry(name, - ooBase.getCitationContext(nameAccess, name, 30, 30, true), - ooBase.getCustomProperty(name)); + Optional> citationEntries = ooBase.guiActionGetCitationEntries(); + this.failedToGetCitationEntries = citationEntries.isEmpty(); + if (citationEntries.isEmpty()) { + return; + } + for (CitationEntry entry : citationEntries.get()) { CitationEntryViewModel itemViewModelEntry = new CitationEntryViewModel(entry); citations.add(itemViewModelEntry); } } public void storeSettings() { - List ciationEntries = citations.stream().map(CitationEntryViewModel::toCitationEntry).collect(Collectors.toList()); - try { - for (CitationEntry entry : ciationEntries) { - Optional pageInfo = entry.getPageInfo(); - if (pageInfo.isPresent()) { - ooBase.setCustomProperty(entry.getRefMarkName(), pageInfo.get()); - } - } - } catch (UnknownPropertyException | NotRemoveableException | PropertyExistException | IllegalTypeException | - IllegalArgumentException ex) { - LOGGER.warn("Problem modifying citation", ex); - dialogService.showErrorDialogAndWait(Localization.lang("Problem modifying citation"), ex); - } + List citationEntries = citations.stream().map(CitationEntryViewModel::toCitationEntry).collect(Collectors.toList()); + ooBase.guiActionApplyCitationEntries(citationEntries); } public ListProperty citationsProperty() { diff --git a/src/main/java/org/jabref/gui/openoffice/OOBibBase.java b/src/main/java/org/jabref/gui/openoffice/OOBibBase.java index 540c5f9216b..5ad5e2634c8 100644 --- a/src/main/java/org/jabref/gui/openoffice/OOBibBase.java +++ b/src/main/java/org/jabref/gui/openoffice/OOBibBase.java @@ -1,1424 +1,862 @@ package org.jabref.gui.openoffice; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.Set; -import java.util.SortedMap; -import java.util.TreeMap; -import java.util.TreeSet; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import java.util.function.Supplier; import java.util.stream.Collectors; -import org.jabref.architecture.AllowedToUseAwt; import org.jabref.gui.DialogService; -import org.jabref.logic.bibtex.comparator.FieldComparator; -import org.jabref.logic.bibtex.comparator.FieldComparatorStack; +import org.jabref.logic.JabRefException; import org.jabref.logic.l10n.Localization; -import org.jabref.logic.layout.Layout; -import org.jabref.logic.openoffice.OOUtil; -import org.jabref.logic.openoffice.UndefinedBibtexEntry; -import org.jabref.logic.openoffice.UndefinedParagraphFormatException; +import org.jabref.logic.openoffice.NoDocumentFoundException; +import org.jabref.logic.openoffice.action.EditInsert; +import org.jabref.logic.openoffice.action.EditMerge; +import org.jabref.logic.openoffice.action.EditSeparate; +import org.jabref.logic.openoffice.action.ExportCited; +import org.jabref.logic.openoffice.action.ManageCitations; +import org.jabref.logic.openoffice.action.Update; +import org.jabref.logic.openoffice.frontend.OOFrontend; +import org.jabref.logic.openoffice.frontend.RangeForOverlapCheck; import org.jabref.logic.openoffice.style.OOBibStyle; -import org.jabref.logic.openoffice.style.OOPreFormatter; import org.jabref.model.database.BibDatabase; import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.field.StandardField; +import org.jabref.model.openoffice.CitationEntry; +import org.jabref.model.openoffice.rangesort.FunctionalTextViewCursor; +import org.jabref.model.openoffice.style.CitationGroupId; +import org.jabref.model.openoffice.style.CitationType; import org.jabref.model.openoffice.uno.CreationException; import org.jabref.model.openoffice.uno.NoDocumentException; +import org.jabref.model.openoffice.uno.UnoCrossRef; +import org.jabref.model.openoffice.uno.UnoCursor; +import org.jabref.model.openoffice.uno.UnoRedlines; +import org.jabref.model.openoffice.uno.UnoStyle; +import org.jabref.model.openoffice.uno.UnoUndo; +import org.jabref.model.openoffice.util.OOResult; +import org.jabref.model.openoffice.util.OOVoidResult; -import com.sun.star.awt.Point; import com.sun.star.beans.IllegalTypeException; import com.sun.star.beans.NotRemoveableException; -import com.sun.star.beans.PropertyExistException; import com.sun.star.beans.PropertyVetoException; -import com.sun.star.beans.UnknownPropertyException; -import com.sun.star.beans.XPropertyContainer; -import com.sun.star.beans.XPropertySet; import com.sun.star.comp.helper.BootstrapException; import com.sun.star.container.NoSuchElementException; -import com.sun.star.container.XEnumeration; -import com.sun.star.container.XEnumerationAccess; -import com.sun.star.container.XNameAccess; -import com.sun.star.container.XNamed; -import com.sun.star.document.XDocumentPropertiesSupplier; -import com.sun.star.frame.XComponentLoader; -import com.sun.star.frame.XController; -import com.sun.star.frame.XDesktop; -import com.sun.star.frame.XModel; import com.sun.star.lang.DisposedException; -import com.sun.star.lang.IllegalArgumentException; -import com.sun.star.lang.Locale; import com.sun.star.lang.WrappedTargetException; -import com.sun.star.lang.XComponent; -import com.sun.star.lang.XMultiComponentFactory; -import com.sun.star.lang.XMultiServiceFactory; -import com.sun.star.text.XBookmarksSupplier; -import com.sun.star.text.XDocumentIndexesSupplier; -import com.sun.star.text.XFootnote; -import com.sun.star.text.XReferenceMarksSupplier; -import com.sun.star.text.XText; -import com.sun.star.text.XTextContent; import com.sun.star.text.XTextCursor; import com.sun.star.text.XTextDocument; -import com.sun.star.text.XTextRange; -import com.sun.star.text.XTextRangeCompare; -import com.sun.star.text.XTextSection; -import com.sun.star.text.XTextSectionsSupplier; -import com.sun.star.text.XTextViewCursor; -import com.sun.star.text.XTextViewCursorSupplier; -import com.sun.star.uno.Any; -import com.sun.star.uno.Type; -import com.sun.star.uno.UnoRuntime; -import com.sun.star.uno.XComponentContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Class for manipulating the Bibliography of the currently start document in OpenOffice. + * Class for manipulating the Bibliography of the currently started document in OpenOffice. */ -@AllowedToUseAwt("Requires AWT for italics and bold") class OOBibBase { - private static final OOPreFormatter POSTFORMATTER = new OOPreFormatter(); + private static final Logger LOGGER = LoggerFactory.getLogger(OOBibBase.class); - private static final String BIB_SECTION_NAME = "JR_bib"; - private static final String BIB_SECTION_END_NAME = "JR_bib_end"; - private static final String BIB_CITATION = "JR_cite"; - private static final Pattern CITE_PATTERN = Pattern.compile(OOBibBase.BIB_CITATION + "\\d*_(\\d*)_(.*)"); + private final DialogService dialogService; - private static final String CHAR_STYLE_NAME = "CharStyleName"; + // After inserting a citation, if ooPrefs.getSyncWhenCiting() returns true, shall we also update the bibliography? + private final boolean refreshBibliographyDuringSyncWhenCiting; - private static final int AUTHORYEAR_PAR = 1; - private static final int AUTHORYEAR_INTEXT = 2; - private static final int INVISIBLE_CIT = 3; + // Shall we add "Cited on pages: ..." to resolved bibliography entries? + private final boolean alwaysAddCitedOnPages; - private static final Logger LOGGER = LoggerFactory.getLogger(OOBibBase.class); - private XMultiServiceFactory mxDocFactory; - private XTextDocument mxDoc; - private XText text; - private final XDesktop xDesktop; - private XTextViewCursorSupplier xViewCursorSupplier; - private XComponent xCurrentComponent; - private XPropertySet propertySet; - - private XPropertyContainer userProperties; - private final boolean atEnd; - private final Comparator entryComparator; - private final Comparator yearAuthorTitleComparator; - private final FieldComparator authComp = new FieldComparator(StandardField.AUTHOR); - private final FieldComparator yearComp = new FieldComparator(StandardField.YEAR); - - private final FieldComparator titleComp = new FieldComparator(StandardField.TITLE); - private final List> authorYearTitleList = new ArrayList<>(3); - - private final List> yearAuthorTitleList = new ArrayList<>(3); - private final Map uniquefiers = new HashMap<>(); - private List sortedReferenceMarks; - - private final DialogService dialogService; + private final OOBibBaseConnect connection; - public OOBibBase(Path loPath, boolean atEnd, DialogService dialogService) throws IllegalAccessException, InvocationTargetException, BootstrapException, CreationException, IOException, ClassNotFoundException { + public OOBibBase(Path loPath, DialogService dialogService) + throws + BootstrapException, + CreationException { this.dialogService = dialogService; + this.connection = new OOBibBaseConnect(loPath, dialogService); - authorYearTitleList.add(authComp); - authorYearTitleList.add(yearComp); - authorYearTitleList.add(titleComp); + this.refreshBibliographyDuringSyncWhenCiting = false; + this.alwaysAddCitedOnPages = false; + } - yearAuthorTitleList.add(yearComp); - yearAuthorTitleList.add(authComp); - yearAuthorTitleList.add(titleComp); + public void guiActionSelectDocument(boolean autoSelectForSingle) { + final String errorTitle = Localization.lang("Problem connecting"); - entryComparator = new FieldComparatorStack<>(authorYearTitleList); - yearAuthorTitleComparator = new FieldComparatorStack<>(yearAuthorTitleList); + try { - this.atEnd = atEnd; + this.connection.selectDocument(autoSelectForSingle); + } catch (NoDocumentFoundException ex) { + OOError.from(ex).showErrorDialog(dialogService); + } catch (DisposedException ex) { + OOError.from(ex).setTitle(errorTitle).showErrorDialog(dialogService); + } catch (WrappedTargetException + | IndexOutOfBoundsException + | NoSuchElementException ex) { + LOGGER.warn("Problem connecting", ex); + OOError.fromMisc(ex).setTitle(errorTitle).showErrorDialog(dialogService); + } - xDesktop = simpleBootstrap(loPath); + if (this.isConnectedToDocument()) { + dialogService.notify(Localization.lang("Connected to document") + ": " + + this.getCurrentDocumentTitle().orElse("")); + } } + /** + * A simple test for document availability. + *

+ * See also `isDocumentConnectionMissing` for a test actually attempting to use the connection. + */ public boolean isConnectedToDocument() { - return xCurrentComponent != null; + return this.connection.isConnectedToDocument(); + } + + /** + * @return true if we are connected to a document + */ + public boolean isDocumentConnectionMissing() { + return this.connection.isDocumentConnectionMissing(); } - public XTextDocument selectComponent(List list) { - List viewModel = list.stream().map(DocumentTitleViewModel::new).collect(Collectors.toList()); - // this whole method is part of a background task when auto-detecting instances, so we need to show dialog in FX thread - Optional selectedDocument = dialogService.showChoiceDialogAndWait(Localization.lang("Select document"), Localization.lang("Found documents:"), Localization.lang("Use selected document"), viewModel); - return selectedDocument.map(DocumentTitleViewModel::getXtextDocument).orElse(null); + /** + * Either return an XTextDocument or return JabRefException. + */ + public OOResult getXTextDocument() { + return this.connection.getXTextDocument(); } + /** + * The title of the current document, or Optional.empty() + */ public Optional getCurrentDocumentTitle() { - return getDocumentTitle(mxDoc); + return this.connection.getCurrentDocumentTitle(); } - private Optional getDocumentTitle(XTextDocument doc) { - if (doc == null) { - return Optional.empty(); - } else { - try { - return Optional.of(String.valueOf(OOUtil.getProperty(doc.getCurrentController().getFrame(), "Title"))); - } catch (UnknownPropertyException | WrappedTargetException e) { - LOGGER.warn("Could not get document title", e); - return Optional.empty(); - } - } + /* ****************************************************** + * + * Tools to collect and show precondition test results + * + * ******************************************************/ + + void showDialog(OOError err) { + err.showErrorDialog(dialogService); } - public void selectDocument() throws NoDocumentException, NoSuchElementException, WrappedTargetException { - List textDocumentList = getTextDocuments(); - XTextDocument selected; - if (textDocumentList.isEmpty()) { - // No text documents found. - throw new NoDocumentException("No Writer documents found"); - } else if (textDocumentList.size() == 1) { - // Get the only one - selected = textDocumentList.get(0); - } else { - // Bring up a dialog - selected = selectComponent(textDocumentList); - } + void showDialog(String errorTitle, OOError err) { + err.setTitle(errorTitle).showErrorDialog(dialogService); + } - if (selected == null) { - return; + OOVoidResult collectResults(String errorTitle, List> results) { + String msg = (results.stream() + .filter(OOVoidResult::isError) + .map(e -> e.getError().getLocalizedMessage()) + .collect(Collectors.joining("\n\n"))); + if (msg.isEmpty()) { + return OOVoidResult.ok(); + } else { + return OOVoidResult.error(new OOError(errorTitle, msg)); } - xCurrentComponent = UnoRuntime.queryInterface(XComponent.class, selected); - mxDoc = selected; - - UnoRuntime.queryInterface(XDocumentIndexesSupplier.class, xCurrentComponent); + } - XModel xModel = UnoRuntime.queryInterface(XModel.class, xCurrentComponent); - XController xController = xModel.getCurrentController(); - xViewCursorSupplier = UnoRuntime.queryInterface(XTextViewCursorSupplier.class, xController); + boolean testDialog(OOVoidResult res) { + return res.ifError(ex -> ex.showErrorDialog(dialogService)).isError(); + } - // get a reference to the body text of the document - text = mxDoc.getText(); + boolean testDialog(String errorTitle, OOVoidResult res) { + return res.ifError(e -> showDialog(e.setTitle(errorTitle))).isError(); + } - // Access the text document's multi service factory: - mxDocFactory = UnoRuntime.queryInterface(XMultiServiceFactory.class, mxDoc); + boolean testDialog(String errorTitle, List> results) { + return testDialog(errorTitle, collectResults(errorTitle, results)); + } - XDocumentPropertiesSupplier supp = UnoRuntime.queryInterface(XDocumentPropertiesSupplier.class, mxDoc); - userProperties = supp.getDocumentProperties().getUserDefinedProperties(); - propertySet = UnoRuntime.queryInterface(XPropertySet.class, userProperties); + @SafeVarargs + final boolean testDialog(String errorTitle, OOVoidResult... results) { + List> resultList = Arrays.asList(results); + return testDialog(collectResults(errorTitle, resultList)); } - private List getTextDocuments() throws NoSuchElementException, WrappedTargetException { - List result = new ArrayList<>(); - XEnumerationAccess enumAccess = xDesktop.getComponents(); - XEnumeration componentEnumeration = enumAccess.createEnumeration(); + /** + * Get the cursor positioned by the user for inserting text. + */ + OOResult getUserCursorForTextInsertion(XTextDocument doc, String errorTitle) { - // TODO: http://api.openoffice.org/docs/DevelopersGuide/OfficeDev/OfficeDev.xhtml#1_1_3_2_1_2_Frame_Hierarchies + // Get the cursor positioned by the user. + XTextCursor cursor = UnoCursor.getViewCursor(doc).orElse(null); - while (componentEnumeration.hasMoreElements()) { - Object nextElement = componentEnumeration.nextElement(); - XComponent component = UnoRuntime.queryInterface(XComponent.class, nextElement); - XTextDocument document = UnoRuntime.queryInterface(XTextDocument.class, component); - if (document != null) { - result.add(document); - } + // Check for crippled XTextViewCursor + Objects.requireNonNull(cursor); + try { + cursor.getStart(); + } catch (com.sun.star.uno.RuntimeException ex) { + String msg = + Localization.lang("Please move the cursor" + + " to the location for the new citation.") + "\n" + + Localization.lang("I cannot insert to the cursors current location."); + return OOResult.error(new OOError(errorTitle, msg, ex)); } - return result; + return OOResult.ok(cursor); } - private XDesktop simpleBootstrap(Path loPath) - throws CreationException, BootstrapException { - - // Get the office component context: - XComponentContext xContext = org.jabref.gui.openoffice.Bootstrap.bootstrap(loPath); - // 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; + /** + * This may move the view cursor. + */ + OOResult getFunctionalTextViewCursor(XTextDocument doc, String errorTitle) { + String messageOnFailureToObtain = + Localization.lang("Please move the cursor into the document text.") + + "\n" + + Localization.lang("To get the visual positions of your citations" + + " I need to move the cursor around," + + " but could not get it."); + OOResult result = FunctionalTextViewCursor.get(doc); + if (result.isError()) { + LOGGER.warn(result.getError()); + } + return result.mapError(detail -> new OOError(errorTitle, messageOnFailureToObtain)); + } + + private static OOVoidResult checkRangeOverlaps(XTextDocument doc, OOFrontend frontend) { + final String errorTitle = "Overlapping ranges"; + boolean requireSeparation = false; + int maxReportedOverlaps = 10; try { - desktop = xServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", xContext); - } catch (Exception e) { - throw new CreationException(e.getMessage()); + return (frontend.checkRangeOverlaps(doc, + new ArrayList<>(), + requireSeparation, + maxReportedOverlaps) + .mapError(OOError::from)); + } catch (NoDocumentException ex) { + return OOVoidResult.error(OOError.from(ex).setTitle(errorTitle)); + } catch (WrappedTargetException ex) { + return OOVoidResult.error(OOError.fromMisc(ex).setTitle(errorTitle)); } - XDesktop resultDesktop = UnoRuntime.queryInterface(XDesktop.class, desktop); - - UnoRuntime.queryInterface(XComponentLoader.class, desktop); - - return resultDesktop; } - public Optional getCustomProperty(String property) throws UnknownPropertyException, WrappedTargetException { - if (propertySet.getPropertySetInfo().hasPropertyByName(property)) { - return Optional.ofNullable(propertySet.getPropertyValue(property).toString()); - } - return Optional.empty(); - } + private static OOVoidResult checkRangeOverlapsWithCursor(XTextDocument doc, OOFrontend frontend) { + final String errorTitle = "Ranges overlapping with cursor"; - public void updateSortedReferenceMarks() throws WrappedTargetException, NoSuchElementException { - sortedReferenceMarks = getSortedReferenceMarks(getReferenceMarks()); - } + List> userRanges; + userRanges = frontend.viewCursorRanges(doc); - public void setCustomProperty(String property, String value) throws UnknownPropertyException, - NotRemoveableException, PropertyExistException, IllegalTypeException, IllegalArgumentException { - if (propertySet.getPropertySetInfo().hasPropertyByName(property)) { - userProperties.removeProperty(property); + boolean requireSeparation = false; + OOVoidResult res; + try { + res = frontend.checkRangeOverlapsWithCursor(doc, + userRanges, + requireSeparation); + } catch (NoDocumentException ex) { + return OOVoidResult.error(OOError.from(ex).setTitle(errorTitle)); + } catch (WrappedTargetException ex) { + return OOVoidResult.error(OOError.fromMisc(ex).setTitle(errorTitle)); } - if (value != null) { - userProperties.addProperty(property, com.sun.star.beans.PropertyAttribute.REMOVEABLE, - new Any(Type.STRING, value)); + + if (res.isError()) { + final String xtitle = Localization.lang("The cursor is in a protected area."); + return OOVoidResult.error( + new OOError(xtitle, xtitle + "\n" + res.getError().getLocalizedMessage() + "\n")); } + return res.mapError(OOError::from); } - /** - * This method inserts a cite marker in the text for the given BibEntry, 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 IllegalTypeException - * @throws PropertyExistException - * @throws NotRemoveableException - * @throws UnknownPropertyException - * @throws UndefinedCharacterFormatException - * @throws NoSuchElementException - * @throws WrappedTargetException - * @throws IOException - * @throws PropertyVetoException - * @throws CreationException - * @throws BibEntryNotFoundException - * @throws UndefinedParagraphFormatException - */ - public void insertEntry(List entries, BibDatabase database, - List allBases, OOBibStyle style, - boolean inParenthesis, boolean withText, String pageInfo, boolean sync) - throws IllegalArgumentException, - UnknownPropertyException, NotRemoveableException, PropertyExistException, IllegalTypeException, - UndefinedCharacterFormatException, WrappedTargetException, NoSuchElementException, PropertyVetoException, - IOException, CreationException, BibEntryNotFoundException, UndefinedParagraphFormatException { - - try { + * Tests for preconditions. + * + * ******************************************************/ - XTextViewCursor xViewCursor = xViewCursorSupplier.getViewCursor(); + private static OOVoidResult checkIfOpenOfficeIsRecordingChanges(XTextDocument doc) { - if (entries.size() > 1) { - if (style.getBooleanCitProperty(OOBibStyle.MULTI_CITE_CHRONOLOGICAL)) { - entries.sort(yearAuthorTitleComparator); - } else { - entries.sort(entryComparator); + String errorTitle = Localization.lang("Recording and/or Recorded changes"); + try { + boolean recordingChanges = UnoRedlines.getRecordChanges(doc); + int nRedlines = UnoRedlines.countRedlines(doc); + if (recordingChanges || (nRedlines > 0)) { + String msg = ""; + if (recordingChanges) { + msg += Localization.lang("Cannot work with" + + " [Edit]/[Track Changes]/[Record] turned on."); } - } - - String keyString = String.join(",", - entries.stream().map(entry -> entry.getCitationKey().orElse("")).collect(Collectors.toList())); - // Insert bookmark: - String bName = getUniqueReferenceMarkName(keyString, - withText ? inParenthesis ? OOBibBase.AUTHORYEAR_PAR : OOBibBase.AUTHORYEAR_INTEXT : OOBibBase.INVISIBLE_CIT); - - // If we should store metadata for page info, do that now: - if (pageInfo != null) { - LOGGER.info("Storing page info: " + pageInfo); - setCustomProperty(bName, pageInfo); - } - - xViewCursor.getText().insertString(xViewCursor, " ", false); - if (style.isFormatCitations()) { - XPropertySet xCursorProps = UnoRuntime.queryInterface(XPropertySet.class, xViewCursor); - String charStyle = style.getCitationCharacterFormat(); - try { - xCursorProps.setPropertyValue(CHAR_STYLE_NAME, charStyle); - } catch (UnknownPropertyException | PropertyVetoException | IllegalArgumentException | - WrappedTargetException ex) { - // Setting the character format failed, so we throw an exception that - // will result in an error message for the user. Before that, - // delete the space we inserted: - xViewCursor.goLeft((short) 1, true); - xViewCursor.setString(""); - throw new UndefinedCharacterFormatException(charStyle); + if (nRedlines > 0) { + if (recordingChanges) { + msg += "\n"; + } + msg += Localization.lang("Changes by JabRef" + + " could result in unexpected interactions with" + + " recorded changes."); + msg += "\n"; + msg += Localization.lang("Use [Edit]/[Track Changes]/[Manage] to resolve them first."); } + return OOVoidResult.error(new OOError(errorTitle, msg)); } - xViewCursor.goLeft((short) 1, false); - Map databaseMap = new HashMap<>(); - for (BibEntry entry : entries) { - databaseMap.put(entry, database); - } - String citeText = style.isNumberEntries() ? "-" : style.getCitationMarker(entries, databaseMap, - inParenthesis, null, null); - insertReferenceMark(bName, citeText, xViewCursor, withText, style); - - 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(allBases, style); - - // Insert it at the current position: - rebuildBibTextSection(allBases, style); - } - - // Go back to the relevant position: - xViewCursor.gotoRange(position, false); - } catch (DisposedException ex) { - // We need to catch this one here because the OpenOfficePanel 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()); + } catch (WrappedTargetException ex) { + String msg = Localization.lang("Error while checking if Writer" + + " is recording changes or has recorded changes."); + return OOVoidResult.error(new OOError(errorTitle, msg, ex)); } + return OOVoidResult.ok(); } - public List getJabRefReferenceMarks(XNameAccess nameAccess) { - String[] names = nameAccess.getElementNames(); - // Remove all reference marks that don't look like JabRef citations: - List result = new ArrayList<>(); - if (names != null) { - for (String name : names) { - if (CITE_PATTERN.matcher(name).find()) { - result.add(name); - } - } + OOVoidResult styleIsRequired(OOBibStyle style) { + if (style == null) { + return OOVoidResult.error(OOError.noValidStyleSelected()); + } else { + return OOVoidResult.ok(); } - return result; } - /** - * Refresh all cite markers in the document. - * - * @param databases The databases to get entries from. - * @param style The bibliography style to use. - * @return A list of those referenced citation keys that could not be resolved. - * @throws UndefinedCharacterFormatException - * @throws NoSuchElementException - * @throws IllegalArgumentException - * @throws WrappedTargetException - * @throws BibEntryNotFoundException - * @throws CreationException - * @throws IOException - * @throws PropertyVetoException - * @throws UnknownPropertyException - */ - public List refreshCiteMarkers(List databases, OOBibStyle style) - throws WrappedTargetException, IllegalArgumentException, NoSuchElementException, - UndefinedCharacterFormatException, UnknownPropertyException, PropertyVetoException, IOException, - CreationException, BibEntryNotFoundException { + OOResult getFrontend(XTextDocument doc) { + final String errorTitle = "Unable to get frontend"; try { - return refreshCiteMarkersInternal(databases, style); - } catch (DisposedException ex) { - // We need to catch this one here because the OpenOfficePanel 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()); + return OOResult.ok(new OOFrontend(doc)); + } catch (NoDocumentException ex) { + return OOResult.error(OOError.from(ex).setTitle(errorTitle)); + } catch (WrappedTargetException + | RuntimeException ex) { + return OOResult.error(OOError.fromMisc(ex).setTitle(errorTitle)); } } - private List refreshCiteMarkersInternal(List databases, OOBibStyle style) - throws WrappedTargetException, IllegalArgumentException, NoSuchElementException, - UndefinedCharacterFormatException, UnknownPropertyException, PropertyVetoException, - CreationException, BibEntryNotFoundException { - - List cited = findCitedKeys(); - Map linkSourceBase = new HashMap<>(); - Map entries = findCitedEntries(databases, cited, linkSourceBase); - - XNameAccess xReferenceMarks = getReferenceMarks(); - - List names; - if (style.isSortByPosition()) { - // We need to sort the reference marks according to their order of appearance: - names = sortedReferenceMarks; - } else if (style.isNumberEntries()) { - // We need to sort the reference marks according to the sorting of the bibliographic - // entries: - SortedMap newMap = new TreeMap<>(entryComparator); - for (Map.Entry bibtexEntryBibtexDatabaseEntry : entries.entrySet()) { - newMap.put(bibtexEntryBibtexDatabaseEntry.getKey(), bibtexEntryBibtexDatabaseEntry.getValue()); - } - entries = newMap; - // Rebuild the list of cited keys according to the sort order: - cited.clear(); - for (BibEntry entry : entries.keySet()) { - cited.add(entry.getCitationKey().orElse(null)); - } - names = Arrays.asList(xReferenceMarks.getElementNames()); + OOVoidResult databaseIsRequired(List databases, + Supplier fun) { + if (databases == null || databases.isEmpty()) { + return OOVoidResult.error(fun.get()); } else { - names = sortedReferenceMarks; - } - - // Remove all reference marks that don't look like JabRef citations: - List tmp = new ArrayList<>(); - for (String name : names) { - if (CITE_PATTERN.matcher(name).find()) { - tmp.add(name); - } + return OOVoidResult.ok(); } - names = tmp; - - Map numbers = new HashMap<>(); - int lastNum = 0; - // First compute citation markers for all citations: - String[] citMarkers = new String[names.size()]; - String[][] normCitMarkers = new String[names.size()][]; - String[][] bibtexKeys = new String[names.size()][]; - - int minGroupingCount = style.getIntCitProperty(OOBibStyle.MINIMUM_GROUPING_COUNT); - - int[] types = new int[names.size()]; - for (int i = 0; i < names.size(); i++) { - Matcher citeMatcher = CITE_PATTERN.matcher(names.get(i)); - if (citeMatcher.find()) { - String typeStr = citeMatcher.group(1); - int type = Integer.parseInt(typeStr); - types[i] = type; // Remember the type in case we need to uniquefy. - String[] keys = citeMatcher.group(2).split(","); - bibtexKeys[i] = keys; - BibEntry[] cEntries = new BibEntry[keys.length]; - for (int j = 0; j < cEntries.length; j++) { - BibDatabase database = linkSourceBase.get(keys[j]); - Optional tmpEntry = Optional.empty(); - if (database != null) { - tmpEntry = database.getEntryByCitationKey(keys[j]); - } - if (tmpEntry.isPresent()) { - cEntries[j] = tmpEntry.get(); - } else { - LOGGER.info("Citation key not found: '" + keys[j] + '\''); - LOGGER.info("Problem with reference mark: '" + names.get(i) + '\''); - throw new BibEntryNotFoundException(names.get(i), Localization - .lang("Could not resolve BibTeX entry for citation marker '%0'.", names.get(i))); - } - } - - String[] normCitMarker = new String[keys.length]; - String citationMarker; - if (style.isCitationKeyCiteMarkers()) { - StringBuilder sb = new StringBuilder(); - normCitMarkers[i] = new String[keys.length]; - for (int j = 0; j < keys.length; j++) { - normCitMarkers[i][j] = cEntries[j].getCitationKey().orElse(null); - sb.append(cEntries[j].getCitationKey().orElse("")); - if (j < (keys.length - 1)) { - sb.append(','); - } - } - citationMarker = sb.toString(); - } else if (style.isNumberEntries()) { - if (style.isSortByPosition()) { - // We have sorted the citation markers according to their order of appearance, - // so we simply count up for each marker referring to a new entry: - List num = new ArrayList<>(keys.length); - for (int j = 0; j < keys.length; j++) { - if (cEntries[j] instanceof UndefinedBibtexEntry) { - num.add(j, -1); - } else { - num.add(j, lastNum + 1); - if (numbers.containsKey(keys[j])) { - num.set(j, numbers.get(keys[j])); - } else { - numbers.put(keys[j], num.get(j)); - lastNum = num.get(j); - } - } - } - citationMarker = style.getNumCitationMarker(num, minGroupingCount, false); - for (int j = 0; j < keys.length; j++) { - normCitMarker[j] = style.getNumCitationMarker(Collections.singletonList(num.get(j)), - minGroupingCount, false); - } - } else { - // We need to find the number of the cited entry in the bibliography, - // and use that number for the cite marker: - List num = findCitedEntryIndex(names.get(i), cited); - - if (num.isEmpty()) { - throw new BibEntryNotFoundException(names.get(i), Localization - .lang("Could not resolve BibTeX entry for citation marker '%0'.", names.get(i))); - } else { - citationMarker = style.getNumCitationMarker(num, minGroupingCount, false); - } - - for (int j = 0; j < keys.length; j++) { - List list = new ArrayList<>(1); - list.add(num.get(j)); - normCitMarker[j] = style.getNumCitationMarker(list, minGroupingCount, false); - } - } - } else { - - if (cEntries.length > 1) { - if (style.getBooleanCitProperty(OOBibStyle.MULTI_CITE_CHRONOLOGICAL)) { - Arrays.sort(cEntries, yearAuthorTitleComparator); - } 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].getCitationKey().orElse(null); - } - } + } - citationMarker = style.getCitationMarker(Arrays.asList(cEntries), entries, - type == OOBibBase.AUTHORYEAR_PAR, null, null); - // We need "normalized" (in parenthesis) markers for uniqueness checking purposes: - for (int j = 0; j < cEntries.length; j++) { - normCitMarker[j] = style.getCitationMarker(Collections.singletonList(cEntries[j]), entries, - true, null, new int[] {-1}); - } - } - citMarkers[i] = citationMarker; - normCitMarkers[i] = normCitMarker; - } + OOVoidResult selectedBibEntryIsRequired(List entries, + Supplier fun) { + if (entries == null || entries.isEmpty()) { + return OOVoidResult.error(fun.get()); + } else { + return OOVoidResult.ok(); } + } - uniquefiers.clear(); - if (!style.isCitationKeyCiteMarkers() && !style.isNumberEntries()) { - // See if there are duplicate citations marks referring to different entries. If so, we need to - // use uniquefiers: - Map> refKeys = new HashMap<>(); - Map> 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 < markers.length; j++) { - String marker = markers[j]; - String currentKey = bibtexKeys[i][j]; - if (refKeys.containsKey(marker)) { - // Ok, we have seen this exact marker before. - if (!refKeys.get(marker).contains(currentKey)) { - // ... but not for this entry. - refKeys.get(marker).add(currentKey); - refNums.get(marker).add(i); - } - } else { - List l = new ArrayList<>(1); - l.add(currentKey); - refKeys.put(marker, l); - List l2 = new ArrayList<>(1); - l2.add(i); - refNums.put(marker, l2); - } - } - } - // Go through the collected lists and see where we need to uniquefy: - for (Map.Entry> stringListEntry : refKeys.entrySet()) { - List keys = stringListEntry.getValue(); - 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(OOBibStyle.MAX_AUTHORS_FIRST); - Set 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]; - BibEntry[] cEntries = new BibEntry[bibtexKeys[j].length]; - for (int k = 0; k < bibtexKeys[j].length; k++) { - String currentKey = bibtexKeys[j][k]; - firstLimAuthors[k] = -1; - if (maxAuthorsFirst > 0) { - if (!seenBefore.contains(currentKey)) { - firstLimAuthors[k] = maxAuthorsFirst; - } - seenBefore.add(currentKey); - } - String uniq = uniquefiers.get(currentKey); - Optional tmpEntry = Optional.empty(); - if (uniq == null) { - if (firstLimAuthors[k] > 0) { - needsChange = true; - BibDatabase database = linkSourceBase.get(currentKey); - if (database != null) { - tmpEntry = database.getEntryByCitationKey(currentKey); - } - } else { - BibDatabase database = linkSourceBase.get(currentKey); - if (database != null) { - tmpEntry = database.getEntryByCitationKey(currentKey); - } - } - uniquif[k] = ""; - } else { - needsChange = true; - BibDatabase database = linkSourceBase.get(currentKey); - if (database != null) { - tmpEntry = database.getEntryByCitationKey(currentKey); - } - uniquif[k] = uniq; + /* + * Checks existence and also checks if it is not an internal name. + */ + private OOVoidResult checkStyleExistsInTheDocument(String familyName, + String styleName, + XTextDocument doc, + String labelInJstyleFile, + String pathToStyleFile) + throws + WrappedTargetException { + + Optional internalName = UnoStyle.getInternalNameOfStyle(doc, familyName, styleName); + + if (internalName.isEmpty()) { + String msg = + switch (familyName) { + case UnoStyle.PARAGRAPH_STYLES -> Localization.lang("The %0 paragraph style '%1' is missing from the document", + labelInJstyleFile, + styleName); + case UnoStyle.CHARACTER_STYLES -> Localization.lang("The %0 character style '%1' is missing from the document", + labelInJstyleFile, + styleName); + default -> throw new IllegalArgumentException("Expected " + UnoStyle.CHARACTER_STYLES + + " or " + UnoStyle.PARAGRAPH_STYLES + + " for familyName"); } - if (tmpEntry.isPresent()) { - cEntries[k] = tmpEntry.get(); + + "\n" + + Localization.lang("Please create it in the document or change in the file:") + + "\n" + + pathToStyleFile; + return OOVoidResult.error(new OOError("StyleIsNotKnown", msg)); + } + + if (!internalName.get().equals(styleName)) { + String msg = + switch (familyName) { + case UnoStyle.PARAGRAPH_STYLES -> Localization.lang("The %0 paragraph style '%1' is a display name for '%2'.", + labelInJstyleFile, + styleName, + internalName.get()); + case UnoStyle.CHARACTER_STYLES -> Localization.lang("The %0 character style '%1' is a display name for '%2'.", + labelInJstyleFile, + styleName, + internalName.get()); + default -> throw new IllegalArgumentException("Expected " + UnoStyle.CHARACTER_STYLES + + " or " + UnoStyle.PARAGRAPH_STYLES + + " for familyName"); } - } - if (needsChange) { - citMarkers[j] = style.getCitationMarker(Arrays.asList(cEntries), entries, - types[j] == OOBibBase.AUTHORYEAR_PAR, uniquif, firstLimAuthors); - } - } + + "\n" + + Localization.lang("Please use the latter in the style file below" + + " to avoid localization problems.") + + "\n" + + pathToStyleFile; + return OOVoidResult.error(new OOError("StyleNameIsNotInternal", msg)); } + return OOVoidResult.ok(); + } - // Refresh all reference marks with the citation markers we computed: - boolean hadBibSection = getBookmarkRange(OOBibBase.BIB_SECTION_NAME) != null; - // Check if we are supposed to set a character format for citations: - boolean mustTestCharFormat = style.isFormatCitations(); - for (int i = 0; i < names.size(); i++) { - Object referenceMark = xReferenceMarks.getByName(names.get(i)); - XTextContent bookmark = UnoRuntime.queryInterface(XTextContent.class, referenceMark); - - XTextCursor cursor = bookmark.getAnchor().getText().createTextCursorByRange(bookmark.getAnchor()); - - if (mustTestCharFormat) { - // If we are supposed to set character format for citations, must run a test before we - // delete old citation markers. Otherwise, if the specified character format doesn't - // exist, we end up deleting the markers before the process crashes due to a the missing - // format, with catastrophic consequences for the user. - mustTestCharFormat = false; // need to do this only once - XPropertySet xCursorProps = UnoRuntime.queryInterface(XPropertySet.class, cursor); - String charStyle = style.getCitationCharacterFormat(); - try { - xCursorProps.setPropertyValue(CHAR_STYLE_NAME, charStyle); - } catch (UnknownPropertyException | PropertyVetoException | IllegalArgumentException | - WrappedTargetException ex) { - throw new UndefinedCharacterFormatException(charStyle); - } - } + public OOVoidResult checkStylesExistInTheDocument(OOBibStyle style, XTextDocument doc) { - text.removeTextContent(bookmark); + String pathToStyleFile = style.getPath(); - insertReferenceMark(names.get(i), citMarkers[i], cursor, types[i] != OOBibBase.INVISIBLE_CIT, style); - if (hadBibSection && (getBookmarkRange(OOBibBase.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(OOBibBase.BIB_SECTION_NAME, cursor); + List> results = new ArrayList<>(); + try { + results.add(checkStyleExistsInTheDocument(UnoStyle.PARAGRAPH_STYLES, + style.getReferenceHeaderParagraphFormat(), + doc, + "ReferenceHeaderParagraphFormat", + pathToStyleFile)); + results.add(checkStyleExistsInTheDocument(UnoStyle.PARAGRAPH_STYLES, + style.getReferenceParagraphFormat(), + doc, + "ReferenceParagraphFormat", + pathToStyleFile)); + if (style.isFormatCitations()) { + results.add(checkStyleExistsInTheDocument(UnoStyle.CHARACTER_STYLES, + style.getCitationCharacterFormat(), + doc, + "CitationCharacterFormat", + pathToStyleFile)); } + } catch (WrappedTargetException ex) { + results.add(OOVoidResult.error(new OOError("Other error in checkStyleExistsInTheDocument", + ex.getMessage(), + ex))); } - List unresolvedKeys = new ArrayList<>(); - for (BibEntry entry : entries.keySet()) { - if (entry instanceof UndefinedBibtexEntry) { - String key = ((UndefinedBibtexEntry) entry).getKey(); - if (!unresolvedKeys.contains(key)) { - unresolvedKeys.add(key); - } - } - } - return unresolvedKeys; + return collectResults("checkStyleExistsInTheDocument failed", results); } - private List getSortedReferenceMarks(final XNameAccess nameAccess) - throws WrappedTargetException, NoSuchElementException { - XTextViewCursorSupplier cursorSupplier = UnoRuntime.queryInterface(XTextViewCursorSupplier.class, - mxDoc.getCurrentController()); - - XTextViewCursor viewCursor = cursorSupplier.getViewCursor(); - XTextRange initialPos = viewCursor.getStart(); - List names = Arrays.asList(nameAccess.getElementNames()); - List positions = new ArrayList<>(names.size()); - for (String name : names) { - XTextContent textContent = UnoRuntime.queryInterface(XTextContent.class, nameAccess.getByName(name)); - XTextRange range = textContent.getAnchor(); - // Check if we are inside a footnote: - if (UnoRuntime.queryInterface(XFootnote.class, range.getText()) != null) { - // Find the linking footnote marker: - XFootnote footer = UnoRuntime.queryInterface(XFootnote.class, range.getText()); - // The footnote's anchor gives the correct position in the text: - range = footer.getAnchor(); - } + /* ****************************************************** + * + * ManageCitationsDialogView + * + * ******************************************************/ + public Optional> guiActionGetCitationEntries() { - positions.add(findPosition(viewCursor, range)); - } - Set set = new TreeSet<>(); - for (int i = 0; i < positions.size(); i++) { - set.add(new ComparableMark(names.get(i), positions.get(i))); - } + final Optional> FAIL = Optional.empty(); + final String errorTitle = Localization.lang("Problem collecting citations"); - List result = new ArrayList<>(set.size()); - for (ComparableMark mark : set) { - result.add(mark.getName()); + OOResult odoc = getXTextDocument(); + if (testDialog(errorTitle, odoc.asVoidResult())) { + return FAIL; } - viewCursor.gotoRange(initialPos, false); - - return result; - } - - public XNameAccess getReferenceMarks() { - XReferenceMarksSupplier supplier = UnoRuntime.queryInterface(XReferenceMarksSupplier.class, xCurrentComponent); - return supplier.getReferenceMarks(); - } + XTextDocument doc = odoc.get(); - private String getUniqueReferenceMarkName(String bibtexKey, int type) { - XNameAccess xNamedRefMarks = getReferenceMarks(); - int i = 0; - String name = OOBibBase.BIB_CITATION + '_' + type + '_' + bibtexKey; - while (xNamedRefMarks.hasByName(name)) { - name = OOBibBase.BIB_CITATION + i + '_' + type + '_' + bibtexKey; - i++; + if (testDialog(errorTitle, checkIfOpenOfficeIsRecordingChanges(doc))) { + LOGGER.warn(errorTitle); + return FAIL; } - return name; - } - public void rebuildBibTextSection(List databases, OOBibStyle style) - throws NoSuchElementException, WrappedTargetException, IllegalArgumentException, - CreationException, PropertyVetoException, UnknownPropertyException, UndefinedParagraphFormatException { - List cited = findCitedKeys(); - Map linkSourceBase = new HashMap<>(); - Map entries = findCitedEntries(databases, cited, linkSourceBase); // Although entries are redefined without use, this also updates linkSourceBase - - List names = sortedReferenceMarks; + try { - if (style.isSortByPosition()) { - // We need to sort the entries according to their order of appearance: - entries = getSortedEntriesFromSortedRefMarks(names, linkSourceBase); - } else { - SortedMap newMap = new TreeMap<>(entryComparator); - for (Map.Entry bibtexEntryBibtexDatabaseEntry : findCitedEntries(databases, cited, - linkSourceBase).entrySet()) { - newMap.put(bibtexEntryBibtexDatabaseEntry.getKey(), bibtexEntryBibtexDatabaseEntry.getValue()); - } - entries = newMap; + return Optional.of(ManageCitations.getCitationEntries(doc)); + } catch (NoDocumentException ex) { + OOError.from(ex).setTitle(errorTitle).showErrorDialog(dialogService); + return FAIL; + } catch (DisposedException ex) { + OOError.from(ex).setTitle(errorTitle).showErrorDialog(dialogService); + return FAIL; + } catch (WrappedTargetException ex) { + LOGGER.warn(errorTitle, ex); + OOError.fromMisc(ex).setTitle(errorTitle).showErrorDialog(dialogService); + return FAIL; } - clearBibTextSectionContent2(); - populateBibTextSection(entries, style); } - private List findCitedKeys() throws NoSuchElementException, WrappedTargetException { - XNameAccess xNamedMarks = getReferenceMarks(); - String[] names = xNamedMarks.getElementNames(); - List keys = new ArrayList<>(); - for (String name1 : names) { - Object bookmark = xNamedMarks.getByName(name1); - UnoRuntime.queryInterface(XTextContent.class, bookmark); - - List newKeys = parseRefMarkName(name1); - for (String key : newKeys) { - if (!keys.contains(key)) { - keys.add(key); - } - } - } + /** + * Apply editable parts of citationEntries to the document: store pageInfo. + *

+ * Does not change presentation. + *

+ * Note: we use no undo context here, because only DocumentConnection.setUserDefinedStringPropertyValue() is called, and Undo in LO will not undo that. + *

+ * GUI: "Manage citations" dialog "OK" button. Called from: ManageCitationsDialogViewModel.storeSettings + * + *

+ * Currently the only editable part is pageInfo. + *

+ * Since the only call to applyCitationEntries() only changes pageInfo w.r.t those returned by getCitationEntries(), we can do with the following restrictions: + *

    + *
  • Missing pageInfo means no action.
  • + *
  • Missing CitationEntry means no action (no attempt to remove + * citation from the text).
  • + *
+ */ + public void guiActionApplyCitationEntries(List citationEntries) { - return keys; - } + final String errorTitle = Localization.lang("Problem modifying citation"); - private Map findCitedEntries(List databases, List keys, - Map linkSourceBase) { - Map entries = new LinkedHashMap<>(); - for (String key : keys) { - boolean found = false; - for (BibDatabase database : databases) { - Optional entry = database.getEntryByCitationKey(key); - if (entry.isPresent()) { - entries.put(entry.get(), database); - linkSourceBase.put(key, database); - found = true; - break; - } - } - - if (!found) { - entries.put(new UndefinedBibtexEntry(key), null); - } + OOResult odoc = getXTextDocument(); + if (testDialog(errorTitle, odoc.asVoidResult())) { + return; } - return entries; - } + XTextDocument doc = odoc.get(); - private Point findPosition(XTextViewCursor cursor, XTextRange range) { - cursor.gotoRange(range, false); - return cursor.getPosition(); - } + try { - /** - * Extract the list of citation keys from a reference mark name. - * - * @param name The reference mark name. - * @return The list of citation keys encoded in the name. - */ - public List parseRefMarkName(String name) { - List keys = new ArrayList<>(); - Matcher citeMatcher = CITE_PATTERN.matcher(name); - if (citeMatcher.find()) { - String[] keystring = citeMatcher.group(2).split(","); - for (String aKeystring : keystring) { - if (!keys.contains(aKeystring)) { - keys.add(aKeystring); - } - } + ManageCitations.applyCitationEntries(doc, citationEntries); + } catch (NoDocumentException ex) { + OOError.from(ex).setTitle(errorTitle).showErrorDialog(dialogService); + } catch (DisposedException ex) { + OOError.from(ex).setTitle(errorTitle).showErrorDialog(dialogService); + } catch (PropertyVetoException + | IllegalTypeException + | WrappedTargetException + | com.sun.star.lang.IllegalArgumentException ex) { + LOGGER.warn(errorTitle, ex); + OOError.fromMisc(ex).setTitle(errorTitle).showErrorDialog(dialogService); } - return keys; } /** - * Resolve the citation key from a citation reference marker name, and look up the index of the key in a list of keys. + * Creates a citation group from {@code entries} at the cursor. + *

+ * Uses LO undo context "Insert citation". + *

+ * Note: Undo does not remove or reestablish custom properties. * - * @param citRefName The name of the ReferenceMark representing the citation. - * @param keys A List of citation 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. + * @param entries The entries to cite. + * @param database The database the entries belong to (all of them). Used when creating the citation mark. + *

+ * Consistency: for each entry in {@code entries}: looking it up in {@code syncOptions.get().databases} (if present) should yield {@code database}. + * @param style The bibliography style we are using. + * @param citationType Indicates whether it is an in-text citation, a citation in parenthesis or an invisible citation. + * @param pageInfo A single page-info for these entries. Attributed to the last entry. + * @param syncOptions Indicates whether in-text citations should be refreshed in the document. Optional.empty() indicates no refresh. Otherwise provides options for refreshing the reference list. */ - private List findCitedEntryIndex(String citRefName, List keys) { - Matcher citeMatcher = CITE_PATTERN.matcher(citRefName); - if (citeMatcher.find()) { - List keyStrings = Arrays.asList(citeMatcher.group(2).split(",")); - List result = new ArrayList<>(keyStrings.size()); - for (String key : keyStrings) { - int ind = keys.indexOf(key); - result.add(ind == -1 ? -1 : 1 + ind); - } - return result; - } else { - return Collections.emptyList(); + public void guiActionInsertEntry(List entries, + BibDatabase database, + OOBibStyle style, + CitationType citationType, + String pageInfo, + Optional syncOptions) { + + final String errorTitle = "Could not insert citation"; + + OOResult odoc = getXTextDocument(); + if (testDialog(errorTitle, + odoc.asVoidResult(), + styleIsRequired(style), + selectedBibEntryIsRequired(entries, OOError::noEntriesSelectedForCitation))) { + return; } - } + XTextDocument doc = odoc.get(); - private Map getSortedEntriesFromSortedRefMarks(List names, - Map linkSourceBase) { - - Map newList = new LinkedHashMap<>(); - for (String name : names) { - Matcher citeMatcher = CITE_PATTERN.matcher(name); - if (citeMatcher.find()) { - String[] keys = citeMatcher.group(2).split(","); - for (String key : keys) { - BibDatabase database = linkSourceBase.get(key); - Optional origEntry = Optional.empty(); - if (database != null) { - origEntry = database.getEntryByCitationKey(key); - } - if (origEntry.isPresent()) { - if (!newList.containsKey(origEntry.get())) { - newList.put(origEntry.get(), database); - } - } else { - LOGGER.info("Citation key not found: '" + key + "'"); - LOGGER.info("Problem with reference mark: '" + name + "'"); - newList.put(new UndefinedBibtexEntry(key), null); - } - } - } + OOResult frontend = getFrontend(doc); + if (testDialog(errorTitle, frontend.asVoidResult())) { + return; } - return newList; - } - - public String getCitationContext(XNameAccess nameAccess, String refMarkName, int charBefore, int charAfter, - boolean htmlMarkup) - throws NoSuchElementException, WrappedTargetException { - Object referenceMark = nameAccess.getByName(refMarkName); - XTextContent bookmark = UnoRuntime.queryInterface(XTextContent.class, referenceMark); - - XTextCursor cursor = bookmark.getAnchor().getText().createTextCursorByRange(bookmark.getAnchor()); - String citPart = cursor.getString(); - int flex = 8; - for (int i = 0; i < charBefore; i++) { - try { - cursor.goLeft((short) 1, true); - if ((i >= (charBefore - flex)) && Character.isWhitespace(cursor.getString().charAt(0))) { - break; - } - } catch (IndexOutOfBoundsException ex) { - LOGGER.warn("Problem going left", ex); - } - } - int length = cursor.getString().length(); - int added = length - citPart.length(); - cursor.collapseToStart(); - for (int i = 0; i < (charAfter + length); i++) { - try { - cursor.goRight((short) 1, true); - if (i >= ((charAfter + length) - flex)) { - String strNow = cursor.getString(); - if (Character.isWhitespace(strNow.charAt(strNow.length() - 1))) { - break; - } - } - } catch (IndexOutOfBoundsException ex) { - LOGGER.warn("Problem going right", ex); - } + OOResult cursor = getUserCursorForTextInsertion(doc, errorTitle); + if (testDialog(errorTitle, cursor.asVoidResult())) { + return; } - String result = cursor.getString(); - if (htmlMarkup) { - result = result.substring(0, added) + "" + citPart + "" + result.substring(length); + if (testDialog(errorTitle, checkRangeOverlapsWithCursor(doc, frontend.get()))) { + return; } - return result.trim(); - } - private void insertFullReferenceAtCursor(XTextCursor cursor, Map entries, OOBibStyle style, - String parFormat) - throws UndefinedParagraphFormatException, IllegalArgumentException, - UnknownPropertyException, PropertyVetoException, WrappedTargetException { - Map correctEntries; - // If we don't have numbered entries, we need to sort the entries before adding them: - if (style.isSortByPosition()) { - // Use the received map directly - correctEntries = entries; - } else { - // Sort map - Map newMap = new TreeMap<>(entryComparator); - newMap.putAll(entries); - correctEntries = newMap; + if (testDialog(errorTitle, + checkStylesExistInTheDocument(style, doc), + checkIfOpenOfficeIsRecordingChanges(doc))) { + return; } - int number = 1; - for (Map.Entry entry : correctEntries.entrySet()) { - if (entry.getKey() instanceof UndefinedBibtexEntry) { - continue; - } - OOUtil.insertParagraphBreak(text, cursor); - if (style.isNumberEntries()) { - int minGroupingCount = style.getIntCitProperty(OOBibStyle.MINIMUM_GROUPING_COUNT); - OOUtil.insertTextAtCurrentLocation(text, cursor, - style.getNumCitationMarker(Collections.singletonList(number++), minGroupingCount, true), Collections.emptyList()); + + /* + * For sync we need a FunctionalTextViewCursor. + */ + OOResult fcursor = null; + if (syncOptions.isPresent()) { + fcursor = getFunctionalTextViewCursor(doc, errorTitle); + if (testDialog(errorTitle, fcursor.asVoidResult())) { + return; } - Layout layout = style.getReferenceFormat(entry.getKey().getType()); - layout.setPostFormatter(POSTFORMATTER); - OOUtil.insertFullReferenceAtCurrentLocation(text, cursor, layout, parFormat, entry.getKey(), - entry.getValue(), uniquefiers.get(entry.getKey().getCitationKey().orElse(null))); } - } - private void createBibTextSection2(boolean end) - throws IllegalArgumentException, CreationException { + syncOptions + .map(e -> e.setUpdateBibliography(this.refreshBibliographyDuringSyncWhenCiting)) + .map(e -> e.setAlwaysAddCitedOnPages(this.alwaysAddCitedOnPages)); - XTextCursor mxDocCursor = text.createTextCursor(); - if (end) { - mxDocCursor.gotoEnd(false); + if (syncOptions.isPresent()) { + if (testDialog(databaseIsRequired(syncOptions.get().databases, + OOError::noDataBaseIsOpenForSyncingAfterCitation))) { + return; + } } - OOUtil.insertParagraphBreak(text, mxDocCursor); - // Create a new TextSection from the document factory and access it's XNamed interface - XNamed xChildNamed; + try { - xChildNamed = UnoRuntime.queryInterface(XNamed.class, - mxDocFactory.createInstance("com.sun.star.text.TextSection")); - } catch (Exception e) { - throw new CreationException(e.getMessage()); + UnoUndo.enterUndoContext(doc, "Insert citation"); + + EditInsert.insertCitationGroup(doc, + frontend.get(), + cursor.get(), + entries, + database, + style, + citationType, + pageInfo); + + if (syncOptions.isPresent()) { + Update.resyncDocument(doc, style, fcursor.get(), syncOptions.get()); + } + } catch (NoDocumentException ex) { + OOError.from(ex).setTitle(errorTitle).showErrorDialog(dialogService); + } catch (DisposedException ex) { + OOError.from(ex).setTitle(errorTitle).showErrorDialog(dialogService); + } catch (CreationException + | IllegalTypeException + | NotRemoveableException + | PropertyVetoException + | WrappedTargetException ex) { + LOGGER.warn("Could not insert entry", ex); + OOError.fromMisc(ex).setTitle(errorTitle).showErrorDialog(dialogService); + } finally { + UnoUndo.leaveUndoContext(doc); } - // Set the new sections name to 'Child_Section' - xChildNamed.setName(OOBibBase.BIB_SECTION_NAME); - // Access the Child_Section's XTextContent interface and insert it into the document - XTextContent xChildSection = UnoRuntime.queryInterface(XTextContent.class, xChildNamed); - text.insertTextContent(mxDocCursor, xChildSection, false); } - private void clearBibTextSectionContent2() - throws NoSuchElementException, WrappedTargetException, IllegalArgumentException, CreationException { - - // Check if the section exists: - XTextSectionsSupplier supplier = UnoRuntime.queryInterface(XTextSectionsSupplier.class, mxDoc); - if (supplier.getTextSections().hasByName(OOBibBase.BIB_SECTION_NAME)) { - XTextSection section = (XTextSection) ((Any) supplier.getTextSections().getByName(OOBibBase.BIB_SECTION_NAME)) - .getObject(); - // Clear it: - XTextCursor cursor = text.createTextCursorByRange(section.getAnchor()); - cursor.gotoRange(section.getAnchor(), false); - cursor.setString(""); - } else { - createBibTextSection2(atEnd); - } - } + /** + * GUI action "Merge citations" + */ + public void guiActionMergeCitationGroups(List databases, OOBibStyle style) { - private void populateBibTextSection(Map entries, OOBibStyle style) - throws NoSuchElementException, WrappedTargetException, PropertyVetoException, - UnknownPropertyException, UndefinedParagraphFormatException, IllegalArgumentException, CreationException { - XTextSectionsSupplier supplier = UnoRuntime.queryInterface(XTextSectionsSupplier.class, mxDoc); - XTextSection section = (XTextSection) ((Any) supplier.getTextSections().getByName(OOBibBase.BIB_SECTION_NAME)) - .getObject(); - XTextCursor cursor = text.createTextCursorByRange(section.getAnchor()); - OOUtil.insertTextAtCurrentLocation(text, cursor, (String) style.getProperty(OOBibStyle.TITLE), - (String) style.getProperty(OOBibStyle.REFERENCE_HEADER_PARAGRAPH_FORMAT)); - insertFullReferenceAtCursor(cursor, entries, style, - (String) style.getProperty(OOBibStyle.REFERENCE_PARAGRAPH_FORMAT)); - insertBookMark(OOBibBase.BIB_SECTION_END_NAME, cursor); - } + final String errorTitle = Localization.lang("Problem combining cite markers"); - private XTextContent insertBookMark(String name, XTextCursor position) - throws IllegalArgumentException, CreationException { - Object bookmark; - try { - bookmark = mxDocFactory.createInstance("com.sun.star.text.Bookmark"); - } catch (Exception e) { - throw new CreationException(e.getMessage()); + OOResult odoc = getXTextDocument(); + if (testDialog(errorTitle, + odoc.asVoidResult(), + styleIsRequired(style), + databaseIsRequired(databases, OOError::noDataBaseIsOpen))) { + return; } - // name the bookmark - XNamed xNamed = UnoRuntime.queryInterface(XNamed.class, bookmark); - xNamed.setName(name); - // get XTextContent interface - 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; - } + XTextDocument doc = odoc.get(); - private void insertReferenceMark(String name, String citationText, XTextCursor position, boolean withText, - OOBibStyle style) - throws UnknownPropertyException, WrappedTargetException, - PropertyVetoException, IllegalArgumentException, UndefinedCharacterFormatException, CreationException { - - // Check if there is "page info" stored for this citation. If so, insert it into - // the citation text before inserting the citation: - Optional pageInfo = getCustomProperty(name); - String citText; - if ((pageInfo.isPresent()) && !pageInfo.get().isEmpty()) { - citText = style.insertPageInfo(citationText, pageInfo.get()); - } else { - citText = citationText; - } + OOResult fcursor = getFunctionalTextViewCursor(doc, errorTitle); - Object bookmark; - try { - bookmark = mxDocFactory.createInstance("com.sun.star.text.ReferenceMark"); - } catch (Exception e) { - throw new CreationException(e.getMessage()); + if (testDialog(errorTitle, + fcursor.asVoidResult(), + checkStylesExistInTheDocument(style, doc), + checkIfOpenOfficeIsRecordingChanges(doc))) { + return; } - // Name the reference - XNamed xNamed = UnoRuntime.queryInterface(XNamed.class, bookmark); - xNamed.setName(name); - if (withText) { - position.setString(citText); - XPropertySet xCursorProps = UnoRuntime.queryInterface(XPropertySet.class, position); + try { + UnoUndo.enterUndoContext(doc, "Merge citations"); - // Set language to [None]: - xCursorProps.setPropertyValue("CharLocale", new Locale("zxx", "", "")); - if (style.isFormatCitations()) { - String charStyle = style.getCitationCharacterFormat(); - try { - xCursorProps.setPropertyValue(CHAR_STYLE_NAME, charStyle); - } catch (UnknownPropertyException | PropertyVetoException | IllegalArgumentException | - WrappedTargetException ex) { - throw new UndefinedCharacterFormatException(charStyle); - } + OOFrontend frontend = new OOFrontend(doc); + boolean madeModifications = EditMerge.mergeCitationGroups(doc, frontend, style); + if (madeModifications) { + UnoCrossRef.refresh(doc); + Update.SyncOptions syncOptions = new Update.SyncOptions(databases); + Update.resyncDocument(doc, style, fcursor.get(), syncOptions); } - } else { - position.setString(""); - } + } catch (NoDocumentException ex) { + OOError.from(ex).setTitle(errorTitle).showErrorDialog(dialogService); + } catch (DisposedException ex) { + OOError.from(ex).setTitle(errorTitle).showErrorDialog(dialogService); + } catch (CreationException + | IllegalTypeException + | NotRemoveableException + | PropertyVetoException + | WrappedTargetException + | com.sun.star.lang.IllegalArgumentException ex) { + LOGGER.warn("Problem combining cite markers", ex); + OOError.fromMisc(ex).setTitle(errorTitle).showErrorDialog(dialogService); + } finally { + UnoUndo.leaveUndoContext(doc); + fcursor.get().restore(doc); + } + } // MergeCitationGroups - // get XTextContent interface - XTextContent xTextContent = UnoRuntime.queryInterface(XTextContent.class, bookmark); + /** + * GUI action "Separate citations". + *

+ * Do the opposite of MergeCitationGroups. Combined markers are split, with a space inserted between. + */ + public void guiActionSeparateCitations(List databases, OOBibStyle style) { - position.getText().insertTextContent(position, xTextContent, true); + final String errorTitle = Localization.lang("Problem during separating cite markers"); - // Check if we should italicize the "et al." string in citations: - boolean italicize = style.getBooleanCitProperty(OOBibStyle.ITALIC_ET_AL); - if (italicize) { - String etAlString = style.getStringCitProperty(OOBibStyle.ET_AL_STRING); - int index = citText.indexOf(etAlString); - if (index >= 0) { - italicizeOrBold(position, true, index, index + etAlString.length()); - } + OOResult odoc = getXTextDocument(); + if (testDialog(errorTitle, + odoc.asVoidResult(), + styleIsRequired(style), + databaseIsRequired(databases, OOError::noDataBaseIsOpen))) { + return; } - position.collapseToEnd(); - } + XTextDocument doc = odoc.get(); + OOResult fcursor = getFunctionalTextViewCursor(doc, errorTitle); + + if (testDialog(errorTitle, + fcursor.asVoidResult(), + checkStylesExistInTheDocument(style, doc), + checkIfOpenOfficeIsRecordingChanges(doc))) { + return; + } - private void removeReferenceMark(String name) throws NoSuchElementException, WrappedTargetException { - XNameAccess xReferenceMarks = getReferenceMarks(); - if (xReferenceMarks.hasByName(name)) { - Object referenceMark = xReferenceMarks.getByName(name); - XTextContent bookmark = UnoRuntime.queryInterface(XTextContent.class, referenceMark); - text.removeTextContent(bookmark); + try { + UnoUndo.enterUndoContext(doc, "Separate citations"); + + OOFrontend frontend = new OOFrontend(doc); + boolean madeModifications = EditSeparate.separateCitations(doc, frontend, databases, style); + if (madeModifications) { + UnoCrossRef.refresh(doc); + Update.SyncOptions syncOptions = new Update.SyncOptions(databases); + Update.resyncDocument(doc, style, fcursor.get(), syncOptions); + } + } catch (NoDocumentException ex) { + OOError.from(ex).setTitle(errorTitle).showErrorDialog(dialogService); + } catch (DisposedException ex) { + OOError.from(ex).setTitle(errorTitle).showErrorDialog(dialogService); + } catch (CreationException + | IllegalTypeException + | NotRemoveableException + | PropertyVetoException + | WrappedTargetException + | com.sun.star.lang.IllegalArgumentException ex) { + LOGGER.warn("Problem during separating cite markers", ex); + OOError.fromMisc(ex).setTitle(errorTitle).showErrorDialog(dialogService); + } finally { + UnoUndo.leaveUndoContext(doc); + fcursor.get().restore(doc); } } /** - * Get the XTextRange corresponding to the named bookmark. + * GUI action for "Export cited" + *

+ * Does not refresh the bibliography. * - * @param name The name of the bookmark to find. - * @return The XTextRange for the bookmark. - * @throws WrappedTargetException - * @throws NoSuchElementException + * @param returnPartialResult If there are some unresolved keys, shall we return an otherwise nonempty result, or Optional.empty()? */ - private XTextRange getBookmarkRange(String name) throws NoSuchElementException, WrappedTargetException { - XNameAccess xNamedBookmarks = getBookmarks(); + public Optional exportCitedHelper(List databases, boolean returnPartialResult) { - // retrieve bookmark by name - if (!xNamedBookmarks.hasByName(name)) { - return null; - } - Object foundBookmark = xNamedBookmarks.getByName(name); - XTextContent xFoundBookmark = UnoRuntime.queryInterface(XTextContent.class, foundBookmark); - return xFoundBookmark.getAnchor(); - } - - private XNameAccess getBookmarks() { - // query XBookmarksSupplier from document model and get bookmarks collection - XBookmarksSupplier xBookmarksSupplier = UnoRuntime.queryInterface(XBookmarksSupplier.class, xCurrentComponent); - XNameAccess xNamedBookmarks = xBookmarksSupplier.getBookmarks(); - return xNamedBookmarks; - } + final Optional FAIL = Optional.empty(); + final String errorTitle = Localization.lang("Unable to generate new library"); - private void italicizeOrBold(XTextCursor position, boolean italicize, int start, int end) - throws UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException { - XTextRange range = position.getStart(); - XTextCursor cursor = position.getText().createTextCursorByRange(range); - cursor.goRight((short) start, false); - cursor.goRight((short) (end - start), true); - XPropertySet xcp = UnoRuntime.queryInterface(XPropertySet.class, cursor); - if (italicize) { - xcp.setPropertyValue("CharPosture", com.sun.star.awt.FontSlant.ITALIC); - } else { - xcp.setPropertyValue("CharWeight", com.sun.star.awt.FontWeight.BOLD); + OOResult odoc = getXTextDocument(); + if (testDialog(errorTitle, + odoc.asVoidResult(), + databaseIsRequired(databases, OOError::noDataBaseIsOpenForExport))) { + return FAIL; } - } + XTextDocument doc = odoc.get(); - public void combineCiteMarkers(List databases, OOBibStyle style) - throws IOException, WrappedTargetException, NoSuchElementException, IllegalArgumentException, - UndefinedCharacterFormatException, UnknownPropertyException, PropertyVetoException, CreationException, - BibEntryNotFoundException { - XNameAccess nameAccess = getReferenceMarks(); - // TODO: doesn't work for citations in footnotes/tables - List names = getSortedReferenceMarks(nameAccess); - - final XTextRangeCompare compare = UnoRuntime.queryInterface(XTextRangeCompare.class, text); - - int piv = 0; - boolean madeModifications = false; - while (piv < (names.size() - 1)) { - XTextRange range1 = UnoRuntime.queryInterface(XTextContent.class, nameAccess.getByName(names.get(piv))) - .getAnchor().getEnd(); - XTextRange range2 = UnoRuntime.queryInterface(XTextContent.class, nameAccess.getByName(names.get(piv + 1))) - .getAnchor().getStart(); - if (range1.getText() != range2.getText()) { - piv++; - continue; - } - XTextCursor mxDocCursor = range1.getText().createTextCursorByRange(range1); - mxDocCursor.goRight((short) 1, true); - boolean couldExpand = true; - while (couldExpand && (compare.compareRegionEnds(mxDocCursor, range2) > 0)) { - couldExpand = mxDocCursor.goRight((short) 1, true); - } - String cursorText = mxDocCursor.getString(); - // Check if the string contains no line breaks and only whitespace: - if ((cursorText.indexOf('\n') == -1) && cursorText.trim().isEmpty()) { - - // If we are supposed to set character format for citations, test this before - // making any changes. This way we can throw an exception before any reference - // marks are removed, preventing damage to the user's document: - if (style.isFormatCitations()) { - XPropertySet xCursorProps = UnoRuntime.queryInterface(XPropertySet.class, mxDocCursor); - String charStyle = style.getCitationCharacterFormat(); - try { - xCursorProps.setPropertyValue(CHAR_STYLE_NAME, charStyle); - } catch (UnknownPropertyException | PropertyVetoException | IllegalArgumentException | - WrappedTargetException ex) { - // Setting the character format failed, so we throw an exception that - // will result in an error message for the user: - throw new UndefinedCharacterFormatException(charStyle); - } - } + try { - List keys = parseRefMarkName(names.get(piv)); - keys.addAll(parseRefMarkName(names.get(piv + 1))); - removeReferenceMark(names.get(piv)); - removeReferenceMark(names.get(piv + 1)); - List entries = new ArrayList<>(); - for (String key : keys) { - for (BibDatabase database : databases) { - Optional entry = database.getEntryByCitationKey(key); - if (entry.isPresent()) { - entries.add(entry.get()); - break; - } - } + ExportCited.GenerateDatabaseResult result; + try { + UnoUndo.enterUndoContext(doc, "Changes during \"Export cited\""); + result = ExportCited.generateDatabase(doc, databases); + } finally { + // There should be no changes, thus no Undo entry should appear + // in LibreOffice. + UnoUndo.leaveUndoContext(doc); + } + + if (!result.newDatabase.hasEntries()) { + dialogService.showErrorDialogAndWait( + Localization.lang("Unable to generate new library"), + Localization.lang("Your OpenOffice/LibreOffice document references" + + " no citation keys" + + " which could also be found in your current library.")); + return FAIL; + } + + List unresolvedKeys = result.unresolvedKeys; + if (!unresolvedKeys.isEmpty()) { + dialogService.showErrorDialogAndWait( + Localization.lang("Unable to generate new library"), + Localization.lang("Your OpenOffice/LibreOffice document references" + + " at least %0 citation keys" + + " which could not be found in your current library." + + " Some of these are %1.", + String.valueOf(unresolvedKeys.size()), + String.join(", ", unresolvedKeys))); + if (returnPartialResult) { + return Optional.of(result.newDatabase); + } else { + return FAIL; } - Collections.sort(entries, new FieldComparator(StandardField.YEAR)); - String keyString = String.join(",", entries.stream().map(entry -> entry.getCitationKey().orElse("")) - .collect(Collectors.toList())); - // Insert bookmark: - String bName = getUniqueReferenceMarkName(keyString, OOBibBase.AUTHORYEAR_PAR); - insertReferenceMark(bName, "tmp", mxDocCursor, true, style); - names.set(piv + 1, bName); - madeModifications = true; } - piv++; - } - if (madeModifications) { - updateSortedReferenceMarks(); - refreshCiteMarkers(databases, style); + return Optional.of(result.newDatabase); + } catch (NoDocumentException ex) { + OOError.from(ex).showErrorDialog(dialogService); + } catch (DisposedException ex) { + OOError.from(ex).setTitle(errorTitle).showErrorDialog(dialogService); + } catch (WrappedTargetException + | com.sun.star.lang.IllegalArgumentException ex) { + LOGGER.warn("Problem generating new database.", ex); + OOError.fromMisc(ex).setTitle(errorTitle).showErrorDialog(dialogService); } + return FAIL; } /** - * Do the opposite of combineCiteMarkers. - * Combined markers are split, with a space inserted between. + * GUI action, refreshes citation markers and bibliography. + * + * @param databases Must have at least one. + * @param style Style. */ - public void unCombineCiteMarkers(List databases, OOBibStyle style) - throws IOException, WrappedTargetException, NoSuchElementException, IllegalArgumentException, - UndefinedCharacterFormatException, UnknownPropertyException, PropertyVetoException, CreationException, - BibEntryNotFoundException { - XNameAccess nameAccess = getReferenceMarks(); - List names = getSortedReferenceMarks(nameAccess); - - final XTextRangeCompare compare = UnoRuntime.queryInterface(XTextRangeCompare.class, text); - - int pivot = 0; - boolean madeModifications = false; - while (pivot < (names.size())) { - XTextRange range1 = UnoRuntime.queryInterface(XTextContent.class, nameAccess.getByName(names.get(pivot))) - .getAnchor(); - - XTextCursor textCursor = range1.getText().createTextCursorByRange(range1); - - // If we are supposed to set character format for citations, test this before - // making any changes. This way we can throw an exception before any reference - // marks are removed, preventing damage to the user's document: - if (style.isFormatCitations()) { - XPropertySet xCursorProps = UnoRuntime.queryInterface(XPropertySet.class, textCursor); - String charStyle = style.getCitationCharacterFormat(); - try { - xCursorProps.setPropertyValue(CHAR_STYLE_NAME, charStyle); - } catch (UnknownPropertyException | PropertyVetoException | IllegalArgumentException | - WrappedTargetException ex) { - // Setting the character format failed, so we throw an exception that - // will result in an error message for the user: - throw new UndefinedCharacterFormatException(charStyle); - } - } + public void guiActionUpdateDocument(List databases, OOBibStyle style) { - List keys = parseRefMarkName(names.get(pivot)); - if (keys.size() > 1) { - removeReferenceMark(names.get(pivot)); - - // Insert bookmark for each key - int last = keys.size() - 1; - int i = 0; - for (String key : keys) { - String newName = getUniqueReferenceMarkName(key, OOBibBase.AUTHORYEAR_PAR); - insertReferenceMark(newName, "tmp", textCursor, true, style); - textCursor.collapseToEnd(); - if (i != last) { - textCursor.setString(" "); - textCursor.collapseToEnd(); - } - i++; - } - madeModifications = true; - } - pivot++; - } - if (madeModifications) { - updateSortedReferenceMarks(); - refreshCiteMarkers(databases, style); - } - } + final String errorTitle = Localization.lang("Unable to synchronize bibliography"); - public BibDatabase generateDatabase(List databases) - throws NoSuchElementException, WrappedTargetException { - BibDatabase resultDatabase = new BibDatabase(); - List cited = findCitedKeys(); - List entriesToInsert = new ArrayList<>(); - - // For each cited key - for (String key : cited) { - // Loop through the available databases - for (BibDatabase loopDatabase : databases) { - Optional entry = loopDatabase.getEntryByCitationKey(key); - // If entry found - if (entry.isPresent()) { - BibEntry clonedEntry = (BibEntry) entry.get().clone(); - // Insert a copy of the entry - entriesToInsert.add(clonedEntry); - // Check if the cloned entry has a crossref field - clonedEntry.getField(StandardField.CROSSREF).ifPresent(crossref -> { - // If the crossref entry is not already in the database - if (!resultDatabase.getEntryByCitationKey(crossref).isPresent()) { - // Add it if it is in the current library - loopDatabase.getEntryByCitationKey(crossref).ifPresent(entriesToInsert::add); - } - }); - - // Be happy with the first found BibEntry and move on to next key - break; - } - } - } - resultDatabase.insertEntries(entriesToInsert); - return resultDatabase; - } + try { - private static class ComparableMark implements Comparable { + OOResult odoc = getXTextDocument(); + if (testDialog(errorTitle, + odoc.asVoidResult(), + styleIsRequired(style))) { + return; + } - private final String name; - private final Point position; + XTextDocument doc = odoc.get(); - public ComparableMark(String name, Point position) { - this.name = name; - this.position = position; - } + OOResult fcursor = getFunctionalTextViewCursor(doc, errorTitle); - @Override - public int compareTo(ComparableMark other) { - if (position.Y == other.position.Y) { - return position.X - other.position.X; - } else { - return position.Y - other.position.Y; - } - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; + if (testDialog(errorTitle, + fcursor.asVoidResult(), + checkStylesExistInTheDocument(style, doc), + checkIfOpenOfficeIsRecordingChanges(doc))) { + return; } - if (o instanceof ComparableMark) { - ComparableMark other = (ComparableMark) o; - return (this.position.X == other.position.X) && (this.position.Y == other.position.Y) - && Objects.equals(this.name, other.name); + OOFrontend frontend = new OOFrontend(doc); + if (testDialog(errorTitle, checkRangeOverlaps(doc, frontend))) { + return; } - return false; - } - - public String getName() { - return name; - } - - @Override - public int hashCode() { - return Objects.hash(position, name); - } - } - - private class DocumentTitleViewModel { - private final XTextDocument xTextDocument; - private final String description; + List unresolvedKeys; + try { + UnoUndo.enterUndoContext(doc, "Refresh bibliography"); - public DocumentTitleViewModel(XTextDocument xTextDocument) { - this.xTextDocument = xTextDocument; - this.description = getDocumentTitle(xTextDocument).orElse(""); - } + Update.SyncOptions syncOptions = new Update.SyncOptions(databases); + syncOptions + .setUpdateBibliography(true) + .setAlwaysAddCitedOnPages(this.alwaysAddCitedOnPages); - public XTextDocument getXtextDocument() { - return xTextDocument; - } + unresolvedKeys = Update.synchronizeDocument(doc, frontend, style, fcursor.get(), syncOptions); + } finally { + UnoUndo.leaveUndoContext(doc); + fcursor.get().restore(doc); + } - @Override - public String toString() { - return description; + if (!unresolvedKeys.isEmpty()) { + String msg = Localization.lang( + "Your OpenOffice/LibreOffice document references the citation key '%0'," + + " which could not be found in your current library.", + unresolvedKeys.get(0)); + dialogService.showErrorDialogAndWait(errorTitle, msg); + } + } catch (NoDocumentException ex) { + OOError.from(ex).setTitle(errorTitle).showErrorDialog(dialogService); + } catch (DisposedException ex) { + OOError.from(ex).setTitle(errorTitle).showErrorDialog(dialogService); + } catch (CreationException + | WrappedTargetException + | com.sun.star.lang.IllegalArgumentException ex) { + LOGGER.warn("Could not update bibliography", ex); + OOError.fromMisc(ex).setTitle(errorTitle).showErrorDialog(dialogService); } } } diff --git a/src/main/java/org/jabref/gui/openoffice/OOBibBaseConnect.java b/src/main/java/org/jabref/gui/openoffice/OOBibBaseConnect.java new file mode 100644 index 00000000000..24660410fc3 --- /dev/null +++ b/src/main/java/org/jabref/gui/openoffice/OOBibBaseConnect.java @@ -0,0 +1,236 @@ +package org.jabref.gui.openoffice; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.jabref.gui.DialogService; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.openoffice.NoDocumentFoundException; +import org.jabref.model.openoffice.uno.CreationException; +import org.jabref.model.openoffice.uno.NoDocumentException; +import org.jabref.model.openoffice.uno.UnoCast; +import org.jabref.model.openoffice.uno.UnoTextDocument; +import org.jabref.model.openoffice.util.OOResult; + +import com.sun.star.comp.helper.BootstrapException; +import com.sun.star.container.NoSuchElementException; +import com.sun.star.container.XEnumeration; +import com.sun.star.container.XEnumerationAccess; +import com.sun.star.frame.XDesktop; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.text.XTextDocument; +import com.sun.star.uno.XComponentContext; + +/** + * Establish connection to a document opened in OpenOffice or LibreOffice. + */ +class OOBibBaseConnect { + + private final DialogService dialogService; + private final XDesktop xDesktop; + + /** + * Created when connected to a document. + *

+ * Cleared (to null) when we discover we lost the connection. + */ + private XTextDocument xTextDocument; + + public OOBibBaseConnect(Path loPath, DialogService dialogService) + throws + BootstrapException, + CreationException { + + this.dialogService = dialogService; + this.xDesktop = simpleBootstrap(loPath); + } + + private XDesktop simpleBootstrap(Path loPath) + throws + CreationException, + BootstrapException { + + // Get the office component context: + XComponentContext context = org.jabref.gui.openoffice.Bootstrap.bootstrap(loPath); + XMultiComponentFactory sem = context.getServiceManager(); + + // Create the desktop, which is the root frame of the + // hierarchy of frames that contain viewable components: + Object desktop; + try { + desktop = sem.createInstanceWithContext("com.sun.star.frame.Desktop", context); + } catch (com.sun.star.uno.Exception e) { + throw new CreationException(e.getMessage()); + } + return UnoCast.cast(XDesktop.class, desktop).get(); + } + + private static List getTextDocuments(XDesktop desktop) + throws + NoSuchElementException, + WrappedTargetException { + + List result = new ArrayList<>(); + + XEnumerationAccess enumAccess = desktop.getComponents(); + XEnumeration compEnum = enumAccess.createEnumeration(); + + while (compEnum.hasMoreElements()) { + Object next = compEnum.nextElement(); + XComponent comp = UnoCast.cast(XComponent.class, next).get(); + Optional doc = UnoCast.cast(XTextDocument.class, comp); + doc.ifPresent(result::add); + } + return result; + } + + /** + * Run a dialog allowing the user to choose among the documents in `list`. + * + * @return Null if no document was selected. Otherwise the document selected. + */ + private static XTextDocument selectDocumentDialog(List list, + DialogService dialogService) { + + class DocumentTitleViewModel { + + private final XTextDocument xTextDocument; + private final String description; + + public DocumentTitleViewModel(XTextDocument xTextDocument) { + this.xTextDocument = xTextDocument; + this.description = UnoTextDocument.getFrameTitle(xTextDocument).orElse(""); + } + + public XTextDocument getXtextDocument() { + return xTextDocument; + } + + @Override + public String toString() { + return description; + } + } + + List viewModel = (list.stream() + .map(DocumentTitleViewModel::new) + .collect(Collectors.toList())); + + // This whole method is part of a background task when + // auto-detecting instances, so we need to show dialog in FX + // thread + Optional selectedDocument = + (dialogService + .showChoiceDialogAndWait(Localization.lang("Select document"), + Localization.lang("Found documents:"), + Localization.lang("Use selected document"), + viewModel)); + + return (selectedDocument + .map(DocumentTitleViewModel::getXtextDocument) + .orElse(null)); + } + + /** + * Choose a document to work with. + *

+ * Assumes we have already connected to LibreOffice or OpenOffice. + *

+ * If there is a single document to choose from, selects that. If there are more than one, shows selection dialog. If there are none, throws NoDocumentFoundException + *

+ * After successful selection connects to the selected document and extracts some frequently used parts (starting points for managing its content). + *

+ * Finally initializes this.xTextDocument with the selected document and parts extracted. + */ + public void selectDocument(boolean autoSelectForSingle) + throws + NoDocumentFoundException, + NoSuchElementException, + WrappedTargetException { + + XTextDocument selected; + List textDocumentList = getTextDocuments(this.xDesktop); + if (textDocumentList.isEmpty()) { + throw new NoDocumentFoundException("No Writer documents found"); + } else if (textDocumentList.size() == 1 && autoSelectForSingle) { + selected = textDocumentList.get(0); // Get the only one + } else { // Bring up a dialog + selected = OOBibBaseConnect.selectDocumentDialog(textDocumentList, + this.dialogService); + } + + if (selected == null) { + return; + } + + this.xTextDocument = selected; + } + + /** + * Mark the current document as missing. + */ + private void forgetDocument() { + this.xTextDocument = null; + } + + /** + * A simple test for document availability. + *

+ * See also `isDocumentConnectionMissing` for a test actually attempting to use teh connection. + */ + public boolean isConnectedToDocument() { + return this.xTextDocument != null; + } + + /** + * @return true if we are connected to a document + */ + public boolean isDocumentConnectionMissing() { + XTextDocument doc = this.xTextDocument; + + if (doc == null) { + return true; + } + + if (UnoTextDocument.isDocumentConnectionMissing(doc)) { + forgetDocument(); + return true; + } + return false; + } + + /** + * Either return a valid XTextDocument or throw NoDocumentException. + */ + public XTextDocument getXTextDocumentOrThrow() + throws + NoDocumentException { + if (isDocumentConnectionMissing()) { + throw new NoDocumentException("Not connected to document"); + } + return this.xTextDocument; + } + + public OOResult getXTextDocument() { + if (isDocumentConnectionMissing()) { + return OOResult.error(OOError.from(new NoDocumentException())); + } + return OOResult.ok(this.xTextDocument); + } + + /** + * The title of the current document, or Optional.empty() + */ + public Optional getCurrentDocumentTitle() { + if (isDocumentConnectionMissing()) { + return Optional.empty(); + } else { + return UnoTextDocument.getFrameTitle(this.xTextDocument); + } + } +} // end of OOBibBaseConnect diff --git a/src/main/java/org/jabref/gui/openoffice/OOError.java b/src/main/java/org/jabref/gui/openoffice/OOError.java new file mode 100644 index 00000000000..c8ad7ef53aa --- /dev/null +++ b/src/main/java/org/jabref/gui/openoffice/OOError.java @@ -0,0 +1,141 @@ +package org.jabref.gui.openoffice; + +import org.jabref.gui.DialogService; +import org.jabref.logic.JabRefException; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.openoffice.NoDocumentFoundException; +import org.jabref.model.openoffice.uno.NoDocumentException; + +import com.sun.star.lang.DisposedException; + +class OOError extends JabRefException { + + private String localizedTitle; + + public OOError(String title, String localizedMessage) { + super(localizedMessage, localizedMessage); + this.localizedTitle = title; + } + + public OOError(String title, String localizedMessage, Throwable cause) { + super(localizedMessage, localizedMessage, cause); + this.localizedTitle = title; + } + + public String getTitle() { + return localizedTitle; + } + + public OOError setTitle(String title) { + localizedTitle = title; + return this; + } + + public void showErrorDialog(DialogService dialogService) { + dialogService.showErrorDialogAndWait(getTitle(), getLocalizedMessage()); + } + + /* + * Conversions from exception caught + */ + + public static OOError from(JabRefException err) { + return new OOError( + Localization.lang("JabRefException"), + err.getLocalizedMessage(), + err); + } + + // For DisposedException + public static OOError from(DisposedException err) { + return new OOError( + Localization.lang("Connection lost"), + Localization.lang("Connection to OpenOffice/LibreOffice has been lost." + + " Please make sure OpenOffice/LibreOffice is running," + + " and try to reconnect."), + err); + } + + // For NoDocumentException + public static OOError from(NoDocumentException err) { + return new OOError( + Localization.lang("Not connected to document"), + Localization.lang("Not connected to any Writer document." + + " Please make sure a document is open," + + " and use the 'Select Writer document' button" + + " to connect to it."), + err); + } + + // For NoDocumentFoundException + public static OOError from(NoDocumentFoundException err) { + return new OOError( + Localization.lang("No Writer documents found"), + Localization.lang("Could not connect to any Writer document." + + " Please make sure a document is open" + + " before using the 'Select Writer document' button" + + " to connect to it."), + err); + } + + public static OOError fromMisc(Exception err) { + return new OOError( + "Exception", + err.getMessage(), + err); + } + + /* + * Messages for error dialog. These are not thrown. + */ + + // noDataBaseIsOpenForCiting + public static OOError noDataBaseIsOpenForCiting() { + return new OOError( + Localization.lang("No database"), + Localization.lang("No bibliography database is open for citation.") + + "\n" + + Localization.lang("Open one before citing.")); + } + + public static OOError noDataBaseIsOpenForSyncingAfterCitation() { + return new OOError( + Localization.lang("No database"), + Localization.lang("No database is open for updating citation markers after citing.") + + "\n" + + Localization.lang("Open one before citing.")); + } + + // noDataBaseIsOpenForExport + public static OOError noDataBaseIsOpenForExport() { + return new OOError( + Localization.lang("No database is open"), + Localization.lang("We need a database to export from. Open one.")); + } + + // noDataBaseIsOpenForExport + public static OOError noDataBaseIsOpen() { + return new OOError( + Localization.lang("No database is open"), + Localization.lang("This operation requires a bibliography database.")); + } + + // noValidStyleSelected + public static OOError noValidStyleSelected() { + return new OOError(Localization.lang("No valid style file defined"), + Localization.lang("No bibliography style is selected for citation.") + + "\n" + + Localization.lang("Select one before citing.") + + "\n" + + Localization.lang("You must select either a valid style file," + + " or use one of the default styles.")); + } + + // noEntriesSelectedForCitation + public static OOError noEntriesSelectedForCitation() { + return new OOError(Localization.lang("No entries selected for citation"), + Localization.lang("No bibliography entries are selected for citation.") + + "\n" + + Localization.lang("Select some before citing.")); + } +} diff --git a/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java b/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java index 681e16ad424..8c40775ce79 100644 --- a/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java +++ b/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java @@ -1,8 +1,6 @@ package org.jabref.gui.openoffice; -import java.io.FileNotFoundException; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -48,24 +46,17 @@ import org.jabref.logic.l10n.Localization; import org.jabref.logic.openoffice.OpenOfficeFileSearch; import org.jabref.logic.openoffice.OpenOfficePreferences; -import org.jabref.logic.openoffice.UndefinedParagraphFormatException; +import org.jabref.logic.openoffice.action.Update; import org.jabref.logic.openoffice.style.OOBibStyle; import org.jabref.logic.openoffice.style.StyleLoader; import org.jabref.model.database.BibDatabase; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; +import org.jabref.model.openoffice.style.CitationType; import org.jabref.model.openoffice.uno.CreationException; -import org.jabref.model.openoffice.uno.NoDocumentException; import org.jabref.preferences.PreferencesService; -import com.sun.star.beans.IllegalTypeException; -import com.sun.star.beans.NotRemoveableException; -import com.sun.star.beans.PropertyExistException; -import com.sun.star.beans.PropertyVetoException; -import com.sun.star.beans.UnknownPropertyException; import com.sun.star.comp.helper.BootstrapException; -import com.sun.star.container.NoSuchElementException; -import com.sun.star.lang.WrappedTargetException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -99,19 +90,19 @@ public class OpenOfficePanel { private final UndoManager undoManager; private final TaskExecutor taskExecutor; private final StyleLoader loader; - private OpenOfficePreferences ooPrefs; + private OpenOfficePreferences openOfficePreferences; private OOBibBase ooBase; private OOBibStyle style; public OpenOfficePanel(PreferencesService preferencesService, - OpenOfficePreferences ooPrefs, + OpenOfficePreferences openOfficePreferences, KeyBindingRepository keyBindingRepository, TaskExecutor taskExecutor, DialogService dialogService, StateManager stateManager, UndoManager undoManager) { ActionFactory factory = new ActionFactory(keyBindingRepository); - this.ooPrefs = ooPrefs; + this.openOfficePreferences = openOfficePreferences; this.preferencesService = preferencesService; this.taskExecutor = taskExecutor; this.dialogService = dialogService; @@ -141,9 +132,8 @@ public OpenOfficePanel(PreferencesService preferencesService, update.setTooltip(new Tooltip(Localization.lang("Sync OpenOffice/LibreOffice bibliography"))); update.setMaxWidth(Double.MAX_VALUE); - loader = new StyleLoader(ooPrefs, - preferencesService.getLayoutFormatterPreferences(Globals.journalAbbreviationRepository), - preferencesService.getGeneralPreferences().getDefaultEncoding()); + loader = new StyleLoader(openOfficePreferences, + preferencesService.getLayoutFormatterPreferences(Globals.journalAbbreviationRepository)); initPanel(); } @@ -152,24 +142,38 @@ public Node getContent() { return vbox; } + /* Note: the style may still be null on return. + * + * Return true if failed. In this case the dialog is already shown. + */ + private boolean getOrUpdateTheStyle(String title) { + final boolean FAIL = true; + final boolean PASS = false; + + if (style == null) { + style = loader.getUsedStyle(); + } else { + try { + style.ensureUpToDate(); + } catch (IOException ex) { + LOGGER.warn("Unable to reload style file '" + style.getPath() + "'", ex); + String msg = (Localization.lang("Unable to reload style file") + + "'" + style.getPath() + "'" + + "\n" + ex.getMessage()); + new OOError(title, msg, ex).showErrorDialog(dialogService); + return FAIL; + } + } + return PASS; + } + private void initPanel() { connect.setOnAction(e -> connectAutomatically()); manualConnect.setOnAction(e -> connectManually()); selectDocument.setTooltip(new Tooltip(Localization.lang("Select which open Writer document to work on"))); - selectDocument.setOnAction(e -> { - - try { - ooBase.selectDocument(); - dialogService.notify(Localization.lang("Connected to document") + ": " - + ooBase.getCurrentDocumentTitle().orElse("")); - } catch (WrappedTargetException | IndexOutOfBoundsException | - NoSuchElementException | NoDocumentException ex) { - LOGGER.warn("Problem connecting", ex); - dialogService.showErrorDialogAndWait(ex); - } - }); + selectDocument.setOnAction(e -> ooBase.guiActionSelectDocument(false)); setStyleFile.setMaxWidth(Double.MAX_VALUE); setStyleFile.setOnAction(event -> @@ -185,107 +189,53 @@ private void initPanel() { })); pushEntries.setTooltip(new Tooltip(Localization.lang("Cite selected entries between parenthesis"))); - pushEntries.setOnAction(e -> pushEntries(true, true, false)); + pushEntries.setOnAction(e -> pushEntries(CitationType.AUTHORYEAR_PAR, false)); pushEntries.setMaxWidth(Double.MAX_VALUE); pushEntriesInt.setTooltip(new Tooltip(Localization.lang("Cite selected entries with in-text citation"))); - pushEntriesInt.setOnAction(e -> pushEntries(false, true, false)); + pushEntriesInt.setOnAction(e -> pushEntries(CitationType.AUTHORYEAR_INTEXT, false)); pushEntriesInt.setMaxWidth(Double.MAX_VALUE); pushEntriesEmpty.setTooltip(new Tooltip(Localization.lang("Insert a citation without text (the entry will appear in the reference list)"))); - pushEntriesEmpty.setOnAction(e -> pushEntries(false, false, false)); + pushEntriesEmpty.setOnAction(e -> pushEntries(CitationType.INVISIBLE_CIT, false)); pushEntriesEmpty.setMaxWidth(Double.MAX_VALUE); pushEntriesAdvanced.setTooltip(new Tooltip(Localization.lang("Cite selected entries with extra information"))); - pushEntriesAdvanced.setOnAction(e -> pushEntries(false, true, true)); + pushEntriesAdvanced.setOnAction(e -> pushEntries(CitationType.AUTHORYEAR_INTEXT, true)); pushEntriesAdvanced.setMaxWidth(Double.MAX_VALUE); update.setTooltip(new Tooltip(Localization.lang("Ensure that the bibliography is up-to-date"))); update.setOnAction(event -> { - try { - if (style == null) { - style = loader.getUsedStyle(); - } else { - style.ensureUpToDate(); - } - - ooBase.updateSortedReferenceMarks(); - - List databases = getBaseList(); - List unresolvedKeys = ooBase.refreshCiteMarkers(databases, style); - ooBase.rebuildBibTextSection(databases, style); - if (!unresolvedKeys.isEmpty()) { - dialogService.showErrorDialogAndWait(Localization.lang("Unable to synchronize bibliography"), - Localization.lang("Your OpenOffice/LibreOffice document references the citation key '%0', which could not be found in your current library.", - unresolvedKeys.get(0))); - } - } catch (UndefinedCharacterFormatException ex) { - reportUndefinedCharacterFormat(ex); - } catch (UndefinedParagraphFormatException ex) { - reportUndefinedParagraphFormat(ex); - } catch (ConnectionLostException ex) { - showConnectionLostErrorMessage(); - } catch (IOException ex) { - LOGGER.warn("Problem with style file", ex); - dialogService.showErrorDialogAndWait(Localization.lang("No valid style file defined"), - Localization.lang("You must select either a valid style file, or use one of the default styles.")); - } catch (BibEntryNotFoundException ex) { - LOGGER.debug("BibEntry not found", ex); - dialogService.showErrorDialogAndWait(Localization.lang("Unable to synchronize bibliography"), Localization.lang( - "Your OpenOffice/LibreOffice document references the citation key '%0', which could not be found in your current library.", - ex.getCitationKey())); - } catch (com.sun.star.lang.IllegalArgumentException | PropertyVetoException | UnknownPropertyException | WrappedTargetException | NoSuchElementException | - CreationException ex) { - LOGGER.warn("Could not update bibliography", ex); + String title = Localization.lang("Could not update bibliography"); + if (getOrUpdateTheStyle(title)) { + return; } + List databases = getBaseList(); + ooBase.guiActionUpdateDocument(databases, style); }); merge.setMaxWidth(Double.MAX_VALUE); merge.setTooltip(new Tooltip(Localization.lang("Combine pairs of citations that are separated by spaces only"))); - merge.setOnAction(e -> { - try { - ooBase.combineCiteMarkers(getBaseList(), style); - } catch (UndefinedCharacterFormatException ex) { - reportUndefinedCharacterFormat(ex); - } catch (com.sun.star.lang.IllegalArgumentException | UnknownPropertyException | PropertyVetoException | - CreationException | NoSuchElementException | WrappedTargetException | IOException | - BibEntryNotFoundException ex) { - LOGGER.warn("Problem combining cite markers", ex); - } - }); + merge.setOnAction(e -> ooBase.guiActionMergeCitationGroups(getBaseList(), style)); unmerge.setMaxWidth(Double.MAX_VALUE); unmerge.setTooltip(new Tooltip(Localization.lang("Separate merged citations"))); - unmerge.setOnAction(e -> { - try { - ooBase.unCombineCiteMarkers(getBaseList(), style); - } catch (UndefinedCharacterFormatException ex) { - reportUndefinedCharacterFormat(ex); - } catch (com.sun.star.lang.IllegalArgumentException | UnknownPropertyException | PropertyVetoException | - CreationException | NoSuchElementException | WrappedTargetException | IOException | - BibEntryNotFoundException ex) { - LOGGER.warn("Problem uncombining cite markers", ex); - } - }); + unmerge.setOnAction(e -> ooBase.guiActionSeparateCitations(getBaseList(), style)); ContextMenu settingsMenu = createSettingsPopup(); settingsB.setMaxWidth(Double.MAX_VALUE); settingsB.setContextMenu(settingsMenu); settingsB.setOnAction(e -> settingsMenu.show(settingsB, Side.BOTTOM, 0, 0)); manageCitations.setMaxWidth(Double.MAX_VALUE); - manageCitations.setOnAction(e -> dialogService.showCustomDialogAndWait(new ManageCitationsDialogView(ooBase))); + manageCitations.setOnAction(e -> { + ManageCitationsDialogView dialog = new ManageCitationsDialogView(ooBase); + if (dialog.isOkToShowThisDialog()) { + dialogService.showCustomDialogAndWait(dialog); + } + }); exportCitations.setMaxWidth(Double.MAX_VALUE); exportCitations.setOnAction(event -> exportEntries()); - selectDocument.setDisable(true); - pushEntries.setDisable(true); - pushEntriesInt.setDisable(true); - pushEntriesEmpty.setDisable(true); - pushEntriesAdvanced.setDisable(true); - update.setDisable(true); - merge.setDisable(true); - unmerge.setDisable(true); - manageCitations.setDisable(true); - exportCitations.setDisable(true); + updateButtonAvailability(); HBox hbox = new HBox(); hbox.getChildren().addAll(connect, manualConnect, selectDocument, update, help); @@ -305,42 +255,18 @@ private void initPanel() { } private void exportEntries() { - try { - if (style == null) { - style = loader.getUsedStyle(); - } else { - style.ensureUpToDate(); - } - - ooBase.updateSortedReferenceMarks(); - - List databases = getBaseList(); - List unresolvedKeys = ooBase.refreshCiteMarkers(databases, style); - BibDatabase newDatabase = ooBase.generateDatabase(databases); - if (!unresolvedKeys.isEmpty()) { - dialogService.showErrorDialogAndWait(Localization.lang("Unable to generate new library"), - Localization.lang("Your OpenOffice/LibreOffice document references the citation key '%0', which could not be found in your current library.", - unresolvedKeys.get(0))); - } - - BibDatabaseContext databaseContext = new BibDatabaseContext(newDatabase); - + List databases = getBaseList(); + boolean returnPartialResult = false; + Optional newDatabase = ooBase.exportCitedHelper(databases, returnPartialResult); + if (newDatabase.isPresent()) { + BibDatabaseContext databaseContext = new BibDatabaseContext(newDatabase.get()); JabRefGUI.getMainFrame().addTab(databaseContext, true); - } catch (BibEntryNotFoundException ex) { - LOGGER.debug("BibEntry not found", ex); - dialogService.showErrorDialogAndWait(Localization.lang("Unable to synchronize bibliography"), - Localization.lang("Your OpenOffice/LibreOffice document references the citation key '%0', which could not be found in your current library.", - ex.getCitationKey())); - } catch (com.sun.star.lang.IllegalArgumentException | UnknownPropertyException | PropertyVetoException | - UndefinedCharacterFormatException | NoSuchElementException | WrappedTargetException | IOException | - CreationException e) { - LOGGER.warn("Problem generating new database.", e); } } private List getBaseList() { List databases = new ArrayList<>(); - if (ooPrefs.getUseAllDatabases()) { + if (openOfficePreferences.getUseAllDatabases()) { for (BibDatabaseContext database : stateManager.getOpenDatabases()) { databases.add(database.getDatabase()); } @@ -401,7 +327,6 @@ private void connectManually() { connect(); } else { dialogService.showErrorDialogAndWait(Localization.lang("Could not connect to running OpenOffice/LibreOffice."), Localization.lang("If connecting manually, please verify program and library paths.")); - } }) .executeWith(taskExecutor); @@ -410,8 +335,34 @@ private void connectManually() { } } + private void updateButtonAvailability() { + boolean isConnected = (ooBase != null); + boolean isConnectedToDocument = isConnected && !ooBase.isDocumentConnectionMissing(); + + // For these, we need to watch something + boolean hasStyle = true; // (style != null); + boolean hasDatabase = true; // !getBaseList().isEmpty(); + boolean hasSelectedBibEntry = true; + + selectDocument.setDisable(!(isConnected)); + pushEntries.setDisable(!(isConnectedToDocument && hasStyle && hasDatabase)); + + boolean canCite = isConnectedToDocument && hasStyle && hasSelectedBibEntry; + pushEntriesInt.setDisable(!canCite); + pushEntriesEmpty.setDisable(!canCite); + pushEntriesAdvanced.setDisable(!canCite); + + boolean canRefreshDocument = isConnectedToDocument && hasStyle; + update.setDisable(!canRefreshDocument); + merge.setDisable(!canRefreshDocument); + unmerge.setDisable(!canRefreshDocument); + manageCitations.setDisable(!canRefreshDocument); + + exportCitations.setDisable(!(isConnectedToDocument && hasDatabase)); + } + private void connect() { - ooPrefs = preferencesService.getOpenOfficePreferences(); + openOfficePreferences = preferencesService.getOpenOfficePreferences(); Task connectTask = new Task<>() { @@ -419,7 +370,7 @@ private void connect() { protected OOBibBase call() throws Exception { updateProgress(ProgressBar.INDETERMINATE_PROGRESS, ProgressBar.INDETERMINATE_PROGRESS); - var path = Path.of(ooPrefs.getExecutablePath()); + var path = Path.of(openOfficePreferences.getExecutablePath()); return createBibBase(path); } }; @@ -427,45 +378,28 @@ protected OOBibBase call() throws Exception { connectTask.setOnSucceeded(value -> { ooBase = connectTask.getValue(); - try { - ooBase.selectDocument(); - } catch (NoSuchElementException | WrappedTargetException | NoDocumentException ex) { - dialogService.showErrorDialogAndWait(Localization.lang("Error connecting to Writer document"), Localization.lang("You need to open Writer with a document before connecting"), ex); - LOGGER.error("Error connecting to writer document", ex); - } - - if (ooBase.isConnectedToDocument()) { - dialogService.notify(Localization.lang("Connected to document") + ": " + ooBase.getCurrentDocumentTitle().orElse("")); - } + ooBase.guiActionSelectDocument(true); // Enable actions that depend on Connect: - selectDocument.setDisable(false); - pushEntries.setDisable(false); - pushEntriesInt.setDisable(false); - pushEntriesEmpty.setDisable(false); - pushEntriesAdvanced.setDisable(false); - update.setDisable(false); - merge.setDisable(false); - unmerge.setDisable(false); - manageCitations.setDisable(false); - exportCitations.setDisable(false); + updateButtonAvailability(); }); + connectTask.setOnFailed(value -> { Throwable ex = connectTask.getException(); if (ex instanceof UnsatisfiedLinkError) { LOGGER.warn("Could not connect to running OpenOffice/LibreOffice", ex); dialogService.showErrorDialogAndWait(Localization.lang("Unable to connect. One possible reason is that JabRef " - + "and OpenOffice/LibreOffice are not both running in either 32 bit mode or 64 bit mode.")); + + "and OpenOffice/LibreOffice are not both running in either 32 bit mode or 64 bit mode.")); } else if (ex instanceof IOException) { LOGGER.warn("Could not connect to running OpenOffice/LibreOffice", ex); dialogService.showErrorDialogAndWait(Localization.lang("Could not connect to running OpenOffice/LibreOffice."), - Localization.lang("Could not connect to running OpenOffice/LibreOffice.") - + "\n" - + Localization.lang("Make sure you have installed OpenOffice/LibreOffice with Java support.") + "\n" - + Localization.lang("If connecting manually, please verify program and library paths.") + "\n" + "\n" + Localization.lang("Error message:"), - ex); + Localization.lang("Could not connect to running OpenOffice/LibreOffice.") + + "\n" + + Localization.lang("Make sure you have installed OpenOffice/LibreOffice with Java support.") + "\n" + + Localization.lang("If connecting manually, please verify program and library paths.") + "\n" + "\n" + Localization.lang("Error message:"), + ex); } else { dialogService.showErrorDialogAndWait(Localization.lang("Autodetection failed"), Localization.lang("Autodetection failed"), ex); } @@ -475,20 +409,59 @@ protected OOBibBase call() throws Exception { taskExecutor.execute(connectTask); } - private OOBibBase createBibBase(Path loPath) throws IOException, InvocationTargetException, IllegalAccessException, - BootstrapException, CreationException, ClassNotFoundException { - return new OOBibBase(loPath, true, dialogService); + private OOBibBase createBibBase(Path loPath) throws BootstrapException, CreationException { + return new OOBibBase(loPath, dialogService); + } + + /** + * Given the withText and inParenthesis options, return the corresponding citationType. + * + * @param withText False means invisible citation (no text). + * @param inParenthesis True means "(Au and Thor 2000)". False means "Au and Thor (2000)". + */ + private static CitationType citationTypeFromOptions(boolean withText, boolean inParenthesis) { + if (!withText) { + return CitationType.INVISIBLE_CIT; + } + return (inParenthesis + ? CitationType.AUTHORYEAR_PAR + : CitationType.AUTHORYEAR_INTEXT); } - private void pushEntries(boolean inParenthesisIn, boolean withText, boolean addPageInfo) { - if (!ooBase.isConnectedToDocument()) { - dialogService.showErrorDialogAndWait(Localization.lang("Error pushing entries"), Localization.lang("Not connected to any Writer document. Please" + " make sure a document is open, and use the 'Select Writer document' button to connect to it.")); + private void pushEntries(CitationType citationType, boolean addPageInfo) { + final String errorDialogTitle = Localization.lang("Error pushing entries"); + + if (stateManager.getActiveDatabase().isEmpty() + || (stateManager.getActiveDatabase().get().getDatabase() == null)) { + OOError.noDataBaseIsOpenForCiting() + .setTitle(errorDialogTitle) + .showErrorDialog(dialogService); + return; + } + + final BibDatabase database = stateManager.getActiveDatabase().get().getDatabase(); + if (database == null) { + OOError.noDataBaseIsOpenForCiting() + .setTitle(errorDialogTitle) + .showErrorDialog(dialogService); + return; + } + + List entries = stateManager.getSelectedEntries(); + if (entries.isEmpty()) { + OOError.noEntriesSelectedForCitation() + .setTitle(errorDialogTitle) + .showErrorDialog(dialogService); + return; + } + + if (getOrUpdateTheStyle(errorDialogTitle)) { return; } - Boolean inParenthesis = inParenthesisIn; String pageInfo = null; if (addPageInfo) { + boolean withText = citationType.withText(); Optional citeDialogViewModel = dialogService.showCustomDialogAndWait(new AdvancedCiteDialogView()); if (citeDialogViewModel.isPresent()) { @@ -497,43 +470,29 @@ private void pushEntries(boolean inParenthesisIn, boolean withText, boolean addP if (!model.pageInfoProperty().getValue().isEmpty()) { pageInfo = model.pageInfoProperty().getValue(); } - inParenthesis = model.citeInParProperty().getValue(); + citationType = citationTypeFromOptions(withText, model.citeInParProperty().getValue()); + } else { + // user canceled + return; } } - Optional databaseContext = stateManager.getActiveDatabase(); - if (databaseContext.isPresent()) { - final BibDatabase database = databaseContext.get().getDatabase(); - final List entries = stateManager.getSelectedEntries(); - if (!entries.isEmpty() && checkThatEntriesHaveKeys(entries)) { - - try { - if (style == null) { - style = loader.getUsedStyle(); - } - ooBase.insertEntry(entries, database, getBaseList(), style, inParenthesis, withText, pageInfo, - ooPrefs.getSyncWhenCiting()); - } catch (FileNotFoundException ex) { - - dialogService.showErrorDialogAndWait( - Localization.lang("No valid style file defined"), - Localization.lang("You must select either a valid style file, or use one of the default styles.")); - - LOGGER.warn("Problem with style file", ex); - } catch (ConnectionLostException ex) { - showConnectionLostErrorMessage(); - } catch (UndefinedCharacterFormatException ex) { - reportUndefinedCharacterFormat(ex); - } catch (UndefinedParagraphFormatException ex) { - reportUndefinedParagraphFormat(ex); - } catch (com.sun.star.lang.IllegalArgumentException | UnknownPropertyException | PropertyVetoException | - CreationException | NoSuchElementException | WrappedTargetException | IOException | - BibEntryNotFoundException | IllegalTypeException | PropertyExistException | - NotRemoveableException ex) { - LOGGER.warn("Could not insert entry", ex); - } - } + if (!checkThatEntriesHaveKeys(entries)) { + // Not all entries have keys and key generation was declined. + return; } + + Optional syncOptions = + (openOfficePreferences.getSyncWhenCiting() + ? Optional.of(new Update.SyncOptions(getBaseList())) + : Optional.empty()); + + ooBase.guiActionInsertEntry(entries, + database, + style, + citationType, + pageInfo, + syncOptions); } /** @@ -588,33 +547,12 @@ private boolean checkThatEntriesHaveKeys(List entries) { } } - private void showConnectionLostErrorMessage() { - dialogService.showErrorDialogAndWait(Localization.lang("Connection lost"), - Localization.lang("Connection to OpenOffice/LibreOffice has been lost. " + "Please make sure OpenOffice/LibreOffice is running, and try to reconnect.")); - } - - private void reportUndefinedParagraphFormat(UndefinedParagraphFormatException ex) { - dialogService.showErrorDialogAndWait(Localization.lang("Undefined paragraph format"), - Localization.lang("Your style file specifies the paragraph format '%0', " - + "which is undefined in your current OpenOffice/LibreOffice document.", - ex.getFormatName()) + "\n" + Localization.lang("The paragraph format is controlled by the property 'ReferenceParagraphFormat' or 'ReferenceHeaderParagraphFormat' in the style file.")); - } - - private void reportUndefinedCharacterFormat(UndefinedCharacterFormatException ex) { - dialogService.showErrorDialogAndWait(Localization.lang("Undefined character format"), - Localization.lang("Your style file specifies the character format '%0', " - + "which is undefined in your current OpenOffice/LibreOffice document.", - ex.getFormatName()) + "\n" + Localization.lang("The character format is controlled by the citation property 'CitationCharacterFormat' in the style file.") - - ); - } - private ContextMenu createSettingsPopup() { ContextMenu contextMenu = new ContextMenu(); CheckMenuItem autoSync = new CheckMenuItem(Localization.lang("Automatically sync bibliography when inserting citations")); - autoSync.selectedProperty().set(ooPrefs.getSyncWhenCiting()); + autoSync.selectedProperty().set(openOfficePreferences.getSyncWhenCiting()); ToggleGroup toggleGroup = new ToggleGroup(); RadioMenuItem useActiveBase = new RadioMenuItem(Localization.lang("Look up BibTeX entries in the active tab only")); @@ -624,31 +562,37 @@ private ContextMenu createSettingsPopup() { MenuItem clearConnectionSettings = new MenuItem(Localization.lang("Clear connection settings")); - if (ooPrefs.getUseAllDatabases()) { + if (openOfficePreferences.getUseAllDatabases()) { useAllBases.setSelected(true); } else { useActiveBase.setSelected(true); } autoSync.setOnAction(e -> { - ooPrefs.setSyncWhenCiting(autoSync.isSelected()); - preferencesService.setOpenOfficePreferences(ooPrefs); + openOfficePreferences.setSyncWhenCiting(autoSync.isSelected()); + preferencesService.setOpenOfficePreferences(openOfficePreferences); }); useAllBases.setOnAction(e -> { - ooPrefs.setUseAllDatabases(useAllBases.isSelected()); - preferencesService.setOpenOfficePreferences(ooPrefs); + openOfficePreferences.setUseAllDatabases(useAllBases.isSelected()); + preferencesService.setOpenOfficePreferences(openOfficePreferences); }); useActiveBase.setOnAction(e -> { - ooPrefs.setUseAllDatabases(!useActiveBase.isSelected()); - preferencesService.setOpenOfficePreferences(ooPrefs); + openOfficePreferences.setUseAllDatabases(!useActiveBase.isSelected()); + preferencesService.setOpenOfficePreferences(openOfficePreferences); }); clearConnectionSettings.setOnAction(e -> { - ooPrefs.clearConnectionSettings(); + openOfficePreferences.clearConnectionSettings(); dialogService.notify(Localization.lang("Cleared connection settings")); - preferencesService.setOpenOfficePreferences(ooPrefs); + preferencesService.setOpenOfficePreferences(openOfficePreferences); }); - contextMenu.getItems().addAll(autoSync, new SeparatorMenuItem(), useActiveBase, useAllBases, new SeparatorMenuItem(), clearConnectionSettings); + contextMenu.getItems().addAll( + autoSync, + new SeparatorMenuItem(), + useActiveBase, + useAllBases, + new SeparatorMenuItem(), + clearConnectionSettings); return contextMenu; } diff --git a/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java b/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java index 6792d2fbb8e..5435dda2abd 100644 --- a/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java +++ b/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java @@ -36,6 +36,7 @@ public class StyleSelectDialogView extends BaseDialog { private final MenuItem edit = new MenuItem(Localization.lang("Edit")); private final MenuItem reload = new MenuItem(Localization.lang("Reload")); private final StyleLoader loader; + @FXML private TableColumn colName; @FXML private TableView tvStyles; @FXML private TableColumn colJournals; diff --git a/src/main/java/org/jabref/gui/openoffice/UndefinedCharacterFormatException.java b/src/main/java/org/jabref/gui/openoffice/UndefinedCharacterFormatException.java deleted file mode 100644 index 4ab29ca2fa5..00000000000 --- a/src/main/java/org/jabref/gui/openoffice/UndefinedCharacterFormatException.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.jabref.gui.openoffice; - -/** - * Exception used to indicate that the plugin attempted to set a character format that is - * not defined in the current OpenOffice document. - */ -class UndefinedCharacterFormatException extends Exception { - - private final String formatName; - - public UndefinedCharacterFormatException(String formatName) { - super(); - this.formatName = formatName; - } - - public String getFormatName() { - return formatName; - } -} diff --git a/src/main/java/org/jabref/gui/preferences/general/GeneralTab.fxml b/src/main/java/org/jabref/gui/preferences/general/GeneralTab.fxml index 0fe621f75c2..73a010b459a 100644 --- a/src/main/java/org/jabref/gui/preferences/general/GeneralTab.fxml +++ b/src/main/java/org/jabref/gui/preferences/general/GeneralTab.fxml @@ -27,8 +27,6 @@

@@ -193,16 +182,11 @@ private Reader getReader(String filename) throws IOException { @Override public void export(final BibDatabaseContext databaseContext, final Path file, - final Charset encoding, List entries) throws Exception { + List entries) throws Exception { Objects.requireNonNull(databaseContext); Objects.requireNonNull(entries); Charset encodingToUse = StandardCharsets.UTF_8; - if (encoding != null) { - encodingToUse = encoding; - } else if (this.encodingOverwritten != null) { - encodingToUse = this.encodingOverwritten; - } if (entries.isEmpty()) { // Do not export if no entries to export -- avoids exports with only template text return; diff --git a/src/main/java/org/jabref/logic/exporter/XmpExporter.java b/src/main/java/org/jabref/logic/exporter/XmpExporter.java index ee52b9e3fbf..49dce5cbd3b 100644 --- a/src/main/java/org/jabref/logic/exporter/XmpExporter.java +++ b/src/main/java/org/jabref/logic/exporter/XmpExporter.java @@ -2,7 +2,7 @@ import java.io.BufferedWriter; import java.io.IOException; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.Collections; @@ -35,11 +35,10 @@ public XmpExporter(XmpPreferences xmpPreferences) { /** * @param databaseContext the database to export from * @param file the file to write to. If it contains "split", then the output is split into different files - * @param encoding the encoding to use * @param entries a list containing all entries that should be exported */ @Override - public void export(BibDatabaseContext databaseContext, Path file, Charset encoding, List entries) throws Exception { + public void export(BibDatabaseContext databaseContext, Path file, List entries) throws Exception { Objects.requireNonNull(databaseContext); Objects.requireNonNull(file); Objects.requireNonNull(entries); @@ -60,16 +59,16 @@ public void export(BibDatabaseContext databaseContext, Path file, Charset encodi } else { entryFile = Path.of(file.getParent().toString() + "/" + suffix); } - this.writeBibToXmp(entryFile, Collections.singletonList(entry), encoding); + this.writeBibToXmp(entryFile, Collections.singletonList(entry)); } } else { - this.writeBibToXmp(file, entries, encoding); + this.writeBibToXmp(file, entries); } } - private void writeBibToXmp(Path file, List entries, Charset encoding) throws IOException { + private void writeBibToXmp(Path file, List entries) throws IOException { String xmpContent = XmpUtilWriter.generateXmpStringWithoutXmpDeclaration(entries, this.xmpPreferences); - try (BufferedWriter writer = Files.newBufferedWriter(file, encoding)) { + try (BufferedWriter writer = Files.newBufferedWriter(file, StandardCharsets.UTF_8)) { writer.write(xmpContent); writer.flush(); } diff --git a/src/main/java/org/jabref/logic/exporter/XmpPdfExporter.java b/src/main/java/org/jabref/logic/exporter/XmpPdfExporter.java index 1b62a4f7b4f..397ee70f1d8 100644 --- a/src/main/java/org/jabref/logic/exporter/XmpPdfExporter.java +++ b/src/main/java/org/jabref/logic/exporter/XmpPdfExporter.java @@ -1,6 +1,5 @@ package org.jabref.logic.exporter; -import java.nio.charset.Charset; import java.nio.file.Path; import java.util.List; import java.util.Objects; @@ -22,8 +21,7 @@ public XmpPdfExporter(XmpPreferences xmpPreferences) { } @Override - public void export(BibDatabaseContext databaseContext, Path pdfFile, Charset encoding, List entries) throws Exception { - + public void export(BibDatabaseContext databaseContext, Path pdfFile, List entries) throws Exception { Objects.requireNonNull(databaseContext); Objects.requireNonNull(pdfFile); Objects.requireNonNull(entries); diff --git a/src/main/java/org/jabref/logic/externalfiles/ExternalFilesContentImporter.java b/src/main/java/org/jabref/logic/externalfiles/ExternalFilesContentImporter.java index b990eb36b29..3158a96652e 100644 --- a/src/main/java/org/jabref/logic/externalfiles/ExternalFilesContentImporter.java +++ b/src/main/java/org/jabref/logic/externalfiles/ExternalFilesContentImporter.java @@ -1,7 +1,6 @@ package org.jabref.logic.externalfiles; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import org.jabref.logic.importer.ImportFormatPreferences; @@ -26,13 +25,13 @@ public ExternalFilesContentImporter(GeneralPreferences generalPreferences, Impor public ParserResult importPDFContent(Path file) { try { - return new PdfMergeMetadataImporter(importerPreferences, importFormatPreferences).importDatabase(file, StandardCharsets.UTF_8); + return new PdfMergeMetadataImporter(importerPreferences, importFormatPreferences).importDatabase(file); } catch (IOException e) { return ParserResult.fromError(e); } } public ParserResult importFromBibFile(Path bibFile, FileUpdateMonitor fileUpdateMonitor) throws IOException { - return OpenDatabase.loadDatabase(bibFile, generalPreferences, importFormatPreferences, fileUpdateMonitor); + return OpenDatabase.loadDatabase(bibFile, importFormatPreferences, fileUpdateMonitor); } } diff --git a/src/main/java/org/jabref/logic/importer/EntryBasedFetcher.java b/src/main/java/org/jabref/logic/importer/EntryBasedFetcher.java index a85c8468060..781a0ed6288 100644 --- a/src/main/java/org/jabref/logic/importer/EntryBasedFetcher.java +++ b/src/main/java/org/jabref/logic/importer/EntryBasedFetcher.java @@ -6,7 +6,7 @@ /** * Searches web resources for bibliographic information based on a {@link BibEntry}. - * Useful to complete an existing entry with fetched information. + * Useful to complete an existing entry with fetched information. * May return multiple search hits. */ public interface EntryBasedFetcher extends WebFetcher { diff --git a/src/main/java/org/jabref/logic/importer/IdBasedFetcher.java b/src/main/java/org/jabref/logic/importer/IdBasedFetcher.java index 0238ef6b89a..62caee59199 100644 --- a/src/main/java/org/jabref/logic/importer/IdBasedFetcher.java +++ b/src/main/java/org/jabref/logic/importer/IdBasedFetcher.java @@ -6,6 +6,7 @@ /** * Searches web resources for bibliographic information based on an identifier. + * Examples are ISBN numbers and DOIs. */ public interface IdBasedFetcher extends WebFetcher { diff --git a/src/main/java/org/jabref/logic/importer/ImportFormatReader.java b/src/main/java/org/jabref/logic/importer/ImportFormatReader.java index e7c10b96f09..66543bd6ef3 100644 --- a/src/main/java/org/jabref/logic/importer/ImportFormatReader.java +++ b/src/main/java/org/jabref/logic/importer/ImportFormatReader.java @@ -115,7 +115,7 @@ public ParserResult importFromFile(String format, Path file) throws ImportExcept } try { - return importer.get().importDatabase(file, generalPreferences.getDefaultEncoding()); + return importer.get().importDatabase(file); } catch (IOException e) { throw new ImportException(e); } @@ -182,13 +182,13 @@ public UnknownFormatImport importUnknownFormat(Path filePath, FileUpdateMonitor Objects.requireNonNull(filePath); try { - UnknownFormatImport unknownFormatImport = importUnknownFormat(importer -> importer.importDatabase(filePath, generalPreferences.getDefaultEncoding()), importer -> importer.isRecognizedFormat(filePath, generalPreferences.getDefaultEncoding())); + UnknownFormatImport unknownFormatImport = importUnknownFormat(importer -> importer.importDatabase(filePath), importer -> importer.isRecognizedFormat(filePath)); unknownFormatImport.parserResult.setPath(filePath); return unknownFormatImport; } catch (ImportException e) { // If all importers fail, try to read the file as BibTeX try { - ParserResult parserResult = OpenDatabase.loadDatabase(filePath, generalPreferences, importFormatPreferences, fileMonitor); + ParserResult parserResult = OpenDatabase.loadDatabase(filePath, importFormatPreferences, fileMonitor); if (parserResult.getDatabase().hasEntries() || !parserResult.getDatabase().hasNoStrings()) { parserResult.setPath(filePath); return new UnknownFormatImport(ImportFormatReader.BIBTEX_FORMAT, parserResult); diff --git a/src/main/java/org/jabref/logic/importer/Importer.java b/src/main/java/org/jabref/logic/importer/Importer.java index 1c790537677..4b1797e949b 100644 --- a/src/main/java/org/jabref/logic/importer/Importer.java +++ b/src/main/java/org/jabref/logic/importer/Importer.java @@ -1,5 +1,6 @@ package org.jabref.logic.importer; +import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -10,16 +11,25 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; +import java.util.Arrays; import java.util.Objects; import org.jabref.logic.util.FileType; +import org.jabref.logic.util.io.FileUtil; import org.jabref.model.database.BibDatabaseModeDetection; +import com.ibm.icu.text.CharsetDetector; +import com.ibm.icu.text.CharsetMatch; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Role of an importer for JabRef. */ public abstract class Importer implements Comparable { + private static final Logger LOGGER = LoggerFactory.getLogger(Importer.class); + /** * Check whether the source is in the correct format for this importer. *

@@ -35,12 +45,11 @@ public abstract class Importer implements Comparable { * Check whether the source is in the correct format for this importer. * * @param filePath the path of the file to check - * @param encoding the encoding of the file * @return true, if the file is in a recognized format * @throws IOException Signals that an I/O exception has occurred. */ - public boolean isRecognizedFormat(Path filePath, Charset encoding) throws IOException { - try (BufferedReader bufferedReader = getReader(filePath, encoding)) { + public boolean isRecognizedFormat(Path filePath) throws IOException { + try (BufferedReader bufferedReader = getReader(filePath)) { return isRecognizedFormat(bufferedReader); } } @@ -76,17 +85,21 @@ public boolean isRecognizedFormat(String data) throws IOException { /** * Parse the database in the specified file. - *

- * Importer having the facilities to detect the correct encoding of a file should overwrite this method, determine - * the encoding and then call {@link #importDatabase(BufferedReader)}. * * @param filePath the path to the file which should be imported - * @param encoding the encoding used to decode the file */ - public ParserResult importDatabase(Path filePath, Charset encoding) throws IOException { - try (BufferedReader bufferedReader = getReader(filePath, encoding)) { + public ParserResult importDatabase(Path filePath) throws IOException { + try (InputStream inputStream = Files.newInputStream(filePath, StandardOpenOption.READ)) { + BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream); + + Charset charset = StandardCharsets.UTF_8; + + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(bufferedInputStream, charset)); ParserResult parserResult = importDatabase(bufferedReader); - parserResult.getMetaData().setEncoding(encoding); + + // store the detected encoding + parserResult.getMetaData().setEncoding(charset); + parserResult.setPath(filePath); // Make sure the mode is always set @@ -97,6 +110,36 @@ public ParserResult importDatabase(Path filePath, Charset encoding) throws IOExc } } + protected static Charset getCharset(BufferedInputStream bufferedInputStream) { + Charset defaultCharSet = StandardCharsets.UTF_8; + + // This reads the first 8000 bytes only, thus the default size of 8192 of the bufferedInputStream is OK. + // See https://github.com/unicode-org/icu/blob/06ef8867f35befee7340e35082fefc9d3561d230/icu4j/main/classes/core/src/com/ibm/icu/text/CharsetDetector.java#L125 for details + CharsetDetector charsetDetector = new CharsetDetector(); + try { + charsetDetector.setText(bufferedInputStream); + + CharsetMatch[] matches = charsetDetector.detectAll(); + if ((matches == null) || (matches.length == 0)) { + return defaultCharSet; + } + if (Arrays.stream(matches).anyMatch(singleCharset -> singleCharset.getName().equals(defaultCharSet.toString()))) { + return defaultCharSet; + } + if (Arrays.stream(matches).anyMatch(singleCharset -> singleCharset.getName().equals(StandardCharsets.UTF_16.toString()))) { + return StandardCharsets.UTF_16; + } + + if (matches[0] != null) { + return Charset.forName(matches[0].getName()); + } + + } catch (IOException e) { + LOGGER.error("Could not determine charset. Using default one.", e); + } + return defaultCharSet; + } + /** * Parse the database in the specified string. *

@@ -114,18 +157,22 @@ public ParserResult importDatabase(String data) throws IOException { } } - protected static BufferedReader getUTF8Reader(Path filePath) throws IOException { - return getReader(filePath, StandardCharsets.UTF_8); - } + public static BufferedReader getReader(Path filePath) throws IOException { + InputStream stream = Files.newInputStream(filePath, StandardOpenOption.READ); + + if (FileUtil.isBibFile(filePath)) { + return getReader(stream); + } + + return new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8)); - protected static BufferedReader getUTF16Reader(Path filePath) throws IOException { - return getReader(filePath, StandardCharsets.UTF_16); } - public static BufferedReader getReader(Path filePath, Charset encoding) - throws IOException { - InputStream stream = Files.newInputStream(filePath, StandardOpenOption.READ); - return new BufferedReader(new InputStreamReader(stream, encoding)); + public static BufferedReader getReader(InputStream stream) throws IOException { + BufferedInputStream bufferedInputStream = new BufferedInputStream(stream); + Charset charset = getCharset(bufferedInputStream); + InputStreamReader reader = new InputStreamReader(bufferedInputStream, charset); + return new BufferedReader(reader); } /** diff --git a/src/main/java/org/jabref/logic/importer/OpenDatabase.java b/src/main/java/org/jabref/logic/importer/OpenDatabase.java index bbc4796a22d..f5e2fc1cd9c 100644 --- a/src/main/java/org/jabref/logic/importer/OpenDatabase.java +++ b/src/main/java/org/jabref/logic/importer/OpenDatabase.java @@ -11,7 +11,6 @@ import org.jabref.migrations.PostOpenMigration; import org.jabref.migrations.SpecialFieldsToSeparateFields; import org.jabref.model.util.FileUpdateMonitor; -import org.jabref.preferences.GeneralPreferences; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -29,10 +28,9 @@ private OpenDatabase() { * @param fileToOpen Name of the BIB-file to open * @return ParserResult which never is null */ - public static ParserResult loadDatabase(Path fileToOpen, GeneralPreferences generalPreferences, ImportFormatPreferences importFormatPreferences, FileUpdateMonitor fileMonitor) + public static ParserResult loadDatabase(Path fileToOpen, ImportFormatPreferences importFormatPreferences, FileUpdateMonitor fileMonitor) throws IOException { - ParserResult result = new BibtexImporter(importFormatPreferences, fileMonitor).importDatabase(fileToOpen, - generalPreferences.getDefaultEncoding()); + ParserResult result = new BibtexImporter(importFormatPreferences, fileMonitor).importDatabase(fileToOpen); performLoadDatabaseMigrations(result, importFormatPreferences.getKeywordSeparator()); diff --git a/src/main/java/org/jabref/logic/importer/SearchBasedFetcher.java b/src/main/java/org/jabref/logic/importer/SearchBasedFetcher.java index 8e3e3d75533..34858548f7e 100644 --- a/src/main/java/org/jabref/logic/importer/SearchBasedFetcher.java +++ b/src/main/java/org/jabref/logic/importer/SearchBasedFetcher.java @@ -15,6 +15,9 @@ /** * Searches web resources for bibliographic information based on a free-text query. * May return multiple search hits. + *

+ * This interface is used for web resources which directly return BibTeX data ({@link BibEntry}) + *

*/ public interface SearchBasedFetcher extends WebFetcher { diff --git a/src/main/java/org/jabref/logic/importer/SearchBasedParserFetcher.java b/src/main/java/org/jabref/logic/importer/SearchBasedParserFetcher.java index 9aadba697b9..1d9c2882acf 100644 --- a/src/main/java/org/jabref/logic/importer/SearchBasedParserFetcher.java +++ b/src/main/java/org/jabref/logic/importer/SearchBasedParserFetcher.java @@ -13,12 +13,25 @@ import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode; /** - * Provides a convenient interface for search-based fetcher, which follow the usual three-step procedure: + * Provides a convenient interface for search-based fetcher, which follows the usual three-step procedure: *
    *
  1. Open a URL based on the search query
  2. *
  3. Parse the response to get a list of {@link BibEntry}
  4. *
  5. Post-process fetched entries
  6. *
+ *

+ * This interface is used for web resources which do NOT provide BibTeX data {@link BibEntry}. + * JabRef's infrastructure to convert arbitrary input data to BibTeX is {@link Parser}. + *

+ *

+ * This interface inherits {@link SearchBasedFetcher}, because the methods performSearch have to be provided by both. + * As non-BibTeX web fetcher one could do "magic" stuff without this helper interface and directly use {@link WebFetcher}, but this is more work. + *

+ *

+ * Note that this interface "should" be an abstract class. + * However, Java does not support multi inheritance with classes (but with interfaces). + * We need multi inheritance, because a fetcher might implement multiple query types (such as id fetching {@link IdBasedFetcher}), complete entry {@link EntryBasedFetcher}, and search-based fetcher (this class). + *

*/ public interface SearchBasedParserFetcher extends SearchBasedFetcher { diff --git a/src/main/java/org/jabref/logic/importer/WebFetchers.java b/src/main/java/org/jabref/logic/importer/WebFetchers.java index efe64b8b3a7..8aee89ee09e 100644 --- a/src/main/java/org/jabref/logic/importer/WebFetchers.java +++ b/src/main/java/org/jabref/logic/importer/WebFetchers.java @@ -1,6 +1,5 @@ package org.jabref.logic.importer; -import java.nio.charset.Charset; import java.util.Comparator; import java.util.HashSet; import java.util.Optional; @@ -137,7 +136,7 @@ public static SortedSet getIdBasedFetchers(ImportFormatPreferenc /** * @return sorted set containing entry based fetchers */ - public static SortedSet getEntryBasedFetchers(ImporterPreferences importerPreferences, ImportFormatPreferences importFormatPreferences, FilePreferences filePreferences, BibDatabaseContext databaseContext, Charset defaultEncoding) { + public static SortedSet getEntryBasedFetchers(ImporterPreferences importerPreferences, ImportFormatPreferences importFormatPreferences, FilePreferences filePreferences, BibDatabaseContext databaseContext) { SortedSet set = new TreeSet<>(Comparator.comparing(WebFetcher::getName)); set.add(new AstrophysicsDataSystem(importFormatPreferences)); set.add(new DoiFetcher(importFormatPreferences)); @@ -145,7 +144,7 @@ public static SortedSet getEntryBasedFetchers(ImporterPrefere set.add(new MathSciNet(importFormatPreferences)); set.add(new CrossRef()); set.add(new ZbMATH(importFormatPreferences)); - set.add(new PdfMergeMetadataImporter.EntryBasedFetcherWrapper(importerPreferences, importFormatPreferences, filePreferences, databaseContext, defaultEncoding)); + set.add(new PdfMergeMetadataImporter.EntryBasedFetcherWrapper(importerPreferences, importFormatPreferences, filePreferences, databaseContext)); return set; } diff --git a/src/main/java/org/jabref/logic/importer/fileformat/ACMPortalParser.java b/src/main/java/org/jabref/logic/importer/fileformat/ACMPortalParser.java index 0e46e834134..9a345ec595a 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/ACMPortalParser.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/ACMPortalParser.java @@ -71,8 +71,8 @@ public List parseDoiSearchPage(InputStream stream) throws ParseException Elements doiHrefs = doc.select("div.issue-item__content-right > h5 > span > a"); for (Element elem : doiHrefs) { - String fullSegement = elem.attr("href"); - String doi = fullSegement.substring(fullSegement.indexOf("10")); + String fullSegment = elem.attr("href"); + String doi = fullSegment.substring(fullSegment.indexOf("10")); doiList.add(doi); } } catch (IOException ex) { diff --git a/src/main/java/org/jabref/logic/importer/fileformat/BibtexImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/BibtexImporter.java index c3d09baa057..e35fe6c73ad 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/BibtexImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/BibtexImporter.java @@ -1,8 +1,11 @@ package org.jabref.logic.importer.fileformat; +import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStream; import java.nio.charset.Charset; +import java.nio.file.Files; import java.nio.file.Path; import java.util.Objects; import java.util.Optional; @@ -12,13 +15,19 @@ import org.jabref.logic.importer.Importer; import org.jabref.logic.importer.ParserResult; import org.jabref.logic.util.StandardFileType; +import org.jabref.model.database.BibDatabaseModeDetection; import org.jabref.model.util.FileUpdateMonitor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * This is a full class to read .bib files. It is used for --import and --importToOpen , too. */ public class BibtexImporter extends Importer { + private static final Logger LOGGER = LoggerFactory.getLogger(BibtexImporter.class); + // Signature written at the top of the .bib file in earlier versions. private static final String SIGNATURE = "This file was created with JabRef"; @@ -41,30 +50,48 @@ public boolean isRecognizedFormat(BufferedReader reader) { } @Override - public ParserResult importDatabase(Path filePath, Charset defaultEncoding) throws IOException { - // We want to check if there is a JabRef signature in the file, because that would tell us - // which character encoding is used. However, to read the signature we must be using a compatible - // encoding in the first place. Since the signature doesn't contain any fancy characters, we can - // read it regardless of encoding, with either UTF-8 or UTF-16. That's the hypothesis, at any rate. - // 8 bit is most likely, so we try that first: - Optional suppliedEncoding; - try (BufferedReader utf8Reader = getUTF8Reader(filePath)) { - suppliedEncoding = getSuppliedEncoding(utf8Reader); + public ParserResult importDatabase(Path filePath) throws IOException { + // We want to check if there is a JabRef encoding heading in the file, because that would tell us + // which character encoding is used. + + // In general, we have to use InputStream and not a Reader, because a Reader requires an encoding specification. + // We do not want to do a byte-by-byte reading or doing wild try/catch magic. + // We therefore use a charset detection library and then read JabRefs "% Encoding" mark + + Charset detectedCharset; + try (InputStream inputStream = Files.newInputStream(filePath)) { + BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream); + bufferedInputStream.mark(8192); + detectedCharset = getCharset(bufferedInputStream); + bufferedInputStream.reset(); + LOGGER.debug("Detected charset: {}", detectedCharset.name()); } - // Now if that did not get us anywhere, we check with the 16 bit encoding: - if (!suppliedEncoding.isPresent()) { - try (BufferedReader utf16Reader = getUTF16Reader(filePath)) { - suppliedEncoding = getSuppliedEncoding(utf16Reader); - } + + Charset encoding; + try (BufferedReader reader = Files.newBufferedReader(filePath, detectedCharset)) { + Optional suppliedEncoding = getSuppliedEncoding(reader); + LOGGER.debug("Supplied encoding: {}", suppliedEncoding); + + // in case no encoding information is present, use the detected one + encoding = suppliedEncoding.orElse(detectedCharset); + LOGGER.debug("Encoding used to read the file: {}", encoding); } - if (suppliedEncoding.isPresent()) { - return super.importDatabase(filePath, suppliedEncoding.get()); - } else { - return super.importDatabase(filePath, defaultEncoding); + try (BufferedReader reader = Files.newBufferedReader(filePath, encoding)) { + ParserResult parserResult = this.importDatabase(reader); + parserResult.getMetaData().setEncoding(encoding); + parserResult.setPath(filePath); + if (parserResult.getMetaData().getMode().isEmpty()) { + parserResult.getMetaData().setMode(BibDatabaseModeDetection.inferMode(parserResult.getDatabase())); + } + return parserResult; } } + /** + * This method does not set the metadata encoding information. The caller needs to set the encoding of the supplied + * reader manually to the meta data + */ @Override public ParserResult importDatabase(BufferedReader reader) throws IOException { return new BibtexParser(importFormatPreferences, fileMonitor).parse(reader); @@ -122,7 +149,7 @@ private static Optional getSuppliedEncoding(BufferedReader reader) { } } } catch (IOException ignored) { - // Ignored + LOGGER.error("Supplied encoding could not be determined", ignored); } return Optional.empty(); } diff --git a/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java b/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java index b2bc701cb87..a91de73f69e 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java @@ -1,13 +1,10 @@ package org.jabref.logic.importer.fileformat; -import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.io.PushbackReader; import java.io.Reader; import java.io.StringWriter; -import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.Deque; import java.util.HashMap; @@ -26,6 +23,7 @@ import org.jabref.logic.exporter.BibtexDatabaseWriter; import org.jabref.logic.exporter.SavePreferences; import org.jabref.logic.importer.ImportFormatPreferences; +import org.jabref.logic.importer.Importer; import org.jabref.logic.importer.ParseException; import org.jabref.logic.importer.Parser; import org.jabref.logic.importer.ParserResult; @@ -109,12 +107,9 @@ public static Optional singleFromString(String bibtexString, ImportFor @Override public List parseEntries(InputStream inputStream) throws ParseException { - BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); - return parseEntries(reader); - } - - public List parseEntries(Reader reader) throws ParseException { + Reader reader; try { + reader = Importer.getReader(inputStream); return parse(reader).getDatabase().getEntries(); } catch (IOException e) { throw new ParseException(e); @@ -126,11 +121,13 @@ public Optional parseSingleEntry(String bibtexString) throws ParseExce } /** - * Parses BibTeX data found when reading from reader. Ignores any encoding supplied in the file by "Encoding: myEncoding". + * Parses BibTeX data found when reading from reader. *

* The reader will be consumed. *

* Multiple calls to parse() return the same results + *

+ * Handling of encoding is done at {@link BibtexImporter} */ public ParserResult parse(Reader in) throws IOException { Objects.requireNonNull(in); @@ -215,7 +212,7 @@ private ParserResult parseFileContent() throws IOException { database.setPreamble(parsePreamble()); // Consume a new line which separates the preamble from the next part (if the file was written with JabRef) skipOneNewline(); - // the preamble is saved verbatim anyways, so the text read so far can be dropped + // the preamble is saved verbatim anyway, so the text read so far can be dropped dumpTextReadSoFarToString(); } else if ("string".equals(entryType)) { parseBibtexString(); @@ -229,7 +226,7 @@ private ParserResult parseFileContent() throws IOException { skipWhitespace(); } - // Instantiate meta data: + // Instantiate meta data try { parserResult.setMetaData(metaDataParser.parse(meta, importFormatPreferences.getKeywordSeparator())); } catch (ParseException exception) { @@ -369,8 +366,13 @@ private String dumpTextReadSoFarToString() { } } + /** + * Purges the given stringToPurge (if it exists) from the given context + * + * @return a stripped version of the context + */ private String purge(String context, String stringToPurge) { - // purge the encoding line if it exists + // purge the given string line if it exists int runningIndex = context.indexOf(stringToPurge); int indexOfAt = context.indexOf("@"); while (runningIndex < indexOfAt) { diff --git a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java index a82e8bf71cc..168fc291bbc 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/EndnoteXmlImporter.java @@ -310,7 +310,7 @@ private List getKeywords(Record record) { .stream() .map(keyword -> keyword.getStyle()) .filter(Objects::nonNull) - .map(style->style.getContent()) + .map(style -> style.getContent()) .collect(Collectors.toList()); } else { return Collections.emptyList(); diff --git a/src/main/java/org/jabref/logic/importer/fileformat/PdfContentImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/PdfContentImporter.java index f9f6cd9ed74..88a0ed54006 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/PdfContentImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/PdfContentImporter.java @@ -3,7 +3,6 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.StringWriter; -import java.nio.charset.Charset; import java.nio.file.Path; import java.util.ArrayList; import java.util.Locale; @@ -199,7 +198,7 @@ public ParserResult importDatabase(String data) throws IOException { } @Override - public ParserResult importDatabase(Path filePath, Charset defaultEncoding) { + public ParserResult importDatabase(Path filePath) { final ArrayList result = new ArrayList<>(1); try (PDDocument document = XmpUtilReader.loadWithAutomaticDecryption(filePath)) { String firstPageContents = getFirstPageContents(document); diff --git a/src/main/java/org/jabref/logic/importer/fileformat/PdfEmbeddedBibFileImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/PdfEmbeddedBibFileImporter.java index f6e6b0ba4f4..b1071d0df01 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/PdfEmbeddedBibFileImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/PdfEmbeddedBibFileImporter.java @@ -2,7 +2,6 @@ import java.io.BufferedReader; import java.io.IOException; -import java.nio.charset.Charset; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -64,7 +63,7 @@ public ParserResult importDatabase(String data) throws IOException { } @Override - public ParserResult importDatabase(Path filePath, Charset defaultEncoding) { + public ParserResult importDatabase(Path filePath) { try (PDDocument document = XmpUtilReader.loadWithAutomaticDecryption(filePath)) { return new ParserResult(getEmbeddedBibFileEntries(document)); } catch (EncryptedPdfsNotSupportedException e) { diff --git a/src/main/java/org/jabref/logic/importer/fileformat/PdfGrobidImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/PdfGrobidImporter.java index 6b680640d1a..9312838ade0 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/PdfGrobidImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/PdfGrobidImporter.java @@ -2,7 +2,6 @@ import java.io.BufferedReader; import java.io.IOException; -import java.nio.charset.Charset; import java.nio.file.Path; import java.util.List; import java.util.Objects; @@ -58,7 +57,7 @@ public ParserResult importDatabase(String data) throws IOException { } @Override - public ParserResult importDatabase(Path filePath, Charset defaultEncoding) { + public ParserResult importDatabase(Path filePath) { Objects.requireNonNull(filePath); try { List result = grobidService.processPDF(filePath, importFormatPreferences); @@ -80,7 +79,7 @@ public boolean isRecognizedFormat(BufferedReader reader) throws IOException { * contains at least one BibEntry. */ @Override - public boolean isRecognizedFormat(Path filePath, Charset defaultEncoding) throws IOException { + public boolean isRecognizedFormat(Path filePath) throws IOException { Objects.requireNonNull(filePath); Optional extension = FileHelper.getFileExtension(filePath); if (extension.isEmpty()) { diff --git a/src/main/java/org/jabref/logic/importer/fileformat/PdfMergeMetadataImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/PdfMergeMetadataImporter.java index 9d8e62cd08a..a53ff26d6b3 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/PdfMergeMetadataImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/PdfMergeMetadataImporter.java @@ -2,7 +2,6 @@ import java.io.BufferedReader; import java.io.IOException; -import java.nio.charset.Charset; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -74,11 +73,11 @@ public ParserResult importDatabase(String data) throws IOException { } @Override - public ParserResult importDatabase(Path filePath, Charset defaultEncoding) throws IOException { + public ParserResult importDatabase(Path filePath) throws IOException { List candidates = new ArrayList<>(); for (Importer metadataImporter : metadataImporters) { - List extractedEntries = metadataImporter.importDatabase(filePath, defaultEncoding).getDatabase().getEntries(); + List extractedEntries = metadataImporter.importDatabase(filePath).getDatabase().getEntries(); if (extractedEntries.size() == 0) { continue; } @@ -149,13 +148,11 @@ public static class EntryBasedFetcherWrapper extends PdfMergeMetadataImporter im private static final Logger LOGGER = LoggerFactory.getLogger(DefaultInjector.class); private final FilePreferences filePreferences; private final BibDatabaseContext databaseContext; - private final Charset defaultEncoding; - public EntryBasedFetcherWrapper(ImporterPreferences importerPreferences, ImportFormatPreferences importFormatPreferences, FilePreferences filePreferences, BibDatabaseContext context, Charset defaultEncoding) { + public EntryBasedFetcherWrapper(ImporterPreferences importerPreferences, ImportFormatPreferences importFormatPreferences, FilePreferences filePreferences, BibDatabaseContext context) { super(importerPreferences, importFormatPreferences); this.filePreferences = filePreferences; this.databaseContext = context; - this.defaultEncoding = defaultEncoding; } @Override @@ -164,7 +161,7 @@ public List performSearch(BibEntry entry) throws FetcherException { Optional filePath = file.findIn(databaseContext, filePreferences); if (filePath.isPresent()) { try { - ParserResult result = importDatabase(filePath.get(), defaultEncoding); + ParserResult result = importDatabase(filePath.get()); if (!result.isEmpty()) { return result.getDatabase().getEntries(); } diff --git a/src/main/java/org/jabref/logic/importer/fileformat/PdfVerbatimBibTextImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/PdfVerbatimBibTextImporter.java index 60405b76f33..1f105a12e5b 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/PdfVerbatimBibTextImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/PdfVerbatimBibTextImporter.java @@ -3,7 +3,6 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.StringWriter; -import java.nio.charset.Charset; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -55,7 +54,7 @@ public ParserResult importDatabase(String data) throws IOException { } @Override - public ParserResult importDatabase(Path filePath, Charset defaultEncoding) { + public ParserResult importDatabase(Path filePath) { List result = new ArrayList<>(1); try (PDDocument document = XmpUtilReader.loadWithAutomaticDecryption(filePath)) { String firstPageContents = getFirstPageContents(document); diff --git a/src/main/java/org/jabref/logic/importer/fileformat/PdfXmpImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/PdfXmpImporter.java index ff653e81028..470d6756fc8 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/PdfXmpImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/PdfXmpImporter.java @@ -2,7 +2,6 @@ import java.io.BufferedReader; import java.io.IOException; -import java.nio.charset.Charset; import java.nio.file.Path; import java.util.Objects; @@ -52,7 +51,7 @@ public ParserResult importDatabase(String data) throws IOException { } @Override - public ParserResult importDatabase(Path filePath, Charset defaultEncoding) { + public ParserResult importDatabase(Path filePath) { Objects.requireNonNull(filePath); try { return new ParserResult(XmpUtilReader.readXmp(filePath, xmpPreferences)); @@ -72,7 +71,7 @@ public boolean isRecognizedFormat(BufferedReader reader) throws IOException { * contains at least one BibEntry. */ @Override - public boolean isRecognizedFormat(Path filePath, Charset defaultEncoding) throws IOException { + public boolean isRecognizedFormat(Path filePath) throws IOException { Objects.requireNonNull(filePath); return XmpUtilShared.hasMetadata(filePath, xmpPreferences); } diff --git a/src/main/java/org/jabref/logic/integrity/IntegrityCheck.java b/src/main/java/org/jabref/logic/integrity/IntegrityCheck.java index 389c04b24eb..6de2d71eb4f 100644 --- a/src/main/java/org/jabref/logic/integrity/IntegrityCheck.java +++ b/src/main/java/org/jabref/logic/integrity/IntegrityCheck.java @@ -1,6 +1,6 @@ package org.jabref.logic.integrity; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -21,7 +21,6 @@ public class IntegrityCheck { public IntegrityCheck(BibDatabaseContext bibDatabaseContext, FilePreferences filePreferences, CitationKeyPatternPreferences citationKeyPatternPreferences, - Charset defaultEncoding, JournalAbbreviationRepository journalAbbreviationRepository, boolean allowIntegerEdition) { this.bibDatabaseContext = bibDatabaseContext; @@ -43,7 +42,7 @@ public IntegrityCheck(BibDatabaseContext bibDatabaseContext, if (bibDatabaseContext.isBiblatexMode()) { entryCheckers.addAll(List.of( new JournalInAbbreviationListChecker(StandardField.JOURNALTITLE, journalAbbreviationRepository), - new UTF8Checker(bibDatabaseContext.getMetaData().getEncoding().orElse(defaultEncoding)) + new UTF8Checker(bibDatabaseContext.getMetaData().getEncoding().orElse(StandardCharsets.UTF_8)) )); } else { entryCheckers.addAll(List.of( diff --git a/src/main/java/org/jabref/logic/l10n/Language.java b/src/main/java/org/jabref/logic/l10n/Language.java index 0711cd25d9e..1841d10f73e 100644 --- a/src/main/java/org/jabref/logic/l10n/Language.java +++ b/src/main/java/org/jabref/logic/l10n/Language.java @@ -9,7 +9,7 @@ */ public enum Language { - BAHASA_INDONESIA("Bahasa Indonesia", "in"), + BAHASA_INDONESIA("Bahasa Indonesia", "id"), BRAZILIAN_PORTUGUESE("Brazilian Portuguese", "pt_BR"), DANISH("Dansk", "da"), GERMAN("Deutsch", "de"), diff --git a/src/main/java/org/jabref/logic/openoffice/NoDocumentFoundException.java b/src/main/java/org/jabref/logic/openoffice/NoDocumentFoundException.java new file mode 100644 index 00000000000..2759a9931aa --- /dev/null +++ b/src/main/java/org/jabref/logic/openoffice/NoDocumentFoundException.java @@ -0,0 +1,12 @@ +package org.jabref.logic.openoffice; + +public class NoDocumentFoundException extends Exception { + + public NoDocumentFoundException(String message) { + super(message); + } + + public NoDocumentFoundException() { + super("No Writer documents found"); + } +} diff --git a/src/main/java/org/jabref/logic/openoffice/OOUtil.java b/src/main/java/org/jabref/logic/openoffice/OOUtil.java deleted file mode 100644 index a5976cb3342..00000000000 --- a/src/main/java/org/jabref/logic/openoffice/OOUtil.java +++ /dev/null @@ -1,284 +0,0 @@ -package org.jabref.logic.openoffice; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.jabref.architecture.AllowedToUseAwt; -import org.jabref.logic.layout.Layout; -import org.jabref.model.database.BibDatabase; -import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.field.Field; -import org.jabref.model.entry.field.UnknownField; - -import com.sun.star.beans.PropertyVetoException; -import com.sun.star.beans.UnknownPropertyException; -import com.sun.star.beans.XPropertySet; -import com.sun.star.lang.WrappedTargetException; -import com.sun.star.text.ControlCharacter; -import com.sun.star.text.XParagraphCursor; -import com.sun.star.text.XText; -import com.sun.star.text.XTextCursor; -import com.sun.star.uno.UnoRuntime; - -/** - * Utility methods for processing OO Writer documents. - */ -@AllowedToUseAwt("Requires AWT for changing document properties") -public class OOUtil { - - private static final String CHAR_STRIKEOUT = "CharStrikeout"; - private static final String CHAR_UNDERLINE = "CharUnderline"; - private static final String PARA_STYLE_NAME = "ParaStyleName"; - private static final String CHAR_CASE_MAP = "CharCaseMap"; - private static final String CHAR_POSTURE = "CharPosture"; - private static final String CHAR_WEIGHT = "CharWeight"; - private static final String CHAR_ESCAPEMENT_HEIGHT = "CharEscapementHeight"; - private static final String CHAR_ESCAPEMENT = "CharEscapement"; - - public enum Formatting { - BOLD, - ITALIC, - SMALLCAPS, - SUPERSCRIPT, - SUBSCRIPT, - UNDERLINE, - STRIKEOUT, - MONOSPACE - } - - private static final Pattern HTML_TAG = Pattern.compile(""); - - private static final Field UNIQUEFIER_FIELD = new UnknownField("uniq"); - - private OOUtil() { - // Just to hide the public constructor - } - - /** - * 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. - */ - public static void insertFullReferenceAtCurrentLocation(XText text, XTextCursor cursor, - Layout layout, String parStyle, BibEntry entry, BibDatabase database, String uniquefier) - throws UndefinedParagraphFormatException, UnknownPropertyException, PropertyVetoException, - WrappedTargetException, IllegalArgumentException { - - // Backup the value of the uniq field, just in case the entry already has it: - Optional oldUniqVal = entry.getField(UNIQUEFIER_FIELD); - - // Set the uniq field with the supplied uniquefier: - if (uniquefier == null) { - entry.clearField(UNIQUEFIER_FIELD); - } else { - entry.setField(UNIQUEFIER_FIELD, uniquefier); - } - - // Do the layout for this entry: - String formattedText = layout.doLayout(entry, database); - - // Afterwards, reset the old value: - if (oldUniqVal.isPresent()) { - entry.setField(UNIQUEFIER_FIELD, oldUniqVal.get()); - } else { - entry.clearField(UNIQUEFIER_FIELD); - } - - // Insert the formatted text: - OOUtil.insertOOFormattedTextAtCurrentLocation(text, cursor, formattedText, 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 WrappedTargetException - * @throws PropertyVetoException - * @throws UnknownPropertyException - * @throws IllegalArgumentException - */ - public static void insertOOFormattedTextAtCurrentLocation(XText text, XTextCursor cursor, String lText, - String parStyle) throws UndefinedParagraphFormatException, UnknownPropertyException, PropertyVetoException, - WrappedTargetException, IllegalArgumentException { - - XParagraphCursor parCursor = UnoRuntime.queryInterface( - XParagraphCursor.class, cursor); - XPropertySet props = UnoRuntime.queryInterface( - XPropertySet.class, parCursor); - - try { - props.setPropertyValue(PARA_STYLE_NAME, parStyle); - } catch (com.sun.star.lang.IllegalArgumentException ex) { - throw new UndefinedParagraphFormatException(parStyle); - } - - List formatting = new ArrayList<>(); - // We need to extract formatting. Use a simple regexp search iteration: - int piv = 0; - Matcher matcher = OOUtil.HTML_TAG.matcher(lText); - while (matcher.find()) { - String currentSubstring = lText.substring(piv, matcher.start()); - if (!currentSubstring.isEmpty()) { - OOUtil.insertTextAtCurrentLocation(text, cursor, currentSubstring, formatting); - } - String tag = matcher.group(); - // Handle tags: - if ("".equals(tag)) { - formatting.add(Formatting.BOLD); - } else if ("".equals(tag)) { - formatting.remove(Formatting.BOLD); - } else if ("".equals(tag) || "".equals(tag)) { - formatting.add(Formatting.ITALIC); - } else if ("".equals(tag) || "".equals(tag)) { - formatting.remove(Formatting.ITALIC); - } else if ("".equals(tag)) { - formatting.add(Formatting.MONOSPACE); - } else if ("".equals(tag)) { - formatting.remove(Formatting.MONOSPACE); - } else if ("".equals(tag)) { - formatting.add(Formatting.SMALLCAPS); - } else if ("".equals(tag)) { - formatting.remove(Formatting.SMALLCAPS); - } else if ("".equals(tag)) { - formatting.add(Formatting.SUPERSCRIPT); - } else if ("".equals(tag)) { - formatting.remove(Formatting.SUPERSCRIPT); - } else if ("".equals(tag)) { - formatting.add(Formatting.SUBSCRIPT); - } else if ("".equals(tag)) { - formatting.remove(Formatting.SUBSCRIPT); - } else if ("".equals(tag)) { - formatting.add(Formatting.UNDERLINE); - } else if ("".equals(tag)) { - formatting.remove(Formatting.UNDERLINE); - } else if ("".equals(tag)) { - formatting.add(Formatting.STRIKEOUT); - } else if ("".equals(tag)) { - formatting.remove(Formatting.STRIKEOUT); - } - - piv = matcher.end(); - } - - if (piv < lText.length()) { - OOUtil.insertTextAtCurrentLocation(text, cursor, lText.substring(piv), formatting); - } - - cursor.collapseToEnd(); - } - - public static void insertParagraphBreak(XText text, XTextCursor cursor) throws IllegalArgumentException { - text.insertControlCharacter(cursor, ControlCharacter.PARAGRAPH_BREAK, true); - cursor.collapseToEnd(); - } - - public static void insertTextAtCurrentLocation(XText text, XTextCursor cursor, String string, - List formatting) - throws UnknownPropertyException, PropertyVetoException, WrappedTargetException, - IllegalArgumentException { - 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 = UnoRuntime.queryInterface( - XPropertySet.class, cursor); - if (formatting.contains(Formatting.BOLD)) { - xCursorProps.setPropertyValue(CHAR_WEIGHT, - com.sun.star.awt.FontWeight.BOLD); - } else { - xCursorProps.setPropertyValue(CHAR_WEIGHT, - com.sun.star.awt.FontWeight.NORMAL); - } - - if (formatting.contains(Formatting.ITALIC)) { - xCursorProps.setPropertyValue(CHAR_POSTURE, - com.sun.star.awt.FontSlant.ITALIC); - } else { - xCursorProps.setPropertyValue(CHAR_POSTURE, - com.sun.star.awt.FontSlant.NONE); - } - - if (formatting.contains(Formatting.SMALLCAPS)) { - xCursorProps.setPropertyValue(CHAR_CASE_MAP, - com.sun.star.style.CaseMap.SMALLCAPS); - } else { - xCursorProps.setPropertyValue(CHAR_CASE_MAP, - com.sun.star.style.CaseMap.NONE); - } - - // TODO: the tag doesn't work - /* - if (formatting.contains(Formatting.MONOSPACE)) { - xCursorProps.setPropertyValue("CharFontPitch", - com.sun.star.awt.FontPitch.FIXED); - } - else { - xCursorProps.setPropertyValue("CharFontPitch", - com.sun.star.awt.FontPitch.VARIABLE); - } */ - if (formatting.contains(Formatting.SUBSCRIPT)) { - xCursorProps.setPropertyValue(CHAR_ESCAPEMENT, - (byte) -101); - xCursorProps.setPropertyValue(CHAR_ESCAPEMENT_HEIGHT, - (byte) 58); - } else if (formatting.contains(Formatting.SUPERSCRIPT)) { - xCursorProps.setPropertyValue(CHAR_ESCAPEMENT, - (byte) 101); - xCursorProps.setPropertyValue(CHAR_ESCAPEMENT_HEIGHT, - (byte) 58); - } else { - xCursorProps.setPropertyValue(CHAR_ESCAPEMENT, - (byte) 0); - xCursorProps.setPropertyValue(CHAR_ESCAPEMENT_HEIGHT, - (byte) 100); - } - - if (formatting.contains(Formatting.UNDERLINE)) { - xCursorProps.setPropertyValue(CHAR_UNDERLINE, com.sun.star.awt.FontUnderline.SINGLE); - } else { - xCursorProps.setPropertyValue(CHAR_UNDERLINE, com.sun.star.awt.FontUnderline.NONE); - } - - if (formatting.contains(Formatting.STRIKEOUT)) { - xCursorProps.setPropertyValue(CHAR_STRIKEOUT, com.sun.star.awt.FontStrikeout.SINGLE); - } else { - xCursorProps.setPropertyValue(CHAR_STRIKEOUT, com.sun.star.awt.FontStrikeout.NONE); - } - cursor.collapseToEnd(); - } - - public static void insertTextAtCurrentLocation(XText text, XTextCursor cursor, String string, String parStyle) - throws WrappedTargetException, PropertyVetoException, UnknownPropertyException, - UndefinedParagraphFormatException { - text.insertString(cursor, string, true); - XParagraphCursor parCursor = 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 = UnoRuntime.queryInterface( - XPropertySet.class, parCursor); - try { - props.setPropertyValue(PARA_STYLE_NAME, parStyle); - } catch (IllegalArgumentException ex) { - throw new UndefinedParagraphFormatException(parStyle); - } - cursor.collapseToEnd(); - } - - public static Object getProperty(Object object, String property) - throws UnknownPropertyException, WrappedTargetException { - XPropertySet props = UnoRuntime.queryInterface(XPropertySet.class, object); - return props.getPropertyValue(property); - } -} diff --git a/src/main/java/org/jabref/logic/openoffice/OpenOfficeFileSearch.java b/src/main/java/org/jabref/logic/openoffice/OpenOfficeFileSearch.java index 309096b08cf..dd59b8a09bf 100644 --- a/src/main/java/org/jabref/logic/openoffice/OpenOfficeFileSearch.java +++ b/src/main/java/org/jabref/logic/openoffice/OpenOfficeFileSearch.java @@ -43,8 +43,9 @@ public static List detectInstallations() { private static List findOpenOfficeDirectories(List programDirectories) { - BiPredicate filePredicate = (path, attr) -> attr.isDirectory() && (path.toString().toLowerCase(Locale.ROOT).contains("openoffice") - || path.toString().toLowerCase(Locale.ROOT).contains("libreoffice")); + BiPredicate filePredicate = (path, attr) -> + attr.isDirectory() && (path.toString().toLowerCase(Locale.ROOT).contains("openoffice") + || path.toString().toLowerCase(Locale.ROOT).contains("libreoffice")); return programDirectories.stream().flatMap(dirs -> { try { diff --git a/src/main/java/org/jabref/logic/openoffice/UndefinedBibtexEntry.java b/src/main/java/org/jabref/logic/openoffice/UndefinedBibtexEntry.java deleted file mode 100644 index 8a1a7cf5e8f..00000000000 --- a/src/main/java/org/jabref/logic/openoffice/UndefinedBibtexEntry.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.jabref.logic.openoffice; - -import org.jabref.logic.openoffice.style.OOBibStyle; -import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.field.StandardField; - -/** - * Subclass of BibEntry for representing entries referenced in a document that can't be found in JabRef's current database. - */ -public class UndefinedBibtexEntry extends BibEntry { - - private final String key; - - public UndefinedBibtexEntry(String key) { - this.key = key; - setField(StandardField.AUTHOR, OOBibStyle.UNDEFINED_CITATION_MARKER); - } - - public String getKey() { - return key; - } -} diff --git a/src/main/java/org/jabref/logic/openoffice/UndefinedParagraphFormatException.java b/src/main/java/org/jabref/logic/openoffice/UndefinedParagraphFormatException.java deleted file mode 100644 index 361f8d44f54..00000000000 --- a/src/main/java/org/jabref/logic/openoffice/UndefinedParagraphFormatException.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.jabref.logic.openoffice; - -/** - * Exception used to indicate that the plugin attempted to set a paragraph format that is not defined in the current OpenOffice document. - */ -public class UndefinedParagraphFormatException extends Exception { - - private final String formatName; - - public UndefinedParagraphFormatException(String formatName) { - super(); - this.formatName = formatName; - } - - public String getFormatName() { - return formatName; - } -} diff --git a/src/main/java/org/jabref/logic/openoffice/action/EditInsert.java b/src/main/java/org/jabref/logic/openoffice/action/EditInsert.java index 0004d3fe6db..9c171553a4b 100644 --- a/src/main/java/org/jabref/logic/openoffice/action/EditInsert.java +++ b/src/main/java/org/jabref/logic/openoffice/action/EditInsert.java @@ -32,17 +32,14 @@ public class EditInsert { private EditInsert() { - /**/ } /** * In insertEntry we receive BibEntry values from the GUI. - * + *

* In the document we store citations by their citation key. - * - * If the citation key is missing, the best we can do is to notify the user. Or the programmer, - * that we cannot accept such input. - * + *

+ * If the citation key is missing, the best we can do is to notify the user. Or the programmer, that we cannot accept such input. */ private static String insertEntryGetCitationKey(BibEntry entry) { Optional key = entry.getCitationKey(); @@ -53,7 +50,7 @@ private static String insertEntryGetCitationKey(BibEntry entry) { } /** - * @param cursor Where to insert. + * @param cursor Where to insert. * @param pageInfo A single pageInfo for a list of entries. This is what we get from the GUI. */ public static void insertCitationGroup(XTextDocument doc, @@ -64,13 +61,13 @@ public static void insertCitationGroup(XTextDocument doc, OOBibStyle style, CitationType citationType, String pageInfo) - throws - NoDocumentException, - NotRemoveableException, - WrappedTargetException, - PropertyVetoException, - CreationException, - IllegalTypeException { + throws + NoDocumentException, + NotRemoveableException, + WrappedTargetException, + PropertyVetoException, + CreationException, + IllegalTypeException { List citationKeys = OOListUtil.map(entries, EditInsert::insertEntryGetCitationKey); @@ -86,13 +83,13 @@ public static void insertCitationGroup(XTextDocument doc, } // The text we insert - OOText citeText = null; + OOText citeText; if (style.isNumberEntries()) { citeText = OOText.fromString("[-]"); // A dash only. Only refresh later. } else { citeText = style.createCitationMarker(citations, - citationType.inParenthesis(), - NonUniqueCitationMarker.FORGIVEN); + citationType.inParenthesis(), + NonUniqueCitationMarker.FORGIVEN); } if (StringUtil.isBlank(OOText.toString(citeText))) { @@ -102,17 +99,16 @@ public static void insertCitationGroup(XTextDocument doc, try { UnoScreenRefresh.lockControllers(doc); UpdateCitationMarkers.createAndFillCitationGroup(frontend, - doc, - citationKeys, - pageInfos, - citationType, - citeText, - cursor, - style, - true /* insertSpaceAfter */); + doc, + citationKeys, + pageInfos, + citationType, + citeText, + cursor, + style, + true /* insertSpaceAfter */); } finally { UnoScreenRefresh.unlockControllers(doc); } - } } diff --git a/src/main/java/org/jabref/logic/openoffice/action/EditMerge.java b/src/main/java/org/jabref/logic/openoffice/action/EditMerge.java index f91e8aec93d..dc2058a9107 100644 --- a/src/main/java/org/jabref/logic/openoffice/action/EditMerge.java +++ b/src/main/java/org/jabref/logic/openoffice/action/EditMerge.java @@ -34,21 +34,20 @@ public class EditMerge { private static final Logger LOGGER = LoggerFactory.getLogger(EditMerge.class); private EditMerge() { - // hide constructor } - /* + /** * @return true if modified document */ public static boolean mergeCitationGroups(XTextDocument doc, OOFrontend frontend, OOBibStyle style) - throws - CreationException, - IllegalArgumentException, - IllegalTypeException, - NoDocumentException, - NotRemoveableException, - PropertyVetoException, - WrappedTargetException { + throws + CreationException, + IllegalArgumentException, + IllegalTypeException, + NoDocumentException, + NotRemoveableException, + PropertyVetoException, + WrappedTargetException { boolean madeModifications; @@ -62,8 +61,8 @@ public static boolean mergeCitationGroups(XTextDocument doc, OOFrontend frontend List groups = joinableGroupData.group; List newCitations = (groups.stream() - .flatMap(group -> group.citationsInStorageOrder.stream()) - .collect(Collectors.toList())); + .flatMap(group -> group.citationsInStorageOrder.stream()) + .collect(Collectors.toList())); CitationType citationType = groups.get(0).citationType; List> pageInfos = frontend.backend.combinePageInfos(groups); @@ -77,18 +76,17 @@ public static boolean mergeCitationGroups(XTextDocument doc, OOFrontend frontend /* insertSpaceAfter: no, it is already there (or could be) */ boolean insertSpaceAfter = false; UpdateCitationMarkers.createAndFillCitationGroup(frontend, - doc, - citationKeys, - pageInfos, - citationType, - OOText.fromString("tmp"), - textCursor, - style, - insertSpaceAfter); + doc, + citationKeys, + pageInfos, + citationType, + OOText.fromString("tmp"), + textCursor, + style, + insertSpaceAfter); } madeModifications = !joinableGroups.isEmpty(); - } finally { UnoScreenRefresh.unlockControllers(doc); } @@ -97,10 +95,14 @@ public static boolean mergeCitationGroups(XTextDocument doc, OOFrontend frontend } private static class JoinableGroupData { - /** A list of consecutive citation groups only separated by spaces. */ + /** + * A list of consecutive citation groups only separated by spaces. + */ List group; - /** A cursor covering the XTextRange of each entry in group (and the spaces between them) */ + /** + * A cursor covering the XTextRange of each entry in group (and the spaces between them) + */ XTextCursor groupCursor; JoinableGroupData(List group, XTextCursor groupCursor) { @@ -119,8 +121,8 @@ private static class ScanState { // null if currentGroup.isEmpty() XTextCursor currentGroupCursor; - // A cursor starting at the end of the last CitationGroup in - // currentGroup. null if currentGroup.isEmpty() + // A cursor starting at the end of the last CitationGroup in currentGroup. + // null if currentGroup.isEmpty() XTextCursor cursorBetween; // The last element of currentGroup. @@ -147,11 +149,9 @@ void reset() { /** * Decide if group could be added to state.currentGroup * - * @param group The CitationGroup to test + * @param group The CitationGroup to test * @param currentRange The XTextRange corresponding to group. - * - * @return false if cannot add, true if can. If returned true, then state.cursorBetween and - * state.currentGroupCursor are expanded to end at the start of currentRange. + * @return false if cannot add, true if can. If returned true, then state.cursorBetween and state.currentGroupCursor are expanded to end at the start of currentRange. */ private static boolean checkAddToGroup(ScanState state, CitationGroup group, XTextRange currentRange) { @@ -184,14 +184,14 @@ private static boolean checkAddToGroup(ScanState state, CitationGroup group, XTe int textOrder = UnoTextRange.compareStarts(state.prevRange, currentRange); if (textOrder != (-1)) { String msg = - String.format("MergeCitationGroups:" - + " \"%s\" supposed to be followed by \"%s\"," - + " but %s", - state.prevRange.getString(), - currentRange.getString(), - ((textOrder == 0) - ? "they start at the same position" - : "the start of the latter precedes the start of the first")); + String.format("MergeCitationGroups:" + + " \"%s\" supposed to be followed by \"%s\"," + + " but %s", + state.prevRange.getString(), + currentRange.getString(), + ((textOrder == 0) + ? "they start at the same position" + : "the start of the latter precedes the start of the first")); LOGGER.warn(msg); return false; } @@ -217,7 +217,7 @@ private static boolean checkAddToGroup(ScanState state, CitationGroup group, XTe XTextRange rangeStart = currentRange.getStart(); boolean couldExpand = true; XTextCursor thisCharCursor = - (currentRange.getText().createTextCursorByRange(state.cursorBetween.getEnd())); + (currentRange.getText().createTextCursorByRange(state.cursorBetween.getEnd())); while (couldExpand && (UnoTextRange.compareEnds(state.cursorBetween, rangeStart) < 0)) { // @@ -247,10 +247,7 @@ private static boolean checkAddToGroup(ScanState state, CitationGroup group, XTe } /** - * Add group to state.currentGroup - * Set state.cursorBetween to start at currentRange.getEnd() - * Expand state.currentGroupCursor to also cover currentRange - * Set state.prev to group, state.prevRange to currentRange + * Add group to state.currentGroup Set state.cursorBetween to start at currentRange.getEnd() Expand state.currentGroupCursor to also cover currentRange Set state.prev to group, state.prevRange to currentRange */ private static void addToCurrentGroup(ScanState state, CitationGroup group, XTextRange currentRange) { final boolean isNewGroup = state.currentGroup.isEmpty(); @@ -271,7 +268,7 @@ private static void addToCurrentGroup(ScanState state, CitationGroup group, XTex // If new group, create currentGroupCursor if (isNewGroup) { state.currentGroupCursor = (currentRange.getText() - .createTextCursorByRange(currentRange.getStart())); + .createTextCursorByRange(currentRange.getStart())); } // include currentRange in currentGroupCursor @@ -288,12 +285,12 @@ private static void addToCurrentGroup(ScanState state, CitationGroup group, XTex } /** - * Scan the document for joinable groups. Return those found. + * Scan the document for joinable groups. Return those found. */ private static List scan(XTextDocument doc, OOFrontend frontend) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { List result = new ArrayList<>(); List groups = frontend.getCitationGroupsSortedWithinPartitions(doc, false /* mapFootnotesToFootnoteMarks */); @@ -306,7 +303,7 @@ private static List scan(XTextDocument doc, OOFrontend fronte for (CitationGroup group : groups) { XTextRange currentRange = (frontend.getMarkRange(doc, group) - .orElseThrow(IllegalStateException::new)); + .orElseThrow(IllegalStateException::new)); /* * Decide if we add group to the group. False when the group is empty. @@ -340,5 +337,4 @@ private static List scan(XTextDocument doc, OOFrontend fronte } return result; } - } diff --git a/src/main/java/org/jabref/logic/openoffice/action/EditSeparate.java b/src/main/java/org/jabref/logic/openoffice/action/EditSeparate.java index 66630a6f8d0..101dffb813a 100644 --- a/src/main/java/org/jabref/logic/openoffice/action/EditSeparate.java +++ b/src/main/java/org/jabref/logic/openoffice/action/EditSeparate.java @@ -25,21 +25,20 @@ public class EditSeparate { private EditSeparate() { - /**/ } public static boolean separateCitations(XTextDocument doc, OOFrontend frontend, List databases, OOBibStyle style) - throws - CreationException, - IllegalTypeException, - NoDocumentException, - NotRemoveableException, - PropertyVetoException, - WrappedTargetException, - com.sun.star.lang.IllegalArgumentException { + throws + CreationException, + IllegalTypeException, + NoDocumentException, + NotRemoveableException, + PropertyVetoException, + WrappedTargetException, + com.sun.star.lang.IllegalArgumentException { boolean madeModifications = false; @@ -58,8 +57,8 @@ public static boolean separateCitations(XTextDocument doc, for (CitationGroup group : groups) { XTextRange range1 = (frontend - .getMarkRange(doc, group) - .orElseThrow(IllegalStateException::new)); + .getMarkRange(doc, group) + .orElseThrow(IllegalStateException::new)); XTextCursor textCursor = range1.getText().createTextCursorByRange(range1); List citations = group.citationsInStorageOrder; @@ -77,14 +76,14 @@ public static boolean separateCitations(XTextDocument doc, Citation citation = citations.get(i); UpdateCitationMarkers.createAndFillCitationGroup(frontend, - doc, - List.of(citation.citationKey), - List.of(citation.getPageInfo()), - group.citationType, - OOText.fromString(citation.citationKey), - textCursor, - style, - insertSpaceAfter); + doc, + List.of(citation.citationKey), + List.of(citation.getPageInfo()), + group.citationType, + OOText.fromString(citation.citationKey), + textCursor, + style, + insertSpaceAfter); textCursor.collapseToEnd(); } diff --git a/src/main/java/org/jabref/logic/openoffice/action/ExportCited.java b/src/main/java/org/jabref/logic/openoffice/action/ExportCited.java index c38cd4fd4cc..4bdc11a7f71 100644 --- a/src/main/java/org/jabref/logic/openoffice/action/ExportCited.java +++ b/src/main/java/org/jabref/logic/openoffice/action/ExportCited.java @@ -19,7 +19,6 @@ public class ExportCited { private ExportCited() { - /**/ } public static class GenerateDatabaseResult { @@ -36,20 +35,16 @@ public static class GenerateDatabaseResult { } /** - * * @param databases The databases to look up the citation keys in the document from. * @return A new database, with cloned entries. - * * If a key is not found, it is added to result.unresolvedKeys - * - * Cross references (in StandardField.CROSSREF) are followed (not recursively): - * If the referenced entry is found, it is included in the result. - * If it is not found, it is silently ignored. + *

+ * Cross references (in StandardField.CROSSREF) are followed (not recursively): If the referenced entry is found, it is included in the result. If it is not found, it is silently ignored. */ public static GenerateDatabaseResult generateDatabase(XTextDocument doc, List databases) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { OOFrontend frontend = new OOFrontend(doc); CitedKeys citationKeys = frontend.citationGroups.getCitedKeysUnordered(); @@ -64,7 +59,6 @@ public static GenerateDatabaseResult generateDatabase(XTextDocument doc, List { + .getField(StandardField.CROSSREF) + .ifPresent(crossReference -> { boolean isNew = !seen.contains(crossReference); if (isNew) { // Add it if it is in the current library loopDatabase - .getEntryByCitationKey(crossReference) - .ifPresent(entriesToInsert::add); + .getEntryByCitationKey(crossReference) + .ifPresent(entriesToInsert::add); seen.add(crossReference); } }); @@ -94,5 +88,4 @@ public static GenerateDatabaseResult generateDatabase(XTextDocument doc, List getCitationEntries(XTextDocument doc) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { OOFrontend frontend = new OOFrontend(doc); return frontend.getCitationEntries(doc); } public static void applyCitationEntries(XTextDocument doc, List citationEntries) - throws - NoDocumentException, - PropertyVetoException, - IllegalTypeException, - WrappedTargetException, - IllegalArgumentException { + throws + NoDocumentException, + PropertyVetoException, + IllegalTypeException, + WrappedTargetException, + IllegalArgumentException { OOFrontend frontend = new OOFrontend(doc); frontend.applyCitationEntries(doc, citationEntries); } diff --git a/src/main/java/org/jabref/logic/openoffice/action/Update.java b/src/main/java/org/jabref/logic/openoffice/action/Update.java index 80263833aec..f5222c47ec0 100644 --- a/src/main/java/org/jabref/logic/openoffice/action/Update.java +++ b/src/main/java/org/jabref/logic/openoffice/action/Update.java @@ -21,10 +21,7 @@ */ public class Update { - static final boolean USE_LOCK_CONTROLLERS = true; - private Update() { - /**/ } /** @@ -37,17 +34,19 @@ private static List updateDocument(XTextDocument doc, FunctionalTextViewCursor fcursor, boolean doUpdateBibliography, boolean alwaysAddCitedOnPages) - throws - CreationException, - NoDocumentException, - WrappedTargetException, - com.sun.star.lang.IllegalArgumentException { + throws + CreationException, + NoDocumentException, + WrappedTargetException, + com.sun.star.lang.IllegalArgumentException { + + final boolean useLockControllers = true; frontend.imposeGlobalOrder(doc, fcursor); OOProcess.produceCitationMarkers(frontend.citationGroups, databases, style); try { - if (USE_LOCK_CONTROLLERS) { + if (useLockControllers) { UnoScreenRefresh.lockControllers(doc); } @@ -55,15 +54,15 @@ private static List updateDocument(XTextDocument doc, if (doUpdateBibliography) { UpdateBibliography.rebuildBibTextSection(doc, - frontend, - frontend.citationGroups.getBibliography().get(), - style, - alwaysAddCitedOnPages); + frontend, + frontend.citationGroups.getBibliography().get(), + style, + alwaysAddCitedOnPages); } return frontend.citationGroups.getUnresolvedKeys(); } finally { - if (USE_LOCK_CONTROLLERS && UnoScreenRefresh.hasControllersLocked(doc)) { + if (useLockControllers && UnoScreenRefresh.hasControllersLocked(doc)) { UnoScreenRefresh.unlockControllers(doc); } } @@ -97,37 +96,36 @@ public static List synchronizeDocument(XTextDocument doc, OOBibStyle style, FunctionalTextViewCursor fcursor, SyncOptions syncOptions) - throws - CreationException, - NoDocumentException, - WrappedTargetException, - com.sun.star.lang.IllegalArgumentException { + throws + CreationException, + NoDocumentException, + WrappedTargetException, + com.sun.star.lang.IllegalArgumentException { return Update.updateDocument(doc, - frontend, - syncOptions.databases, - style, - fcursor, - syncOptions.updateBibliography, - syncOptions.alwaysAddCitedOnPages); + frontend, + syncOptions.databases, + style, + fcursor, + syncOptions.updateBibliography, + syncOptions.alwaysAddCitedOnPages); } - /* + /** * Reread document before sync */ public static List resyncDocument(XTextDocument doc, OOBibStyle style, FunctionalTextViewCursor fcursor, SyncOptions syncOptions) - throws - CreationException, - NoDocumentException, - WrappedTargetException, - com.sun.star.lang.IllegalArgumentException { + throws + CreationException, + NoDocumentException, + WrappedTargetException, + com.sun.star.lang.IllegalArgumentException { OOFrontend frontend = new OOFrontend(doc); return Update.synchronizeDocument(doc, frontend, style, fcursor, syncOptions); } - } diff --git a/src/main/java/org/jabref/logic/openoffice/backend/Backend52.java b/src/main/java/org/jabref/logic/openoffice/backend/Backend52.java index 4a0d8d05e0e..e433d18e72f 100644 --- a/src/main/java/org/jabref/logic/openoffice/backend/Backend52.java +++ b/src/main/java/org/jabref/logic/openoffice/backend/Backend52.java @@ -37,9 +37,7 @@ import org.slf4j.LoggerFactory; /** - * Backend52, Codec52 and OODataModel.JabRef52 refer to the mode of storage, encoding and - * what-is-stored in the document under JabRef version 5.2. These basically did not change up to - * JabRef 5.4. + * Backend52, Codec52 and OODataModel.JabRef52 refer to the mode of storage, encoding and what-is-stored in the document under JabRef version 5.2. These basically did not change up to JabRef 5.4. */ public class Backend52 { private static final Logger LOGGER = LoggerFactory.getLogger(Backend52.class); @@ -55,25 +53,21 @@ public Backend52() { } /** - * Get reference mark names from the document matching the pattern - * used for JabRef reference mark names. - * + * Get reference mark names from the document matching the pattern used for JabRef reference mark names. + *

* Note: the names returned are in arbitrary order. - * */ public List getJabRefReferenceMarkNames(XTextDocument doc) - throws - NoDocumentException { + throws + NoDocumentException { List allNames = this.citationStorageManager.getUsedNames(doc); return Codec52.filterIsJabRefReferenceMarkName(allNames); } /** - * Names of custom properties belonging to us, but without a corresponding reference mark. - * These can be deleted. + * Names of custom properties belonging to us, but without a corresponding reference mark. These can be deleted. * * @param citationGroupNames These are the names that are used. - * */ private List findUnusedJabrefPropertyNames(XTextDocument doc, List citationGroupNames) { @@ -82,10 +76,10 @@ private List findUnusedJabrefPropertyNames(XTextDocument doc, List pageInfoThrash = new ArrayList<>(); List jabrefPropertyNames = - UnoUserDefinedProperty.getListOfNames(doc) - .stream() - .filter(Codec52::isJabRefReferenceMarkName) - .collect(Collectors.toList()); + UnoUserDefinedProperty.getListOfNames(doc) + .stream() + .filter(Codec52::isJabRefReferenceMarkName) + .toList(); for (String pn : jabrefPropertyNames) { if (!citationGroupNamesSet.contains(pn)) { pageInfoThrash.add(pn); @@ -95,21 +89,21 @@ private List findUnusedJabrefPropertyNames(XTextDocument doc, } /** - * @return Optional.empty if all is OK, message text otherwise. + * @return Optional.empty if all is OK, message text otherwise. */ public Optional healthReport(XTextDocument doc) - throws - NoDocumentException { + throws + NoDocumentException { List pageInfoThrash = - this.findUnusedJabrefPropertyNames(doc, this.getJabRefReferenceMarkNames(doc)); + this.findUnusedJabrefPropertyNames(doc, this.getJabRefReferenceMarkNames(doc)); if (pageInfoThrash.isEmpty()) { return Optional.empty(); } - StringBuilder msg = new StringBuilder("Backend52: found unused pageInfo data, with names listed below.\n"); - msg.append("In LibreOffice you may remove these in [File]/[Properties]/[Custom Properties]\n"); - msg.append(String.join("\n", pageInfoThrash)); - return Optional.of(msg.toString()); + String msg = "Backend52: found unused pageInfo data, with names listed below.\n" + + "In LibreOffice you may remove these in [File]/[Properties]/[Custom Properties]\n" + + String.join("\n", pageInfoThrash); + return Optional.of(msg); } private static void setPageInfoInDataInitial(List citations, Optional pageInfo) { @@ -131,51 +125,44 @@ private static Optional getPageInfoFromData(CitationGroup group) { * @param markName Reference mark name */ public CitationGroup readCitationGroupFromDocumentOrThrow(XTextDocument doc, String markName) - throws - WrappedTargetException, - NoDocumentException { + throws + WrappedTargetException, + NoDocumentException { Codec52.ParsedMarkName parsed = Codec52.parseMarkName(markName).orElseThrow(IllegalArgumentException::new); List citations = (parsed.citationKeys.stream() - .map(Citation::new) - .collect(Collectors.toList())); + .map(Citation::new) + .collect(Collectors.toList())); Optional pageInfo = (UnoUserDefinedProperty.getStringValue(doc, markName) - .map(OOText::fromString)); + .map(OOText::fromString)); pageInfo = PageInfo.normalizePageInfo(pageInfo); setPageInfoInDataInitial(citations, pageInfo); NamedRange namedRange = (citationStorageManager.getNamedRangeFromDocument(doc, markName) - .orElseThrow(IllegalArgumentException::new)); + .orElseThrow(IllegalArgumentException::new)); CitationGroupId groupId = new CitationGroupId(markName); CitationGroup group = new CitationGroup(OODataModel.JabRef52, - groupId, - parsed.citationType, - citations, - Optional.of(markName)); + groupId, + parsed.citationType, + citations, + Optional.of(markName)); this.cgidToNamedRange.put(groupId, namedRange); return group; } /** - * Create a reference mark at the end of {@code position} in the document. - * - * On return {@code position} is collapsed, and is after the inserted space, or at the end of - * the reference mark. + * Create a reference mark at the end of {@code position} in the document. + *

+ * On return {@code position} is collapsed, and is after the inserted space, or at the end of the reference mark. * - * @param citationKeys Keys to be cited. - * - * @param pageInfos An optional pageInfo for each citation key. - * Backend52 only uses and stores the last pageInfo, - * all others should be Optional.empty() - * - * @param position Collapsed to its end. - * - * @param insertSpaceAfter We insert a space after the mark, that carries on format of - * characters from the original position. + * @param citationKeys Keys to be cited. + * @param pageInfos An optional pageInfo for each citation key. Backend52 only uses and stores the last pageInfo, all others should be Optional.empty() + * @param position Collapsed to its end. + * @param insertSpaceAfter We insert a space after the mark, that carries on format of characters from the original position. */ public CitationGroup createCitationGroup(XTextDocument doc, List citationKeys, @@ -183,13 +170,13 @@ public CitationGroup createCitationGroup(XTextDocument doc, CitationType citationType, XTextCursor position, boolean insertSpaceAfter) - throws - CreationException, - NoDocumentException, - WrappedTargetException, - NotRemoveableException, - PropertyVetoException, - IllegalTypeException { + throws + CreationException, + NoDocumentException, + WrappedTargetException, + NotRemoveableException, + PropertyVetoException, + IllegalTypeException { Objects.requireNonNull(pageInfos); if (pageInfos.size() != citationKeys.size()) { @@ -213,7 +200,7 @@ public CitationGroup createCitationGroup(XTextDocument doc, } else { if (pageInfo.isPresent()) { LOGGER.warn("dataModel JabRef52" - + " only supports pageInfo for the last citation of a group"); + + " only supports pageInfo for the last citation of a group"); } } break; @@ -231,8 +218,8 @@ public CitationGroup createCitationGroup(XTextDocument doc, * has to be unique in the document. */ final String markName = Codec52.getUniqueMarkName(new HashSet<>(citationStorageManager.getUsedNames(doc)), - citationKeys, - citationType); + citationKeys, + citationType); final CitationGroupId groupId = new CitationGroupId(markName); @@ -241,10 +228,10 @@ public CitationGroup createCitationGroup(XTextDocument doc, */ boolean withoutBrackets = (citationType == CitationType.INVISIBLE_CIT); NamedRange namedRange = this.citationStorageManager.createNamedRange(doc, - markName, - position, - insertSpaceAfter, - withoutBrackets); + markName, + position, + insertSpaceAfter, + withoutBrackets); switch (dataModel) { case JabRef52: @@ -258,9 +245,9 @@ public CitationGroup createCitationGroup(XTextDocument doc, UnoUserDefinedProperty.removeIfExists(doc, markName); } CitationGroup group = new CitationGroup(OODataModel.JabRef52, - groupId, - citationType, citations, - Optional.of(markName)); + groupId, + citationType, citations, + Optional.of(markName)); this.cgidToNamedRange.put(groupId, namedRange); return group; case JabRef60: @@ -272,8 +259,7 @@ public CitationGroup createCitationGroup(XTextDocument doc, /** * @return A list with a nullable pageInfo entry for each citation in joinableGroups. - * - * TODO: JabRef52 combinePageInfos is not reversible. Should warn user to check the result. Or + * TODO: JabRef52 combinePageInfos is not reversible. Should warn user to check the result. Or * ask what to do. */ public static List> @@ -282,18 +268,18 @@ public CitationGroup createCitationGroup(XTextDocument doc, case JabRef52: // collect to pageInfos List> pageInfos = OOListUtil.map(joinableGroup, - Backend52::getPageInfoFromData); + Backend52::getPageInfoFromData); // Try to do something of the pageInfos. String singlePageInfo = (pageInfos.stream() - .filter(Optional::isPresent) - .map(pi -> OOText.toString(pi.get())) - .distinct() - .collect(Collectors.joining("; "))); + .filter(Optional::isPresent) + .map(pi -> OOText.toString(pi.get())) + .distinct() + .collect(Collectors.joining("; "))); int totalCitations = (joinableGroup.stream() - .map(CitationGroup::numberOfCitations) - .mapToInt(Integer::intValue).sum()); + .map(CitationGroup::numberOfCitations) + .mapToInt(Integer::intValue).sum()); if ("".equals(singlePageInfo)) { singlePageInfo = null; } @@ -301,17 +287,14 @@ public CitationGroup createCitationGroup(XTextDocument doc, case JabRef60: return (joinableGroup.stream() - .flatMap(group -> (group.citationsInStorageOrder.stream() - .map(Citation::getPageInfo))) - .collect(Collectors.toList())); + .flatMap(group -> (group.citationsInStorageOrder.stream() + .map(Citation::getPageInfo))) + .collect(Collectors.toList())); default: throw new IllegalArgumentException("unhandled dataModel here"); } } - /** - * - */ public List> combinePageInfos(List joinableGroup) { return combinePageInfosCommon(this.dataModel, joinableGroup); } @@ -325,10 +308,10 @@ private NamedRange getNamedRangeOrThrow(CitationGroup group) { } public void removeCitationGroup(CitationGroup group, XTextDocument doc) - throws - WrappedTargetException, - NoDocumentException, - NotRemoveableException { + throws + WrappedTargetException, + NoDocumentException, + NotRemoveableException { NamedRange namedRange = getNamedRangeOrThrow(group); String refMarkName = namedRange.getRangeName(); namedRange.removeFromDocument(doc); @@ -340,22 +323,21 @@ public void removeCitationGroup(CitationGroup group, XTextDocument doc) * @return Optional.empty if the reference mark is missing. */ public Optional getMarkRange(CitationGroup group, XTextDocument doc) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { NamedRange namedRange = getNamedRangeOrThrow(group); return namedRange.getMarkRange(doc); } /** - * Cursor for the reference marks as is: not prepared for filling, but does not need - * cleanFillCursorForCitationGroup either. + * Cursor for the reference marks as is: not prepared for filling, but does not need cleanFillCursorForCitationGroup either. */ public Optional getRawCursorForCitationGroup(CitationGroup group, XTextDocument doc) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { NamedRange namedRange = getNamedRangeOrThrow(group); return namedRange.getRawCursor(doc); } @@ -364,44 +346,46 @@ public Optional getRawCursorForCitationGroup(CitationGroup group, X * Must be followed by call to cleanFillCursorForCitationGroup */ public XTextCursor getFillCursorForCitationGroup(CitationGroup group, XTextDocument doc) - throws - NoDocumentException, - WrappedTargetException, - CreationException { + throws + NoDocumentException, + WrappedTargetException, + CreationException { NamedRange namedRange = getNamedRangeOrThrow(group); return namedRange.getFillCursor(doc); } - /** To be called after getFillCursorForCitationGroup */ + /** + * To be called after getFillCursorForCitationGroup + */ public void cleanFillCursorForCitationGroup(CitationGroup group, XTextDocument doc) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { NamedRange namedRange = getNamedRangeOrThrow(group); namedRange.cleanFillCursor(doc); } - public List getCitationEntries(XTextDocument doc, CitationGroups cgs) - throws - WrappedTargetException, - NoDocumentException { + public List getCitationEntries(XTextDocument doc, CitationGroups citationGroups) + throws + WrappedTargetException, + NoDocumentException { switch (dataModel) { case JabRef52: // One context per CitationGroup: Backend52 (DataModel.JabRef52) // For DataModel.JabRef60 (Backend60) we need one context per Citation - List citations = new ArrayList<>(cgs.numberOfCitationGroups()); - for (CitationGroup group : cgs.getCitationGroupsUnordered()) { + List citations = new ArrayList<>(citationGroups.numberOfCitationGroups()); + for (CitationGroup group : citationGroups.getCitationGroupsUnordered()) { String name = group.groupId.citationGroupIdAsString(); XTextCursor cursor = (this - .getRawCursorForCitationGroup(group, doc) - .orElseThrow(IllegalStateException::new)); + .getRawCursorForCitationGroup(group, doc) + .orElseThrow(IllegalStateException::new)); String context = GetContext.getCursorStringWithContext(cursor, 30, 30, true); Optional pageInfo = (group.numberOfCitations() > 0 - ? (getPageInfoFromData(group) - .map(e -> OOText.toString(e))) - : Optional.empty()); + ? (getPageInfoFromData(group) + .map(e -> OOText.toString(e))) + : Optional.empty()); CitationEntry entry = new CitationEntry(name, context, pageInfo); citations.add(entry); } @@ -414,15 +398,15 @@ public List getCitationEntries(XTextDocument doc, CitationGroups } } - /* + /** * Only applies to storage. Citation markers are not changed. */ public void applyCitationEntries(XTextDocument doc, List citationEntries) - throws - PropertyVetoException, - IllegalTypeException, - IllegalArgumentException, - WrappedTargetException { + throws + PropertyVetoException, + IllegalTypeException, + IllegalArgumentException, + WrappedTargetException { switch (dataModel) { case JabRef52: @@ -436,12 +420,11 @@ public void applyCitationEntries(XTextDocument doc, List citation } break; case JabRef60: - // xx + // ToDo: Implement throw new IllegalStateException("applyCitationEntries for JabRef60 is not implemented yet"); default: throw new IllegalStateException("applyCitationEntries: unhandled dataModel "); } } - } diff --git a/src/main/java/org/jabref/logic/openoffice/backend/Codec52.java b/src/main/java/org/jabref/logic/openoffice/backend/Codec52.java index 45f3bd3ca04..0b8932fda6c 100644 --- a/src/main/java/org/jabref/logic/openoffice/backend/Codec52.java +++ b/src/main/java/org/jabref/logic/openoffice/backend/Codec52.java @@ -12,30 +12,35 @@ import org.jabref.model.openoffice.style.CitationType; /** - * How and what is encoded in reference mark names under JabRef 5.2. - * - * - pageInfo does not appear here. It is not encoded in the mark name. + * How and what is encoded in reference mark names under JabRef 5.2. + *

+ * - pageInfo does not appear here. It is not encoded in the mark name. */ class Codec52 { private static final String BIB_CITATION = "JR_cite"; private static final Pattern CITE_PATTERN = - // Pattern.compile(BIB_CITATION + "(\\d*)_(\\d*)_(.*)"); - // citationType is always "1" "2" or "3" - Pattern.compile(BIB_CITATION + "(\\d*)_([123])_(.*)"); + // Pattern.compile(BIB_CITATION + "(\\d*)_(\\d*)_(.*)"); + // citationType is always "1" "2" or "3" + Pattern.compile(BIB_CITATION + "(\\d*)_([123])_(.*)"); private Codec52() { - /**/ } /** * This is what we get back from parsing a refMarkName. */ public static class ParsedMarkName { - /** "", "0", "1" ... */ + /** + * "", "0", "1" ... + */ public final String index; - /** in-text-citation type */ + /** + * in-text-citation type + */ public final CitationType citationType; - /** Citation keys embedded in the reference mark. */ + /** + * Citation keys embedded in the reference mark. + */ public final List citationKeys; ParsedMarkName(String index, CitationType citationType, List citationKeys) { @@ -64,21 +69,19 @@ private static int citationTypeToInt(CitationType type) { case AUTHORYEAR_PAR -> 1; case AUTHORYEAR_INTEXT -> 2; case INVISIBLE_CIT -> 3; - default -> throw new IllegalArgumentException("Invalid CitationType"); }; } /** - * Produce a reference mark name for JabRef for the given citationType and list citation keys that - * does not yet appear among the reference marks of the document. + * Produce a reference mark name for JabRef for the given citationType and list citation keys that does not yet appear among the reference marks of the document. * * @param usedNames Reference mark names already in use. * @param citationKeys Identifies the cited sources. * @param citationType Encodes the effect of withText and inParenthesis options. - * - * The first occurrence of citationKeys gets no serial number, the second gets 0, the third 1 ... - * - * Or the first unused in this series, after removals. + *

+ * The first occurrence of citationKeys gets no serial number, the second gets 0, the third 1 ... + *

+ * Or the first unused in this series, after removals. */ public static String getUniqueMarkName(Set usedNames, List citationKeys, @@ -100,7 +103,6 @@ public static String getUniqueMarkName(Set usedNames, * Parse a JabRef (reference) mark name. * * @return Optional.empty() on failure. - * */ public static Optional parseMarkName(String refMarkName) { @@ -117,8 +119,7 @@ public static Optional parseMarkName(String refMarkName) { } /** - * @return true if name matches the pattern used for JabRef - * reference mark names. + * @return true if name matches the pattern used for JabRef reference mark names. */ public static boolean isJabRefReferenceMarkName(String name) { return (CITE_PATTERN.matcher(name).find()); diff --git a/src/main/java/org/jabref/logic/openoffice/backend/GetContext.java b/src/main/java/org/jabref/logic/openoffice/backend/GetContext.java index ffce5b9553e..865682f0ccc 100644 --- a/src/main/java/org/jabref/logic/openoffice/backend/GetContext.java +++ b/src/main/java/org/jabref/logic/openoffice/backend/GetContext.java @@ -12,21 +12,17 @@ public class GetContext { private static final Logger LOGGER = LoggerFactory.getLogger(GetContext.class); private GetContext() { - // Just to hide the public constructor } /** - * Get the text belonging to cursor with up to - * charBefore and charAfter characters of context. - * - * The actual context may be smaller than requested. - * - * @param cursor - * @param charBefore Number of characters requested. - * @param charAfter Number of characters requested. - * @param htmlMarkup If true, the text belonging to the reference mark is surrounded by bold - * html tag. + * Get the text belonging to cursor with up to charBefore and charAfter characters of context. + *

+ * The actual context may be smaller than requested. * + * @param cursor + * @param charBefore Number of characters requested. + * @param charAfter Number of characters requested. + * @param htmlMarkup If true, the text belonging to the reference mark is surrounded by bold html tag. */ public static String getCursorStringWithContext(XTextCursor cursor, int charBefore, @@ -43,7 +39,7 @@ public static String getCursorStringWithContext(XTextCursor cursor, // If we are close to charBefore and see a space, then cut here. Might avoid cutting // a word in half. if ((i >= (charBefore - flex)) - && Character.isWhitespace(cursor.getString().charAt(0))) { + && Character.isWhitespace(cursor.getString().charAt(0))) { break; } } catch (IndexOutOfBoundsException ex) { @@ -72,10 +68,9 @@ public static String getCursorStringWithContext(XTextCursor cursor, String result = cursor.getString(); if (htmlMarkup) { result = (result.substring(0, addedBefore) - + "" + citPart + "" - + result.substring(lengthWithBefore)); + + "" + citPart + "" + + result.substring(lengthWithBefore)); } return result.trim(); } - } diff --git a/src/main/java/org/jabref/logic/openoffice/backend/NamedRangeManagerReferenceMark.java b/src/main/java/org/jabref/logic/openoffice/backend/NamedRangeManagerReferenceMark.java index 93ad6d12908..fead1169b8e 100644 --- a/src/main/java/org/jabref/logic/openoffice/backend/NamedRangeManagerReferenceMark.java +++ b/src/main/java/org/jabref/logic/openoffice/backend/NamedRangeManagerReferenceMark.java @@ -21,23 +21,23 @@ public NamedRange createNamedRange(XTextDocument doc, XTextCursor position, boolean insertSpaceAfter, boolean withoutBrackets) - throws - CreationException { + throws + CreationException { return NamedRangeReferenceMark.create(doc, refMarkName, position, insertSpaceAfter, withoutBrackets); } @Override public List getUsedNames(XTextDocument doc) - throws - NoDocumentException { + throws + NoDocumentException { return UnoReferenceMark.getListOfNames(doc); } @Override public Optional getNamedRangeFromDocument(XTextDocument doc, String refMarkName) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { return (NamedRangeReferenceMark .getFromDocument(doc, refMarkName) .map(x -> x)); diff --git a/src/main/java/org/jabref/logic/openoffice/backend/NamedRangeReferenceMark.java b/src/main/java/org/jabref/logic/openoffice/backend/NamedRangeReferenceMark.java index 324b984377c..e816b3bfa97 100644 --- a/src/main/java/org/jabref/logic/openoffice/backend/NamedRangeReferenceMark.java +++ b/src/main/java/org/jabref/logic/openoffice/backend/NamedRangeReferenceMark.java @@ -17,25 +17,26 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -// was StorageBaseRefMark - class NamedRangeReferenceMark implements NamedRange { private static final String ZERO_WIDTH_SPACE = "\u200b"; // for debugging we may want visible bracket private static final boolean - REFERENCE_MARK_USE_INVISIBLE_BRACKETS = true; // !debug; + REFERENCE_MARK_USE_INVISIBLE_BRACKETS = true; // !debug; public static final String - REFERENCE_MARK_LEFT_BRACKET = REFERENCE_MARK_USE_INVISIBLE_BRACKETS ? ZERO_WIDTH_SPACE : "<"; + REFERENCE_MARK_LEFT_BRACKET = REFERENCE_MARK_USE_INVISIBLE_BRACKETS ? ZERO_WIDTH_SPACE : "<"; public static final String - REFERENCE_MARK_RIGHT_BRACKET = REFERENCE_MARK_USE_INVISIBLE_BRACKETS ? ZERO_WIDTH_SPACE : ">"; + REFERENCE_MARK_RIGHT_BRACKET = REFERENCE_MARK_USE_INVISIBLE_BRACKETS ? ZERO_WIDTH_SPACE : ">"; private static final Logger LOGGER = LoggerFactory.getLogger(NamedRangeReferenceMark.class); - private String rangeId; /* reference mark name */ + /** + * reference mark name + */ + private final String rangeId; private NamedRangeReferenceMark(String rangeId) { this.rangeId = rangeId; @@ -46,20 +47,15 @@ String getId() { } /** - * Insert {@code n} spaces in a way that reference marks just before or just after the cursor - * are not affected. - * - * This is based on the observation, that starting two new paragraphs separates us from - * reference marks on either side. - * - * The pattern used is: - * {@code safeInsertSpaces(n): para, para, left, space(n), right-delete, left(n), left-delete} - * - * @param position Where to insert (at position.getStart()) - * @param numSpaces Number of spaces to insert. - * - * @return a new cursor, covering the just-inserted spaces. + * Insert {@code n} spaces in a way that reference marks just before or just after the cursor are not affected. + *

+ * This is based on the observation, that starting two new paragraphs separates us from reference marks on either side. + *

+ * The pattern used is: {@code safeInsertSpaces(n): para, para, left, space(n), right-delete, left(n), left-delete} * + * @param position Where to insert (at position.getStart()) + * @param numSpaces Number of spaces to insert. + * @return a new cursor, covering the just-inserted spaces. */ private static XTextCursor safeInsertSpacesBetweenReferenceMarks(XTextRange position, int numSpaces) { // Start with an empty cursor at position.getStart(); @@ -82,8 +78,8 @@ private static void createReprInDocument(XTextDocument doc, XTextCursor position, boolean insertSpaceAfter, boolean withoutBrackets) - throws - CreationException { + throws + CreationException { // The cursor we received: we push it before us. position.collapseToEnd(); @@ -101,8 +97,8 @@ private static void createReprInDocument(XTextDocument doc, final String left = NamedRangeReferenceMark.REFERENCE_MARK_LEFT_BRACKET; final String right = NamedRangeReferenceMark.REFERENCE_MARK_RIGHT_BRACKET; String bracketedContent = (withoutBrackets - ? "" - : left + right); + ? "" + : left + right); cursor.getText().insertString(cursor, bracketedContent, true); @@ -123,8 +119,8 @@ static NamedRangeReferenceMark create(XTextDocument doc, XTextCursor position, boolean insertSpaceAfter, boolean withoutBrackets) - throws - CreationException { + throws + CreationException { createReprInDocument(doc, refMarkName, position, insertSpaceAfter, withoutBrackets); return new NamedRangeReferenceMark(refMarkName); @@ -134,23 +130,23 @@ static NamedRangeReferenceMark create(XTextDocument doc, * @return Optional.empty if there is no corresponding range. */ static Optional getFromDocument(XTextDocument doc, String refMarkName) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { return (UnoReferenceMark.getAnchor(doc, refMarkName) - .map(e -> new NamedRangeReferenceMark(refMarkName))); + .map(e -> new NamedRangeReferenceMark(refMarkName))); } /** * Remove it from the document. - * + *

* See: removeCitationGroups */ @Override public void removeFromDocument(XTextDocument doc) - throws - WrappedTargetException, - NoDocumentException { + throws + WrappedTargetException, + NoDocumentException { UnoReferenceMark.removeIfExists(doc, this.getRangeName()); } @@ -160,34 +156,27 @@ public String getRangeName() { } /** - * - * @return Optional.empty if the reference mark is missing. - * - * See: UnoReferenceMark.getAnchor + * @return Optional.empty if the reference mark is missing. See: UnoReferenceMark.getAnchor */ @Override public Optional getMarkRange(XTextDocument doc) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { String name = this.getRangeName(); return UnoReferenceMark.getAnchor(doc, name); } /** - * Cursor for the reference marks as is, not prepared for filling, but does not need - * cleanFillCursor either. - * - * @return Optional.empty() if reference mark is missing from the document, - * otherwise an XTextCursor for getMarkRange + * Cursor for the reference marks as is, not prepared for filling, but does not need cleanFillCursor either. * - * See: getRawCursorForCitationGroup + * @return Optional.empty() if reference mark is missing from the document, otherwise an XTextCursor for getMarkRange See: getRawCursorForCitationGroup */ @Override public Optional getRawCursor(XTextDocument doc) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { String name = this.getRangeName(); @@ -210,10 +199,10 @@ public Optional getRawCursor(XTextDocument doc) */ @Override public XTextCursor getFillCursor(XTextDocument doc) - throws - NoDocumentException, - WrappedTargetException, - CreationException { + throws + NoDocumentException, + WrappedTargetException, + CreationException { String name = this.getRangeName(); @@ -357,8 +346,8 @@ public static void checkFillCursor(XTextCursor cursor) { alpha.goLeft(leftLength, true); if (!left.equals(alpha.getString())) { String msg = String.format("checkFillCursor:" - + " ('%s') is not prefixed with REFERENCE_MARK_LEFT_BRACKET, has '%s'", - cursor.getString(), alpha.getString()); + + " ('%s') is not prefixed with REFERENCE_MARK_LEFT_BRACKET, has '%s'", + cursor.getString(), alpha.getString()); throw new IllegalStateException(msg); } } @@ -369,24 +358,23 @@ public static void checkFillCursor(XTextCursor cursor) { omega.goRight(rightLength, true); if (!right.equals(omega.getString())) { String msg = String.format("checkFillCursor:" - + " ('%s') is not followed by REFERENCE_MARK_RIGHT_BRACKET, has '%s'", - cursor.getString(), omega.getString()); + + " ('%s') is not followed by REFERENCE_MARK_RIGHT_BRACKET, has '%s'", + cursor.getString(), omega.getString()); throw new IllegalStateException(msg); } } } /** - * Remove brackets, but if the result would become empty, leave them; if the result would be a - * single characer, leave the left bracket. - * + * Remove brackets, but if the result would become empty, leave them; if the result would be a single characer, leave the left bracket. + *

* See: cleanFillCursorForCitationGroup */ @Override public void cleanFillCursor(XTextDocument doc) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { // alwaysRemoveBrackets : full compatibility with JabRef 5.2: brackets are temporary, only // exist between getFillCursor and cleanFillCursor. @@ -422,12 +410,12 @@ public void cleanFillCursor(XTextDocument doc) } boolean removeRight = ((contentLength >= 1) - || ((contentLength == 0) && removeBracketsFromEmpty) - || alwaysRemoveBrackets); + || ((contentLength == 0) && removeBracketsFromEmpty) + || alwaysRemoveBrackets); boolean removeLeft = ((contentLength >= 2) - || ((contentLength == 0) && removeBracketsFromEmpty) - || alwaysRemoveBrackets); + || ((contentLength == 0) && removeBracketsFromEmpty) + || alwaysRemoveBrackets); if (removeRight) { XTextCursor omega = full.getText().createTextCursorByRange(full); diff --git a/src/main/java/org/jabref/logic/openoffice/frontend/OOFrontend.java b/src/main/java/org/jabref/logic/openoffice/frontend/OOFrontend.java index 58057c382e7..01470867257 100644 --- a/src/main/java/org/jabref/logic/openoffice/frontend/OOFrontend.java +++ b/src/main/java/org/jabref/logic/openoffice/frontend/OOFrontend.java @@ -47,9 +47,9 @@ public class OOFrontend { public final CitationGroups citationGroups; public OOFrontend(XTextDocument doc) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { // TODO: dataModel should come from looking at the document and preferences. this.backend = new Backend52(); @@ -58,7 +58,7 @@ public OOFrontend(XTextDocument doc) List citationGroupNames = this.backend.getJabRefReferenceMarkNames(doc); Map citationGroups = - readCitationGroupsFromDocument(this.backend, doc, citationGroupNames); + readCitationGroupsFromDocument(this.backend, doc, citationGroupNames); this.citationGroups = new CitationGroups(citationGroups); } @@ -67,8 +67,8 @@ public OODataModel getDataModel() { } public Optional healthReport(XTextDocument doc) - throws - NoDocumentException { + throws + NoDocumentException { return backend.healthReport(doc); } @@ -76,9 +76,9 @@ public Optional healthReport(XTextDocument doc) readCitationGroupsFromDocument(Backend52 backend, XTextDocument doc, List citationGroupNames) - throws - WrappedTargetException, - NoDocumentException { + throws + WrappedTargetException, + NoDocumentException { Map citationGroups = new HashMap<>(); for (String name : citationGroupNames) { @@ -89,32 +89,27 @@ public Optional healthReport(XTextDocument doc) } /** - * Creates a list of {@code RangeSortable} values for our {@code CitationGroup} - * values. Originally designed to be passed to {@code visualSort}. - * + * Creates a list of {@code RangeSortable} values for our {@code CitationGroup} values. Originally designed to be passed to {@code visualSort}. + *

* The elements of the returned list are actually of type {@code RangeSortEntry}. + *

+ * The result is sorted within {@code XTextRange.getText()} partitions of the citation groups according to their {@code XTextRange} (before mapping to footnote marks). + *

+ * In the result, RangeSortable.getIndexInPosition() contains unique indexes within the original partition (not after mapFootnotesToFootnoteMarks). * - * The result is sorted within {@code XTextRange.getText()} partitions of the citation groups - * according to their {@code XTextRange} (before mapping to footnote marks). - * - * In the result, RangeSortable.getIndexInPosition() contains unique indexes within the original - * partition (not after mapFootnotesToFootnoteMarks). - * - * @param mapFootnotesToFootnoteMarks If true, replace ranges in footnotes with the range of the - * corresponding footnote mark. This is used for numbering the citations. - * + * @param mapFootnotesToFootnoteMarks If true, replace ranges in footnotes with the range of the corresponding footnote mark. This is used for numbering the citations. */ - private List> - createVisualSortInput(XTextDocument doc, boolean mapFootnotesToFootnoteMarks) - throws - NoDocumentException, - WrappedTargetException { + private List> createVisualSortInput(XTextDocument doc, + boolean mapFootnotesToFootnoteMarks) + throws + NoDocumentException, + WrappedTargetException { List> sortables = new ArrayList<>(); for (CitationGroup group : citationGroups.getCitationGroupsUnordered()) { XTextRange range = (this - .getMarkRange(doc, group) - .orElseThrow(IllegalStateException::new)); + .getMarkRange(doc, group) + .orElseThrow(IllegalStateException::new)); sortables.add(new RangeSortEntry<>(range, 0, group)); } @@ -137,7 +132,7 @@ public Optional healthReport(XTextDocument doc) // Sort within partitions RangeSort.RangePartitions> partitions = - RangeSort.partitionAndSortRanges(sortables); + RangeSort.partitionAndSortRanges(sortables); // build final list List> result = new ArrayList<>(); @@ -148,75 +143,64 @@ public Optional healthReport(XTextDocument doc) sortable.setIndexInPosition(indexInPartition++); if (mapFootnotesToFootnoteMarks) { Optional footnoteMarkRange = - UnoTextRange.getFootnoteMarkRange(sortable.getRange()); + UnoTextRange.getFootnoteMarkRange(sortable.getRange()); // Adjust range if we are inside a footnote: - if (footnoteMarkRange.isPresent()) { - sortable.setRange(footnoteMarkRange.get()); - } + footnoteMarkRange.ifPresent(sortable::setRange); } result.add(sortable); } } - return result.stream().map(e -> e).collect(Collectors.toList()); + return new ArrayList<>(result); } /** - * @param mapFootnotesToFootnoteMarks If true, sort reference marks in footnotes as if they - * appeared at the corresponding footnote mark. - * - * @return citation groups sorted by their visual positions. - * - * Limitation: for two column layout visual (top-down, left-right) order does not match the - * expected (textual) order. - * + * @param mapFootnotesToFootnoteMarks If true, sort reference marks in footnotes as if they appeared at the corresponding footnote mark. + * @return citation groups sorted by their visual positions. Limitation: for two column layout visual (top-down, left-right) order does not match the expected (textual) order. */ private List getVisuallySortedCitationGroups(XTextDocument doc, boolean mapFootnotesToFootnoteMarks, FunctionalTextViewCursor fcursor) - throws - WrappedTargetException, - NoDocumentException { + throws + WrappedTargetException, + NoDocumentException { List> sortables = createVisualSortInput(doc, mapFootnotesToFootnoteMarks); List> sorted = RangeSortVisual.visualSort(sortables, doc, fcursor); return (sorted.stream() - .map(RangeSortable::getContent) - .collect(Collectors.toList())); + .map(RangeSortable::getContent) + .collect(Collectors.toList())); } /** * Return citation groups in visual order within (but not across) XText partitions. - * - * This is (1) sufficient for combineCiteMarkers which looks for consecutive XTextRanges within - * each XText, (2) not confused by multicolumn layout or multipage display. + *

+ * This is (1) sufficient for combineCiteMarkers which looks for consecutive XTextRanges within each XText, (2) not confused by multicolumn layout or multipage display. */ public List getCitationGroupsSortedWithinPartitions(XTextDocument doc, boolean mapFootnotesToFootnoteMarks) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { // This is like getVisuallySortedCitationGroups, // but we skip the visualSort part. List> sortables = - createVisualSortInput(doc, mapFootnotesToFootnoteMarks); + createVisualSortInput(doc, mapFootnotesToFootnoteMarks); - return (sortables.stream().map(e -> e.getContent()).collect(Collectors.toList())); + return (sortables.stream().map(RangeSortable::getContent).collect(Collectors.toList())); } /** - * Create a citation group for the given citation keys, at the end of position. - * - * On return {@code position} is collapsed, and is after the inserted space, or at the end of - * the reference mark. + * Create a citation group for the given citation keys, at the end of position. + *

+ * On return {@code position} is collapsed, and is after the inserted space, or at the end of the reference mark. * - * @param citationKeys In storage order - * @param pageInfos In storage order + * @param citationKeys In storage order + * @param pageInfos In storage order * @param citationType - * @param position Collapsed to its end. - * @param insertSpaceAfter If true, we insert a space after the mark, that carries on format of - * characters from the original position. + * @param position Collapsed to its end. + * @param insertSpaceAfter If true, we insert a space after the mark, that carries on format of characters from the original position. */ public CitationGroup createCitationGroup(XTextDocument doc, List citationKeys, @@ -224,24 +208,24 @@ public CitationGroup createCitationGroup(XTextDocument doc, CitationType citationType, XTextCursor position, boolean insertSpaceAfter) - throws - CreationException, - NoDocumentException, - WrappedTargetException, - NotRemoveableException, - PropertyVetoException, - IllegalTypeException { + throws + CreationException, + NoDocumentException, + WrappedTargetException, + NotRemoveableException, + PropertyVetoException, + IllegalTypeException { Objects.requireNonNull(pageInfos); if (pageInfos.size() != citationKeys.size()) { throw new IllegalArgumentException("pageInfos.size != citationKeys.size"); } CitationGroup group = backend.createCitationGroup(doc, - citationKeys, - pageInfos, - citationType, - position, - insertSpaceAfter); + citationKeys, + pageInfos, + citationType, + position, + insertSpaceAfter); this.citationGroups.afterCreateCitationGroup(group); return group; @@ -251,22 +235,22 @@ public CitationGroup createCitationGroup(XTextDocument doc, * Remove {@code group} both from the document and notify {@code citationGroups} */ public void removeCitationGroup(CitationGroup group, XTextDocument doc) - throws - WrappedTargetException, - NoDocumentException, - NotRemoveableException { + throws + WrappedTargetException, + NoDocumentException, + NotRemoveableException { backend.removeCitationGroup(group, doc); this.citationGroups.afterRemoveCitationGroup(group); } - public void removeCitationGroups(List cgs, XTextDocument doc) - throws - WrappedTargetException, - NoDocumentException, - NotRemoveableException { + public void removeCitationGroups(List citationGroups, XTextDocument doc) + throws + WrappedTargetException, + NoDocumentException, + NotRemoveableException { - for (CitationGroup group : cgs) { + for (CitationGroup group : citationGroups) { removeCitationGroup(group, doc); } } @@ -275,20 +259,19 @@ public void removeCitationGroups(List cgs, XTextDocument doc) * ranges controlled by citation groups should not overlap with each other. * * @return Optional.empty() if the reference mark is missing. - * */ public Optional getMarkRange(XTextDocument doc, CitationGroup group) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { return backend.getMarkRange(group, doc); } public XTextCursor getFillCursorForCitationGroup(XTextDocument doc, CitationGroup group) - throws - NoDocumentException, - WrappedTargetException, - CreationException { + throws + NoDocumentException, + WrappedTargetException, + CreationException { return backend.getFillCursorForCitationGroup(group, doc); } @@ -296,41 +279,39 @@ public XTextCursor getFillCursorForCitationGroup(XTextDocument doc, CitationGrou * Remove brackets added by getFillCursorForCitationGroup. */ public void cleanFillCursorForCitationGroup(XTextDocument doc, CitationGroup group) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { backend.cleanFillCursorForCitationGroup(group, doc); } /** - * @return A RangeForOverlapCheck for each citation group. - * - * result.size() == nRefMarks + * @return A RangeForOverlapCheck for each citation group. result.size() == nRefMarks */ public List> citationRanges(XTextDocument doc) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { List> result = - new ArrayList<>(citationGroups.numberOfCitationGroups()); + new ArrayList<>(citationGroups.numberOfCitationGroups()); for (CitationGroup group : citationGroups.getCitationGroupsUnordered()) { XTextRange range = this.getMarkRange(doc, group).orElseThrow(IllegalStateException::new); String description = group.groupId.citationGroupIdAsString(); result.add(new RangeForOverlapCheck<>(range, - group.groupId, - RangeForOverlapCheck.REFERENCE_MARK_KIND, - description)); + group.groupId, + RangeForOverlapCheck.REFERENCE_MARK_KIND, + description)); } return result; } public List> bibliographyRanges(XTextDocument doc) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { List> result = new ArrayList<>(); @@ -338,9 +319,9 @@ public List> bibliographyRanges(XTextDocum if (range.isPresent()) { String description = "bibliography"; result.add(new RangeForOverlapCheck<>(range.get(), - new CitationGroupId("bibliography"), - RangeForOverlapCheck.BIBLIOGRAPHY_MARK_KIND, - description)); + new CitationGroupId("bibliography"), + RangeForOverlapCheck.BIBLIOGRAPHY_MARK_KIND, + description)); } return result; } @@ -353,23 +334,17 @@ public List> viewCursorRanges(XTextDocumen if (range.isPresent()) { String description = "cursor"; result.add(new RangeForOverlapCheck<>(range.get(), - new CitationGroupId("cursor"), - RangeForOverlapCheck.CURSOR_MARK_KIND, - description)); + new CitationGroupId("cursor"), + RangeForOverlapCheck.CURSOR_MARK_KIND, + description)); } return result; } /** - * @return A range for each footnote mark where the footnote contains at least one citation group. - * - * Purpose: We do not want markers of footnotes containing reference marks to overlap with - * reference marks. Overwriting these footnote marks might kill our reference marks in the - * footnote. - * - * Note: Here we directly communicate to the document, not through the backend. This is because - * mapping ranges to footnote marks does not depend on how do we mark or structure those - * ranges. + * @return A range for each footnote mark where the footnote contains at least one citation group. Purpose: We do not want markers of footnotes containing reference marks to overlap with reference marks. Overwriting these footnote marks might kill our reference marks in the footnote. + *

+ * Note: Here we directly communicate to the document, not through the backend. This is because mapping ranges to footnote marks does not depend on how do we mark or structure those ranges. */ public List> footnoteMarkRanges(XTextDocument doc, List> citationRanges) { @@ -379,7 +354,7 @@ public List> viewCursorRanges(XTextDocumen List> result = new ArrayList<>(); RangeSort.RangePartitions> partitions = - RangeSort.partitionRanges(citationRanges); + RangeSort.partitionRanges(citationRanges); // Each partition corresponds to an XText, and each footnote has a single XText. // (This latter ignores the possibility of XTextContents inserted into footnotes.) @@ -398,9 +373,9 @@ public List> viewCursorRanges(XTextDocumen } result.add(new RangeForOverlapCheck<>(footnoteMarkRange.get(), - citationRange.idWithinKind, - RangeForOverlapCheck.FOOTNOTE_MARK_KIND, - "FootnoteMark for " + citationRange.format())); + citationRange.idWithinKind, + RangeForOverlapCheck.FOOTNOTE_MARK_KIND, + "FootnoteMark for " + citationRange.format())); } return result; } @@ -414,14 +389,14 @@ static String rangeOverlapsToMessage(List> overlap : overlaps) { String listOfRanges = (overlap.valuesForOverlappingRanges.stream() - .map(v -> String.format("'%s'", v.format())) - .collect(Collectors.joining(", "))); + .map(v -> String.format("'%s'", v.format())) + .collect(Collectors.joining(", "))); msg.append( - switch (overlap.kind) { - case EQUAL_RANGE -> Localization.lang("Found identical ranges"); - case OVERLAP -> Localization.lang("Found overlapping ranges"); - case TOUCH -> Localization.lang("Found touching ranges"); - }); + switch (overlap.kind) { + case EQUAL_RANGE -> Localization.lang("Found identical ranges"); + case OVERLAP -> Localization.lang("Found overlapping ranges"); + case TOUCH -> Localization.lang("Found touching ranges"); + }); msg.append(": "); msg.append(listOfRanges); msg.append("\n"); @@ -431,18 +406,18 @@ static String rangeOverlapsToMessage(List * Assume userRanges is small (usually 1 elements for checking the cursor) - * + *

* Returns on first problem found. */ public OOVoidResult checkRangeOverlapsWithCursor(XTextDocument doc, List> userRanges, boolean requireSeparation) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { List> citationRanges = citationRanges(doc); List> ranges = new ArrayList<>(); @@ -453,30 +428,29 @@ static String rangeOverlapsToMessage(List>> overlaps = - RangeOverlapBetween.findFirst(doc, - userRanges, - ranges, - requireSeparation); + RangeOverlapBetween.findFirst(doc, + userRanges, + ranges, + requireSeparation); if (overlaps.isEmpty()) { return OOVoidResult.ok(); } return OOVoidResult.error(new JabRefException("Found overlapping or touching ranges", - rangeOverlapsToMessage(overlaps))); + rangeOverlapsToMessage(overlaps))); } /** * @param requireSeparation Report range pairs that only share a boundary. - * @param reportAtMost Limit number of overlaps reported (0 for no limit) - * + * @param reportAtMost Limit number of overlaps reported (0 for no limit) */ public OOVoidResult checkRangeOverlaps(XTextDocument doc, List> userRanges, boolean requireSeparation, int reportAtMost) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { List> citationRanges = citationRanges(doc); List> ranges = new ArrayList<>(); @@ -486,69 +460,56 @@ public OOVoidResult checkRangeOverlaps(XTextDocument doc, ranges.addAll(footnoteMarkRanges(doc, citationRanges)); List>> overlaps = - RangeOverlapWithin.findOverlappingRanges(doc, ranges, requireSeparation, reportAtMost); + RangeOverlapWithin.findOverlappingRanges(doc, ranges, requireSeparation, reportAtMost); if (overlaps.isEmpty()) { return OOVoidResult.ok(); } return OOVoidResult.error(new JabRefException("Found overlapping or touching ranges", - rangeOverlapsToMessage(overlaps))); + rangeOverlapsToMessage(overlaps))); } /** - * GUI: Get a list of CitationEntry objects corresponding to citations - * in the document. - * + * GUI: Get a list of CitationEntry objects corresponding to citations in the document. + *

* Called from: ManageCitationsDialogViewModel constructor. * - * @return A list with entries corresponding to citations in the text, in arbitrary order (same - * order as from getJabRefReferenceMarkNames). - * - * Note: visual or alphabetic order could be more manageable for the user. We - * could provide these here, but switching between them needs change on GUI - * (adding a toggle or selector). - * - * Note: CitationEntry implements Comparable, where compareTo() and equals() are - * based on refMarkName. The order used in the "Manage citations" dialog - * does not seem to use that. - * - * The 1st is labeled "Citation" (show citation in bold, and some context - * around it). - * - * The columns can be sorted by clicking on the column title. For the - * "Citation" column, the sorting is based on the content, (the context - * before the citation), not on the citation itself. - * - * In the "Extra information ..." column some visual indication of the - * editable part could be helpful. - * - * Wish: selecting an entry (or a button in the line) in the GUI could move the cursor - * in the document to the entry. + * @return A list with entries corresponding to citations in the text, in arbitrary order (same order as from getJabRefReferenceMarkNames). Note: visual or alphabetic order could be more manageable for the user. We could provide these here, but switching between them needs change on GUI (adding a toggle or selector). + *

+ * Note: CitationEntry implements Comparable, where compareTo() and equals() are based on refMarkName. The order used in the "Manage citations" dialog does not seem to use that. + *

+ * The 1st is labeled "Citation" (show citation in bold, and some context around it). + *

+ * The columns can be sorted by clicking on the column title. For the "Citation" column, the sorting is based on the content, (the context before the citation), not on the citation itself. + *

+ * In the "Extra information ..." column some visual indication of the editable part could be helpful. + *

+ * Wish: selecting an entry (or a button in the line) in the GUI could move the cursor in the document to the entry. */ public List getCitationEntries(XTextDocument doc) - throws - WrappedTargetException, - NoDocumentException { + throws + WrappedTargetException, + NoDocumentException { return this.backend.getCitationEntries(doc, citationGroups); } public void applyCitationEntries(XTextDocument doc, List citationEntries) - throws - PropertyVetoException, - IllegalTypeException, - IllegalArgumentException, - WrappedTargetException { + throws + PropertyVetoException, + IllegalTypeException, + IllegalArgumentException, + WrappedTargetException { this.backend.applyCitationEntries(doc, citationEntries); } public void imposeGlobalOrder(XTextDocument doc, FunctionalTextViewCursor fcursor) - throws - WrappedTargetException, - NoDocumentException { + throws + WrappedTargetException, + NoDocumentException { boolean mapFootnotesToFootnoteMarks = true; List sortedCitationGroups = - getVisuallySortedCitationGroups(doc, mapFootnotesToFootnoteMarks, fcursor); + getVisuallySortedCitationGroups(doc, mapFootnotesToFootnoteMarks, fcursor); List sortedCitationGroupIds = OOListUtil.map(sortedCitationGroups, group -> group.groupId); citationGroups.setGlobalOrder(sortedCitationGroupIds); } diff --git a/src/main/java/org/jabref/logic/openoffice/frontend/RangeForOverlapCheck.java b/src/main/java/org/jabref/logic/openoffice/frontend/RangeForOverlapCheck.java index 6cbf560ec62..914195bd243 100644 --- a/src/main/java/org/jabref/logic/openoffice/frontend/RangeForOverlapCheck.java +++ b/src/main/java/org/jabref/logic/openoffice/frontend/RangeForOverlapCheck.java @@ -6,17 +6,10 @@ /** * Describe a protected range for overlap checking and reporting. - * - * To check that our protected ranges do not overlap, we collect - * these ranges. To check for overlaps between these, we need the - * {@code range} itself. To report the results of overlap - * checking, we need a {@code description} that can be understood - * by the user. - * - * To be able to refer back to more extended data, we might need to - * identify its {@code kind}, and its index in the corresponding - * tables or other identifier within its kind ({@code idWithinKind}) - * + *

+ * To check that our protected ranges do not overlap, we collect these ranges. To check for overlaps between these, we need the {@code range} itself. To report the results of overlap checking, we need a {@code description} that can be understood by the user. + *

+ * To be able to refer back to more extended data, we might need to identify its {@code kind}, and its index in the corresponding tables or other identifier within its kind ({@code idWithinKind}) */ public class RangeForOverlapCheck implements RangeHolder { diff --git a/src/main/java/org/jabref/logic/openoffice/frontend/UpdateBibliography.java b/src/main/java/org/jabref/logic/openoffice/frontend/UpdateBibliography.java index ebda8359ba5..99e71e13725 100644 --- a/src/main/java/org/jabref/logic/openoffice/frontend/UpdateBibliography.java +++ b/src/main/java/org/jabref/logic/openoffice/frontend/UpdateBibliography.java @@ -17,22 +17,18 @@ import com.sun.star.text.XTextDocument; import com.sun.star.text.XTextRange; -/* - * Update document: citation marks and bibliography - */ public class UpdateBibliography { private static final String BIB_SECTION_NAME = "JR_bib"; private static final String BIB_SECTION_END_NAME = "JR_bib_end"; private UpdateBibliography() { - /**/ } public static Optional getBibliographyRange(XTextDocument doc) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { return UnoTextSection.getAnchor(doc, BIB_SECTION_NAME); } @@ -44,28 +40,28 @@ public static void rebuildBibTextSection(XTextDocument doc, CitedKeys bibliography, OOBibStyle style, boolean alwaysAddCitedOnPages) - throws - WrappedTargetException, - CreationException, - NoDocumentException { + throws + WrappedTargetException, + CreationException, + NoDocumentException { clearBibTextSectionContent2(doc); populateBibTextSection(doc, - frontend, - bibliography, - style, - alwaysAddCitedOnPages); + frontend, + bibliography, + style, + alwaysAddCitedOnPages); } /** * Insert a paragraph break and create a text section for the bibliography. - * + *

* Only called from `clearBibTextSectionContent2` */ private static void createBibTextSection2(XTextDocument doc) - throws - CreationException { + throws + CreationException { // Always creating at the end of the document. // Alternatively, we could receive a cursor. @@ -75,23 +71,20 @@ private static void createBibTextSection2(XTextDocument doc) } /** - * Find and clear the text section BIB_SECTION_NAME to "", - * or create it. - * + * Find and clear the text section BIB_SECTION_NAME to "", or create it. + *

* Only called from: `rebuildBibTextSection` - * */ private static void clearBibTextSectionContent2(XTextDocument doc) - throws - CreationException, - NoDocumentException, - WrappedTargetException { + throws + CreationException, + NoDocumentException, + WrappedTargetException { // Optional sectionRange = UnoTextSection.getAnchor(doc, BIB_SECTION_NAME); Optional sectionRange = getBibliographyRange(doc); if (sectionRange.isEmpty()) { createBibTextSection2(doc); - return; } else { // Clear it XTextCursor cursor = doc.getText().createTextCursorByRange(sectionRange.get()); @@ -101,7 +94,7 @@ private static void clearBibTextSectionContent2(XTextDocument doc) /** * Only called from: `rebuildBibTextSection` - * + *

* Assumes the section named BIB_SECTION_NAME exists. */ private static void populateBibTextSection(XTextDocument doc, @@ -109,11 +102,11 @@ private static void populateBibTextSection(XTextDocument doc, CitedKeys bibliography, OOBibStyle style, boolean alwaysAddCitedOnPages) - throws - CreationException, - IllegalArgumentException, - NoDocumentException, - WrappedTargetException { + throws + CreationException, + IllegalArgumentException, + NoDocumentException, + WrappedTargetException { XTextRange sectionRange = getBibliographyRange(doc).orElseThrow(IllegalStateException::new); @@ -122,9 +115,9 @@ private static void populateBibTextSection(XTextDocument doc, // emit the title of the bibliography OOTextIntoOO.removeDirectFormatting(cursor); OOText bibliographyText = OOFormatBibliography.formatBibliography(frontend.citationGroups, - bibliography, - style, - alwaysAddCitedOnPages); + bibliography, + style, + alwaysAddCitedOnPages); OOTextIntoOO.write(doc, cursor, bibliographyText); cursor.collapseToEnd(); @@ -140,5 +133,4 @@ private static void populateBibTextSection(XTextDocument doc, cursor.collapseToEnd(); } - } diff --git a/src/main/java/org/jabref/logic/openoffice/frontend/UpdateCitationMarkers.java b/src/main/java/org/jabref/logic/openoffice/frontend/UpdateCitationMarkers.java index 834fce1d0ce..d61e0cd8e2e 100644 --- a/src/main/java/org/jabref/logic/openoffice/frontend/UpdateCitationMarkers.java +++ b/src/main/java/org/jabref/logic/openoffice/frontend/UpdateCitationMarkers.java @@ -22,34 +22,26 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -/* - * Update document: citation marks and bibliography - */ public class UpdateCitationMarkers { private static final Logger LOGGER = LoggerFactory.getLogger(UpdateCitationMarkers.class); private UpdateCitationMarkers() { - /**/ } /** - * Visit each reference mark in referenceMarkNames, overwrite its - * text content. - * - * After each fillCitationMarkInCursor call check if we lost the - * BIB_SECTION_NAME bookmark and recreate it if we did. + * Visit each reference mark in referenceMarkNames, overwrite its text content. + *

+ * After each fillCitationMarkInCursor call check if we lost the BIB_SECTION_NAME bookmark and recreate it if we did. * * @param frontend - * - * @param style Bibliography style to use. - * + * @param style Bibliography style to use. */ public static void applyNewCitationMarkers(XTextDocument doc, OOFrontend frontend, OOBibStyle style) - throws - NoDocumentException, - CreationException, - WrappedTargetException { + throws + NoDocumentException, + CreationException, + WrappedTargetException { CitationGroups citationGroups = frontend.citationGroups; @@ -58,9 +50,9 @@ public static void applyNewCitationMarkers(XTextDocument doc, OOFrontend fronten boolean withText = (group.citationType != CitationType.INVISIBLE_CIT); Optional marker = group.getCitationMarker(); - if (!marker.isPresent()) { + if (marker.isEmpty()) { LOGGER.warn("applyNewCitationMarkers: no marker for {}", - group.groupId.citationGroupIdAsString()); + group.groupId.citationGroupIdAsString()); continue; } @@ -72,7 +64,6 @@ public static void applyNewCitationMarkers(XTextDocument doc, OOFrontend fronten frontend.cleanFillCursorForCitationGroup(doc, group); } - } } @@ -81,10 +72,10 @@ public static void fillCitationMarkInCursor(XTextDocument doc, OOText citationText, boolean withText, OOBibStyle style) - throws - WrappedTargetException, - CreationException, - IllegalArgumentException { + throws + WrappedTargetException, + CreationException, + IllegalArgumentException { Objects.requireNonNull(cursor); Objects.requireNonNull(citationText); @@ -102,21 +93,15 @@ public static void fillCitationMarkInCursor(XTextDocument doc, } /** - * Inserts a citation group in the document: creates and fills it. + * Inserts a citation group in the document: creates and fills it. * - * @param citationKeys BibTeX keys of + * @param citationKeys BibTeX keys of * @param pageInfos * @param citationType - * - * @param citationText Text for the citation. A citation mark or - * placeholder if not yet available. - * - * @param position Location to insert at. + * @param citationText Text for the citation. A citation mark or placeholder if not yet available. + * @param position Location to insert at. * @param style - * @param insertSpaceAfter A space inserted after the reference - * mark makes it easier to separate from the text - * coming after. But is not wanted when we recreate a - * reference mark. + * @param insertSpaceAfter A space inserted after the reference mark makes it easier to separate from the text coming after. But is not wanted when we recreate a reference mark. */ public static void createAndFillCitationGroup(OOFrontend frontend, XTextDocument doc, @@ -127,25 +112,25 @@ public static void createAndFillCitationGroup(OOFrontend frontend, XTextCursor position, OOBibStyle style, boolean insertSpaceAfter) - throws - NotRemoveableException, - WrappedTargetException, - PropertyVetoException, - IllegalArgumentException, - CreationException, - NoDocumentException, - IllegalTypeException { + throws + NotRemoveableException, + WrappedTargetException, + PropertyVetoException, + IllegalArgumentException, + CreationException, + NoDocumentException, + IllegalTypeException { Objects.requireNonNull(pageInfos); if (pageInfos.size() != citationKeys.size()) { throw new IllegalArgumentException("pageInfos.size != citationKeys.size"); } CitationGroup group = frontend.createCitationGroup(doc, - citationKeys, - pageInfos, - citationType, - position, - insertSpaceAfter); + citationKeys, + pageInfos, + citationType, + position, + insertSpaceAfter); final boolean withText = citationType.withText(); @@ -158,5 +143,4 @@ public static void createAndFillCitationGroup(OOFrontend frontend, } position.collapseToEnd(); } - } diff --git a/src/main/java/org/jabref/logic/openoffice/style/OOBibStyle.java b/src/main/java/org/jabref/logic/openoffice/style/OOBibStyle.java index 5108c94c8b3..cada4950204 100644 --- a/src/main/java/org/jabref/logic/openoffice/style/OOBibStyle.java +++ b/src/main/java/org/jabref/logic/openoffice/style/OOBibStyle.java @@ -1,15 +1,13 @@ package org.jabref.logic.openoffice.style; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.StringReader; -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -25,11 +23,6 @@ import org.jabref.logic.layout.LayoutFormatter; import org.jabref.logic.layout.LayoutFormatterPreferences; import org.jabref.logic.layout.LayoutHelper; -import org.jabref.model.database.BibDatabase; -import org.jabref.model.entry.Author; -import org.jabref.model.entry.AuthorList; -import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.FieldFactory; import org.jabref.model.entry.field.OrFields; import org.jabref.model.entry.field.StandardField; @@ -42,7 +35,6 @@ import org.jabref.model.openoffice.style.CitationMarkerNumericBibEntry; import org.jabref.model.openoffice.style.CitationMarkerNumericEntry; import org.jabref.model.openoffice.style.NonUniqueCitationMarker; -import org.jabref.model.strings.StringUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -138,31 +130,27 @@ public class OOBibStyle implements Comparable { private final Map citProperties = new HashMap<>(); private final boolean fromResource; private final String path; - private final Charset encoding; private final LayoutFormatterPreferences prefs; private String name = ""; private Layout defaultBibLayout; private boolean valid; - private File styleFile; + private Path styleFile; private long styleFileModificationTime = Long.MIN_VALUE; private String localCopy; private boolean isDefaultLayoutPresent; - public OOBibStyle(File styleFile, LayoutFormatterPreferences prefs, - Charset encoding) throws IOException { + public OOBibStyle(Path styleFile, LayoutFormatterPreferences prefs) throws IOException { this.prefs = Objects.requireNonNull(prefs); this.styleFile = Objects.requireNonNull(styleFile); - this.encoding = Objects.requireNonNull(encoding); setDefaultProperties(); reload(); fromResource = false; - path = styleFile.getPath(); + path = styleFile.toAbsolutePath().toString(); } public OOBibStyle(String resourcePath, LayoutFormatterPreferences prefs) throws IOException { this.prefs = Objects.requireNonNull(prefs); Objects.requireNonNull(resourcePath); - this.encoding = StandardCharsets.UTF_8; setDefaultProperties(); initialize(OOBibStyle.class.getResourceAsStream(resourcePath)); fromResource = true; @@ -234,7 +222,7 @@ public String getPath() { return path; } - public File getFile() { + public Path getFile() { return styleFile; } @@ -245,7 +233,7 @@ public Set getJournals() { private void initialize(InputStream stream) throws IOException { Objects.requireNonNull(stream); - try (Reader reader = new InputStreamReader(stream, encoding)) { + try (Reader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) { readFormatFile(reader); } } @@ -270,8 +258,8 @@ public void ensureUpToDate() throws IOException { */ private void reload() throws IOException { if (styleFile != null) { - this.styleFileModificationTime = styleFile.lastModified(); - try (InputStream stream = new FileInputStream(styleFile)) { + this.styleFileModificationTime = Files.getLastModifiedTime(styleFile).toMillis(); + try (InputStream stream = Files.newInputStream(styleFile)) { initialize(stream); } } @@ -287,7 +275,11 @@ private boolean isUpToDate() { if (styleFile == null) { return true; } else { - return styleFile.lastModified() == this.styleFileModificationTime; + try { + return Files.getLastModifiedTime(styleFile).toMillis() == this.styleFileModificationTime; + } catch (IOException e) { + return false; + } } } @@ -446,351 +438,6 @@ public Layout getReferenceFormat(EntryType type) { } } - /* begin_old */ - /** - * Format a number-based citation marker for the given number. - * - * @param number The citation numbers. - * @return The text for the citation. - */ - public String getNumCitationMarker(List number, int minGroupingCount, boolean inList) { - String bracketBefore = getStringCitProperty(BRACKET_BEFORE); - if (inList && (citProperties.containsKey(BRACKET_BEFORE_IN_LIST))) { - bracketBefore = getStringCitProperty(BRACKET_BEFORE_IN_LIST); - } - String bracketAfter = getStringCitProperty(BRACKET_AFTER); - if (inList && (citProperties.containsKey(BRACKET_AFTER_IN_LIST))) { - bracketAfter = getStringCitProperty(BRACKET_AFTER_IN_LIST); - } - // Sort the numbers: - List lNum = new ArrayList<>(number); - Collections.sort(lNum); - StringBuilder stringBuilder = new StringBuilder(bracketBefore); - int combineFrom = -1; - int written = 0; - for (int i = 0; i < lNum.size(); i++) { - int i1 = lNum.get(i); - if (combineFrom < 0) { - // Check if next entry is the next in the ref list: - if ((i < (lNum.size() - 1)) && (lNum.get(i + 1) == (i1 + 1)) && (i1 > 0)) { - combineFrom = i1; - } else { - // Add single entry: - if (i > 0) { - stringBuilder.append(getStringCitProperty(CITATION_SEPARATOR)); - } - stringBuilder.append(lNum.get(i) > 0 ? String.valueOf(lNum.get(i)) : OOBibStyle.UNDEFINED_CITATION_MARKER); - written++; - } - } else { - // We are building a list of combined entries. - // Check if it ends here: - if ((i == (lNum.size() - 1)) || (lNum.get(i + 1) != (i1 + 1))) { - if (written > 0) { - stringBuilder.append(getStringCitProperty(CITATION_SEPARATOR)); - } - if ((minGroupingCount > 0) && (((i1 + 1) - combineFrom) >= minGroupingCount)) { - stringBuilder.append(combineFrom); - stringBuilder.append(getStringCitProperty(GROUPED_NUMBERS_SEPARATOR)); - stringBuilder.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++) { - stringBuilder.append(jj); - if (jj < i1) { - stringBuilder.append(getStringCitProperty(CITATION_SEPARATOR)); - } - written++; - } - } - combineFrom = -1; - } - // If it doesn't end here, just keep iterating. - } - } - stringBuilder.append(bracketAfter); - return stringBuilder.toString(); - } - /* end_old */ - - /* begin_old */ - public String getCitationMarker(List entries, Map 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].isEmpty()) { - // 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); - } - - piv = -1; - } else { - BibEntry currentEntry = entries.get(i); - if (piv == -1) { - piv = i; - tmpMarker = getAuthorYearParenthesisMarker(Collections.singletonList(currentEntry), database, - null, unlimAuthors); - } else { - // See if this entry can go into a group with the previous one: - String thisMarker = getAuthorYearParenthesisMarker(Collections.singletonList(currentEntry), - database, null, unlimAuthors); - - String authorField = getStringCitProperty(AUTHOR_FIELD); - int maxAuthors = getIntCitProperty(MAX_AUTHORS); - String author = getCitationMarkerField(currentEntry, database.get(currentEntry), - authorField); - AuthorList al = AuthorList.parse(author); - int prevALim = unlimAuthors[i - 1]; // i always at least 1 here - if (!thisMarker.equals(tmpMarker) - || ((al.getNumberOfAuthors() > 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); - } - tmpMarker = thisMarker; - piv = i; - } - } - } - - } - // 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); - } - } - - if (inParenthesis) { - return getAuthorYearParenthesisMarker(entries, database, uniquefiers, unlimAuthors); - } else { - return getAuthorYearInTextMarker(entries, database, uniquefiers, unlimAuthors); - } - } - /* end_old */ - - /* begin_old */ - /** - * Modify entry and uniquefier arrays to facilitate a grouped presentation of uniquefied 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) - */ - private void group(List entries, String[] uniquefiers, int from, int to) { - String separator = getStringCitProperty(UNIQUEFIER_SEPARATOR); - StringBuilder stringBuilder = new StringBuilder(uniquefiers[from]); - for (int i = from + 1; i <= to; i++) { - stringBuilder.append(separator); - stringBuilder.append(uniquefiers[i]); - entries.set(i, null); - } - uniquefiers[from] = stringBuilder.toString(); - } - /* end_old */ - - /* begin_old */ - /** - * This method produces (Author, year) style citation strings in many different forms. - * - * @param entries The list of BibEntry to get fields from. - * @param database A map of BibEntry-BibDatabase pairs. - * @param uniquifiers Optional parameter to separate similar citations. Elements can be null if not needed. - * @return The formatted citation. - */ - private String getAuthorYearParenthesisMarker(List entries, Map database, - String[] uniquifiers, int[] unlimAuthors) { - - String authorField = getStringCitProperty(AUTHOR_FIELD); // The bibtex field providing author names, e.g. "author" or "editor". - int maxA = getIntCitProperty(MAX_AUTHORS); // The maximum number of authors to write out in full without using etal. Set to - // -1 to always write out all authors. - String yearSep = getStringCitProperty(YEAR_SEPARATOR); // The String to separate authors from year, e.g. "; ". - String startBrace = getStringCitProperty(BRACKET_BEFORE); // The opening parenthesis. - String endBrace = getStringCitProperty(BRACKET_AFTER); // The closing parenthesis. - String citationSeparator = getStringCitProperty(CITATION_SEPARATOR); // The String to separate citations from each other. - String yearField = getStringCitProperty(YEAR_FIELD); // The bibtex field providing the year, e.g. "year". - String andString = getStringCitProperty(AUTHOR_LAST_SEPARATOR); // The String to add between the two last author names, e.g. " & ". - StringBuilder stringBuilder = new StringBuilder(startBrace); - for (int j = 0; j < entries.size(); j++) { - BibEntry currentEntry = entries.get(j); - - // Check if this entry has been nulled due to grouping with the previous entry(ies): - if (currentEntry == null) { - continue; - } - - if (j > 0) { - stringBuilder.append(citationSeparator); - } - - BibDatabase currentDatabase = database.get(currentEntry); - int unlimA = unlimAuthors == null ? -1 : unlimAuthors[j]; - int maxAuthors = unlimA > 0 ? unlimA : maxA; - - String author = getCitationMarkerField(currentEntry, currentDatabase, authorField); - String authorString = createAuthorList(author, maxAuthors, andString, yearSep); - stringBuilder.append(authorString); - String year = getCitationMarkerField(currentEntry, currentDatabase, yearField); - if (year != null) { - stringBuilder.append(year); - } - if ((uniquifiers != null) && (uniquifiers[j] != null)) { - stringBuilder.append(uniquifiers[j]); - } - } - stringBuilder.append(endBrace); - return stringBuilder.toString(); - } - /* end_old */ - - /* begin_old */ - /** - * This method produces "Author (year)" style citation strings in many different forms. - * - * @param entries The list of BibEntry to get fields from. - * @param database A map of BibEntry-BibDatabase pairs. - * @param uniquefiers Optional parameters to separate similar citations. Can be null if not needed. - * @return The formatted citation. - */ - private String getAuthorYearInTextMarker(List entries, Map database, - String[] uniquefiers, - int[] unlimAuthors) { - String authorField = getStringCitProperty(AUTHOR_FIELD); // The bibtex field providing author names, e.g. "author" or "editor". - int maxA = getIntCitProperty(MAX_AUTHORS); // The maximum number of authors to write out in full without using etal. Set to - // -1 to always write out all authors. - String yearSep = getStringCitProperty(IN_TEXT_YEAR_SEPARATOR); // The String to separate authors from year, e.g. "; ". - String startBrace = getStringCitProperty(BRACKET_BEFORE); // The opening parenthesis. - String endBrace = getStringCitProperty(BRACKET_AFTER); // The closing parenthesis. - String citationSeparator = getStringCitProperty(CITATION_SEPARATOR); // The String to separate citations from each other. - String yearField = getStringCitProperty(YEAR_FIELD); // The bibtex field providing the year, e.g. "year". - String andString = getStringCitProperty(AUTHOR_LAST_SEPARATOR_IN_TEXT); // The String to add between the two last author names, e.g. " & ". - - if (andString == null) { - // Use the default one if no explicit separator for text is defined - andString = getStringCitProperty(AUTHOR_LAST_SEPARATOR); - } - StringBuilder stringBuilder = new StringBuilder(); - for (int i = 0; i < entries.size(); i++) { - BibEntry currentEntry = entries.get(i); - - // Check if this entry has been nulled due to grouping with the previous entry(ies): - if (currentEntry == null) { - continue; - } - - BibDatabase currentDatabase = database.get(currentEntry); - int unlimA = unlimAuthors == null ? -1 : unlimAuthors[i]; - int maxAuthors = unlimA > 0 ? unlimA : maxA; - - if (i > 0) { - stringBuilder.append(citationSeparator); - } - String author = getCitationMarkerField(currentEntry, currentDatabase, authorField); - String authorString = createAuthorList(author, maxAuthors, andString, yearSep); - stringBuilder.append(authorString); - stringBuilder.append(startBrace); - String year = getCitationMarkerField(currentEntry, currentDatabase, yearField); - if (year != null) { - stringBuilder.append(year); - } - if ((uniquefiers != null) && (uniquefiers[i] != null)) { - stringBuilder.append(uniquefiers[i]); - } - stringBuilder.append(endBrace); - } - return stringBuilder.toString(); - - } - /* end_old */ - - /* begin_old */ - /* moved to OOBibStyleGetCitationMarker */ - /** - * This method looks up a field for an 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 fields 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 StandardField.orFields(StandardField.AUTHOR, StandardField.EDITOR). - * @return The resolved field content, or an empty string if the field(s) were empty. - */ - private String getCitationMarkerField(BibEntry entry, BibDatabase database, String fields) { - Objects.requireNonNull(entry, "Entry cannot be null"); - Objects.requireNonNull(database, "database cannot be null"); - - Set authorFields = FieldFactory.parseOrFields(getStringCitProperty(AUTHOR_FIELD)); - for (Field field : FieldFactory.parseOrFields(fields)) { - Optional content = entry.getResolvedFieldOrAlias(field, database); - - if ((content.isPresent()) && !content.get().trim().isEmpty()) { - if (authorFields.contains(field) && StringUtil.isInCurlyBrackets(content.get())) { - return "{" + fieldFormatter.format(content.get()) + "}"; - } - return fieldFormatter.format(content.get()); - } - } - // No luck? Return an empty string: - return ""; - } - /* end_old */ - - /* begin_old */ - /* moved to OOBibStyleGetCitationMarker */ - /** - * 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. - */ - private String getAuthorLastName(AuthorList al, int number) { - StringBuilder stringBuilder = new StringBuilder(); - - if (al.getNumberOfAuthors() > number) { - Author a = al.getAuthor(number); - a.getVon().filter(von -> !von.isEmpty()).ifPresent(von -> stringBuilder.append(von).append(' ')); - stringBuilder.append(a.getLast().orElse("")); - } - - return stringBuilder.toString(); - } - /* end_old */ - - /* begin_old */ - /* to be removed */ - /** - * Take a finished citation and insert a string at the end (but inside the end bracket) - * separated by "PageInfoSeparator" - * - * @param citation - * @param pageInfo - * @return - */ - public String insertPageInfo(String citation, String pageInfo) { - String bracketAfter = getStringCitProperty(BRACKET_AFTER); - if (citation.endsWith(bracketAfter)) { - String first = citation.substring(0, citation.length() - bracketAfter.length()); - return first + getStringCitProperty(PAGE_INFO_SEPARATOR) + pageInfo + bracketAfter; - } else { - return citation + getStringCitProperty(PAGE_INFO_SEPARATOR) + pageInfo; - } - } - /* end_old */ - /** * Convenience method for checking the property for whether we use number citations or * author-year citations. @@ -916,39 +563,6 @@ public int hashCode() { return Objects.hash(path, name, citProperties, properties); } - /* begin_old */ - /* moved to OOBibStyleGetCitationMarker as formatAuthorList */ - private String createAuthorList(String author, int maxAuthors, String andString, - String yearSep) { - Objects.requireNonNull(author); - String etAlString = getStringCitProperty(ET_AL_STRING); // The String to represent authors that are not mentioned, e.g. " et al." - String authorSep = getStringCitProperty(AUTHOR_SEPARATOR); // The String to add between author names except the last two, e.g. ", ". - String oxfordComma = getStringCitProperty(OXFORD_COMMA); // The String to put after the second to last author in case of three or more authors - StringBuilder stringBuilder = new StringBuilder(); - AuthorList al = AuthorList.parse(author); - if (!al.isEmpty()) { - stringBuilder.append(getAuthorLastName(al, 0)); - } - if ((al.getNumberOfAuthors() > 1) && ((al.getNumberOfAuthors() <= maxAuthors) || (maxAuthors < 0))) { - int j = 1; - while (j < (al.getNumberOfAuthors() - 1)) { - stringBuilder.append(authorSep); - stringBuilder.append(getAuthorLastName(al, j)); - j++; - } - if (al.getNumberOfAuthors() > 2) { - stringBuilder.append(oxfordComma); - } - stringBuilder.append(andString); - stringBuilder.append(getAuthorLastName(al, al.getNumberOfAuthors() - 1)); - } else if (al.getNumberOfAuthors() > maxAuthors) { - stringBuilder.append(etAlString); - } - stringBuilder.append(yearSep); - return stringBuilder.toString(); - } - /* end_old */ - enum BibStyleMode { NONE, LAYOUT, diff --git a/src/main/java/org/jabref/logic/openoffice/style/OOBibStyleGetCitationMarker.java b/src/main/java/org/jabref/logic/openoffice/style/OOBibStyleGetCitationMarker.java index 2e5227d080e..e44b3ac9d3f 100644 --- a/src/main/java/org/jabref/logic/openoffice/style/OOBibStyleGetCitationMarker.java +++ b/src/main/java/org/jabref/logic/openoffice/style/OOBibStyleGetCitationMarker.java @@ -23,7 +23,6 @@ class OOBibStyleGetCitationMarker { private OOBibStyleGetCitationMarker() { - /**/ } /** diff --git a/src/main/java/org/jabref/logic/openoffice/style/OOBibStyleGetNumCitationMarker.java b/src/main/java/org/jabref/logic/openoffice/style/OOBibStyleGetNumCitationMarker.java index 60b5222cf5b..28ef8ac12cf 100644 --- a/src/main/java/org/jabref/logic/openoffice/style/OOBibStyleGetNumCitationMarker.java +++ b/src/main/java/org/jabref/logic/openoffice/style/OOBibStyleGetNumCitationMarker.java @@ -12,13 +12,10 @@ class OOBibStyleGetNumCitationMarker { - /* - * The number encoding "this entry is unresolved" - */ + // The number encoding "this entry is unresolved" public final static int UNRESOLVED_ENTRY_NUMBER = 0; private OOBibStyleGetNumCitationMarker() { - /**/ } /** @@ -159,7 +156,6 @@ private static void emitBlock(List block, stringBuilder.append(block.get(j).getNumber().get()); } } - return; } } diff --git a/src/main/java/org/jabref/logic/openoffice/style/OOFormatBibliography.java b/src/main/java/org/jabref/logic/openoffice/style/OOFormatBibliography.java index ea311193068..38034693d16 100644 --- a/src/main/java/org/jabref/logic/openoffice/style/OOFormatBibliography.java +++ b/src/main/java/org/jabref/logic/openoffice/style/OOFormatBibliography.java @@ -29,20 +29,20 @@ private OOFormatBibliography() { /** * @return The formatted bibliography, including its title. */ - public static OOText formatBibliography(CitationGroups cgs, + public static OOText formatBibliography(CitationGroups citationGroups, CitedKeys bibliography, OOBibStyle style, boolean alwaysAddCitedOnPages) { OOText title = style.getFormattedBibliographyTitle(); - OOText body = formatBibliographyBody(cgs, bibliography, style, alwaysAddCitedOnPages); + OOText body = formatBibliographyBody(citationGroups, bibliography, style, alwaysAddCitedOnPages); return OOText.fromString(title.toString() + body.toString()); } /** * @return Formatted body of the bibliography. Excludes the title. */ - public static OOText formatBibliographyBody(CitationGroups cgs, + public static OOText formatBibliographyBody(CitationGroups citationGroups, CitedKeys bibliography, OOBibStyle style, boolean alwaysAddCitedOnPages) { @@ -50,7 +50,7 @@ public static OOText formatBibliographyBody(CitationGroups cgs, StringBuilder stringBuilder = new StringBuilder(); for (CitedKey citedKey : bibliography.values()) { - OOText entryText = formatBibliographyEntry(cgs, citedKey, style, alwaysAddCitedOnPages); + OOText entryText = formatBibliographyEntry(citationGroups, citedKey, style, alwaysAddCitedOnPages); stringBuilder.append(entryText.toString()); } @@ -60,7 +60,7 @@ public static OOText formatBibliographyBody(CitationGroups cgs, /** * @return A paragraph. Includes label and "Cited on pages". */ - public static OOText formatBibliographyEntry(CitationGroups cgs, + public static OOText formatBibliographyEntry(CitationGroups citationGroups, CitedKey citedKey, OOBibStyle style, boolean alwaysAddCitedOnPages) { @@ -79,7 +79,7 @@ public static OOText formatBibliographyEntry(CitationGroups cgs, // Add "Cited on pages" if (citedKey.getLookupResult().isEmpty() || alwaysAddCitedOnPages) { - stringBuilder.append(formatCitedOnPages(cgs, citedKey).toString()); + stringBuilder.append(formatCitedOnPages(citationGroups, citedKey).toString()); } // Add paragraph @@ -154,9 +154,9 @@ private static OOText formatFullReferenceOfBibEntry(Layout layout, * - The links are created as references that show page numbers of the reference marks. * - We do not control the text shown, that is provided by OpenOffice. */ - private static OOText formatCitedOnPages(CitationGroups cgs, CitedKey citedKey) { + private static OOText formatCitedOnPages(CitationGroups citationGroups, CitedKey citedKey) { - if (!cgs.citationGroupsProvideReferenceMarkNameForLinking()) { + if (!citationGroups.citationGroupsProvideReferenceMarkNameForLinking()) { return OOText.fromString(""); } @@ -166,25 +166,25 @@ private static OOText formatCitedOnPages(CitationGroups cgs, CitedKey citedKey) final String suffix = ")"; stringBuilder.append(prefix); - List citationGroups = new ArrayList<>(); - for (CitationPath p : citedKey.getCitationPaths()) { - CitationGroupId groupId = p.group; - Optional group = cgs.getCitationGroup(groupId); + List filteredList = new ArrayList<>(); + for (CitationPath path : citedKey.getCitationPaths()) { + CitationGroupId groupId = path.group; + Optional group = citationGroups.getCitationGroup(groupId); if (group.isEmpty()) { throw new IllegalStateException(); } - citationGroups.add(group.get()); + filteredList.add(group.get()); } // sort the citationGroups according to their indexInGlobalOrder - citationGroups.sort((a, b) -> { + filteredList.sort((a, b) -> { Integer aa = a.getIndexInGlobalOrder().orElseThrow(IllegalStateException::new); Integer bb = b.getIndexInGlobalOrder().orElseThrow(IllegalStateException::new); return (aa.compareTo(bb)); }); int index = 0; - for (CitationGroup group : citationGroups) { + for (CitationGroup group : filteredList) { if (index > 0) { stringBuilder.append(", "); } diff --git a/src/main/java/org/jabref/logic/openoffice/style/OOPreFormatter.java b/src/main/java/org/jabref/logic/openoffice/style/OOPreFormatter.java index dc02daf6ee9..caeaf8cce2a 100644 --- a/src/main/java/org/jabref/logic/openoffice/style/OOPreFormatter.java +++ b/src/main/java/org/jabref/logic/openoffice/style/OOPreFormatter.java @@ -8,8 +8,7 @@ import org.jabref.model.strings.StringUtil; /** - * This formatter preprocesses JabRef fields before they are run through the layout of the - * bibliography style. It handles translation of LaTeX italic/bold commands into HTML tags. + * This formatter preprocesses JabRef fields before they are run through the layout of the bibliography style. It handles translation of LaTeX italic/bold commands into HTML tags. */ public class OOPreFormatter implements LayoutFormatter { @@ -46,7 +45,6 @@ public String format(String field) { currentCommand = new StringBuilder(); } else if (!incommand && ((c == '{') || (c == '}'))) { // Swallow braces, necessary for replacing encoded characters - } else if (Character.isLetter(c) || (c == '%') || StringUtil.SPECIAL_COMMAND_CHARS.contains(String.valueOf(c))) { escaped = false; @@ -88,10 +86,7 @@ public String format(String field) { if ((i + 1) == finalResult.length()) { String command = currentCommand.toString(); String result = OOPreFormatter.CHARS.get(command); - /* If found, then use translated version. If not, - * then keep - * the text of the parameter intact. - */ + // If found, then use translated version. If not, then keep the text of the parameter intact. sb.append(Objects.requireNonNullElse(result, command)); } } @@ -104,9 +99,7 @@ public String format(String field) { } else if (Character.isWhitespace(c) || (c == '{') || (c == '}')) { String command = currentCommand.toString(); - // Test if we are dealing with a formatting - // command. - // If so, handle. + // Test if we are dealing with a formatting command. If so, handle. String tag = getHTMLTag(command); if (!tag.isEmpty()) { String part = StringUtil.getPart(finalResult, i, true); @@ -118,14 +111,11 @@ public String format(String field) { argument = part; // handle common case of general latex command String result = OOPreFormatter.CHARS.get(command + argument); - // If found, then use translated version. If not, then keep - // the - // text of the parameter intact. + // If found, then use translated version. If not, then keep the text of the parameter intact. sb.append(Objects.requireNonNullElse(result, argument)); } else if (c == '}') { - // This end brace terminates a command. This can be the case in - // constructs like {\aa}. The correct behaviour should be to - // substitute the evaluated command and swallow the brace: + // This end brace terminates a command. This can be the case in constructs like {\aa}. The + // correct behaviour should be to substitute the evaluated command and swallow the brace: String result = OOPreFormatter.CHARS.get(command); // If the command is unknown, just print it: sb.append(Objects.requireNonNullElse(result, command)); @@ -139,13 +129,10 @@ public String format(String field) { // argument = ""; } else { /* - * TODO: this point is reached, apparently, if a command is - * terminated in a strange way, such as with "$\omega$". - * Also, the command "\&" causes us to get here. The former - * issue is maybe a little difficult to address, since it - * involves the LaTeX math mode. We don't have a complete - * LaTeX parser, so maybe it's better to ignore these - * commands? + * TODO: this point is reached, apparently, if a command is terminated in a strange way, such as + * with "$\omega$". Also, the command "\&" causes us to get here. The former issue is maybe a + * little difficult to address, since it involves the LaTeX math mode. We don't have a complete + * LaTeX parser, so maybe it's better to ignore these commands? */ } @@ -160,44 +147,17 @@ public String format(String field) { private String getHTMLTag(String latexCommand) { String result = ""; switch (latexCommand) { - // Italic - case "textit": - case "it": - case "emph": // Should really separate between emphasized and italic but since in later stages both are converted to italic... - case "em": - result = "i"; - break; - // Bold font - case "textbf": - case "bf": - result = "b"; - break; - // Small capitals - case "textsc": - result = "smallcaps"; // Not a proper HTML tag, but used here for convenience - break; - // Underline - case "underline": - result = "u"; - break; - // Strikeout, sout is the "standard" command, although it is actually based on the package ulem - case "sout": - result = "s"; - break; - // Monospace font - case "texttt": - result = "tt"; - break; - // Superscript - case "textsuperscript": - result = "sup"; - break; - // Subscript - case "textsubscript": - result = "sub"; - break; - default: - break; + // Should really separate between emphasized and italic but since in later stages both are converted to italic... + case "textit", "it", "emph", "em" -> result = "i"; // Italic + case "textbf", "bf" -> result = "b"; // Bold font + case "textsc" -> result = "smallcaps"; // Small caps + // Not a proper HTML tag, but used here for convenience + case "underline" -> result = "u"; // Underline + case "sout" -> result = "s"; // Strikeout + // sout is the "standard" command, although it is actually based on the package ulem + case "texttt" -> result = "tt"; // Monospace font + case "textsuperscript" -> result = "sup"; // Superscript + case "textsubscript" -> result = "sub"; // Subscript } return result; } diff --git a/src/main/java/org/jabref/logic/openoffice/style/OOProcess.java b/src/main/java/org/jabref/logic/openoffice/style/OOProcess.java index f8f7de6c7b7..5fff6848133 100644 --- a/src/main/java/org/jabref/logic/openoffice/style/OOProcess.java +++ b/src/main/java/org/jabref/logic/openoffice/style/OOProcess.java @@ -16,7 +16,6 @@ public class OOProcess { static final Comparator YEAR_AUTHOR_TITLE_COMPARATOR = makeYearAuthorTitleComparator(); private OOProcess() { - /**/ } private static Comparator makeAuthorYearTitleComparator() { @@ -51,25 +50,25 @@ public static Comparator comparatorForMulticite(OOBibStyle style) { } /** - * Fill cgs.bibliography and cgs.citationGroupsUnordered//CitationMarker + * Fill citationGroups.bibliography and cgs.citationGroupsUnordered//CitationMarker * according to style. */ - public static void produceCitationMarkers(CitationGroups cgs, List databases, OOBibStyle style) { + public static void produceCitationMarkers(CitationGroups citationGroups, List databases, OOBibStyle style) { - if (!cgs.hasGlobalOrder()) { - throw new IllegalStateException("produceCitationMarkers: globalOrder is misssing in cgs"); + if (!citationGroups.hasGlobalOrder()) { + throw new IllegalStateException("produceCitationMarkers: globalOrder is misssing in citationGroups"); } - cgs.lookupCitations(databases); - cgs.imposeLocalOrder(comparatorForMulticite(style)); + citationGroups.lookupCitations(databases); + citationGroups.imposeLocalOrder(comparatorForMulticite(style)); // fill CitationGroup.citationMarker if (style.isCitationKeyCiteMarkers()) { - OOProcessCitationKeyMarkers.produceCitationMarkers(cgs, style); + OOProcessCitationKeyMarkers.produceCitationMarkers(citationGroups, style); } else if (style.isNumberEntries()) { - OOProcessNumericMarkers.produceCitationMarkers(cgs, style); + OOProcessNumericMarkers.produceCitationMarkers(citationGroups, style); } else { - OOProcessAuthorYearMarkers.produceCitationMarkers(cgs, style); + OOProcessAuthorYearMarkers.produceCitationMarkers(citationGroups, style); } } diff --git a/src/main/java/org/jabref/logic/openoffice/style/OOProcessAuthorYearMarkers.java b/src/main/java/org/jabref/logic/openoffice/style/OOProcessAuthorYearMarkers.java index affbc7584ae..d01e3627104 100644 --- a/src/main/java/org/jabref/logic/openoffice/style/OOProcessAuthorYearMarkers.java +++ b/src/main/java/org/jabref/logic/openoffice/style/OOProcessAuthorYearMarkers.java @@ -22,7 +22,6 @@ class OOProcessAuthorYearMarkers { private OOProcessAuthorYearMarkers() { - /**/ } /** @@ -46,11 +45,11 @@ private static void createNormalizedCitationMarkers(CitedKeys sortedCitedKeys, O * Clears uniqueLetters before filling. * * On return: Each citedKey in sortedCitedKeys has uniqueLetter set as needed. - * The same values are copied to the corresponding citations in cgs. + * The same values are copied to the corresponding citations in citationGroups. * * Depends on: style, citations and their order. */ - private static void createUniqueLetters(CitedKeys sortedCitedKeys, CitationGroups cgs) { + private static void createUniqueLetters(CitedKeys sortedCitedKeys, CitationGroups citationGroups) { // The entries in the clashingKeys lists preserve // firstAppearance order from sortedCitedKeys.values(). @@ -93,7 +92,7 @@ private static void createUniqueLetters(CitedKeys sortedCitedKeys, CitationGroup nextUniqueLetter++; } } - sortedCitedKeys.distributeUniqueLetters(cgs); + sortedCitedKeys.distributeUniqueLetters(citationGroups); } /* *************************************** @@ -108,9 +107,9 @@ private static void createUniqueLetters(CitedKeys sortedCitedKeys, CitationGroup * * Preconditions: globalOrder, localOrder */ - private static void setIsFirstAppearanceOfSourceInCitations(CitationGroups cgs) { + private static void setIsFirstAppearanceOfSourceInCitations(CitationGroups citationGroups) { Set seenBefore = new HashSet<>(); - for (CitationGroup group : cgs.getCitationGroupsInGlobalOrder()) { + for (CitationGroup group : citationGroups.getCitationGroupsInGlobalOrder()) { for (Citation cit : group.getCitationsInLocalOrder()) { String currentKey = cit.citationKey; if (!seenBefore.contains(currentKey)) { @@ -127,25 +126,25 @@ private static void setIsFirstAppearanceOfSourceInCitations(CitationGroups cgs) * Produce citMarkers for normal * (!isCitationKeyCiteMarkers && !isNumberEntries) styles. * - * @param cgs + * @param citationGroups * @param style Bibliography style. */ - static void produceCitationMarkers(CitationGroups cgs, OOBibStyle style) { + static void produceCitationMarkers(CitationGroups citationGroups, OOBibStyle style) { assert !style.isCitationKeyCiteMarkers(); assert !style.isNumberEntries(); // Citations in (Au1, Au2 2000) form - CitedKeys citedKeys = cgs.getCitedKeysSortedInOrderOfAppearance(); + CitedKeys citedKeys = citationGroups.getCitedKeysSortedInOrderOfAppearance(); createNormalizedCitationMarkers(citedKeys, style); - createUniqueLetters(citedKeys, cgs); - cgs.createPlainBibliographySortedByComparator(OOProcess.AUTHOR_YEAR_TITLE_COMPARATOR); + createUniqueLetters(citedKeys, citationGroups); + citationGroups.createPlainBibliographySortedByComparator(OOProcess.AUTHOR_YEAR_TITLE_COMPARATOR); // Mark first appearance of each citationKey - setIsFirstAppearanceOfSourceInCitations(cgs); + setIsFirstAppearanceOfSourceInCitations(citationGroups); - for (CitationGroup group : cgs.getCitationGroupsInGlobalOrder()) { + for (CitationGroup group : citationGroups.getCitationGroupsInGlobalOrder()) { final boolean inParenthesis = (group.citationType == CitationType.AUTHORYEAR_PAR); final NonUniqueCitationMarker strictlyUnique = NonUniqueCitationMarker.THROWS; diff --git a/src/main/java/org/jabref/logic/openoffice/style/OOProcessCitationKeyMarkers.java b/src/main/java/org/jabref/logic/openoffice/style/OOProcessCitationKeyMarkers.java index 5329d9ca021..16fe8279123 100644 --- a/src/main/java/org/jabref/logic/openoffice/style/OOProcessCitationKeyMarkers.java +++ b/src/main/java/org/jabref/logic/openoffice/style/OOProcessCitationKeyMarkers.java @@ -11,20 +11,19 @@ class OOProcessCitationKeyMarkers { private OOProcessCitationKeyMarkers() { - /**/ } /** * Produce citation markers for the case when the citation * markers are the citation keys themselves, separated by commas. */ - static void produceCitationMarkers(CitationGroups cgs, OOBibStyle style) { + static void produceCitationMarkers(CitationGroups citationGroups, OOBibStyle style) { assert style.isCitationKeyCiteMarkers(); - cgs.createPlainBibliographySortedByComparator(OOProcess.AUTHOR_YEAR_TITLE_COMPARATOR); + citationGroups.createPlainBibliographySortedByComparator(OOProcess.AUTHOR_YEAR_TITLE_COMPARATOR); - for (CitationGroup group : cgs.getCitationGroupsInGlobalOrder()) { + for (CitationGroup group : citationGroups.getCitationGroupsInGlobalOrder()) { String citMarker = style.getCitationGroupMarkupBefore() + String.join(",", OOListUtil.map(group.getCitationsInLocalOrder(), Citation::getCitationKey)) diff --git a/src/main/java/org/jabref/logic/openoffice/style/OOProcessNumericMarkers.java b/src/main/java/org/jabref/logic/openoffice/style/OOProcessNumericMarkers.java index deddab66cca..3a6396817e6 100644 --- a/src/main/java/org/jabref/logic/openoffice/style/OOProcessNumericMarkers.java +++ b/src/main/java/org/jabref/logic/openoffice/style/OOProcessNumericMarkers.java @@ -12,7 +12,6 @@ class OOProcessNumericMarkers { private OOProcessNumericMarkers() { - /**/ } /** @@ -23,21 +22,21 @@ private OOProcessNumericMarkers() { * Numbering is according to first appearance. * Assumes global order and local order are already applied. * - * @param cgs + * @param citationGroups * @param style * */ - static void produceCitationMarkers(CitationGroups cgs, OOBibStyle style) { + static void produceCitationMarkers(CitationGroups citationGroups, OOBibStyle style) { assert style.isNumberEntries(); if (style.isSortByPosition()) { - cgs.createNumberedBibliographySortedInOrderOfAppearance(); + citationGroups.createNumberedBibliographySortedInOrderOfAppearance(); } else { - cgs.createNumberedBibliographySortedByComparator(OOProcess.AUTHOR_YEAR_TITLE_COMPARATOR); + citationGroups.createNumberedBibliographySortedByComparator(OOProcess.AUTHOR_YEAR_TITLE_COMPARATOR); } - for (CitationGroup group : cgs.getCitationGroupsInGlobalOrder()) { + for (CitationGroup group : citationGroups.getCitationGroupsInGlobalOrder()) { List cits = OOListUtil.map(group.getCitationsInLocalOrder(), e -> e); OOText citMarker = style.getNumCitationMarker2(cits); group.setCitationMarker(Optional.of(citMarker)); diff --git a/src/main/java/org/jabref/logic/openoffice/style/StyleLoader.java b/src/main/java/org/jabref/logic/openoffice/style/StyleLoader.java index 3098e06233c..90e1bc50158 100644 --- a/src/main/java/org/jabref/logic/openoffice/style/StyleLoader.java +++ b/src/main/java/org/jabref/logic/openoffice/style/StyleLoader.java @@ -1,9 +1,8 @@ package org.jabref.logic.openoffice.style; -import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; -import java.nio.charset.Charset; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -28,18 +27,15 @@ public class StyleLoader { private final OpenOfficePreferences openOfficePreferences; private final LayoutFormatterPreferences layoutFormatterPreferences; - private final Charset encoding; // Lists of the internal // and external styles private final List internalStyles = new ArrayList<>(); private final List externalStyles = new ArrayList<>(); - public StyleLoader(OpenOfficePreferences openOfficePreferences, LayoutFormatterPreferences formatterPreferences, - Charset encoding) { + public StyleLoader(OpenOfficePreferences openOfficePreferences, LayoutFormatterPreferences formatterPreferences) { this.openOfficePreferences = Objects.requireNonNull(openOfficePreferences); this.layoutFormatterPreferences = Objects.requireNonNull(formatterPreferences); - this.encoding = Objects.requireNonNull(encoding); loadInternalStyles(); loadExternalStyles(); } @@ -59,7 +55,7 @@ public List getStyles() { public boolean addStyleIfValid(String filename) { Objects.requireNonNull(filename); try { - OOBibStyle newStyle = new OOBibStyle(new File(filename), layoutFormatterPreferences, encoding); + OOBibStyle newStyle = new OOBibStyle(Path.of(filename), layoutFormatterPreferences); if (externalStyles.contains(newStyle)) { LOGGER.info("External style file {} already existing.", filename); } else if (newStyle.isValid()) { @@ -84,7 +80,7 @@ private void loadExternalStyles() { List lists = openOfficePreferences.getExternalStyles(); for (String filename : lists) { try { - OOBibStyle style = new OOBibStyle(new File(filename), layoutFormatterPreferences, encoding); + OOBibStyle style = new OOBibStyle(Path.of(filename), layoutFormatterPreferences); if (style.isValid()) { // Problem! externalStyles.add(style); } else { diff --git a/src/main/java/org/jabref/logic/texparser/TexBibEntriesResolver.java b/src/main/java/org/jabref/logic/texparser/TexBibEntriesResolver.java index 84322da6ece..75a30c14491 100644 --- a/src/main/java/org/jabref/logic/texparser/TexBibEntriesResolver.java +++ b/src/main/java/org/jabref/logic/texparser/TexBibEntriesResolver.java @@ -48,7 +48,7 @@ public LatexBibEntriesResolverResult resolve(LatexParserResult latexParserResult Map bibDatabases = resolverResult.getBibFiles().values().stream().distinct().collect(Collectors.toMap( Function.identity(), path -> { try { - return OpenDatabase.loadDatabase(path, generalPreferences, importFormatPreferences, fileMonitor).getDatabase(); + return OpenDatabase.loadDatabase(path, importFormatPreferences, fileMonitor).getDatabase(); } catch (IOException e) { LOGGER.error("Error opening file '{}'", path, e); return ParserResult.fromError(e).getDatabase(); diff --git a/src/main/java/org/jabref/logic/xmp/DublinCoreExtractor.java b/src/main/java/org/jabref/logic/xmp/DublinCoreExtractor.java index 78ed8b6a64a..59af0cb3869 100644 --- a/src/main/java/org/jabref/logic/xmp/DublinCoreExtractor.java +++ b/src/main/java/org/jabref/logic/xmp/DublinCoreExtractor.java @@ -1,7 +1,6 @@ package org.jabref.logic.xmp; -import java.io.IOException; -import java.util.Calendar; +import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.Map.Entry; @@ -16,6 +15,7 @@ import org.jabref.model.entry.Author; import org.jabref.model.entry.AuthorList; import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.Date; import org.jabref.model.entry.Month; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.FieldFactory; @@ -24,7 +24,6 @@ import org.jabref.model.entry.types.EntryTypeFactory; import org.jabref.model.strings.StringUtil; -import org.apache.xmpbox.DateConverter; import org.apache.xmpbox.schema.DublinCoreSchema; import org.apache.xmpbox.type.BadFieldValueException; import org.slf4j.Logger; @@ -32,6 +31,10 @@ public class DublinCoreExtractor { + public static final String DC_COVERAGE = "coverage"; + public static final String DC_RIGHTS = "rights"; + public static final String DC_SOURCE = "source"; + private static final Logger LOGGER = LoggerFactory.getLogger(DublinCoreExtractor.class); private final DublinCoreSchema dcSchema; @@ -71,32 +74,19 @@ private void extractAuthor() { } /** - * Year in BibTex - Date in DublinCore is only the year information, because dc interprets empty months as January. - * Tries to extract the month as well. In JabRef the bibtex/month/value is prioritized.
The problem is the - * default value of the calendar, which is always January, also if there is no month information in the xmp metdata. - * The idea is, to reject all information with YYYY-01-01. In cases, where xmp is written with JabRef the month - * property filled with jan will override this behavior and no data is lost. In the cases, where xmp is written by - * another service, the assumption is, that the 1st January is not a publication date at all. + * Bibtex-Fields : year, [month], [day] - 'dc:date' in DublinCore */ - private void extractYearAndMonth() { + private void extractDate() { List dates = dcSchema.getUnqualifiedSequenceValueList("date"); if ((dates != null) && !dates.isEmpty()) { + String date = dates.get(0).trim(); - Calendar calender = null; - try { - calender = DateConverter.toCalendar(date); - } catch (IOException ignored) { - // Ignored - } - if (calender != null) { - bibEntry.setField(StandardField.YEAR, String.valueOf(calender.get(Calendar.YEAR))); - int monthNumber = calender.get(Calendar.MONTH) + 1; - // not the 1st of January - if (!((monthNumber == 1) && (calender.get(Calendar.DAY_OF_MONTH) == 1))) { - Month.getMonthByNumber(monthNumber) - .ifPresent(month -> bibEntry.setMonth(month)); - } - } + Date.parse(date) + .ifPresent(dateValue -> { + dateValue.getDay().ifPresent(day -> bibEntry.setField(StandardField.DAY, Integer.toString(day))); + dateValue.getMonth().ifPresent(bibEntry::setMonth); + dateValue.getYear().ifPresent(year -> bibEntry.setField(StandardField.YEAR, Integer.toString(year))); + }); } } @@ -182,7 +172,7 @@ private void extractRights() { LOGGER.warn("Could not extract rights", e); } if (!StringUtil.isNullOrEmpty(rights)) { - bibEntry.setField(new UnknownField("rights"), rights); + bibEntry.setField(new UnknownField(DC_RIGHTS), rights); } } @@ -192,7 +182,7 @@ private void extractRights() { private void extractSource() { String source = dcSchema.getSource(); if (!StringUtil.isNullOrEmpty(source)) { - bibEntry.setField(new UnknownField("source"), source); + bibEntry.setField(new UnknownField(DC_SOURCE), source); } } @@ -234,6 +224,29 @@ private void extractType() { } } + /** + * No Equivalent in BibTex. Will create an Unknown "Coverage" Field + */ + private void extractCoverage() { + String coverage = dcSchema.getCoverage(); + if (!StringUtil.isNullOrEmpty(coverage)) { + bibEntry.setField(FieldFactory.parseField(DC_COVERAGE), coverage); + } + } + + /** + * Language is equivalent in both formats (BibTex and DublinCore) + */ + private void extractLanguages() { + StringBuilder builder = new StringBuilder(); + + List languages = dcSchema.getLanguages(); + if (languages != null && !languages.isEmpty()) { + languages.forEach(language -> builder.append(",").append(language)); + bibEntry.setField(StandardField.LANGUAGE, builder.substring(1)); + } + } + /** * Helper function for retrieving a BibEntry from the DublinCore metadata in a PDF file. *

@@ -252,7 +265,7 @@ public Optional extractBibtexEntry() { // then extract all "standard" dublin core entries this.extractEditor(); this.extractAuthor(); - this.extractYearAndMonth(); + this.extractDate(); this.extractAbstract(); this.extractDOI(); this.extractPublisher(); @@ -261,6 +274,8 @@ public Optional extractBibtexEntry() { this.extractSubject(); this.extractTitle(); this.extractType(); + this.extractCoverage(); + this.extractLanguages(); // we pass a new BibEntry in the constructor which is never empty as it already consists of "@misc" if (bibEntry.getFieldMap().isEmpty()) { @@ -350,6 +365,37 @@ private void fillTitle(String title) { dcSchema.setTitle(title); } + /** + * BibTex : Coverage (Custom Field); DC Field : Coverage + * + * @param coverage + */ + private void fillCoverage(String coverage) { + dcSchema.setCoverage(coverage); + } + + /** + * BibTex Field : language ; DC Field : dc:language + */ + private void fillLanguages(String languages) { + Arrays.stream(languages.split(",")) + .forEach(dcSchema::addLanguage); + } + + /** + * BibTex : Rights (Custom Field); DC Field : dc:rights + */ + private void fillRights(String rights) { + dcSchema.addRights(null, rights.split(",")[0]); + } + + /** + * BibTex : Source (Custom Field); DC Field : Source + */ + private void fillSource(String source) { + dcSchema.setSource(source); + } + /** * All others (+ citation key) get packaged in the relation attribute * @@ -366,29 +412,60 @@ public void fillDublinCoreSchema() { Set> fieldValues = new TreeSet<>(Comparator.comparing(fieldStringEntry -> fieldStringEntry.getKey().getName())); fieldValues.addAll(bibEntry.getFieldMap().entrySet()); + boolean hasStandardYearField = fieldValues.stream().anyMatch(field -> StandardField.YEAR.equals(field.getKey())); for (Entry field : fieldValues) { if (useXmpPrivacyFilter && xmpPreferences.getXmpPrivacyFilter().contains(field.getKey())) { continue; } - if (StandardField.EDITOR.equals(field.getKey())) { - this.fillContributor(field.getValue()); - } else if (StandardField.AUTHOR.equals(field.getKey())) { - this.fillCreator(field.getValue()); - } else if (StandardField.YEAR.equals(field.getKey())) { - this.fillDate(); - } else if (StandardField.ABSTRACT.equals(field.getKey())) { - this.fillDescription(field.getValue()); - } else if (StandardField.DOI.equals(field.getKey())) { - this.fillIdentifier(field.getValue()); - } else if (StandardField.PUBLISHER.equals(field.getKey())) { - this.fillPublisher(field.getValue()); - } else if (StandardField.KEYWORDS.equals(field.getKey())) { - this.fillKeywords(field.getValue()); - } else if (StandardField.TITLE.equals(field.getKey())) { - this.fillTitle(field.getValue()); + Field fieldEntry = field.getKey(); + if (fieldEntry instanceof StandardField) { + switch ((StandardField) fieldEntry) { + case EDITOR: + this.fillContributor(field.getValue()); + break; + case AUTHOR: + this.fillCreator(field.getValue()); + break; + case YEAR: + this.fillDate(); + break; + case ABSTRACT: + this.fillDescription(field.getValue()); + break; + case DOI: + this.fillIdentifier(field.getValue()); + break; + case PUBLISHER: + this.fillPublisher(field.getValue()); + break; + case KEYWORDS: + this.fillKeywords(field.getValue()); + break; + case TITLE: + this.fillTitle(field.getValue()); + break; + case LANGUAGE: + this.fillLanguages(field.getValue()); + break; + case DAY: + case MONTH: + if (hasStandardYearField) { + break; + } + default: + this.fillCustomField(field.getKey(), field.getValue()); + } } else { - this.fillCustomField(field.getKey(), field.getValue()); + if (DC_COVERAGE.equals(fieldEntry.getName())) { + this.fillCoverage(field.getValue()); + } else if (DC_RIGHTS.equals(fieldEntry.getName())) { + this.fillRights(field.getValue()); + } else if (DC_SOURCE.equals(fieldEntry.getName())) { + this.fillSource(field.getValue()); + } else { + this.fillCustomField(field.getKey(), field.getValue()); + } } } diff --git a/src/main/java/org/jabref/logic/xmp/XmpUtilReader.java b/src/main/java/org/jabref/logic/xmp/XmpUtilReader.java index 21be8d96000..51248543d94 100644 --- a/src/main/java/org/jabref/logic/xmp/XmpUtilReader.java +++ b/src/main/java/org/jabref/logic/xmp/XmpUtilReader.java @@ -10,6 +10,7 @@ import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.LinkedFile; +import org.jabref.model.schema.DublinCoreSchemaCustom; import org.apache.pdfbox.Loader; import org.apache.pdfbox.pdmodel.PDDocument; @@ -77,8 +78,8 @@ public static List readXmp(Path path, XmpPreferences xmpPreferences) if (!xmpMetaList.isEmpty()) { // Only support Dublin Core since JabRef 4.2 for (XMPMetadata xmpMeta : xmpMetaList) { - DublinCoreSchema dcSchema = xmpMeta.getDublinCoreSchema(); + DublinCoreSchema dcSchema = DublinCoreSchemaCustom.copyDublinCoreSchema(xmpMeta.getDublinCoreSchema()); if (dcSchema != null) { DublinCoreExtractor dcExtractor = new DublinCoreExtractor(dcSchema, xmpPreferences, new BibEntry()); Optional entry = dcExtractor.extractBibtexEntry(); diff --git a/src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java b/src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java index 7133d3773b6..60fbc825b5b 100644 --- a/src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java +++ b/src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java @@ -19,6 +19,7 @@ import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.Field; import org.jabref.model.entry.field.StandardField; +import org.jabref.model.schema.DublinCoreSchemaCustom; import org.apache.pdfbox.Loader; import org.apache.pdfbox.pdmodel.PDDocument; @@ -160,7 +161,7 @@ private static void writeDublinCore(PDDocument document, meta.removeSchema(meta.getDublinCoreSchema()); for (BibEntry entry : resolvedEntries) { - DublinCoreSchema dcSchema = meta.createAndAddDublinCoreSchema(); + DublinCoreSchema dcSchema = DublinCoreSchemaCustom.copyDublinCoreSchema(meta.createAndAddDublinCoreSchema()); XmpUtilWriter.writeToDCSchema(dcSchema, entry, null, xmpPreferences); } diff --git a/src/main/java/org/jabref/migrations/MergeReviewIntoCommentMigration.java b/src/main/java/org/jabref/migrations/MergeReviewIntoCommentMigration.java index 19c9563fbfc..10f8c3fb5a8 100644 --- a/src/main/java/org/jabref/migrations/MergeReviewIntoCommentMigration.java +++ b/src/main/java/org/jabref/migrations/MergeReviewIntoCommentMigration.java @@ -13,7 +13,7 @@ import org.slf4j.LoggerFactory; public class MergeReviewIntoCommentMigration { - public static final Logger LOGGER = LoggerFactory.getLogger(MergeReviewIntoCommentMigration.class); + private static final Logger LOGGER = LoggerFactory.getLogger(MergeReviewIntoCommentMigration.class); public static boolean needsMigration(ParserResult parserResult) { return parserResult.getDatabase().getEntries().stream() diff --git a/src/main/java/org/jabref/model/database/BibDatabaseContext.java b/src/main/java/org/jabref/model/database/BibDatabaseContext.java index 23e5d04e188..3fb270f0645 100644 --- a/src/main/java/org/jabref/model/database/BibDatabaseContext.java +++ b/src/main/java/org/jabref/model/database/BibDatabaseContext.java @@ -218,7 +218,7 @@ public List getEntries() { * @return true if the database has any empty entries; otherwise false */ public boolean hasEmptyEntries() { - return this.getEntries().stream().anyMatch(entry->entry.getFields().isEmpty()); + return this.getEntries().stream().anyMatch(entry -> entry.getFields().isEmpty()); } public static Path getFulltextIndexBasePath() { diff --git a/src/main/java/org/jabref/model/entry/BibEntry.java b/src/main/java/org/jabref/model/entry/BibEntry.java index 546afc1916c..5be8671718a 100644 --- a/src/main/java/org/jabref/model/entry/BibEntry.java +++ b/src/main/java/org/jabref/model/entry/BibEntry.java @@ -469,7 +469,7 @@ private Optional genericGetFieldOrAlias(Field field, BiFunction formatStrings = Arrays.asList( - "uuuu-M-d", // covers 2009-1-15 - "uuuu-M", // covers 2009-11 - "d-M-uuuu", // covers 15-1-2012 - "M-uuuu", // covers 1-2012 - "M/uuuu", // covers 9/2015 and 09/2015 - "M/uu", // covers 9/15 - "MMMM d, uuuu", // covers September 1, 2015 - "MMMM, uuuu", // covers September, 2015 - "d.M.uuuu", // covers 15.1.2015 - "uuuu.M.d", // covers 2015.1.15 - "uuuu", // covers 2015 - "MMM, uuuu"); // covers Jan, 2020 + "uuuu-MM-dd'T'HH:mm:ss[xxx][xx][X]", // covers 2018-10-03T07:24:14+03:00 + "uuuu-M-d", // covers 2009-1-15 + "uuuu-M", // covers 2009-11 + "d-M-uuuu", // covers 15-1-2012 + "M-uuuu", // covers 1-2012 + "M/uuuu", // covers 9/2015 and 09/2015 + "M/uu", // covers 9/15 + "MMMM d, uuuu", // covers September 1, 2015 + "MMMM, uuuu", // covers September, 2015 + "d.M.uuuu", // covers 15.1.2015 + "uuuu.M.d", // covers 2015.1.15 + "uuuu", // covers 2015 + "MMM, uuuu"); // covers Jan, 2020 SIMPLE_DATE_FORMATS = formatStrings.stream() .map(DateTimeFormatter::ofPattern) diff --git a/src/main/java/org/jabref/model/entry/LinkedFile.java b/src/main/java/org/jabref/model/entry/LinkedFile.java index 63907ee01a5..158336c7a53 100644 --- a/src/main/java/org/jabref/model/entry/LinkedFile.java +++ b/src/main/java/org/jabref/model/entry/LinkedFile.java @@ -11,6 +11,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.regex.Pattern; import javafx.beans.Observable; import javafx.beans.property.SimpleStringProperty; @@ -26,6 +27,9 @@ */ public class LinkedFile implements Serializable { + private static final String REGEX_URL = "^((?:https?\\:\\/\\/|www\\.)(?:[-a-z0-9]+\\.)*[-a-z0-9]+.*)"; + private static final Pattern URL_PATTERN = Pattern.compile(REGEX_URL); + private static final LinkedFile NULL_OBJECT = new LinkedFile("", Path.of(""), ""); // We have to mark these properties as transient because they can't be serialized directly @@ -145,7 +149,7 @@ private void readObject(ObjectInputStream in) throws IOException { */ public static boolean isOnlineLink(String toCheck) { String normalizedFilePath = toCheck.trim().toLowerCase(); - return normalizedFilePath.startsWith("http://") || normalizedFilePath.startsWith("https://") || normalizedFilePath.contains("www."); + return URL_PATTERN.matcher(normalizedFilePath).matches(); } @Override diff --git a/src/main/java/org/jabref/model/openoffice/backend/NamedRange.java b/src/main/java/org/jabref/model/openoffice/backend/NamedRange.java index 63981ceba70..57fba4dc272 100644 --- a/src/main/java/org/jabref/model/openoffice/backend/NamedRange.java +++ b/src/main/java/org/jabref/model/openoffice/backend/NamedRange.java @@ -11,13 +11,9 @@ import com.sun.star.text.XTextRange; /** - * NamedRange (with NamedRangeManager) attempts to provide a common interface for working with - * reference mark based and bookmark based text ranges to be used as locations to fill with citation - * markers. LibreOffice supports name-based lookup and listing names for both (hence the name). - * - * Note: currently only implemented for refence marks (in NamedRangeReferenceMark and - * NamedRangeManagerReferenceMark). - * + * NamedRange (with NamedRangeManager) attempts to provide a common interface for working with reference mark based and bookmark based text ranges to be used as locations to fill with citation markers. LibreOffice supports name-based lookup and listing names for both (hence the name). + *

+ * Note: currently only implemented for refence marks (in NamedRangeReferenceMark and NamedRangeManagerReferenceMark). */ public interface NamedRange { @@ -27,45 +23,42 @@ public interface NamedRange { * @return Optional.empty if the mark is missing from the document. */ Optional getMarkRange(XTextDocument doc) - throws - NoDocumentException, - WrappedTargetException; + throws + NoDocumentException, + WrappedTargetException; /** - * Cursor for the reference marks as is, not prepared for filling, but does not need - * cleanFillCursor either. + * Cursor for the reference marks as is, not prepared for filling, but does not need cleanFillCursor either. */ Optional getRawCursor(XTextDocument doc) - throws - NoDocumentException, - WrappedTargetException; + throws + NoDocumentException, + WrappedTargetException; /** * Get a cursor for filling in text. - * + *

* Must be followed by cleanFillCursor() */ XTextCursor getFillCursor(XTextDocument doc) - throws - NoDocumentException, - WrappedTargetException, - CreationException; + throws + NoDocumentException, + WrappedTargetException, + CreationException; /** - * Remove brackets, but if the result would become empty, leave them; if the result would be a - * single character, leave the left bracket. - * + * Remove brackets, but if the result would become empty, leave them; if the result would be a single character, leave the left bracket. */ void cleanFillCursor(XTextDocument doc) - throws - NoDocumentException, - WrappedTargetException; + throws + NoDocumentException, + WrappedTargetException; /** - * Note: create is in NamedRangeManager + * Note: create is in NamedRangeManager */ void removeFromDocument(XTextDocument doc) - throws - WrappedTargetException, - NoDocumentException; + throws + WrappedTargetException, + NoDocumentException; } diff --git a/src/main/java/org/jabref/model/openoffice/backend/NamedRangeManager.java b/src/main/java/org/jabref/model/openoffice/backend/NamedRangeManager.java index 9bbcc752350..25a82b4ad19 100644 --- a/src/main/java/org/jabref/model/openoffice/backend/NamedRangeManager.java +++ b/src/main/java/org/jabref/model/openoffice/backend/NamedRangeManager.java @@ -17,15 +17,15 @@ NamedRange createNamedRange(XTextDocument doc, XTextCursor position, boolean insertSpaceAfter, boolean withoutBrackets) - throws - CreationException; + throws + CreationException; List getUsedNames(XTextDocument doc) - throws - NoDocumentException; + throws + NoDocumentException; Optional getNamedRangeFromDocument(XTextDocument doc, String markName) - throws - NoDocumentException, - WrappedTargetException; + throws + NoDocumentException, + WrappedTargetException; } diff --git a/src/main/java/org/jabref/model/openoffice/ootext/OOFormat.java b/src/main/java/org/jabref/model/openoffice/ootext/OOFormat.java index 6b4a96de644..14f5822de4f 100644 --- a/src/main/java/org/jabref/model/openoffice/ootext/OOFormat.java +++ b/src/main/java/org/jabref/model/openoffice/ootext/OOFormat.java @@ -4,40 +4,33 @@ /** * Helper functions to produce some of the markup as understood by OOTextIntoOO.write - * - * These do not cover all tags, only those needed to embed markup - * from Layout and citation marker formatters into citation markers and - * bibliography. + *

+ * These do not cover all tags, only those needed to embed markup from Layout and citation marker formatters into citation markers and bibliography. */ public class OOFormat { private OOFormat() { - /* */ } /** * Mark {@code ootext} as using a character locale known to OO. * * @param locale language[-country[-territory]] - * - * https://www.openoffice.org/api/docs/common/ref/com/sun/star/lang/Locale.html - * - * The country part is optional. - * - * The territory part is not only optional, the allowed "codes are vendor and browser-specific", - * so probably best to avoid them if possible. - * + *

+ * https://www.openoffice.org/api/docs/common/ref/com/sun/star/lang/Locale.html + *

+ * The country part is optional. + *

+ * The territory part is not only optional, the allowed "codes are vendor and browser-specific", so probably best to avoid them if possible. */ public static OOText setLocale(OOText ootext, String locale) { return OOText.fromString(String.format("", locale) + ootext.toString() + ""); } /** - * Mark {@code ootext} as using the character locale "zxx", which means "no language", "no - * linguistic content". - * + * Mark {@code ootext} as using the character locale "zxx", which means "no language", "no linguistic content". + *

* Used around citation marks, probably to turn off spellchecking. - * */ public static OOText setLocaleNone(OOText ootext) { return OOFormat.setLocale(ootext, "zxx"); @@ -46,14 +39,12 @@ public static OOText setLocaleNone(OOText ootext) { /** * Mark {@code ootext} using a character style {@code charStyle} * - * @param charStyle Name of a character style known to OO. May be empty for "Standard", which in - * turn means do not override any properties. - * + * @param charStyle Name of a character style known to OO. May be empty for "Standard", which in turn means do not override any properties. */ public static OOText setCharStyle(OOText ootext, String charStyle) { return OOText.fromString(String.format("", charStyle) - + ootext.toString() - + ""); + + ootext.toString() + + ""); } /** @@ -81,4 +72,4 @@ public static OOText formatReferenceToPageNumberOfReferenceMark(String reference String string = String.format("", referenceMarkName); return OOText.fromString(string); } - } +} diff --git a/src/main/java/org/jabref/model/openoffice/ootext/OOText.java b/src/main/java/org/jabref/model/openoffice/ootext/OOText.java index 5b5fa4caba9..8478ca4a65a 100644 --- a/src/main/java/org/jabref/model/openoffice/ootext/OOText.java +++ b/src/main/java/org/jabref/model/openoffice/ootext/OOText.java @@ -4,9 +4,8 @@ /** * Text with HTML-like markup as understood by OOTextIntoOO.write - * - * Some of the tags can be added using OOFormat methods. Others come from the layout engine, either - * by interpreting LaTeX markup or from settings in the jstyle file. + *

+ * Some of the tags can be added using OOFormat methods. Others come from the layout engine, either by interpreting LaTeX markup or from settings in the jstyle file. */ public class OOText { @@ -17,7 +16,9 @@ private OOText(String data) { this.data = data; } - /** @return null for null input, otherwise the argument wrapped into a new OOText */ + /** + * @return null for null input, otherwise the argument wrapped into a new OOText + */ public static OOText fromString(String string) { if (string == null) { return null; @@ -25,7 +26,9 @@ public static OOText fromString(String string) { return new OOText(string); } - /** @return null for null input, otherwise the string inside the argument */ + /** + * @return null for null input, otherwise the string inside the argument + */ public static String toString(OOText ootext) { if (ootext == null) { return null; diff --git a/src/main/java/org/jabref/model/openoffice/ootext/OOTextIntoOO.java b/src/main/java/org/jabref/model/openoffice/ootext/OOTextIntoOO.java index 909b088b5b3..bbe77c33e04 100644 --- a/src/main/java/org/jabref/model/openoffice/ootext/OOTextIntoOO.java +++ b/src/main/java/org/jabref/model/openoffice/ootext/OOTextIntoOO.java @@ -53,7 +53,7 @@ public class OOTextIntoOO { private static final Logger LOGGER = LoggerFactory.getLogger(OOTextIntoOO.class); /** - * "ParaStyleName" is an OpenOffice Property name. + * "ParaStyleName" is an OpenOffice Property name. */ private static final String PARA_STYLE_NAME = "ParaStyleName"; @@ -77,78 +77,60 @@ public class OOTextIntoOO { private static final byte SUBSCRIPT_HEIGHT = (byte) 58; private static final String TAG_NAME_REGEXP = - "(?:b|i|em|tt|smallcaps|sup|sub|u|s|p|span|oo:referenceToPageNumberOfReferenceMark)"; + "(?:b|i|em|tt|smallcaps|sup|sub|u|s|p|span|oo:referenceToPageNumberOfReferenceMark)"; private static final String ATTRIBUTE_NAME_REGEXP = - "(?:oo:ParaStyleName|oo:CharStyleName|lang|style|target)"; + "(?:oo:ParaStyleName|oo:CharStyleName|lang|style|target)"; private static final String ATTRIBUTE_VALUE_REGEXP = "\"([^\"]*)\""; private static final Pattern HTML_TAG = - Pattern.compile("<(/" + TAG_NAME_REGEXP + ")>" - + "|" - + "<(" + TAG_NAME_REGEXP + ")" - + "((?:\\s+(" + ATTRIBUTE_NAME_REGEXP + ")=" + ATTRIBUTE_VALUE_REGEXP + ")*)" - + ">"); + Pattern.compile("<(/" + TAG_NAME_REGEXP + ")>" + + "|" + + "<(" + TAG_NAME_REGEXP + ")" + + "((?:\\s+(" + ATTRIBUTE_NAME_REGEXP + ")=" + ATTRIBUTE_VALUE_REGEXP + ")*)" + + ">"); private static final Pattern ATTRIBUTE_PATTERN = - Pattern.compile("\\s+(" + ATTRIBUTE_NAME_REGEXP + ")=" + ATTRIBUTE_VALUE_REGEXP); + Pattern.compile("\\s+(" + ATTRIBUTE_NAME_REGEXP + ")=" + ATTRIBUTE_VALUE_REGEXP); private OOTextIntoOO() { - // Hide the public constructor } /** - * Insert a text with formatting indicated by HTML-like tags, into - * a text at the position given by a cursor. - * - * Limitation: understands no entities. It does not receive any either, unless - * the user provides it. - * - * To limit the damage {@code TAG_NAME_REGEXP} and {@code ATTRIBUTE_NAME_REGEXP} - * explicitly lists the names we care about. - * + * Insert a text with formatting indicated by HTML-like tags, into a text at the position given by a cursor. + *

+ * Limitation: understands no entities. It does not receive any either, unless the user provides it. + *

+ * To limit the damage {@code TAG_NAME_REGEXP} and {@code ATTRIBUTE_NAME_REGEXP} explicitly lists the names we care about. + *

* Notable changes w.r.t insertOOFormattedTextAtCurrentLocation: - * + *

* - new tags: + *

+ * - {@code } - earlier was applied from code + *

+ * - {@code } - earlier was applied from code, for "CitationCharacterFormat" + *

+ * - {@code

} start new paragraph - earlier was applied from code + *

+ * - {@code

} : start new paragraph and apply ParStyleName - earlier was applied from code + *

+ * - {@code } - earlier: known, but ignored - now: equivalent to {@code } - {@code } (self-closing) + *

+ * - closing tags try to properly restore state (in particular, the "not directly set" state) instead of dictating an "off" state. This makes a difference when the value inherited from another level (for example the paragraph) is not the "off" state. + *

+ * An example: a style with {@code ReferenceParagraphFormat="JR_bibentry"} Assume JR_bibentry in LibreOffice is a paragraph style that prescribes "bold" font. LAYOUT only prescribes bold around year. Which parts of the bibliography entries should come out as bold? + *

+ * - The user can format citation marks (it is enough to format their start) and the properties not (everywhere) dictated by the style are preserved (where they are not). * - * - {@code } - * - earlier was applied from code - * - * - {@code } - * - earlier was applied from code, for "CitationCharacterFormat" - * - * - {@code

} start new paragraph - * - earlier was applied from code - * - * - {@code

} : start new paragraph and apply ParStyleName - * - earlier was applied from code - * - * - {@code } - * - earlier: known, but ignored - * - now: equivalent to {@code } - * - {@code } (self-closing) - * - * - closing tags try to properly restore state (in particular, the "not directly set" state) - * instead of dictating an "off" state. This makes a difference when the value inherited from - * another level (for example the paragraph) is not the "off" state. - * - * An example: a style with - * {@code ReferenceParagraphFormat="JR_bibentry"} - * Assume JR_bibentry in LibreOffice is a paragraph style that prescribes "bold" font. - * LAYOUT only prescribes bold around year. - * Which parts of the bibliography entries should come out as bold? - * - * - The user can format citation marks (it is enough to format their start) and the - * properties not (everywhere) dictated by the style are preserved (where they are not). - * - * @param position The cursor giving the insert location. Not modified. - * @param ootext The marked-up text to insert. + * @param position The cursor giving the insert location. Not modified. + * @param ootext The marked-up text to insert. */ public static void write(XTextDocument doc, XTextCursor position, OOText ootext) - throws - WrappedTargetException, - CreationException { + throws + WrappedTargetException, + CreationException { Objects.requireNonNull(doc); Objects.requireNonNull(ootext); @@ -231,7 +213,7 @@ public static void write(XTextDocument doc, XTextCursor position, OOText ootext) case "oo:ParaStyleName": //

if (StringUtil.isNullOrEmpty(value)) { - LOGGER.debug(String.format("oo:ParaStyleName inherited")); + LOGGER.debug("oo:ParaStyleName inherited"); } else { if (setParagraphStyle(cursor, value)) { // Presumably tested already: @@ -250,12 +232,8 @@ public static void write(XTextDocument doc, XTextCursor position, OOText ootext) String key = pair.a; String value = pair.b; switch (key) { - case "target": - UnoCrossRef.insertReferenceToPageNumberOfReferenceMark(doc, value, cursor); - break; - default: - LOGGER.warn(String.format("Unexpected attribute '%s' for <%s>", key, tagName)); - break; + case "target" -> UnoCrossRef.insertReferenceToPageNumberOfReferenceMark(doc, value, cursor); + default -> LOGGER.warn(String.format("Unexpected attribute '%s' for <%s>", key, tagName)); } } break; @@ -270,27 +248,23 @@ public static void write(XTextDocument doc, XTextCursor position, OOText ootext) String key = pair.a; String value = pair.b; switch (key) { - case "oo:CharStyleName": - // - settings.addAll(setCharStyleName(value)); - break; - case "lang": - // - // - settings.addAll(setCharLocale(value)); - break; - case "style": + case "oo:CharStyleName" -> + // + settings.addAll(setCharStyleName(value)); + case "lang" -> + // + // + settings.addAll(setCharLocale(value)); + case "style" -> { // HTML-style small-caps if ("font-variant: small-caps".equals(value)) { settings.addAll(setCharCaseMap(CaseMap.SMALLCAPS)); break; } LOGGER.warn(String.format("Unexpected value %s for attribute '%s' for <%s>", - value, key, tagName)); - break; - default: - LOGGER.warn(String.format("Unexpected attribute '%s' for <%s>", key, tagName)); - break; + value, key, tagName)); + } + default -> LOGGER.warn(String.format("Unexpected attribute '%s' for <%s>", key, tagName)); } } formatStack.pushLayer(settings); @@ -310,9 +284,9 @@ public static void write(XTextDocument doc, XTextCursor position, OOText ootext) String expected = expectEnd.pop(); if (!tagName.equals(expected)) { LOGGER.warn(String.format("expected '<%s>', found '<%s>' after '%s'", - expected, - tagName, - currentSubstring)); + expected, + tagName, + currentSubstring)); } break; default: @@ -330,21 +304,18 @@ public static void write(XTextDocument doc, XTextCursor position, OOText ootext) cursor.collapseToEnd(); if (!expectEnd.empty()) { - String rest = ""; + StringBuilder rest = new StringBuilder(); for (String s : expectEnd) { - rest = String.format("<%s>", s) + rest; + rest.insert(0, String.format("<%s>", s)); } - LOGGER.warn(String.format("OOTextIntoOO.write:" - + " expectEnd stack is not empty at the end: %s%n", - rest)); + LOGGER.warn(String.format("OOTextIntoOO.write: expectEnd stack is not empty at the end: %s%n", rest)); } } /** - * Purpose: in some cases we do not want to inherit direct - * formatting from the context. - * - * In particular, when filling the bibliography title and body. + * Purpose: in some cases we do not want to inherit direct formatting from the context. + *

+ * In particular, when filling the bibliography title and body. */ public static void removeDirectFormatting(XTextCursor cursor) { @@ -358,8 +329,8 @@ public static void removeDirectFormatting(XTextCursor cursor) { propertySet.setPropertyValue(CHAR_STYLE_NAME, "Standard"); xPropertyState.setPropertyToDefault("CharCaseMap"); } catch (UnknownPropertyException | - PropertyVetoException | - WrappedTargetException ex) { + PropertyVetoException | + WrappedTargetException ex) { LOGGER.warn("exception caught", ex); } @@ -374,14 +345,14 @@ public static void removeDirectFormatting(XTextCursor cursor) { // Only report those we do not yet know about final Set knownToFail = Set.of("ListAutoFormat", - "ListId", - "NumberingIsNumber", - "NumberingLevel", - "NumberingRules", - "NumberingStartValue", - "ParaChapterNumberingLevel", - "ParaIsNumberingRestart", - "ParaStyleName"); + "ListId", + "NumberingIsNumber", + "NumberingLevel", + "NumberingRules", + "NumberingStartValue", + "ParaChapterNumberingLevel", + "ParaIsNumberingRestart", + "ParaStyleName"); // query again, just in case it matters propertySet = UnoCast.cast(XPropertySet.class, cursor).get(); @@ -422,34 +393,34 @@ static class MyPropertyStack { */ static final Set CONTROLLED_PROPERTIES = Set.of( - /* Used for SuperScript, SubScript. - * - * These three are interdependent: changing one may change others. - */ - "CharEscapement", "CharEscapementHeight", "CharAutoEscapement", + /* Used for SuperScript, SubScript. + * + * These three are interdependent: changing one may change others. + */ + "CharEscapement", "CharEscapementHeight", "CharAutoEscapement", - /* used for Bold */ - "CharWeight", + /* used for Bold */ + "CharWeight", - /* Used for Italic */ - "CharPosture", + /* Used for Italic */ + "CharPosture", - /* Used for strikeout. These two are interdependent. */ - "CharStrikeout", "CharCrossedOut", + /* Used for strikeout. These two are interdependent. */ + "CharStrikeout", "CharCrossedOut", - /* Used for underline. These three are interdependent, but apparently - * we can leave out the last two. - */ - "CharUnderline", // "CharUnderlineColor", "CharUnderlineHasColor", + /* Used for underline. These three are interdependent, but apparently + * we can leave out the last two. + */ + "CharUnderline", // "CharUnderlineColor", "CharUnderlineHasColor", - /* Used for lang="zxx", to silence spellchecker. */ - "CharLocale", + /* Used for lang="zxx", to silence spellchecker. */ + "CharLocale", - /* Used for CitationCharacterFormat. */ - "CharStyleName", + /* Used for CitationCharacterFormat. */ + "CharStyleName", - /* Used for and */ - "CharCaseMap"); + /* Used for and */ + "CharCaseMap"); /** * The number of properties actually controlled. @@ -467,9 +438,7 @@ static class MyPropertyStack { final String[] goodNames; /** - * Maintain a stack of layers, each containing a description of the desired state of - * properties. Each description is an ArrayList of property values, Optional.empty() - * encoding "not directly set". + * Maintain a stack of layers, each containing a description of the desired state of properties. Each description is an ArrayList of property values, Optional.empty() encoding "not directly set". */ final Stack>> layers; @@ -478,9 +447,7 @@ static class MyPropertyStack { XPropertySet propertySet = UnoCast.cast(XPropertySet.class, cursor).get(); XPropertySetInfo propertySetInfo = propertySet.getPropertySetInfo(); - /* - * On creation, initialize the property name -- index mapping. - */ + // On creation, initialize the property name -- index mapping. this.goodNameToIndex = new HashMap<>(); int nextIndex = 0; for (Property p : propertySetInfo.getProperties()) { @@ -498,19 +465,16 @@ static class MyPropertyStack { this.goodNames = new String[goodSize]; for (Map.Entry entry : goodNameToIndex.entrySet()) { - goodNames[ entry.getValue() ] = entry.getKey(); + goodNames[entry.getValue()] = entry.getKey(); } - // XMultiPropertySet.setPropertyValues() requires alphabetically sorted property names. - // We adjust here: + // XMultiPropertySet.setPropertyValues() requires alphabetically sorted property names. We adjust here: Arrays.sort(goodNames); for (int i = 0; i < goodSize; i++) { this.goodNameToIndex.put(goodNames[i], i); } - /* - * Get the initial state of the properties and add the first layer. - */ + // Get the initial state of the properties and add the first layer. XMultiPropertyStates mpss = UnoCast.cast(XMultiPropertyStates.class, cursor).get(); PropertyState[] propertyStates; try { @@ -537,9 +501,8 @@ static class MyPropertyStack { } /** - * Given a list of property name, property value pairs, construct and push a new layer - * describing the intended state after these have been applied. - * + * Given a list of property name, property value pairs, construct and push a new layer describing the intended state after these have been applied. + *

* Opening tags usually call this. */ void pushLayer(List> settings) { @@ -571,7 +534,7 @@ void popLayer() { /** * Apply the current desired formatting state to a cursor. - * + *

* The idea is to minimize the number of calls to OpenOffice. */ void apply(XTextCursor cursor) { @@ -629,24 +592,22 @@ private static List> parseAttributes(String attributes) { while (attributeMatcher.find()) { String key = attributeMatcher.group(1); String value = attributeMatcher.group(2); - res.add(new OOPair(key, value)); + res.add(new OOPair<>(key, value)); } return res; } - /* - * We rely on property values being either DIRECT_VALUE or DEFAULT_VALUE (not - * AMBIGUOUS_VALUE). If the cursor covers a homogeneous region, or is collapsed, then this is - * true. + /** + * We rely on property values being either DIRECT_VALUE or DEFAULT_VALUE (not AMBIGUOUS_VALUE). If the cursor covers a homogeneous region, or is collapsed, then this is true. */ private static boolean isPropertyDefault(XTextCursor cursor, String propertyName) - throws - UnknownPropertyException { + throws + UnknownPropertyException { XPropertyState xPropertyState = UnoCast.cast(XPropertyState.class, cursor).get(); PropertyState state = xPropertyState.getPropertyState(propertyName); if (state == PropertyState.AMBIGUOUS_VALUE) { throw new java.lang.IllegalArgumentException("PropertyState.AMBIGUOUS_VALUE" - + " (expected properties for a homogeneous cursor)"); + + " (expected properties for a homogeneous cursor)"); } return state == PropertyState.DEFAULT_VALUE; } @@ -657,33 +618,33 @@ private static boolean isPropertyDefault(XTextCursor cursor, String propertyName private static List> setCharWeight(float value) { List> settings = new ArrayList<>(); - settings.add(new OOPair<>("CharWeight", (Float) value)); + settings.add(new OOPair<>("CharWeight", value)); return settings; } private static List> setCharPosture(FontSlant value) { List> settings = new ArrayList<>(); - settings.add(new OOPair<>("CharPosture", (Object) value)); + settings.add(new OOPair<>("CharPosture", value)); return settings; } private static List> setCharCaseMap(short value) { List> settings = new ArrayList<>(); - settings.add(new OOPair<>("CharCaseMap", (Short) value)); + settings.add(new OOPair<>("CharCaseMap", value)); return settings; } // com.sun.star.awt.FontUnderline private static List> setCharUnderline(short value) { List> settings = new ArrayList<>(); - settings.add(new OOPair<>(CHAR_UNDERLINE, (Short) value)); + settings.add(new OOPair<>(CHAR_UNDERLINE, value)); return settings; } // com.sun.star.awt.FontStrikeout private static List> setCharStrikeout(short value) { List> settings = new ArrayList<>(); - settings.add(new OOPair<>(CHAR_STRIKEOUT, (Short) value)); + settings.add(new OOPair<>(CHAR_STRIKEOUT, value)); return settings; } @@ -701,7 +662,7 @@ private static List> setCharStyleName(String value) { // Locale private static List> setCharLocale(Locale value) { List> settings = new ArrayList<>(); - settings.add(new OOPair<>("CharLocale", (Object) value)); + settings.add(new OOPair<>("CharLocale", value)); return settings; } @@ -731,12 +692,12 @@ private static List> setCharEscapement(Optional va MyPropertyStack formatStack) { List> settings = new ArrayList<>(); Optional oldValue = (formatStack - .getPropertyValue(CHAR_ESCAPEMENT) - .map(e -> (short) e)); + .getPropertyValue(CHAR_ESCAPEMENT) + .map(e -> (short) e)); Optional oldHeight = (formatStack - .getPropertyValue(CHAR_ESCAPEMENT_HEIGHT) - .map(e -> (byte) e)); + .getPropertyValue(CHAR_ESCAPEMENT_HEIGHT) + .map(e -> (byte) e)); if (relative && (value.isPresent() || height.isPresent())) { double oldHeightFloat = oldHeight.orElse(CHAR_ESCAPEMENT_HEIGHT_DEFAULT) * 0.01; @@ -746,17 +707,17 @@ private static List> setCharEscapement(Optional va byte newHeight = (byte) Math.round(heightFloat * oldHeightFloat); short newValue = (short) Math.round(valueFloat * oldHeightFloat + oldValueFloat); if (value.isPresent()) { - settings.add(new OOPair<>(CHAR_ESCAPEMENT, (Short) newValue)); + settings.add(new OOPair<>(CHAR_ESCAPEMENT, newValue)); } if (height.isPresent()) { - settings.add(new OOPair<>(CHAR_ESCAPEMENT_HEIGHT, (Byte) newHeight)); + settings.add(new OOPair<>(CHAR_ESCAPEMENT_HEIGHT, newHeight)); } } else { if (value.isPresent()) { - settings.add(new OOPair<>(CHAR_ESCAPEMENT, (Short) value.get())); + settings.add(new OOPair<>(CHAR_ESCAPEMENT, value.get())); } if (height.isPresent()) { - settings.add(new OOPair<>(CHAR_ESCAPEMENT_HEIGHT, (Byte) height.get())); + settings.add(new OOPair<>(CHAR_ESCAPEMENT_HEIGHT, height.get())); } } return settings; @@ -764,19 +725,19 @@ private static List> setCharEscapement(Optional va private static List> setSubScript(MyPropertyStack formatStack) { return setCharEscapement(Optional.of(SUBSCRIPT_VALUE), - Optional.of(SUBSCRIPT_HEIGHT), - true, - formatStack); + Optional.of(SUBSCRIPT_HEIGHT), + true, + formatStack); } private static List> setSuperScript(MyPropertyStack formatStack) { return setCharEscapement(Optional.of(SUPERSCRIPT_VALUE), - Optional.of(SUPERSCRIPT_HEIGHT), - true, - formatStack); + Optional.of(SUPERSCRIPT_HEIGHT), + true, + formatStack); } - /* + /** * @return true on failure */ public static boolean setParagraphStyle(XTextCursor cursor, String paragraphStyle) { @@ -789,9 +750,9 @@ public static boolean setParagraphStyle(XTextCursor cursor, String paragraphStyl propertySet.setPropertyValue(PARA_STYLE_NAME, paragraphStyle); return PASS; } catch (UnknownPropertyException - | PropertyVetoException - | com.sun.star.lang.IllegalArgumentException - | WrappedTargetException ex) { + | PropertyVetoException + | com.sun.star.lang.IllegalArgumentException + | WrappedTargetException ex) { return FAIL; } } @@ -806,5 +767,4 @@ private static void insertParagraphBreak(XText text, XTextCursor cursor) { throw new java.lang.IllegalArgumentException("Caught unexpected com.sun.star.lang.IllegalArgumentException", ex); } } - } diff --git a/src/main/java/org/jabref/model/openoffice/rangesort/FunctionalTextViewCursor.java b/src/main/java/org/jabref/model/openoffice/rangesort/FunctionalTextViewCursor.java index e08a7f4a2ad..314de5e37f3 100644 --- a/src/main/java/org/jabref/model/openoffice/rangesort/FunctionalTextViewCursor.java +++ b/src/main/java/org/jabref/model/openoffice/rangesort/FunctionalTextViewCursor.java @@ -44,13 +44,13 @@ public class FunctionalTextViewCursor { /* The initial position of the cursor or null. */ - private XTextRange initialPosition; + private final XTextRange initialPosition; /* The initial selection in the document or null. */ - private XServiceInfo initialSelection; + private final XServiceInfo initialSelection; /* The view cursor, potentially moved from its original location. */ - private XTextViewCursor viewCursor; + private final XTextViewCursor viewCursor; private FunctionalTextViewCursor(XTextRange initialPosition, XServiceInfo initialSelection, @@ -90,8 +90,8 @@ public static OOResult get(XTextDocument doc) if (initialSelection == null) { String errorMessage = ("Selection is not available: cannot provide a functional view cursor"); return OOResult.error(errorMessage); - } else if (!Arrays.stream(initialSelection.getSupportedServiceNames()) - .anyMatch("com.sun.star.text.TextRanges"::equals)) { + } else if (Arrays.stream(initialSelection.getSupportedServiceNames()) + .noneMatch("com.sun.star.text.TextRanges"::equals)) { // initialSelection does not support TextRanges. // We need to change it (and the viewCursor with it). XTextRange newSelection = doc.getText().getStart(); diff --git a/src/main/java/org/jabref/model/openoffice/rangesort/RangeOverlap.java b/src/main/java/org/jabref/model/openoffice/rangesort/RangeOverlap.java index 3edd059d7ff..1f4f3ae0ed4 100644 --- a/src/main/java/org/jabref/model/openoffice/rangesort/RangeOverlap.java +++ b/src/main/java/org/jabref/model/openoffice/rangesort/RangeOverlap.java @@ -3,7 +3,7 @@ import java.util.List; /** - * Used in reporting range overlaps. + * Used in reporting range overlaps. */ public class RangeOverlap { public final RangeOverlapKind kind; diff --git a/src/main/java/org/jabref/model/openoffice/rangesort/RangeOverlapBetween.java b/src/main/java/org/jabref/model/openoffice/rangesort/RangeOverlapBetween.java index 16b7735fb7a..a5cb13fb4f0 100644 --- a/src/main/java/org/jabref/model/openoffice/rangesort/RangeOverlapBetween.java +++ b/src/main/java/org/jabref/model/openoffice/rangesort/RangeOverlapBetween.java @@ -14,13 +14,14 @@ public class RangeOverlapBetween { - private RangeOverlapBetween() { } + private RangeOverlapBetween() { + } /** * Check for any overlap between two sets of XTextRange values. - * + *

* Assume fewHolders is small (usually a single element, for checking the cursor) - * + *

* Returns on first problem found. */ public static @@ -44,8 +45,8 @@ List> findFirst(XTextDocument doc, for (V aHolder : fewHolders) { XText aText = aHolder.getRange().getText(); fewTuples.add(new OOTuple3<>(aText, - UnoCast.cast(XTextRangeCompare.class, aText).get(), - aHolder)); + UnoCast.cast(XTextRangeCompare.class, aText).get(), + aHolder)); } /* @@ -81,14 +82,14 @@ List> findFirst(XTextDocument doc, // // We return EQUAL_RANGE RangeOverlapKind kind = (equal ? RangeOverlapKind.EQUAL_RANGE - : (touching ? RangeOverlapKind.TOUCH - : RangeOverlapKind.OVERLAP)); + : (touching ? RangeOverlapKind.TOUCH + : RangeOverlapKind.OVERLAP)); List valuesForOverlappingRanges = new ArrayList<>(); valuesForOverlappingRanges.add(aHolder); valuesForOverlappingRanges.add(bHolder); - result.add(new RangeOverlap(kind, valuesForOverlappingRanges)); + result.add(new RangeOverlap<>(kind, valuesForOverlappingRanges)); return result; } } diff --git a/src/main/java/org/jabref/model/openoffice/rangesort/RangeOverlapKind.java b/src/main/java/org/jabref/model/openoffice/rangesort/RangeOverlapKind.java index 2bb7f8f4af7..1098a85a87f 100644 --- a/src/main/java/org/jabref/model/openoffice/rangesort/RangeOverlapKind.java +++ b/src/main/java/org/jabref/model/openoffice/rangesort/RangeOverlapKind.java @@ -2,13 +2,19 @@ public enum RangeOverlapKind { - /** The ranges share a boundary */ + /** + * The ranges share a boundary + */ TOUCH, - /** They share some characters */ + /** + * They share some characters + */ OVERLAP, - /** They cover the same XTextRange */ + /** + * They cover the same XTextRange + */ EQUAL_RANGE } diff --git a/src/main/java/org/jabref/model/openoffice/rangesort/RangeOverlapWithin.java b/src/main/java/org/jabref/model/openoffice/rangesort/RangeOverlapWithin.java index a8534b630ae..69ff4ca91d1 100644 --- a/src/main/java/org/jabref/model/openoffice/rangesort/RangeOverlapWithin.java +++ b/src/main/java/org/jabref/model/openoffice/rangesort/RangeOverlapWithin.java @@ -12,23 +12,18 @@ public class RangeOverlapWithin { - private RangeOverlapWithin() { } + private RangeOverlapWithin() { + } /** * Report identical, overlapping or touching ranges between elements of rangeHolders. + *

+ * For overlapping and touching, only report consecutive ranges and only with a single sample of otherwise identical ranges. * - * For overlapping and touching, only report consecutive ranges and only with a single sample of - * otherwise identical ranges. - * - * @param rangeHolders represent the ranges to be checked. - * - * Note: for each rangeHolder, rangeHolder.getRange() is called multiple times. - * To avoid repeated work, they should keep a copy of the range instead of - * getting it each time from the document. - * - * @param reportAtMost Limit the number of records returned to atMost. - * Zero {@code reportAtMost} means no limit. - * + * @param rangeHolders represent the ranges to be checked. + *

+ * Note: for each rangeHolder, rangeHolder.getRange() is called multiple times. To avoid repeated work, they should keep a copy of the range instead of getting it each time from the document. + * @param reportAtMost Limit the number of records returned to atMost. Zero {@code reportAtMost} means no limit. * @param includeTouching Should the result contain ranges sharing only a boundary? */ public static @@ -44,13 +39,10 @@ List> findOverlappingRanges(XTextDocument doc, /** * Report identical, overlapping or touching ranges. + *

+ * For overlapping and touching, only report consecutive ranges and only with a single sample of otherwise identical ranges. * - * For overlapping and touching, only report consecutive ranges and only with a single sample of - * otherwise identical ranges. - * - * @param atMost Limit the number of records returned to atMost. - * Zero {@code atMost} means no limit. - * + * @param atMost Limit the number of records returned to atMost. Zero {@code atMost} means no limit. * @param includeTouching Should the result contain ranges sharing only a boundary? */ public static @@ -66,7 +58,7 @@ List> findOverlappingRanges(RangeSort.RangePartitions input, continue; } XTextRangeCompare cmp = UnoCast.cast(XTextRangeCompare.class, - partition.get(0).getRange().getText()).get(); + partition.get(0).getRange().getText()).get(); for (int i = 0; i < (partition.size() - 1); i++) { V aHolder = partition.get(i); @@ -82,15 +74,15 @@ List> findOverlappingRanges(RangeSort.RangePartitions input, // aValues.add(bHolder); // collect those equal while (i < (partition.size() - 1) && - UnoTextRange.compareStartsThenEndsUnsafe( - cmp, - aRange, - partition.get(i + 1).getRange()) == 0) { + UnoTextRange.compareStartsThenEndsUnsafe( + cmp, + aRange, + partition.get(i + 1).getRange()) == 0) { bHolder = partition.get(i + 1); aValues.add(bHolder); i++; } - result.add(new RangeOverlap(RangeOverlapKind.EQUAL_RANGE, aValues)); + result.add(new RangeOverlap<>(RangeOverlapKind.EQUAL_RANGE, aValues)); if (atMost > 0 && result.size() >= atMost) { return result; } @@ -105,17 +97,16 @@ List> findOverlappingRanges(RangeSort.RangePartitions input, List valuesForOverlappingRanges = new ArrayList<>(); valuesForOverlappingRanges.add(aHolder); valuesForOverlappingRanges.add(bHolder); - result.add(new RangeOverlap((cmpResult == 0) - ? RangeOverlapKind.TOUCH - : RangeOverlapKind.OVERLAP, - valuesForOverlappingRanges)); + result.add(new RangeOverlap<>((cmpResult == 0) + ? RangeOverlapKind.TOUCH + : RangeOverlapKind.OVERLAP, + valuesForOverlappingRanges)); } if (atMost > 0 && result.size() >= atMost) { - return result; + return result; } } } return result; } - } diff --git a/src/main/java/org/jabref/model/openoffice/rangesort/RangeSort.java b/src/main/java/org/jabref/model/openoffice/rangesort/RangeSort.java index 99ace5154e1..77982a9a7db 100644 --- a/src/main/java/org/jabref/model/openoffice/rangesort/RangeSort.java +++ b/src/main/java/org/jabref/model/openoffice/rangesort/RangeSort.java @@ -13,22 +13,17 @@ import com.sun.star.text.XTextRangeCompare; /** - * RangeSort provides sorting based on XTextRangeCompare, which only provides comparison - * between XTextRange values within the same XText. + * RangeSort provides sorting based on XTextRangeCompare, which only provides comparison between XTextRange values within the same XText. */ public class RangeSort { private RangeSort() { - /**/ } /** * Compare two RangeHolders (using RangeHolder.getRange()) within an XText. - * - * Note: since we only look at the ranges, this comparison is generally not consistent with - * `equals` on the RangeHolders. Probably should not be used for key comparison in - * {@code TreeMap} or {@code Set} - * + *

+ * Note: since we only look at the ranges, this comparison is generally not consistent with `equals` on the RangeHolders. Probably should not be used for key comparison in {@code TreeMap} or {@code Set} */ private static class HolderComparatorWithinPartition implements Comparator { @@ -36,7 +31,7 @@ private static class HolderComparatorWithinPartition implements Comparator * Note: RangeHolder.getRange() is called many times. */ public static void sortWithinPartition(List rangeHolders) { @@ -83,7 +78,7 @@ public List> getPartitions() { } /** - * Partition RangeHolders by the corresponding XText. + * Partition RangeHolders by the corresponding XText. */ public static RangePartitions partitionRanges(List holders) { RangePartitions result = new RangePartitions<>(); diff --git a/src/main/java/org/jabref/model/openoffice/rangesort/RangeSortEntry.java b/src/main/java/org/jabref/model/openoffice/rangesort/RangeSortEntry.java index 0ed686ee901..a9b834027ff 100644 --- a/src/main/java/org/jabref/model/openoffice/rangesort/RangeSortEntry.java +++ b/src/main/java/org/jabref/model/openoffice/rangesort/RangeSortEntry.java @@ -9,7 +9,7 @@ public class RangeSortEntry implements RangeSortable { private XTextRange range; private int indexInPosition; - private T content; + private final T content; public RangeSortEntry(XTextRange range, int indexInPosition, T content) { this.range = range; diff --git a/src/main/java/org/jabref/model/openoffice/rangesort/RangeSortVisual.java b/src/main/java/org/jabref/model/openoffice/rangesort/RangeSortVisual.java index e412f4ade6c..b83db3f1555 100644 --- a/src/main/java/org/jabref/model/openoffice/rangesort/RangeSortVisual.java +++ b/src/main/java/org/jabref/model/openoffice/rangesort/RangeSortVisual.java @@ -14,25 +14,21 @@ /** * Sort XTextRange values visually (top-down,left-to-right). - * + *

* Requires functional XTextViewCursor. - * - * Problem: for multicolumn layout and when viewing pages side-by-side in LO, the - * (top-down,left-to-right) order interpreted as-on-the-screen: an XTextRange at the top of - * the second column or second page is sorted before an XTextRange at the bottom of the - * first column of the first page. + *

+ * Problem: for multicolumn layout and when viewing pages side-by-side in LO, the (top-down,left-to-right) order interpreted as-on-the-screen: an XTextRange at the top of the second column or second page is sorted before an XTextRange at the bottom of the first column of the first page. */ public class RangeSortVisual { private static final Logger LOGGER = LoggerFactory.getLogger(RangeSortVisual.class); private RangeSortVisual() { - /**/ } /** * Sort the input {@code inputs} visually. - * + *

* Requires a functional {@code XTextViewCursor}. * * @return The input, sorted by the elements XTextRange and getIndexInPosition. @@ -63,8 +59,8 @@ public static List> visualSort(List> input for (int i = 0; i < inputSize; i++) { RangeSortable input = inputs.get(i); comparableMarks.add(new ComparableMark<>(positions.get(i), - input.getIndexInPosition(), - input)); + input.getIndexInPosition(), + input)); } comparableMarks.sort(RangeSortVisual::compareTopToBottomLeftToRight); @@ -82,22 +78,16 @@ public static List> visualSort(List> input } /** - * Given a location, return its position: coordinates relative to the top left position of the - * first page of the document. - * - * Note: for text layouts with two or more columns, this gives the wrong order: - * top-down/left-to-right does not match reading order. - * - * Note: The "relative to the top left position of the first page" is meant "as it appears on - * the screen". - * - * In particular: when viewing pages side-by-side, the top half of the right page is - * higher than the lower half of the left page. Again, top-down/left-to-right does not - * match reading order. + * Given a location, return its position: coordinates relative to the top left position of the first page of the document. + *

+ * Note: for text layouts with two or more columns, this gives the wrong order: top-down/left-to-right does not match reading order. + *

+ * Note: The "relative to the top left position of the first page" is meant "as it appears on the screen". + *

+ * In particular: when viewing pages side-by-side, the top half of the right page is higher than the lower half of the left page. Again, top-down/left-to-right does not match reading order. * * @param range Location. - * @param cursor To get the position, we need az XTextViewCursor. - * It will be moved to the range. + * @param cursor To get the position, we need az XTextViewCursor. It will be moved to the range. */ private static Point findPositionOfTextRange(XTextRange range, XTextViewCursor cursor) { cursor.gotoRange(range, false); @@ -117,10 +107,9 @@ private static int compareTopToBottomLeftToRight(ComparableMark a, Compar /** * A reference mark name paired with its visual position. - * - * Comparison is based on (Y,X,indexInPosition): vertical compared first, horizontal second, - * indexInPosition third. - * + *

+ * Comparison is based on (Y,X,indexInPosition): vertical compared first, horizontal second, indexInPosition third. + *

* Used for sorting reference marks by their visual positions. */ private static class ComparableMark { @@ -138,7 +127,5 @@ public ComparableMark(Point position, int indexInPosition, T content) { public T getContent() { return content; } - } - } diff --git a/src/main/java/org/jabref/model/openoffice/rangesort/RangeSortable.java b/src/main/java/org/jabref/model/openoffice/rangesort/RangeSortable.java index 59a4c3fa9af..15482f0a3e6 100644 --- a/src/main/java/org/jabref/model/openoffice/rangesort/RangeSortable.java +++ b/src/main/java/org/jabref/model/openoffice/rangesort/RangeSortable.java @@ -7,9 +7,10 @@ */ public interface RangeSortable extends RangeHolder { - /** The XTextRange - * - * For citation marks in footnotes this may be the range of the footnote mark. + /** + * The XTextRange + *

+ * For citation marks in footnotes this may be the range of the footnote mark. */ XTextRange getRange(); diff --git a/src/main/java/org/jabref/model/openoffice/style/Citation.java b/src/main/java/org/jabref/model/openoffice/style/Citation.java index 7bae4fd2548..899013773f2 100644 --- a/src/main/java/org/jabref/model/openoffice/style/Citation.java +++ b/src/main/java/org/jabref/model/openoffice/style/Citation.java @@ -10,27 +10,36 @@ public class Citation implements ComparableCitation, CitationMarkerEntry, CitationMarkerNumericEntry { - /** key in database */ + /** + * key in database + */ public final String citationKey; - /** Result from database lookup. Optional.empty() if not found. */ + /** + * Result from database lookup. Optional.empty() if not found. + */ private Optional db; - /** The number used for numbered citation styles . */ + /** + * The number used for numbered citation styles . + */ private Optional number; - /** Letter that makes the in-text citation unique. */ + /** + * Letter that makes the in-text citation unique. + */ private Optional uniqueLetter; - /** pageInfo */ + /** + * pageInfo + */ private Optional pageInfo; - /** isFirstAppearanceOfSource */ - private boolean isFirstAppearanceOfSource; - /** - * + * isFirstAppearanceOfSource */ + private boolean isFirstAppearanceOfSource; + public Citation(String citationKey) { this.citationKey = citationKey; this.db = Optional.empty(); @@ -57,9 +66,7 @@ public boolean getIsFirstAppearanceOfSource() { @Override public Optional getBibEntry() { - return (db.isPresent() - ? Optional.of(db.get().entry) - : Optional.empty()); + return db.map(citationLookupResult -> citationLookupResult.entry); } public static Optional lookup(BibDatabase database, String key) { @@ -70,10 +77,10 @@ public static Optional lookup(BibDatabase database, String public static Optional lookup(List databases, String key) { return (databases.stream() - .map(database -> Citation.lookup(database, key)) - .filter(Optional::isPresent) - .map(Optional::get) - .findFirst()); + .map(database -> Citation.lookup(database, key)) + .filter(Optional::isPresent) + .map(Optional::get) + .findFirst()); } public void lookupInDatabases(List databases) { @@ -129,18 +136,17 @@ public void setIsFirstAppearanceOfSource(boolean value) { * Setters for CitationGroups.distribute() */ public static void setLookupResult(OOPair> pair) { - Citation cit = pair.a; - cit.db = pair.b; + Citation citation = pair.a; + citation.db = pair.b; } public static void setNumber(OOPair> pair) { - Citation cit = pair.a; - cit.number = pair.b; + Citation citation = pair.a; + citation.number = pair.b; } public static void setUniqueLetter(OOPair> pair) { - Citation cit = pair.a; - cit.uniqueLetter = pair.b; + Citation citation = pair.a; + citation.uniqueLetter = pair.b; } - } diff --git a/src/main/java/org/jabref/model/openoffice/style/CitationGroup.java b/src/main/java/org/jabref/model/openoffice/style/CitationGroup.java index 90afb872d4f..30cfbdd512e 100644 --- a/src/main/java/org/jabref/model/openoffice/style/CitationGroup.java +++ b/src/main/java/org/jabref/model/openoffice/style/CitationGroup.java @@ -28,10 +28,6 @@ public class CitationGroup { public final CitationType citationType; public final List citationsInStorageOrder; - /* - * Extra data - */ - /* * A name of a reference mark to link to by formatCitedOnPages. * May be initially empty, if backend does not use reference marks. @@ -98,7 +94,7 @@ void imposeLocalOrder(Comparator entryComparator) { } this.localOrder = OOListUtil.order(citationsInStorageOrder, - new CompareCitation(entryComparator, true)); + new CompareCitation(entryComparator, true)); if (dataModel == OODataModel.JabRef52) { getCitationsInLocalOrder().get(last).setPageInfo(lastPageInfo); @@ -114,7 +110,7 @@ public List getLocalOrder() { */ public List getCitationsInLocalOrder() { - return OOListUtil.map(localOrder, i -> citationsInStorageOrder.get(i)); + return OOListUtil.map(localOrder, citationsInStorageOrder::get); } /* @@ -152,5 +148,4 @@ public void setCitationMarker(Optional citationMarker) { public Optional getCitationMarker() { return this.citationMarker; } - } diff --git a/src/main/java/org/jabref/model/openoffice/style/CitationGroupId.java b/src/main/java/org/jabref/model/openoffice/style/CitationGroupId.java index baaa931214c..6c271b12267 100644 --- a/src/main/java/org/jabref/model/openoffice/style/CitationGroupId.java +++ b/src/main/java/org/jabref/model/openoffice/style/CitationGroupId.java @@ -5,6 +5,7 @@ */ public class CitationGroupId { String groupId; + public CitationGroupId(String groupId) { this.groupId = groupId; } diff --git a/src/main/java/org/jabref/model/openoffice/style/CitationGroups.java b/src/main/java/org/jabref/model/openoffice/style/CitationGroups.java index e5e642fa652..68dcd714974 100644 --- a/src/main/java/org/jabref/model/openoffice/style/CitationGroups.java +++ b/src/main/java/org/jabref/model/openoffice/style/CitationGroups.java @@ -19,15 +19,14 @@ /** * CitationGroups : the set of citation groups in the document. - * + *

* This is the main input (as well as output) for creating citation markers and bibliography. - * */ public class CitationGroups { private static final Logger LOGGER = LoggerFactory.getLogger(CitationGroups.class); - private Map citationGroupsUnordered; + private final Map citationGroupsUnordered; /** * Provides order of appearance for the citation groups. @@ -35,7 +34,7 @@ public class CitationGroups { private Optional> globalOrder; /** - * This is going to be the bibliography + * This is going to be the bibliography */ private Optional bibliography; @@ -114,13 +113,12 @@ public List getCitationGroupsInGlobalOrder() { if (globalOrder.isEmpty()) { throw new IllegalStateException("getCitationGroupsInGlobalOrder: not ordered yet"); } - return OOListUtil.map(globalOrder.get(), groupId -> citationGroupsUnordered.get(groupId)); + return OOListUtil.map(globalOrder.get(), citationGroupsUnordered::get); } /** - * Impose an order of citation groups by providing the order of their citation group - * idendifiers. - * + * Impose an order of citation groups by providing the order of their citation group idendifiers. + *

* Also set indexInGlobalOrder for each citation group. */ public void setGlobalOrder(List globalOrder) { @@ -151,8 +149,7 @@ public void imposeLocalOrder(Comparator entryComparator) { } /** - * Collect citations into a list of cited sources using neither CitationGroup.globalOrder or - * Citation.localOrder + * Collect citations into a list of cited sources using neither CitationGroup.globalOrder or Citation.localOrder */ public CitedKeys getCitedKeysUnordered() { LinkedHashMap res = new LinkedHashMap<>(); @@ -216,9 +213,9 @@ public List getUnresolvedKeys() { } public void createNumberedBibliographySortedInOrderOfAppearance() { - if (!bibliography.isEmpty()) { + if (bibliography.isPresent()) { throw new IllegalStateException("createNumberedBibliographySortedInOrderOfAppearance:" - + " already have a bibliography"); + + " already have a bibliography"); } CitedKeys citedKeys = getCitedKeysSortedInOrderOfAppearance(); citedKeys.numberCitedKeysInCurrentOrder(); @@ -230,7 +227,7 @@ public void createNumberedBibliographySortedInOrderOfAppearance() { * precondition: database lookup already performed (otherwise we just sort citation keys) */ public void createPlainBibliographySortedByComparator(Comparator entryComparator) { - if (!bibliography.isEmpty()) { + if (bibliography.isPresent()) { throw new IllegalStateException("createPlainBibliographySortedByComparator: already have a bibliography"); } CitedKeys citedKeys = getCitedKeysUnordered(); @@ -242,7 +239,7 @@ public void createPlainBibliographySortedByComparator(Comparator entry * precondition: database lookup already performed (otherwise we just sort citation keys) */ public void createNumberedBibliographySortedByComparator(Comparator entryComparator) { - if (!bibliography.isEmpty()) { + if (bibliography.isPresent()) { throw new IllegalStateException("createNumberedBibliographySortedByComparator: already have a bibliography"); } CitedKeys citedKeys = getCitedKeysUnordered(); @@ -261,7 +258,7 @@ public Optional getCitationGroup(CitationGroupId groupId) { return Optional.ofNullable(group); } - /* + /** * @return true if all citation groups have referenceMarkNameForLinking */ public boolean citationGroupsProvideReferenceMarkNameForLinking() { @@ -290,5 +287,4 @@ public void afterRemoveCitationGroup(CitationGroup group) { bibliography = Optional.empty(); } - } diff --git a/src/main/java/org/jabref/model/openoffice/style/CitationLookupResult.java b/src/main/java/org/jabref/model/openoffice/style/CitationLookupResult.java index bfe6dc1debe..c82177a7e69 100644 --- a/src/main/java/org/jabref/model/openoffice/style/CitationLookupResult.java +++ b/src/main/java/org/jabref/model/openoffice/style/CitationLookupResult.java @@ -19,16 +19,12 @@ public CitationLookupResult(BibEntry entry, BibDatabase database) { /** * Note: BibEntry overrides Object.equals, but BibDatabase does not. - * - * Consequently, {@code this.database.equals(that.database)} below - * is equivalent to {@code this.database == that.database}. - * - * Since within each GUI call we use a fixed list of databases, it is OK. - * - * CitationLookupResult.equals is used in CitedKey.addPath to check the added Citation - * refers to the same source as the others. As long as we look up each citation key - * only once (in CitationGroups.lookupCitations), the default implementation for equals - * would be sufficient (and could also omit hashCode below). + *

+ * Consequently, {@code this.database.equals(that.database)} below is equivalent to {@code this.database == that.database}. + *

+ * Since within each GUI call we use a fixed list of databases, it is OK. + *

+ * CitationLookupResult.equals is used in CitedKey.addPath to check the added Citation refers to the same source as the others. As long as we look up each citation key only once (in CitationGroups.lookupCitations), the default implementation for equals would be sufficient (and could also omit hashCode below). */ @Override public boolean equals(Object otherObject) { diff --git a/src/main/java/org/jabref/model/openoffice/style/CitationMarkerEntry.java b/src/main/java/org/jabref/model/openoffice/style/CitationMarkerEntry.java index 5fcb9bcc1a8..18bbe5588b3 100644 --- a/src/main/java/org/jabref/model/openoffice/style/CitationMarkerEntry.java +++ b/src/main/java/org/jabref/model/openoffice/style/CitationMarkerEntry.java @@ -15,14 +15,12 @@ public interface CitationMarkerEntry extends CitationMarkerNormEntry { Optional getUniqueLetter(); /** - * pageInfo for this citation, provided by the user. - * May be empty, for none. + * pageInfo for this citation, provided by the user. May be empty, for none. */ Optional getPageInfo(); /** - * @return true if this citation is the first appearance of the source cited. Some styles use - * different limit on the number of authors shown in this case. + * @return true if this citation is the first appearance of the source cited. Some styles use different limit on the number of authors shown in this case. */ boolean getIsFirstAppearanceOfSource(); } diff --git a/src/main/java/org/jabref/model/openoffice/style/CitationMarkerNormEntry.java b/src/main/java/org/jabref/model/openoffice/style/CitationMarkerNormEntry.java index a2581b38b60..1489dede932 100644 --- a/src/main/java/org/jabref/model/openoffice/style/CitationMarkerNormEntry.java +++ b/src/main/java/org/jabref/model/openoffice/style/CitationMarkerNormEntry.java @@ -7,14 +7,16 @@ */ public interface CitationMarkerNormEntry { - /** Citation key. This is what we usually get from the document. - * - * Used if getLookupResult() returns empty, which indicates failure to lookup in the databases. + /** + * Citation key. This is what we usually get from the document. + *

+ * Used if getLookupResult() returns empty, which indicates failure to lookup in the databases. */ String getCitationKey(); - /** Result of looking up citation key in databases. - * + /** + * Result of looking up citation key in databases. + *

* Optional.empty() indicates unresolved citation. */ Optional getLookupResult(); diff --git a/src/main/java/org/jabref/model/openoffice/style/CitationPath.java b/src/main/java/org/jabref/model/openoffice/style/CitationPath.java index 0920ea20feb..ba562ebe6bf 100644 --- a/src/main/java/org/jabref/model/openoffice/style/CitationPath.java +++ b/src/main/java/org/jabref/model/openoffice/style/CitationPath.java @@ -1,8 +1,7 @@ package org.jabref.model.openoffice.style; /** - * Identifies a citation with the identifier of the citation group containing it and its storage - * index within. + * Identifies a citation with the identifier of the citation group containing it and its storage index within. */ public class CitationPath { diff --git a/src/main/java/org/jabref/model/openoffice/style/CitedKey.java b/src/main/java/org/jabref/model/openoffice/style/CitedKey.java index 5331204bd75..cd3dc74684e 100644 --- a/src/main/java/org/jabref/model/openoffice/style/CitedKey.java +++ b/src/main/java/org/jabref/model/openoffice/style/CitedKey.java @@ -10,14 +10,13 @@ /** * Cited keys are collected from the citations in citation groups. - * - * They contain backreferences to the corresponding citations in {@code where}. This allows the - * extra information generated using CitedKeys to be distributed back to the in-text citations. + *

+ * They contain backreferences to the corresponding citations in {@code where}. This allows the extra information generated using CitedKeys to be distributed back to the in-text citations. */ public class CitedKey implements - ComparableCitedKey, - CitationMarkerNormEntry, - CitationMarkerNumericBibEntry { + ComparableCitedKey, + CitationMarkerNormEntry, + CitationMarkerNumericBibEntry { public final String citationKey; private final List where; @@ -27,16 +26,16 @@ public class CitedKey implements private Optional uniqueLetter; // For AuthorYear citation styles. private Optional normCitMarker; // For AuthorYear citation styles. - CitedKey(String citationKey, CitationPath path, Citation cit) { + CitedKey(String citationKey, CitationPath path, Citation citation) { this.citationKey = citationKey; this.where = new ArrayList<>(); // remember order this.where.add(path); // synchronized with Citation - this.db = cit.getLookupResult(); - this.number = cit.getNumber(); - this.uniqueLetter = cit.getUniqueLetter(); + this.db = citation.getLookupResult(); + this.number = citation.getNumber(); + this.uniqueLetter = citation.getUniqueLetter(); // CitedKey only this.normCitMarker = Optional.empty(); @@ -120,19 +119,19 @@ void lookupInDatabases(List databases) { this.db = Citation.lookup(databases, this.citationKey); } - void distributeLookupResult(CitationGroups cgs) { - cgs.distributeToCitations(where, Citation::setLookupResult, db); + void distributeLookupResult(CitationGroups citationGroups) { + citationGroups.distributeToCitations(where, Citation::setLookupResult, db); } /* * Make unique using a letter or by numbering */ - void distributeNumber(CitationGroups cgs) { - cgs.distributeToCitations(where, Citation::setNumber, number); + void distributeNumber(CitationGroups citationGroups) { + citationGroups.distributeToCitations(where, Citation::setNumber, number); } - void distributeUniqueLetter(CitationGroups cgs) { - cgs.distributeToCitations(where, Citation::setUniqueLetter, uniqueLetter); + void distributeUniqueLetter(CitationGroups citationGroups) { + citationGroups.distributeToCitations(where, Citation::setUniqueLetter, uniqueLetter); } } diff --git a/src/main/java/org/jabref/model/openoffice/style/CitedKeys.java b/src/main/java/org/jabref/model/openoffice/style/CitedKeys.java index 059c1b6123a..7b95d1ece19 100644 --- a/src/main/java/org/jabref/model/openoffice/style/CitedKeys.java +++ b/src/main/java/org/jabref/model/openoffice/style/CitedKeys.java @@ -63,21 +63,21 @@ public void lookupInDatabases(List databases) { } } - void distributeLookupResults(CitationGroups cgs) { + void distributeLookupResults(CitationGroups citationGroups) { for (CitedKey ck : this.data.values()) { - ck.distributeLookupResult(cgs); + ck.distributeLookupResult(citationGroups); } } - void distributeNumbers(CitationGroups cgs) { + void distributeNumbers(CitationGroups citationGroups) { for (CitedKey ck : this.data.values()) { - ck.distributeNumber(cgs); + ck.distributeNumber(citationGroups); } } - public void distributeUniqueLetters(CitationGroups cgs) { + public void distributeUniqueLetters(CitationGroups citationGroups) { for (CitedKey ck : this.data.values()) { - ck.distributeUniqueLetter(cgs); + ck.distributeUniqueLetter(citationGroups); } } diff --git a/src/main/java/org/jabref/model/openoffice/style/ComparableCitation.java b/src/main/java/org/jabref/model/openoffice/style/ComparableCitation.java index 81120c09b2a..42a7e5869ba 100644 --- a/src/main/java/org/jabref/model/openoffice/style/ComparableCitation.java +++ b/src/main/java/org/jabref/model/openoffice/style/ComparableCitation.java @@ -5,8 +5,7 @@ import org.jabref.model.openoffice.ootext.OOText; /** - * When sorting citations (in a group), we also consider pageInfo. - * Otherwise we sort citations as cited keys. + * When sorting citations (in a group), we also consider pageInfo. Otherwise we sort citations as cited keys. */ public interface ComparableCitation extends ComparableCitedKey { Optional getPageInfo(); diff --git a/src/main/java/org/jabref/model/openoffice/style/CompareCitation.java b/src/main/java/org/jabref/model/openoffice/style/CompareCitation.java index 966715b11a8..1d27674ba1d 100644 --- a/src/main/java/org/jabref/model/openoffice/style/CompareCitation.java +++ b/src/main/java/org/jabref/model/openoffice/style/CompareCitation.java @@ -10,7 +10,7 @@ */ public class CompareCitation implements Comparator { - private CompareCitedKey citedKeyComparator; + private final CompareCitedKey citedKeyComparator; CompareCitation(Comparator entryComparator, boolean unresolvedComesFirst) { this.citedKeyComparator = new CompareCitedKey(entryComparator, unresolvedComesFirst); diff --git a/src/main/java/org/jabref/model/openoffice/style/NonUniqueCitationMarker.java b/src/main/java/org/jabref/model/openoffice/style/NonUniqueCitationMarker.java index 34300734d2f..e633f7a9c70 100644 --- a/src/main/java/org/jabref/model/openoffice/style/NonUniqueCitationMarker.java +++ b/src/main/java/org/jabref/model/openoffice/style/NonUniqueCitationMarker.java @@ -1,15 +1,18 @@ package org.jabref.model.openoffice.style; /** - * What should createCitationMarker do if it discovers that uniqueLetters provided are not - * sufficient for unique presentation? + * What should createCitationMarker do if it discovers that uniqueLetters provided are not sufficient for unique presentation? */ public enum NonUniqueCitationMarker { - /** Give an insufficient representation anyway. */ + /** + * Give an insufficient representation anyway. + */ FORGIVEN, - /** Throw an exception */ + /** + * Throw an exception + */ THROWS } diff --git a/src/main/java/org/jabref/model/openoffice/style/OODataModel.java b/src/main/java/org/jabref/model/openoffice/style/OODataModel.java index 835715dfca5..470edc1694d 100644 --- a/src/main/java/org/jabref/model/openoffice/style/OODataModel.java +++ b/src/main/java/org/jabref/model/openoffice/style/OODataModel.java @@ -6,13 +6,19 @@ import org.jabref.model.openoffice.ootext.OOText; -/** What is the data stored? */ +/** + * What is the data stored? + */ public enum OODataModel { - /** JabRef52: pageInfo belongs to CitationGroup, not Citation. */ + /** + * JabRef52: pageInfo belongs to CitationGroup, not Citation. + */ JabRef52, - /** JabRef60: pageInfo belongs to Citation. */ + /** + * JabRef60: pageInfo belongs to Citation. + */ JabRef60; /** diff --git a/src/main/java/org/jabref/model/openoffice/style/PageInfo.java b/src/main/java/org/jabref/model/openoffice/style/PageInfo.java index 1ff87569a3b..c92ad335b49 100644 --- a/src/main/java/org/jabref/model/openoffice/style/PageInfo.java +++ b/src/main/java/org/jabref/model/openoffice/style/PageInfo.java @@ -7,7 +7,6 @@ public class PageInfo { private PageInfo() { - // hide public constructor } /* @@ -27,7 +26,7 @@ public static Optional normalizePageInfo(Optional optionalText) /** * Defines sort order for pageInfo strings. - * + *

* Optional.empty comes before non-empty. */ public static int comparePageInfo(Optional a, Optional b) { diff --git a/src/main/java/org/jabref/model/openoffice/uno/CreationException.java b/src/main/java/org/jabref/model/openoffice/uno/CreationException.java index 091d5469e2d..84e3c8afe55 100644 --- a/src/main/java/org/jabref/model/openoffice/uno/CreationException.java +++ b/src/main/java/org/jabref/model/openoffice/uno/CreationException.java @@ -2,14 +2,12 @@ /** * Exception used to indicate failure in either - * - * XMultiServiceFactory.createInstance() - * XMultiComponentFactory.createInstanceWithContext() + *

+ * XMultiServiceFactory.createInstance() XMultiComponentFactory.createInstanceWithContext() */ public class CreationException extends Exception { public CreationException(String message) { super(message); } - } diff --git a/src/main/java/org/jabref/model/openoffice/uno/UnoBookmark.java b/src/main/java/org/jabref/model/openoffice/uno/UnoBookmark.java index fdbbb0dd1c6..f187527aeab 100644 --- a/src/main/java/org/jabref/model/openoffice/uno/UnoBookmark.java +++ b/src/main/java/org/jabref/model/openoffice/uno/UnoBookmark.java @@ -14,14 +14,15 @@ public class UnoBookmark { - private UnoBookmark() { } + private UnoBookmark() { + } /** * Provides access to bookmarks by name. */ public static XNameAccess getNameAccess(XTextDocument doc) - throws - NoDocumentException { + throws + NoDocumentException { XBookmarksSupplier supplier = UnoCast.cast(XBookmarksSupplier.class, doc).get(); try { @@ -38,32 +39,28 @@ public static XNameAccess getNameAccess(XTextDocument doc) * @return The XTextRange for the bookmark, or Optional.empty(). */ public static Optional getAnchor(XTextDocument doc, String name) - throws - WrappedTargetException, - NoDocumentException { + throws + WrappedTargetException, + NoDocumentException { XNameAccess nameAccess = getNameAccess(doc); return (UnoNameAccess.getTextContentByName(nameAccess, name).map(XTextContent::getAnchor)); } /** - * Insert a bookmark with the given name at the cursor provided, or with another name if the one - * we asked for is already in use. - * + * Insert a bookmark with the given name at the cursor provided, or with another name if the one we asked for is already in use. + *

* In LibreOffice the another name is in "{name}{number}" format. * - * @param name For the bookmark. - * @param range Cursor marking the location or range for the bookmark. - * @param absorb Shall we incorporate range? - * + * @param name For the bookmark. + * @param range Cursor marking the location or range for the bookmark. + * @param absorb Shall we incorporate range? * @return The XNamed interface of the bookmark. - * - * result.getName() should be checked by the caller, because its name may differ from - * the one requested. + * result.getName() should be checked by the caller, because its name may differ from the one requested. */ public static XNamed create(XTextDocument doc, String name, XTextRange range, boolean absorb) - throws - CreationException { + throws + CreationException { return UnoNamed.insertNamedTextContent(doc, "com.sun.star.text.Bookmark", name, range, absorb); } @@ -71,9 +68,9 @@ public static XNamed create(XTextDocument doc, String name, XTextRange range, bo * Remove the named bookmark if it exists. */ public static void removeIfExists(XTextDocument doc, String name) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { XNameAccess marks = UnoBookmark.getNameAccess(doc); diff --git a/src/main/java/org/jabref/model/openoffice/uno/UnoCast.java b/src/main/java/org/jabref/model/openoffice/uno/UnoCast.java index fcc1bcc3e12..3234e4d130a 100644 --- a/src/main/java/org/jabref/model/openoffice/uno/UnoCast.java +++ b/src/main/java/org/jabref/model/openoffice/uno/UnoCast.java @@ -6,7 +6,8 @@ public class UnoCast { - private UnoCast() { } + private UnoCast() { + } /** * cast : short for Optional.ofNullable(UnoRuntime.queryInterface(...)) diff --git a/src/main/java/org/jabref/model/openoffice/uno/UnoCrossRef.java b/src/main/java/org/jabref/model/openoffice/uno/UnoCrossRef.java index f5d20a1de4f..7df6d7dc04c 100644 --- a/src/main/java/org/jabref/model/openoffice/uno/UnoCrossRef.java +++ b/src/main/java/org/jabref/model/openoffice/uno/UnoCrossRef.java @@ -14,7 +14,8 @@ public class UnoCrossRef { - private UnoCrossRef() { } + private UnoCrossRef() { + } /** * Update TextFields, etc. We use it to refresh cross-references in the document. @@ -26,17 +27,16 @@ public static void refresh(XTextDocument doc) { } /** - * Insert a clickable cross-reference to a reference mark, with a label containing the target's - * page number. - * + * Insert a clickable cross-reference to a reference mark, with a label containing the target's page number. + *

* May need a documentConnection.refresh() after, to update the text shown. */ public static void insertReferenceToPageNumberOfReferenceMark(XTextDocument doc, String referenceMarkName, XTextRange cursor) - throws - CreationException, - WrappedTargetException { + throws + CreationException, + WrappedTargetException { // based on: https://wiki.openoffice.org/wiki/Documentation/DevGuide/Text/Reference_Marks XMultiServiceFactory msf = UnoCast.cast(XMultiServiceFactory.class, doc).get(); @@ -62,20 +62,20 @@ public static void insertReferenceToPageNumberOfReferenceMark(XTextDocument doc, try { // specify that the source is a reference mark (could also be a footnote, // bookmark or sequence field) - xFieldProps.setPropertyValue("ReferenceFieldSource", Short.valueOf(ReferenceFieldSource.REFERENCE_MARK)); + xFieldProps.setPropertyValue("ReferenceFieldSource", ReferenceFieldSource.REFERENCE_MARK); } catch (UnknownPropertyException ex) { throw new java.lang.IllegalStateException("The created GetReference does not have property" - + " 'ReferenceFieldSource'"); + + " 'ReferenceFieldSource'"); } catch (PropertyVetoException ex) { throw new java.lang.IllegalStateException("Caught PropertyVetoException on 'ReferenceFieldSource'"); } try { // We want the reference displayed as page number - xFieldProps.setPropertyValue("ReferenceFieldPart", Short.valueOf(ReferenceFieldPart.PAGE)); + xFieldProps.setPropertyValue("ReferenceFieldPart", ReferenceFieldPart.PAGE); } catch (UnknownPropertyException ex) { throw new java.lang.IllegalStateException("The created GetReference does not have property" - + " 'ReferenceFieldPart'"); + + " 'ReferenceFieldPart'"); } catch (PropertyVetoException ex) { throw new java.lang.IllegalStateException("Caught PropertyVetoException on 'ReferenceFieldPart'"); } diff --git a/src/main/java/org/jabref/model/openoffice/uno/UnoCursor.java b/src/main/java/org/jabref/model/openoffice/uno/UnoCursor.java index e761a56e12f..da29ee84d92 100644 --- a/src/main/java/org/jabref/model/openoffice/uno/UnoCursor.java +++ b/src/main/java/org/jabref/model/openoffice/uno/UnoCursor.java @@ -11,22 +11,22 @@ public class UnoCursor { - private UnoCursor() { } + private UnoCursor() { + } /** * Get the cursor positioned by the user. */ public static Optional getViewCursor(XTextDocument doc) { return (UnoTextDocument.getCurrentController(doc) - .flatMap(e -> UnoCast.cast(XTextViewCursorSupplier.class, e)) - .map(XTextViewCursorSupplier::getViewCursor)); + .flatMap(e -> UnoCast.cast(XTextViewCursorSupplier.class, e)) + .map(XTextViewCursorSupplier::getViewCursor)); } /** * Create a text cursor for a textContent. * * @return Optional.empty if mark is null, otherwise cursor. - * */ public static Optional getTextCursorOfTextContentAnchor(XTextContent mark) { if (mark == null) { diff --git a/src/main/java/org/jabref/model/openoffice/uno/UnoNameAccess.java b/src/main/java/org/jabref/model/openoffice/uno/UnoNameAccess.java index 243c136f382..1250d56d923 100644 --- a/src/main/java/org/jabref/model/openoffice/uno/UnoNameAccess.java +++ b/src/main/java/org/jabref/model/openoffice/uno/UnoNameAccess.java @@ -9,14 +9,15 @@ public class UnoNameAccess { - private UnoNameAccess() { } + private UnoNameAccess() { + } /** * @return null if name not found, or if the result does not support the XTextContent interface. */ public static Optional getTextContentByName(XNameAccess nameAccess, String name) - throws - WrappedTargetException { + throws + WrappedTargetException { try { return UnoCast.cast(XTextContent.class, nameAccess.getByName(name)); } catch (NoSuchElementException ex) { diff --git a/src/main/java/org/jabref/model/openoffice/uno/UnoNamed.java b/src/main/java/org/jabref/model/openoffice/uno/UnoNamed.java index 5f1f50c873d..b9f43e56f80 100644 --- a/src/main/java/org/jabref/model/openoffice/uno/UnoNamed.java +++ b/src/main/java/org/jabref/model/openoffice/uno/UnoNamed.java @@ -8,38 +8,27 @@ public class UnoNamed { - private UnoNamed() { } + private UnoNamed() { + } /** * Insert a new instance of a service at the provided cursor position. * - * @param service For example - * "com.sun.star.text.ReferenceMark", - * "com.sun.star.text.Bookmark" or - * "com.sun.star.text.TextSection". - * - * Passed to this.asXMultiServiceFactory().createInstance(service) - * The result is expected to support the XNamed and XTextContent interfaces. - * - * @param name For the ReferenceMark, Bookmark, TextSection. - * If the name is already in use, LibreOffice may change the name. - * + * @param service For example "com.sun.star.text.ReferenceMark", "com.sun.star.text.Bookmark" or "com.sun.star.text.TextSection". + *

+ * Passed to this.asXMultiServiceFactory().createInstance(service) The result is expected to support the XNamed and XTextContent interfaces. + * @param name For the ReferenceMark, Bookmark, TextSection. If the name is already in use, LibreOffice may change the name. * @param range Marks the location or range for the thing to be inserted. - * - * @param absorb ReferenceMark, Bookmark and TextSection can incorporate a text range. - * If absorb is true, the text in the range becomes part of the thing. - * If absorb is false, the thing is inserted at the end of the range. - * + * @param absorb ReferenceMark, Bookmark and TextSection can incorporate a text range. If absorb is true, the text in the range becomes part of the thing. If absorb is false, the thing is inserted at the end of the range. * @return The XNamed interface, in case we need to check the actual name. - * */ static XNamed insertNamedTextContent(XTextDocument doc, String service, String name, XTextRange range, boolean absorb) - throws - CreationException { + throws + CreationException { XMultiServiceFactory msf = UnoCast.cast(XMultiServiceFactory.class, doc).get(); @@ -51,14 +40,13 @@ static XNamed insertNamedTextContent(XTextDocument doc, } XNamed xNamed = (UnoCast.cast(XNamed.class, xObject) - .orElseThrow(() -> new IllegalArgumentException("Service is not an XNamed"))); + .orElseThrow(() -> new IllegalArgumentException("Service is not an XNamed"))); xNamed.setName(name); // get XTextContent interface XTextContent xTextContent = (UnoCast.cast(XTextContent.class, xObject) - .orElseThrow(() -> new IllegalArgumentException("Service is not an XTextContent"))); + .orElseThrow(() -> new IllegalArgumentException("Service is not an XTextContent"))); range.getText().insertTextContent(range, xTextContent, absorb); return xNamed; } - } diff --git a/src/main/java/org/jabref/model/openoffice/uno/UnoProperties.java b/src/main/java/org/jabref/model/openoffice/uno/UnoProperties.java index 3a47818cf8b..80ea0c11c80 100644 --- a/src/main/java/org/jabref/model/openoffice/uno/UnoProperties.java +++ b/src/main/java/org/jabref/model/openoffice/uno/UnoProperties.java @@ -15,42 +15,31 @@ import com.sun.star.lang.WrappedTargetException; /** - * Utilities for properties. + * Utilities for properties. */ public class UnoProperties { - private UnoProperties() { } - - /* - * asPropertySet - */ + private UnoProperties() { + } public static Optional asPropertySet(XPropertyContainer propertyContainer) { return UnoCast.cast(XPropertySet.class, propertyContainer); } - /* - * getPropertySetInfo - */ - public static Optional getPropertySetInfo(XPropertySet propertySet) { return (Optional.ofNullable(propertySet) - .flatMap(e -> Optional.ofNullable(e.getPropertySetInfo()))); + .flatMap(e -> Optional.ofNullable(e.getPropertySetInfo()))); } public static Optional getPropertySetInfo(XPropertyContainer propertyContainer) { return Optional.ofNullable(propertyContainer).flatMap(UnoProperties::getPropertySetInfo); } - /* - * getPropertyNames - */ - public static List getPropertyNames(Property[] properties) { Objects.requireNonNull(properties); return (Arrays.stream(properties) - .map(p -> p.Name) - .collect(Collectors.toList())); + .map(p -> p.Name) + .collect(Collectors.toList())); } public static List getPropertyNames(XPropertySetInfo propertySetInfo) { @@ -67,13 +56,9 @@ public static List getPropertyNames(XPropertyContainer propertyContainer .orElse(new ArrayList<>())); } - /* - * getPropertyValue - */ - public static Optional getValueAsObject(XPropertySet propertySet, String property) - throws - WrappedTargetException { + throws + WrappedTargetException { Objects.requireNonNull(propertySet); Objects.requireNonNull(property); try { @@ -84,8 +69,8 @@ public static Optional getValueAsObject(XPropertySet propertySet, String } public static Optional getValueAsObject(XPropertyContainer propertyContainer, String property) - throws - WrappedTargetException { + throws + WrappedTargetException { Optional propertySet = asPropertySet(propertyContainer); if (propertySet.isEmpty()) { return Optional.empty(); diff --git a/src/main/java/org/jabref/model/openoffice/uno/UnoRedlines.java b/src/main/java/org/jabref/model/openoffice/uno/UnoRedlines.java index 2c408648d6f..3793ce7a079 100644 --- a/src/main/java/org/jabref/model/openoffice/uno/UnoRedlines.java +++ b/src/main/java/org/jabref/model/openoffice/uno/UnoRedlines.java @@ -12,13 +12,13 @@ import com.sun.star.text.XTextDocument; /** - * Change tracking and Redlines + * Change tracking and Redlines */ public class UnoRedlines { public static boolean getRecordChanges(XTextDocument doc) - throws - WrappedTargetException { + throws + WrappedTargetException { // https://wiki.openoffice.org/wiki/Documentation/DevGuide/Text/Settings // "Properties of com.sun.star.text.TextDocument" diff --git a/src/main/java/org/jabref/model/openoffice/uno/UnoReferenceMark.java b/src/main/java/org/jabref/model/openoffice/uno/UnoReferenceMark.java index 7a719042d79..062564b8156 100644 --- a/src/main/java/org/jabref/model/openoffice/uno/UnoReferenceMark.java +++ b/src/main/java/org/jabref/model/openoffice/uno/UnoReferenceMark.java @@ -17,17 +17,17 @@ public class UnoReferenceMark { - private UnoReferenceMark() { } + private UnoReferenceMark() { + } /** * @throws NoDocumentException If cannot get reference marks - * - * Note: also used by `isDocumentConnectionMissing` to test if we have a working connection. - * + *

+ * Note: also used by `isDocumentConnectionMissing` to test if we have a working connection. */ public static XNameAccess getNameAccess(XTextDocument doc) - throws - NoDocumentException { + throws + NoDocumentException { XReferenceMarksSupplier supplier = UnoCast.cast(XReferenceMarksSupplier.class, doc).get(); @@ -40,11 +40,11 @@ public static XNameAccess getNameAccess(XTextDocument doc) /** * Names of all reference marks. - * + *

* Empty list for nothing. */ public static List getListOfNames(XTextDocument doc) - throws NoDocumentException { + throws NoDocumentException { XNameAccess nameAccess = UnoReferenceMark.getNameAccess(doc); String[] names = nameAccess.getElementNames(); @@ -56,13 +56,13 @@ public static List getListOfNames(XTextDocument doc) /** * Remove the named reference mark. - * + *

* Removes both the text and the mark itself. */ public static void removeIfExists(XTextDocument doc, String name) - throws - WrappedTargetException, - NoDocumentException { + throws + WrappedTargetException, + NoDocumentException { XNameAccess xReferenceMarks = UnoReferenceMark.getNameAccess(doc); @@ -80,46 +80,41 @@ public static void removeIfExists(XTextDocument doc, String name) } /** - * @return reference mark as XTextContent, Optional.empty if not found. + * @return reference mark as XTextContent, Optional.empty if not found. */ public static Optional getAsTextContent(XTextDocument doc, String name) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { XNameAccess nameAccess = UnoReferenceMark.getNameAccess(doc); return UnoNameAccess.getTextContentByName(nameAccess, name); } /** - * XTextRange for the named reference mark, Optional.empty if not found. + * XTextRange for the named reference mark, Optional.empty if not found. */ public static Optional getAnchor(XTextDocument doc, String name) - throws - NoDocumentException, - WrappedTargetException { + throws + NoDocumentException, + WrappedTargetException { return (UnoReferenceMark.getAsTextContent(doc, name) - .map(XTextContent::getAnchor)); + .map(XTextContent::getAnchor)); } /** * Insert a new reference mark at the provided cursor position. + *

+ * If {@code absorb} is true, the text in the cursor range will become the text with gray background. + *

+ * Note: LibreOffice 6.4.6.2 will create multiple reference marks with the same name without error or renaming. Its GUI does not allow this, but we can create them programmatically. In the GUI, clicking on any of those identical names will move the cursor to the same mark. * - * If {@code absorb} is true, the text in the cursor range will become the text with gray - * background. - * - * Note: LibreOffice 6.4.6.2 will create multiple reference marks with the same name without - * error or renaming. - * Its GUI does not allow this, but we can create them programmatically. - * In the GUI, clicking on any of those identical names will move the cursor to the same - * mark. - * - * @param name For the reference mark. + * @param name For the reference mark. * @param range Cursor marking the location or range for the reference mark. */ public static XNamed create(XTextDocument doc, String name, XTextRange range, boolean absorb) - throws - CreationException { + throws + CreationException { return UnoNamed.insertNamedTextContent(doc, "com.sun.star.text.ReferenceMark", name, range, absorb); } } diff --git a/src/main/java/org/jabref/model/openoffice/uno/UnoScreenRefresh.java b/src/main/java/org/jabref/model/openoffice/uno/UnoScreenRefresh.java index e5c27fcbb5c..6de0afe5ad6 100644 --- a/src/main/java/org/jabref/model/openoffice/uno/UnoScreenRefresh.java +++ b/src/main/java/org/jabref/model/openoffice/uno/UnoScreenRefresh.java @@ -7,17 +7,17 @@ */ public class UnoScreenRefresh { - private UnoScreenRefresh() { } + private UnoScreenRefresh() { + } /** * Disable screen refresh. - * + *

* Must be paired with unlockControllers() - * + *

* https://www.openoffice.org/api/docs/common/ref/com/sun/star/frame/XModel.html - * - * While there is at least one lock remaining, some - * notifications for display updates are not broadcasted. + *

+ * While there is at least one lock remaining, some notifications for display updates are not broadcasted. */ public static void lockControllers(XTextDocument doc) { doc.lockControllers(); diff --git a/src/main/java/org/jabref/model/openoffice/uno/UnoSelection.java b/src/main/java/org/jabref/model/openoffice/uno/UnoSelection.java index 43d89ed157b..a6e581cfce1 100644 --- a/src/main/java/org/jabref/model/openoffice/uno/UnoSelection.java +++ b/src/main/java/org/jabref/model/openoffice/uno/UnoSelection.java @@ -17,7 +17,8 @@ public class UnoSelection { private static final Logger LOGGER = LoggerFactory.getLogger(UnoSelection.class); - private UnoSelection() { } + private UnoSelection() { + } private static Optional getSelectionSupplier(XTextDocument doc) { if (doc == null) { @@ -39,46 +40,21 @@ private static Optional getSelectionSupplier(XTextDocument d /** * @return may be Optional.empty(), or some type supporting XServiceInfo - * - * - * So far it seems the first thing we have to do - * with a selection is to decide what do we have. - * + * So far it seems the first thing we have to do with a selection is to decide what do we have. + *

* One way to do that is accessing its XServiceInfo interface. - * - * Experiments using printServiceInfo with cursor in various - * positions in the document: - * - * With cursor within the frame, in text: - * *** xserviceinfo.getImplementationName: "SwXTextRanges" - * "com.sun.star.text.TextRanges" - * - * With cursor somewhere else in text: - * *** xserviceinfo.getImplementationName: "SwXTextRanges" - * "com.sun.star.text.TextRanges" - * - * With cursor in comment (also known as "annotation"): - * *** XSelectionSupplier is OK - * *** Object initialSelection is null - * *** xserviceinfo is null - * - * With frame selected: - * *** xserviceinfo.getImplementationName: "SwXTextFrame" - * "com.sun.star.text.BaseFrame" - * "com.sun.star.text.TextContent" - * "com.sun.star.document.LinkTarget" - * "com.sun.star.text.TextFrame" - * "com.sun.star.text.Text" - * - * With cursor selecting an inserted image: - * *** XSelectionSupplier is OK - * *** Object initialSelection is OK - * *** xserviceinfo is OK - * *** xserviceinfo.getImplementationName: "SwXTextGraphicObject" - * "com.sun.star.text.BaseFrame" - * "com.sun.star.text.TextContent" - * "com.sun.star.document.LinkTarget" - * "com.sun.star.text.TextGraphicObject" + *

+ * Experiments using printServiceInfo with cursor in various positions in the document: + *

+ * With cursor within the frame, in text: *** xserviceinfo.getImplementationName: "SwXTextRanges" "com.sun.star.text.TextRanges" + *

+ * With cursor somewhere else in text: *** xserviceinfo.getImplementationName: "SwXTextRanges" "com.sun.star.text.TextRanges" + *

+ * With cursor in comment (also known as "annotation"): *** XSelectionSupplier is OK *** Object initialSelection is null *** xserviceinfo is null + *

+ * With frame selected: *** xserviceinfo.getImplementationName: "SwXTextFrame" "com.sun.star.text.BaseFrame" "com.sun.star.text.TextContent" "com.sun.star.document.LinkTarget" "com.sun.star.text.TextFrame" "com.sun.star.text.Text" + *

+ * With cursor selecting an inserted image: *** XSelectionSupplier is OK *** Object initialSelection is OK *** xserviceinfo is OK *** xserviceinfo.getImplementationName: "SwXTextGraphicObject" "com.sun.star.text.BaseFrame" "com.sun.star.text.TextContent" "com.sun.star.document.LinkTarget" "com.sun.star.text.TextGraphicObject" */ public static Optional getSelectionAsXServiceInfo(XTextDocument doc) { Objects.requireNonNull(doc); @@ -100,13 +76,9 @@ public static Optional getSelectionAsXServiceInfo(XTextDocument do } /** - * Select the object represented by {@code newSelection} if it is - * known and selectable in this {@code XSelectionSupplier} object. - * - * Presumably result from {@code XSelectionSupplier.getSelection()} is - * usually OK. It also accepted - * {@code XTextRange newSelection = doc.getText().getStart();} - * + * Select the object represented by {@code newSelection} if it is known and selectable in this {@code XSelectionSupplier} object. + *

+ * Presumably result from {@code XSelectionSupplier.getSelection()} is usually OK. It also accepted {@code XTextRange newSelection = doc.getText().getStart();} */ public static void select(XTextDocument doc, Object newSelection) { Objects.requireNonNull(doc); diff --git a/src/main/java/org/jabref/model/openoffice/uno/UnoStyle.java b/src/main/java/org/jabref/model/openoffice/uno/UnoStyle.java index cd4065ba8b3..aa659919fab 100644 --- a/src/main/java/org/jabref/model/openoffice/uno/UnoStyle.java +++ b/src/main/java/org/jabref/model/openoffice/uno/UnoStyle.java @@ -18,11 +18,12 @@ public class UnoStyle { public static final String CHARACTER_STYLES = "CharacterStyles"; public static final String PARAGRAPH_STYLES = "ParagraphStyles"; - private UnoStyle() { } + private UnoStyle() { + } private static Optional getStyleFromFamily(XTextDocument doc, String familyName, String styleName) - throws - WrappedTargetException { + throws + WrappedTargetException { XStyleFamiliesSupplier fss = UnoCast.cast(XStyleFamiliesSupplier.class, doc).get(); XNameAccess families = UnoCast.cast(XNameAccess.class, fss.getStyleFamilies()).get(); @@ -43,34 +44,34 @@ private static Optional getStyleFromFamily(XTextDocument doc, String fam } public static Optional getParagraphStyle(XTextDocument doc, String styleName) - throws - WrappedTargetException { + throws + WrappedTargetException { return getStyleFromFamily(doc, PARAGRAPH_STYLES, styleName); } public static Optional getCharacterStyle(XTextDocument doc, String styleName) - throws - WrappedTargetException { + throws + WrappedTargetException { return getStyleFromFamily(doc, CHARACTER_STYLES, styleName); } public static Optional getInternalNameOfStyle(XTextDocument doc, String familyName, String name) - throws - WrappedTargetException { + throws + WrappedTargetException { return (getStyleFromFamily(doc, familyName, name) .map(XStyle::getName)); } public static Optional getInternalNameOfParagraphStyle(XTextDocument doc, String name) - throws - WrappedTargetException { + throws + WrappedTargetException { return getInternalNameOfStyle(doc, PARAGRAPH_STYLES, name); } public static Optional getInternalNameOfCharacterStyle(XTextDocument doc, String name) - throws - WrappedTargetException { + throws + WrappedTargetException { return getInternalNameOfStyle(doc, CHARACTER_STYLES, name); } } diff --git a/src/main/java/org/jabref/model/openoffice/uno/UnoTextDocument.java b/src/main/java/org/jabref/model/openoffice/uno/UnoTextDocument.java index c7e94e6bb4c..3f154a4ae9c 100644 --- a/src/main/java/org/jabref/model/openoffice/uno/UnoTextDocument.java +++ b/src/main/java/org/jabref/model/openoffice/uno/UnoTextDocument.java @@ -7,6 +7,7 @@ import com.sun.star.document.XDocumentPropertiesSupplier; import com.sun.star.frame.XController; import com.sun.star.frame.XFrame; +import com.sun.star.lang.DisposedException; import com.sun.star.lang.WrappedTargetException; import com.sun.star.text.XTextDocument; import org.slf4j.Logger; @@ -16,25 +17,21 @@ public class UnoTextDocument { private static final Logger LOGGER = LoggerFactory.getLogger(UnoTextDocument.class); - private UnoTextDocument() { } + private UnoTextDocument() { + } /** - * @return True if we cannot reach the current document. + * @return True if we cannot reach the current document. */ public static boolean isDocumentConnectionMissing(XTextDocument doc) { - boolean missing = false; - if (doc == null) { - missing = true; - } + boolean missing = doc == null; // Attempt to check document is really available if (!missing) { try { UnoReferenceMark.getNameAccess(doc); - } catch (NoDocumentException ex) { - missing = true; - } catch (com.sun.star.lang.DisposedException ex) { + } catch (NoDocumentException | DisposedException ex) { missing = true; } } @@ -54,8 +51,8 @@ public static Optional getCurrentController(XTextDocument doc) { } /** - * @param doc The XTextDocument we want the frame title for. Null allowed. - * @return The title or Optional.empty() + * @param doc The XTextDocument we want the frame title for. Null allowed. + * @return The title or Optional.empty() */ public static Optional getFrameTitle(XTextDocument doc) { @@ -84,8 +81,8 @@ public static Optional getFrameTitle(XTextDocument doc) { static Optional getDocumentProperties(XTextDocument doc) { return (Optional.ofNullable(doc) - .flatMap(e -> UnoCast.cast(XDocumentPropertiesSupplier.class, e)) - .map(XDocumentPropertiesSupplier::getDocumentProperties)); + .flatMap(e -> UnoCast.cast(XDocumentPropertiesSupplier.class, e)) + .map(XDocumentPropertiesSupplier::getDocumentProperties)); } } diff --git a/src/main/java/org/jabref/model/openoffice/uno/UnoTextRange.java b/src/main/java/org/jabref/model/openoffice/uno/UnoTextRange.java index 56cb1498e2a..520878833e5 100644 --- a/src/main/java/org/jabref/model/openoffice/uno/UnoTextRange.java +++ b/src/main/java/org/jabref/model/openoffice/uno/UnoTextRange.java @@ -3,33 +3,30 @@ import java.util.Optional; import com.sun.star.text.XFootnote; +import com.sun.star.text.XTextContent; import com.sun.star.text.XTextRange; import com.sun.star.text.XTextRangeCompare; public class UnoTextRange { - private UnoTextRange() { } + private UnoTextRange() { + } /** - * If original is in a footnote, return a range containing - * the corresponding footnote marker. - * - * Returns Optional.empty if not in a footnote. + * If original is in a footnote, return a range containing the corresponding footnote marker. + *

+ * Returns Optional.empty if not in a footnote. */ public static Optional getFootnoteMarkRange(XTextRange original) { Optional footer = UnoCast.cast(XFootnote.class, original.getText()); - if (footer.isPresent()) { - // If we are inside a footnote, - // find the linking footnote marker: - // The footnote's anchor gives the correct position in the text: - return Optional.ofNullable(footer.get().getAnchor()); - } - return Optional.empty(); + // If we are inside a footnote, + // find the linking footnote marker: + // The footnote's anchor gives the correct position in the text: + return footer.map(XTextContent::getAnchor); } /** - * Test if two XTextRange values are comparable (i.e. they share - * the same getText()). + * Test if two XTextRange values are comparable (i.e. they share the same getText()). */ public static boolean comparables(XTextRange a, XTextRange b) { return a.getText() == b.getText(); @@ -37,7 +34,6 @@ public static boolean comparables(XTextRange a, XTextRange b) { /** * @return follows java conventions - * * 1 if (a > b); (-1) if (a < b) */ public static int compareStartsUnsafe(XTextRangeCompare compare, XTextRange a, XTextRange b) { @@ -54,7 +50,6 @@ public static int compareStarts(XTextRange a, XTextRange b) { /** * @return follows java conventions - * * 1 if (a > b); (-1) if (a < b) */ public static int compareEnds(XTextRange a, XTextRange b) { diff --git a/src/main/java/org/jabref/model/openoffice/uno/UnoTextSection.java b/src/main/java/org/jabref/model/openoffice/uno/UnoTextSection.java index 3b9797f553e..56293eee947 100644 --- a/src/main/java/org/jabref/model/openoffice/uno/UnoTextSection.java +++ b/src/main/java/org/jabref/model/openoffice/uno/UnoTextSection.java @@ -17,11 +17,11 @@ public class UnoTextSection { /** - * @return An XNameAccess to find sections by name. + * @return An XNameAccess to find sections by name. */ public static XNameAccess getNameAccess(XTextDocument doc) - throws - NoDocumentException { + throws + NoDocumentException { XTextSectionsSupplier supplier = UnoCast.cast(XTextSectionsSupplier.class, doc).get(); try { @@ -32,12 +32,12 @@ public static XNameAccess getNameAccess(XTextDocument doc) } /** - * Get an XTextSection by name. + * Get an XTextSection by name. */ public static Optional getByName(XTextDocument doc, String name) - throws - WrappedTargetException, - NoDocumentException { + throws + WrappedTargetException, + NoDocumentException { XNameAccess nameAccess = getNameAccess(doc); try { return Optional.ofNullable((XTextSection) ((Any) nameAccess.getByName(name)).getObject()); @@ -53,26 +53,25 @@ public static Optional getByName(XTextDocument doc, String name) * @return The XTextRange for the section, or Optional.empty(). */ public static Optional getAnchor(XTextDocument doc, String name) - throws - WrappedTargetException, - NoDocumentException { + throws + WrappedTargetException, + NoDocumentException { XNameAccess nameAccess = getNameAccess(doc); return (UnoNameAccess.getTextContentByName(nameAccess, name).map(XTextContent::getAnchor)); } /** - * Create a text section with the provided name and insert it at the provided cursor. + * Create a text section with the provided name and insert it at the provided cursor. * - * @param name The desired name for the section. - * @param range The location to insert at. - * - * If an XTextSection by that name already exists, LibreOffice (6.4.6.2) creates a section with - * a name different from what we requested, in "Section {number}" format. + * @param name The desired name for the section. + * @param range The location to insert at. + *

+ * If an XTextSection by that name already exists, LibreOffice (6.4.6.2) creates a section with a name different from what we requested, in "Section {number}" format. */ public static XNamed create(XTextDocument doc, String name, XTextRange range, boolean absorb) - throws - CreationException { + throws + CreationException { return UnoNamed.insertNamedTextContent(doc, "com.sun.star.text.TextSection", name, range, absorb); } diff --git a/src/main/java/org/jabref/model/openoffice/uno/UnoUndo.java b/src/main/java/org/jabref/model/openoffice/uno/UnoUndo.java index 4f08bb0ed5c..bd1f85e1690 100644 --- a/src/main/java/org/jabref/model/openoffice/uno/UnoUndo.java +++ b/src/main/java/org/jabref/model/openoffice/uno/UnoUndo.java @@ -12,23 +12,20 @@ */ public class UnoUndo { - private UnoUndo() { } + private UnoUndo() { + } public static Optional getXUndoManager(XTextDocument doc) { // https://www.openoffice.org/api/docs/common/ref/com/sun/star/document/XUndoManager.html return (UnoCast.cast(XUndoManagerSupplier.class, doc) - .map(XUndoManagerSupplier::getUndoManager)); + .map(XUndoManagerSupplier::getUndoManager)); } /** - * Each call to enterUndoContext must be paired by a call to leaveUndoContext, otherwise, the - * document's undo stack is left in an inconsistent state. + * Each call to enterUndoContext must be paired by a call to leaveUndoContext, otherwise, the document's undo stack is left in an inconsistent state. */ public static void enterUndoContext(XTextDocument doc, String title) { - Optional undoManager = getXUndoManager(doc); - if (undoManager.isPresent()) { - undoManager.get().enterUndoContext(title); - } + getXUndoManager(doc).ifPresent(undoManager -> undoManager.enterUndoContext(title)); } public static void leaveUndoContext(XTextDocument doc) { diff --git a/src/main/java/org/jabref/model/openoffice/uno/UnoUserDefinedProperty.java b/src/main/java/org/jabref/model/openoffice/uno/UnoUserDefinedProperty.java index f5ec43f3211..85158db2d1c 100644 --- a/src/main/java/org/jabref/model/openoffice/uno/UnoUserDefinedProperty.java +++ b/src/main/java/org/jabref/model/openoffice/uno/UnoUserDefinedProperty.java @@ -24,14 +24,15 @@ /** * Document level user-defined properties. - * - * LibreOffice GUI: [File]/[Properties]/[Custom Properties] + *

+ * LibreOffice GUI: [File]/[Properties]/[Custom Properties] */ public class UnoUserDefinedProperty { private static final Logger LOGGER = LoggerFactory.getLogger(UnoUserDefinedProperty.class); - private UnoUserDefinedProperty() { } + private UnoUserDefinedProperty() { + } public static Optional getPropertyContainer(XTextDocument doc) { return UnoTextDocument.getDocumentProperties(doc).map(XDocumentProperties::getUserDefinedProperties); @@ -39,24 +40,20 @@ public static Optional getPropertyContainer(XTextDocument do public static List getListOfNames(XTextDocument doc) { return (UnoUserDefinedProperty.getPropertyContainer(doc) - .map(UnoProperties::getPropertyNames) - .orElse(new ArrayList<>())); + .map(UnoProperties::getPropertyNames) + .orElse(new ArrayList<>())); } /** * @param property Name of a custom document property in the current document. - * * @return The value of the property or Optional.empty() - * - * These properties are used to store extra data about individual citation. - * In particular, the `pageInfo` part. - * + * These properties are used to store extra data about individual citation. In particular, the `pageInfo` part. */ public static Optional getStringValue(XTextDocument doc, String property) - throws - WrappedTargetException { + throws + WrappedTargetException { Optional propertySet = (UnoUserDefinedProperty.getPropertyContainer(doc) - .flatMap(UnoProperties::asPropertySet)); + .flatMap(UnoProperties::asPropertySet)); if (propertySet.isEmpty()) { throw new java.lang.IllegalArgumentException("getting UserDefinedProperties as XPropertySet failed"); } @@ -69,16 +66,14 @@ public static Optional getStringValue(XTextDocument doc, String property } /** - * @param property Name of a custom document property in the current document. - * Created if does not exist yet. - * - * @param value The value to be stored. + * @param property Name of a custom document property in the current document. Created if does not exist yet. + * @param value The value to be stored. */ public static void setStringProperty(XTextDocument doc, String property, String value) - throws - IllegalTypeException, - PropertyVetoException, - WrappedTargetException { + throws + IllegalTypeException, + PropertyVetoException, + WrappedTargetException { Objects.requireNonNull(property); Objects.requireNonNull(value); @@ -114,12 +109,12 @@ public static void setStringProperty(XTextDocument doc, String property, String /** * @param property Name of a custom document property in the current document. - * - * Logs warning if does not exist. + *

+ * Logs warning if does not exist. */ public static void remove(XTextDocument doc, String property) - throws - NotRemoveableException { + throws + NotRemoveableException { Objects.requireNonNull(property); @@ -133,18 +128,18 @@ public static void remove(XTextDocument doc, String property) container.get().removeProperty(property); } catch (UnknownPropertyException ex) { LOGGER.warn(String.format("UnoUserDefinedProperty.remove(%s) This property was not there to remove", - property)); + property)); } } /** * @param property Name of a custom document property in the current document. - * - * Keep silent if property did not exist. + *

+ * Keep silent if property did not exist. */ public static void removeIfExists(XTextDocument doc, String property) - throws - NotRemoveableException { + throws + NotRemoveableException { Objects.requireNonNull(property); diff --git a/src/main/java/org/jabref/model/openoffice/util/OOListUtil.java b/src/main/java/org/jabref/model/openoffice/util/OOListUtil.java index 59295c798fe..c61b81655a7 100644 --- a/src/main/java/org/jabref/model/openoffice/util/OOListUtil.java +++ b/src/main/java/org/jabref/model/openoffice/util/OOListUtil.java @@ -1,6 +1,5 @@ package org.jabref.model.openoffice.util; -import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.function.Function; @@ -10,22 +9,22 @@ public class OOListUtil { public static List map(List list, Function fun) { - return list.stream().map(e -> fun.apply(e)).collect(Collectors.toList()); + return list.stream().map(fun).collect(Collectors.toList()); } - /** Integers 0..(len-1) */ + /** + * Integers 0..(len-1) + */ public static List makeIndices(int len) { return Stream.iterate(0, i -> i + 1).limit(len).collect(Collectors.toList()); } - /** Return indices so that list.get(indices.get(i)) is sorted. */ + /** + * Return indices so that list.get(indices.get(i)) is sorted. + */ public static List order(List list, Comparator comparator) { List indices = makeIndices(list.size()); - Collections.sort(indices, new Comparator() { - @Override public int compare(final Integer a, final Integer b) { - return comparator.compare((U) list.get(a), (U) list.get(b)); - } - }); + indices.sort((a, b) -> comparator.compare(list.get(a), list.get(b))); return indices; } } diff --git a/src/main/java/org/jabref/model/openoffice/util/OOPair.java b/src/main/java/org/jabref/model/openoffice/util/OOPair.java index 9d1596d19ef..006c33e942e 100644 --- a/src/main/java/org/jabref/model/openoffice/util/OOPair.java +++ b/src/main/java/org/jabref/model/openoffice/util/OOPair.java @@ -3,6 +3,7 @@ public class OOPair { public final A a; public final B b; + public OOPair(A a, B b) { this.a = a; this.b = b; diff --git a/src/main/java/org/jabref/model/openoffice/util/OOResult.java b/src/main/java/org/jabref/model/openoffice/util/OOResult.java index c90bc68ad13..afbdeaf617e 100644 --- a/src/main/java/org/jabref/model/openoffice/util/OOResult.java +++ b/src/main/java/org/jabref/model/openoffice/util/OOResult.java @@ -91,12 +91,16 @@ public OOResult mapError(Function fun) { } } - /** Throw away the error part. */ + /** + * Throw away the error part. + */ public Optional getOptional() { return result; } - /** Throw away the result part. */ + /** + * Throw away the result part. + */ public OOVoidResult asVoidResult() { if (isError()) { return OOVoidResult.error(getError()); @@ -104,6 +108,5 @@ public OOVoidResult asVoidResult() { return OOVoidResult.ok(); } } - } diff --git a/src/main/java/org/jabref/model/openoffice/util/OOTuple3.java b/src/main/java/org/jabref/model/openoffice/util/OOTuple3.java index 8742e06764f..cff3079efa1 100644 --- a/src/main/java/org/jabref/model/openoffice/util/OOTuple3.java +++ b/src/main/java/org/jabref/model/openoffice/util/OOTuple3.java @@ -1,13 +1,11 @@ package org.jabref.model.openoffice.util; /** - * This class allows three objects to be packed together, and later accessed as fields `a`, `b` and - * `c`. - * + * This class allows three objects to be packed together, and later accessed as fields `a`, `b` and `c`. + *

* Can be used to avoid creating a new class for just this purpose. - * + *

* Can be useful if you do not have `Trifunction` at hand but need to pass three objects at a time. - * */ public class OOTuple3 { diff --git a/src/main/java/org/jabref/model/schema/DublinCoreSchemaCustom.java b/src/main/java/org/jabref/model/schema/DublinCoreSchemaCustom.java new file mode 100644 index 00000000000..e4d4cfe3215 --- /dev/null +++ b/src/main/java/org/jabref/model/schema/DublinCoreSchemaCustom.java @@ -0,0 +1,66 @@ +package org.jabref.model.schema; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.reflect.FieldUtils; +import org.apache.xmpbox.XMPMetadata; +import org.apache.xmpbox.schema.DublinCoreSchema; +import org.apache.xmpbox.type.AbstractField; +import org.apache.xmpbox.type.ArrayProperty; +import org.apache.xmpbox.type.DateType; +import org.apache.xmpbox.type.StructuredType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A DublinCoreSchema extension Class. + * In case anyone intends to alter standard behaviour. + */ +@StructuredType(preferedPrefix = "dc", namespace = "http://purl.org/dc/elements/1.1/") +public class DublinCoreSchemaCustom extends DublinCoreSchema { + + private static final Logger LOGGER = LoggerFactory.getLogger(DublinCoreSchemaCustom.class); + + public DublinCoreSchemaCustom(XMPMetadata metadata) { + super(metadata); + } + + public static DublinCoreSchema copyDublinCoreSchema(DublinCoreSchema dcSchema) { + if (Objects.isNull(dcSchema)) { + return null; + } + + try { + DublinCoreSchemaCustom dublinCoreSchemaCustom = new DublinCoreSchemaCustom(dcSchema.getMetadata()); + FieldUtils.writeField(dublinCoreSchemaCustom, "container", dcSchema.getContainer(), true); + FieldUtils.writeField(dublinCoreSchemaCustom, "attributes", + FieldUtils.readField(dcSchema, "attributes", true), true); + return dublinCoreSchemaCustom; + } catch (Exception e) { + LOGGER.error("Error making custom DC Schema. Using the default", e); + return dcSchema; + } + } + + /** + * Overloaded XMP Schema method + * Behaviour is same except when seqName is "Date". Will return raw value instead + */ + @Override + public List getUnqualifiedSequenceValueList(String seqName) { + AbstractField abstractProperty = getAbstractProperty(seqName); + if (abstractProperty instanceof ArrayProperty) { + if ("date".equals(seqName)) { + return ((ArrayProperty) abstractProperty).getContainer() + .getAllProperties() + .stream() + .map(field -> (String) ((DateType) field).getRawValue()) + .collect(Collectors.toList()); + } + return ((ArrayProperty) abstractProperty).getElementsAsString(); + } + return null; + } +} diff --git a/src/main/java/org/jabref/preferences/GeneralPreferences.java b/src/main/java/org/jabref/preferences/GeneralPreferences.java index 4598c00e392..1383e6c11b4 100644 --- a/src/main/java/org/jabref/preferences/GeneralPreferences.java +++ b/src/main/java/org/jabref/preferences/GeneralPreferences.java @@ -1,7 +1,5 @@ package org.jabref.preferences; -import java.nio.charset.Charset; - import javafx.beans.property.BooleanProperty; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleBooleanProperty; @@ -10,7 +8,6 @@ import org.jabref.model.database.BibDatabaseMode; public class GeneralPreferences { - private final ObjectProperty defaultEncoding; private final ObjectProperty defaultBibDatabaseMode; private final BooleanProperty warnAboutDuplicatesInInspection; private final BooleanProperty confirmDelete; @@ -18,13 +15,11 @@ public class GeneralPreferences { private final BooleanProperty memoryStickMode; private final BooleanProperty showAdvancedHints; - public GeneralPreferences(Charset defaultEncoding, - BibDatabaseMode defaultBibDatabaseMode, + public GeneralPreferences(BibDatabaseMode defaultBibDatabaseMode, boolean warnAboutDuplicatesInInspection, boolean confirmDelete, boolean memoryStickMode, boolean showAdvancedHints) { - this.defaultEncoding = new SimpleObjectProperty<>(defaultEncoding); this.defaultBibDatabaseMode = new SimpleObjectProperty<>(defaultBibDatabaseMode); this.warnAboutDuplicatesInInspection = new SimpleBooleanProperty(warnAboutDuplicatesInInspection); this.confirmDelete = new SimpleBooleanProperty(confirmDelete); @@ -33,18 +28,6 @@ public GeneralPreferences(Charset defaultEncoding, this.showAdvancedHints = new SimpleBooleanProperty(showAdvancedHints); } - public Charset getDefaultEncoding() { - return defaultEncoding.get(); - } - - public ObjectProperty defaultEncodingProperty() { - return defaultEncoding; - } - - public void setDefaultEncoding(Charset defaultEncoding) { - this.defaultEncoding.set(defaultEncoding); - } - public BibDatabaseMode getDefaultBibDatabaseMode() { return defaultBibDatabaseMode.get(); } diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index 4354c31be99..06e93691543 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -8,7 +8,6 @@ import java.io.StringReader; import java.net.InetAddress; import java.net.UnknownHostException; -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -1124,7 +1123,7 @@ public void setOpenOfficePreferences(OpenOfficePreferences openOfficePreferences @Override public JournalAbbreviationPreferences getJournalAbbreviationPreferences() { - return new JournalAbbreviationPreferences(getStringList(EXTERNAL_JOURNAL_LISTS), getGeneralPreferences().getDefaultEncoding()); + return new JournalAbbreviationPreferences(getStringList(EXTERNAL_JOURNAL_LISTS), StandardCharsets.UTF_8); } @Override @@ -1294,14 +1293,12 @@ public GeneralPreferences getGeneralPreferences() { } generalPreferences = new GeneralPreferences( - Charset.forName(get(DEFAULT_ENCODING)), getBoolean(BIBLATEX_DEFAULT_MODE) ? BibDatabaseMode.BIBLATEX : BibDatabaseMode.BIBTEX, getBoolean(WARN_ABOUT_DUPLICATES_IN_INSPECTION), getBoolean(CONFIRM_DELETE), getBoolean(MEMORY_STICK_MODE), getBoolean(SHOW_ADVANCED_HINTS)); - EasyBind.listen(generalPreferences.defaultEncodingProperty(), (obs, oldValue, newValue) -> put(DEFAULT_ENCODING, newValue.name())); EasyBind.listen(generalPreferences.defaultBibDatabaseModeProperty(), (obs, oldValue, newValue) -> putBoolean(BIBLATEX_DEFAULT_MODE, (newValue == BibDatabaseMode.BIBLATEX))); EasyBind.listen(generalPreferences.isWarnAboutDuplicatesInInspectionProperty(), (obs, oldValue, newValue) -> putBoolean(WARN_ABOUT_DUPLICATES_IN_INSPECTION, newValue)); EasyBind.listen(generalPreferences.confirmDeleteProperty(), (obs, oldValue, newValue) -> putBoolean(CONFIRM_DELETE, newValue)); diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties index 078e5f7fe5f..285e04aca97 100644 --- a/src/main/resources/l10n/JabRef_da.properties +++ b/src/main/resources/l10n/JabRef_da.properties @@ -192,7 +192,7 @@ Library\ properties=Libraryegenskaber Default=Standard -Default\ encoding=Standard kodning +The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=Den valgte tegnkodning '%0' kunne ikke kode de følgende tegn\: @@ -688,8 +688,6 @@ Statically\ group\ entries\ by\ manual\ assignment=Grupper poster statisk ved ma Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Skifter mellem fuldt og forkortet tidsskriftsnavn hvis navnet er kendt. -The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=Den valgte tegnkodning '%0' kunne ikke kode de følgende tegn\: - the\ field\ %0=feltet %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Gruppen "%0" indeholder allerede de valgte poster. @@ -920,6 +918,7 @@ Path\ to\ %0=Sti til %0 Could\ not\ connect\ to\ %0=Kunne ikke forbinde til %0 + Invalid\ DOI\:\ '%0'.=Ugyldig DOI\: '%0'. diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties index 2fdb5eee39f..2bdec562f1e 100644 --- a/src/main/resources/l10n/JabRef_de.properties +++ b/src/main/resources/l10n/JabRef_de.properties @@ -172,7 +172,11 @@ Copied=Kopiert Copy=Kopieren +Copy\ title=Kopiere Titel +Copy\ \\cite{citation\ key}=Kopiere \\cite{citation key} Copy\ citation\ key=Kopiere Zitationsschlüssel +Copy\ citation\ key\ and\ link=Zitationscchlüssel und Titel kopieren +Copy\ citation\ key\ and\ title=Zitationscchlüssel und Titel kopieren Copy\ to\ clipboard=In die Zwischenablage kopieren @@ -227,7 +231,7 @@ Library\ properties=Eigenschaften der Bibliothek Default=Standard -Default\ encoding=Standard-Zeichenkodierung +The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=Die gewählte Kodierung '%0' konnte folgende Buchstaben nicht darstellen\: Downloading=Lade herunter @@ -825,8 +829,6 @@ Sublibrary\ from\ AUX\ to\ BibTeX=Subbibliothek von AUX bis BibTeX Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Wechselt zwischen vollem und abgekürztem Zeitschriftentitel falls bekannt. -The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=Die gewählte Kodierung '%0' konnte folgende Buchstaben nicht darstellen\: - the\ field\ %0=das Feld %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Die Gruppe "%0" enthält bereits diese Auswahl. @@ -1291,9 +1293,7 @@ Save\ changes=Änderungen speichern Discard\ changes=Änderungen verwerfen Library\ '%0'\ has\ changed.=Die Bibliothek '%0' wurde geändert. Print\ entry\ preview=Eintragsvorschau drucken -Copy\ title=Kopiere Titel -Copy\ \\cite{citation\ key}=Kopiere \\cite{citation key} -Copy\ citation\ key\ and\ title=Zitationscchlüssel und Titel kopieren + Invalid\ DOI\:\ '%0'.=Ungültiger DOI\: '%0'. Same\ DOI\ used\ in\ multiple\ entries=Gleiche DOI wird in mehreren Einträgen benutzt should\ start\ with\ a\ name=sollte mit einem Name beginnen @@ -1702,7 +1702,6 @@ should\ be\ normalized=Sollte normalisiert sein Empty\ search\ ID=Leere Such-ID The\ given\ search\ ID\ was\ empty.=Die übergebene Such-ID ist leer. -Copy\ citation\ key\ and\ link=Zitationscchlüssel und Titel kopieren biblatex\ field\ only=Nur ein biblatex-Feld Error\ while\ generating\ fetch\ URL=Fehler beim generieren der Abruf URL @@ -1846,7 +1845,6 @@ Check\ integrity=Integrität prüfen Cleanup\ URL\ link=URL-Link bereinigen Cleanup\ URL\ link\ by\ removing\ special\ symbols\ and\ extracting\ simple\ link=URL-Link bereinigen durch Entfernen von Sondersymbolen und Extraktion des einfachen Links Copy\ DOI\ url=DOI-URL kopieren -Copy\ citation=Kopiere Zitation Development\ version=Entwicklungsversion Export\ selected\ entries=Ausgewählte Einträge exportieren Export\ selected\ entries\ to\ clipboard=Ausgewählte Einträge in die Zwischenablage kopieren diff --git a/src/main/resources/l10n/JabRef_el.properties b/src/main/resources/l10n/JabRef_el.properties index c5e38c110fa..1741d794533 100644 --- a/src/main/resources/l10n/JabRef_el.properties +++ b/src/main/resources/l10n/JabRef_el.properties @@ -147,6 +147,7 @@ Copied=Αντιγράφηκε Copy=Αντιγραφή +Copy\ title=Αντιγραφή τίτλου Copy\ to\ clipboard=Αντιγραφή στο πρόχειρο @@ -197,7 +198,7 @@ Library\ properties=Ιδιότητες βιβλιοθήκης Default=Προεπιλογή -Default\ encoding=Προεπιλεγμένη κωδικοποίηση +The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=Η επιλεγμένη κωδικοποίηση '%0' δεν κατάφερε να κωδικοποιήσει τους παρακάτω χαρακτήρες\: @@ -727,8 +728,6 @@ Status=Κατάσταση Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Εναλλαγή από πλήρες ή συντετμημένο όνομα περιοδικού, εάν το όνομα του περιοδικού είναι άγνωστο. -The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=Η επιλεγμένη κωδικοποίηση '%0' δεν κατάφερε να κωδικοποιήσει τους παρακάτω χαρακτήρες\: - the\ field\ %0=το πεδίο %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Η ομάδα "%0" περιέχει ήδη την επιλογή. @@ -1113,7 +1112,7 @@ Save\ changes=Αποθήκευση αλλαγών Discard\ changes=Απόρριψη αλλαγών Library\ '%0'\ has\ changed.=Η βιβλιοθήκη '%0' έχει αλλάξει. Print\ entry\ preview=Προεπισκόπηση εκτύπωσης καταχώρησης -Copy\ title=Αντιγραφή τίτλου + Invalid\ DOI\:\ '%0'.=Μη έγκυρο DOI\: '%0'. should\ start\ with\ a\ name=πρέπει να ξεκινάει με όνομα should\ end\ with\ a\ name=πρέπει να τελειώνει με όνομα @@ -1603,7 +1602,6 @@ The\ group\ name\ contains\ the\ keyword\ separator\ "%0"\ and\ thus\ probably\ Blog=Ιστολόγιο Check\ integrity=Έλεγχος συνοχής Copy\ DOI\ url=Αντιγραφή DOI URL -Copy\ citation=Αντιγραφή αναφοράς Development\ version=Έκδοση ανάπτυξης λογισμικού Export\ selected\ entries=Εξαγωγή επιλεγμένων καταχωρήσεων Export\ selected\ entries\ to\ clipboard=Εξαγωγή των επιλεγμένων καταχωρήσεων στο πρόχειρο diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index aabe159a6a5..6b6d7dff88a 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -233,7 +233,9 @@ Library\ properties=Library properties Default=Default -Default\ encoding=Default encoding +Character\ encoding\ UTF-8\ is\ not\ supported.=Character encoding UTF-8 is not supported. +UTF-8\ could\ not\ be\ used\ to\ encode\ the\ following\ characters\:\ %0=UTF-8 could not be used to encode the following characters: %0 +The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=The chosen encoding '%0' could not encode the following characters: Downloading=Downloading @@ -540,6 +542,10 @@ Moved\ group\ "%0".=Moved group "%0". Mr.\ DLib\ Privacy\ settings=Mr. DLib Privacy settings +No\ database\ is\ open=No database is open + +We\ need\ a\ database\ to\ export\ from.\ Open\ one.=We need a database to export from. Open one. + No\ recommendations\ received\ from\ Mr.\ DLib\ for\ this\ entry.=No recommendations received from Mr. DLib for this entry. Error\ while\ fetching\ recommendations\ from\ Mr.DLib.=Error while fetching recommendations from Mr.DLib. @@ -836,8 +842,6 @@ Sublibrary\ from\ AUX\ to\ BibTeX=Sublibrary from AUX to BibTeX Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Switches between full and abbreviated journal name if the journal name is known. -The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=The chosen encoding '%0' could not encode the following characters: - the\ field\ %0=the field %0 The\ group\ "%0"\ already\ contains\ the\ selection.=The group "%0" already contains the selection. @@ -1043,9 +1047,9 @@ Cite\ special=Cite special Extra\ information\ (e.g.\ page\ number)=Extra information (e.g. page number) Manage\ citations=Manage citations Problem\ modifying\ citation=Problem modifying citation +Problem\ collecting\ citations=Problem collecting citations Citation=Citation Connecting...=Connecting... -Could\ not\ resolve\ BibTeX\ entry\ for\ citation\ marker\ '%0'.=Could not resolve BibTeX entry for citation marker '%0'. Select\ style=Select style Journals=Journals Cite=Cite @@ -1057,17 +1061,36 @@ Select\ Writer\ document=Select Writer document Sync\ OpenOffice/LibreOffice\ bibliography=Sync OpenOffice/LibreOffice bibliography Select\ which\ open\ Writer\ document\ to\ work\ on=Select which open Writer document to work on Connected\ to\ document=Connected to document + +Could\ not\ connect\ to\ any\ Writer\ document.\ Please\ make\ sure\ a\ document\ is\ open\ before\ using\ the\ 'Select\ Writer\ document'\ button\ to\ connect\ to\ it.=Could not connect to any Writer document. Please make sure a document is open before using the 'Select Writer document' button to connect to it. + +No\ Writer\ documents\ found=No Writer documents found + Insert\ a\ citation\ without\ text\ (the\ entry\ will\ appear\ in\ the\ reference\ list)=Insert a citation without text (the entry will appear in the reference list) Cite\ selected\ entries\ with\ extra\ information=Cite selected entries with extra information Ensure\ that\ the\ bibliography\ is\ up-to-date=Ensure that the bibliography is up-to-date + Your\ OpenOffice/LibreOffice\ document\ references\ the\ citation\ key\ '%0',\ which\ could\ not\ be\ found\ in\ your\ current\ library.=Your OpenOffice/LibreOffice document references the citation key '%0', which could not be found in your current library. + +This\ operation\ requires\ a\ bibliography\ database.=This operation requires a bibliography database. + +Your\ OpenOffice/LibreOffice\ document\ references\ at\ least\ %0\ citation\ keys\ which\ could\ not\ be\ found\ in\ your\ current\ library.\ Some\ of\ these\ are\ %1.=Your OpenOffice/LibreOffice document references at least %0 citation keys which could not be found in your current library. Some of these are %1. + +Your\ OpenOffice/LibreOffice\ document\ references\ no\ citation\ keys\ which\ could\ also\ be\ found\ in\ your\ current\ library.=Your OpenOffice/LibreOffice document references no citation keys which could also be found in your current library. + Unable\ to\ synchronize\ bibliography=Unable to synchronize bibliography Combine\ pairs\ of\ citations\ that\ are\ separated\ by\ spaces\ only=Combine pairs of citations that are separated by spaces only Autodetection\ failed=Autodetection failed Please\ wait...=Please wait... Connection\ lost=Connection lost -The\ paragraph\ format\ is\ controlled\ by\ the\ property\ 'ReferenceParagraphFormat'\ or\ 'ReferenceHeaderParagraphFormat'\ in\ the\ style\ file.=The paragraph format is controlled by the property 'ReferenceParagraphFormat' or 'ReferenceHeaderParagraphFormat' in the style file. -The\ character\ format\ is\ controlled\ by\ the\ citation\ property\ 'CitationCharacterFormat'\ in\ the\ style\ file.=The character format is controlled by the citation property 'CitationCharacterFormat' in the style file. + +Could\ not\ update\ bibliography=Could not update bibliography +Not\ connected\ to\ document=Not connected to document +Problem\ combining\ cite\ markers=Problem combining cite markers +Unable\ to\ reload\ style\ file=Unable to reload style file + +Problem\ during\ separating\ cite\ markers=Problem during separating cite markers + Automatically\ sync\ bibliography\ when\ inserting\ citations=Automatically sync bibliography when inserting citations Look\ up\ BibTeX\ entries\ in\ the\ active\ tab\ only=Look up BibTeX entries in the active tab only Look\ up\ BibTeX\ entries\ in\ all\ open\ libraries=Look up BibTeX entries in all open libraries @@ -1169,7 +1192,9 @@ Toggle\ relevance=Toggle relevance Toggle\ quality\ assured=Toggle quality assured Toggle\ print\ status=Toggle print status Update\ keywords=Update keywords +Problem\ connecting=Problem connecting Connection\ to\ OpenOffice/LibreOffice\ has\ been\ lost.\ Please\ make\ sure\ OpenOffice/LibreOffice\ is\ running,\ and\ try\ to\ reconnect.=Connection to OpenOffice/LibreOffice has been lost. Please make sure OpenOffice/LibreOffice is running, and try to reconnect. + JabRef\ will\ send\ at\ least\ one\ request\ per\ entry\ to\ a\ publisher.=JabRef will send at least one request per entry to a publisher. Correct\ the\ entry,\ and\ reopen\ editor\ to\ display/edit\ source.=Correct the entry, and reopen editor to display/edit source. Could\ not\ connect\ to\ running\ OpenOffice/LibreOffice.=Could not connect to running OpenOffice/LibreOffice. @@ -1183,8 +1208,6 @@ To\ disable\ the\ memory\ stick\ mode\ rename\ or\ remove\ the\ jabref.xml\ file Unable\ to\ connect.\ One\ possible\ reason\ is\ that\ JabRef\ and\ OpenOffice/LibreOffice\ are\ not\ both\ running\ in\ either\ 32\ bit\ mode\ or\ 64\ bit\ mode.=Unable to connect. One possible reason is that JabRef and OpenOffice/LibreOffice are not both running in either 32 bit mode or 64 bit mode. Delimiter(s)=Delimiter(s) When\ downloading\ files,\ or\ moving\ linked\ files\ to\ the\ file\ directory,\ use\ the\ bib\ file\ location.=When downloading files, or moving linked files to the file directory, use the bib file location. -Your\ style\ file\ specifies\ the\ character\ format\ '%0',\ which\ is\ undefined\ in\ your\ current\ OpenOffice/LibreOffice\ document.=Your style file specifies the character format '%0', which is undefined in your current OpenOffice/LibreOffice document. -Your\ style\ file\ specifies\ the\ paragraph\ format\ '%0',\ which\ is\ undefined\ in\ your\ current\ OpenOffice/LibreOffice\ document.=Your style file specifies the paragraph format '%0', which is undefined in your current OpenOffice/LibreOffice document. Searching...=Searching... Please\ enter\ a\ search\ string=Please enter a search string @@ -1564,6 +1587,22 @@ Custom=Custom Export\ cited=Export cited Unable\ to\ generate\ new\ library=Unable to generate new library +The\ cursor\ is\ in\ a\ protected\ area.=The cursor is in a protected area. +JabRefException=JabRefException +No\ bibliography\ database\ is\ open\ for\ citation.=No bibliography database is open for citation. + +No\ database\ is\ open\ for\ updating\ citation\ markers\ after\ citing.=No database is open for updating citation markers after citing. + +No\ bibliography\ entries\ are\ selected\ for\ citation.=No bibliography entries are selected for citation. +No\ bibliography\ style\ is\ selected\ for\ citation.=No bibliography style is selected for citation. +No\ database=No database + +No\ entries\ selected\ for\ citation=No entries selected for citation +Open\ one\ before\ citing.=Open one before citing. + +Select\ one\ before\ citing.=Select one before citing. +Select\ some\ before\ citing.=Select some before citing. + Found\ identical\ ranges=Found identical ranges Found\ overlapping\ ranges=Found overlapping ranges Found\ touching\ ranges=Found touching ranges @@ -1832,9 +1871,6 @@ Could\ not\ connect\ to\ Vim\ server.\ Make\ sure\ that\ Vim\ is\ running\ with\ Could\ not\ connect\ to\ a\ running\ gnuserv\ process.\ Make\ sure\ that\ Emacs\ or\ XEmacs\ is\ running,\ and\ that\ the\ server\ has\ been\ started\ (by\ running\ the\ command\ 'server-start'/'gnuserv-start').=Could not connect to a running gnuserv process. Make sure that Emacs or XEmacs is running, and that the server has been started (by running the command 'server-start'/'gnuserv-start'). Error\ pushing\ entries=Error pushing entries -Undefined\ character\ format=Undefined character format -Undefined\ paragraph\ format=Undefined paragraph format - Preamble=Preamble Markings=Markings Use\ selected\ instance=Use selected instance @@ -2314,8 +2350,6 @@ Separate\ merged\ citations=Separate merged citations Separate\ citations=Separate citations Unprotect\ terms=Unprotect terms -Error\ connecting\ to\ Writer\ document=Error connecting to Writer document -You\ need\ to\ open\ Writer\ with\ a\ document\ before\ connecting=You need to open Writer with a document before connecting Generate\ a\ new\ key\ for\ imported\ entries\ (overwriting\ their\ default)=Generate a new key for imported entries (overwriting their default) Warn\ about\ duplicates\ on\ import=Warn about duplicates on import @@ -2324,6 +2358,35 @@ Custom\ DOI\ URI=Custom DOI URI Use\ custom\ DOI\ base\ URI\ for\ article\ access=Use custom DOI base URI for article access Cited\ on\ pages=Cited on pages +Please\ move\ the\ cursor\ into\ the\ document\ text.=Please\ move\ the\ cursor\ into\ the\ document\ text. +To\ get\ the\ visual\ positions\ of\ your\ citations\ I\ need\ to\ move\ the\ cursor\ around,\ but\ could\ not\ get\ it.=To\ get\ the\ visual\ positions\ of\ your\ citations\ I\ need\ to\ move\ the\ cursor\ around,\ but\ could\ not\ get\ it. + +I\ cannot\ insert\ to\ the\ cursors\ current\ location.=I\ cannot\ insert\ to\ the\ cursors\ current\ location. + +Please\ move\ the\ cursor\ to\ the\ location\ for\ the\ new\ citation.=Please\ move\ the\ cursor\ to\ the\ location\ for\ the\ new\ citation. + +Please\ create\ it\ in\ the\ document\ or\ change\ in\ the\ file\:=Please create it in the document or change in the file: + +Please\ use\ the\ latter\ in\ the\ style\ file\ below\ to\ avoid\ localization\ problems.=Please use the latter in the style file below to avoid localization problems. + +The\ %0\ character\ style\ '%1'\ is\ a\ display\ name\ for\ '%2'.=The %0 character style '%1' is a display name for '%2'. + +The\ %0\ character\ style\ '%1'\ is\ missing\ from\ the\ document=The %0 character style '%1' is missing from the document + +The\ %0\ paragraph\ style\ '%1'\ is\ a\ display\ name\ for\ '%2'.=The %0 paragraph style '%1' is a display name for '%2'. + +The\ %0\ paragraph\ style\ '%1'\ is\ missing\ from\ the\ document=The %0 paragraph style '%1' is missing from the document + +Error\ while\ checking\ if\ Writer\ is\ recording\ changes\ or\ has\ recorded\ changes.=Error while checking if Writer is recording changes or has recorded changes. + +Cannot\ work\ with\ [Edit]/[Track\ Changes]/[Record]\ turned\ on.=Cannot work with [Edit]/[Track Changes]/[Record] turned on. + +Changes\ by\ JabRef\ could\ result\ in\ unexpected\ interactions\ with\ recorded\ changes.=Changes by JabRef could result in unexpected interactions with recorded changes. + +Recording\ and/or\ Recorded\ changes=Recording and/or Recorded changes + +Use\ [Edit]/[Track\ Changes]/[Manage]\ to\ resolve\ them\ first.=Use [Edit]/[Track Changes]/[Manage] to resolve them first. + Unable\ to\ find\ valid\ certification\ path\ to\ requested\ target(%0),\ download\ anyway?=Unable to find valid certification path to requested target(%0), download anyway? Download\ operation\ canceled.=Download operation canceled. diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties index 94ef1ff63b7..3438b83cda0 100644 --- a/src/main/resources/l10n/JabRef_es.properties +++ b/src/main/resources/l10n/JabRef_es.properties @@ -166,7 +166,11 @@ Copied=Copiado Copy=Copiar +Copy\ title=Copiar título +Copy\ \\cite{citation\ key}=Copiar \\cite{citation key} Copy\ citation\ key=Copiar clave de cita +Copy\ citation\ key\ and\ link=Copiar clave de cita y enlace +Copy\ citation\ key\ and\ title=Copiar clave y título de cita Copy\ to\ clipboard=Copiar al portapapeles @@ -219,7 +223,7 @@ Library\ properties=Propiedades de la biblioteca Default=Por defecto -Default\ encoding=Codificación por defecto +The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=La codificación de caracteres '%' no puede codificar los siguientes caracteres\: Downloading=Descargando @@ -806,8 +810,6 @@ Sublibrary\ from\ AUX\ to\ BibTeX=Subbiblioteca de AUX a BibTeX Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Cambia entre nombre completo y abreviado de la revista si se conoce el nombre de la revista. -The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=La codificación de caracteres '%' no puede codificar los siguientes caracteres\: - the\ field\ %0=el campo %0 The\ group\ "%0"\ already\ contains\ the\ selection.=El grupo "%0" ya contiene la selección. @@ -1253,9 +1255,7 @@ Save\ changes=Guardar cambios Discard\ changes=Descartar cambios Library\ '%0'\ has\ changed.=La biblioteca '%0' ha cambiado. Print\ entry\ preview=Imprimir vista previa de la entrada -Copy\ title=Copiar título -Copy\ \\cite{citation\ key}=Copiar \\cite{citation key} -Copy\ citation\ key\ and\ title=Copiar clave y título de cita + Invalid\ DOI\:\ '%0'.=DOI no válida\: '%0'. Same\ DOI\ used\ in\ multiple\ entries=El mismo DOI usado en múltiples entradas should\ start\ with\ a\ name=debería comenzar por un nombre @@ -1658,7 +1658,6 @@ should\ be\ normalized=debería ser normalizado Empty\ search\ ID=Vaciar ID de búsqueda The\ given\ search\ ID\ was\ empty.=La ID de búsqueda está vacía. -Copy\ citation\ key\ and\ link=Copiar clave de cita y enlace biblatex\ field\ only=Sólo campo biblatex Error\ while\ generating\ fetch\ URL=Error al generar la URL de recolección @@ -1800,7 +1799,6 @@ Check\ integrity=Verificar integridad Cleanup\ URL\ link=Limpiar un enlace URL Cleanup\ URL\ link\ by\ removing\ special\ symbols\ and\ extracting\ simple\ link=Limpiar un enlace URL eliminando los símbolos especiales y extrayendo un enlace simple Copy\ DOI\ url=Copiar la url del DOI -Copy\ citation=Copiar cita Development\ version=Versión de desarrollo Export\ selected\ entries=Exportar registros seleccionados Export\ selected\ entries\ to\ clipboard=Exportar las entradas seleccionadas al portapapeles diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties index f67fc4b180d..cd304d70092 100644 --- a/src/main/resources/l10n/JabRef_fa.properties +++ b/src/main/resources/l10n/JabRef_fa.properties @@ -443,7 +443,6 @@ Library\ saved=کتابخانه ذخیره شد - Will\ write\ metadata\ to\ the\ PDFs\ linked\ from\ selected\ entries.=فراداده‌ ها را روی فایل‌های PDF پیوند داده شده از ورودی‌های انتخابی می‌نویسد. @@ -497,6 +496,7 @@ Save\ selected\ as\ plain\ BibTeX...=.\=منتخب‌شده را به صورت + Focus\ entry\ table=تمرکز بر جدول ورودی Import\ into\ current\ library=وارد کردن به پایگاه داده‌ی فعلی Import\ into\ new\ library=وارد کردن به پایگاه داده‌ی جدید diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties index 34d54aa4ac8..64ecbb5db8d 100644 --- a/src/main/resources/l10n/JabRef_fr.properties +++ b/src/main/resources/l10n/JabRef_fr.properties @@ -172,7 +172,13 @@ Copied=Copié Copy=Copier +Copy\ title=Copier le titre +Copy\ \\cite{citation\ key}=Copier \\cite{citation key} +Copy\ citation\ (html)=Copier la citation (html) +Copy\ citation\ (text)=Copier la citation (texte) Copy\ citation\ key=Copier la clef de citation +Copy\ citation\ key\ and\ link=Copier la clef de citation et le lien +Copy\ citation\ key\ and\ title=Copier la clef de citation et le titre Copy\ to\ clipboard=Copier dans le presse-papier @@ -194,7 +200,7 @@ Could\ not\ print\ preview=Échec de l'impression de l'aperçu Could\ not\ run\ the\ 'vim'\ program.=Le programme 'vim' n'a pas pu être lancé. Could\ not\ save\ file.=Le fichier n'a pas pu être enregistré. -Character\ encoding\ '%0'\ is\ not\ supported.=L'encodage de caractères « %0 » n'est pas supporté. +Character\ encoding\ '%0'\ is\ not\ supported.=L'encodage de caractères '%0' n'est pas pris en charge. Create\ custom\ fields\ for\ each\ BibTeX\ entry=Créer des champs personnalisés pour chaque entrée BibTeX @@ -227,7 +233,9 @@ Library\ properties=Propriétés du fichier Default=Défaut -Default\ encoding=Encodage par défaut +Character\ encoding\ UTF-8\ is\ not\ supported.=L'encodage de caractères UTF-8 n'est pas pris en charge. +UTF-8\ could\ not\ be\ used\ to\ encode\ the\ following\ characters\:\ %0=L'UTF-8 n'a pas pu être utilisé pour encoder les caractères suivants \: %0 +The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=L'encodage « %0 » choisi ne peut pas encoder les caractères suivants \: Downloading=Téléchargement @@ -830,8 +838,6 @@ Sublibrary\ from\ AUX\ to\ BibTeX=Sous-fichier à partir du AUX vers BibTeX Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Bascule entre les noms de journaux développés et abrégés si le nom de journal est connu. -The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=L'encodage « %0 » choisi ne peut pas encoder les caractères suivants \: - the\ field\ %0=le champ %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Le groupe « %0 » contient déjà la sélection. @@ -1297,9 +1303,7 @@ Save\ changes=Enregistrer les modifications Discard\ changes=Abandonner les modifications Library\ '%0'\ has\ changed.=Le fichier « %0 » a été modifié. Print\ entry\ preview=Imprimer la prévisualisation de l'entrée -Copy\ title=Copier le titre -Copy\ \\cite{citation\ key}=Copier \\cite{citation key} -Copy\ citation\ key\ and\ title=Copier la clef de citation et le titre + Invalid\ DOI\:\ '%0'.=DOI invalide \: « %0 ». Same\ DOI\ used\ in\ multiple\ entries=Un DOI identique est présent dans plusieurs entrées should\ start\ with\ a\ name=Devrait débuter par un nom @@ -1536,7 +1540,7 @@ Message=Message MathSciNet\ Review=Review MathSciNet Reset\ Bindings=Réinitialiser les associations -Decryption\ not\ supported.=Déchiffrement non supporté. +Decryption\ not\ supported.=Déchiffrement non pris en charge. Cleared\ '%0'\ for\ %1\ entries=Réinitialisés « %0 » pour %1 entrées Set\ '%0'\ to\ '%1'\ for\ %2\ entries=« %0 » mis à « %1 » pour %2 entrées @@ -1708,7 +1712,6 @@ should\ be\ normalized=Devrait être une abréviation standard Empty\ search\ ID=Identifiant de recherche vide The\ given\ search\ ID\ was\ empty.=L'Identifiant de recherche entré était vide. -Copy\ citation\ key\ and\ link=Copier la clef de citation et le lien biblatex\ field\ only=Champ biblatex uniquement Error\ while\ generating\ fetch\ URL=Erreur lors de la création de l'URL de recherche @@ -1851,8 +1854,8 @@ Blog=Blog Check\ integrity=Vérifier l'intégrité Cleanup\ URL\ link=Nettoyer un lien URL Cleanup\ URL\ link\ by\ removing\ special\ symbols\ and\ extracting\ simple\ link=Nettoyer un lien URL en en supprimant les symboles spéciaux et en en extrayant un lien simple -Copy\ DOI\ url=Copier le DOI -Copy\ citation=Copier la citation +Copy\ DOI=Copier le DOI +Copy\ DOI\ url=Copier l'URL du DOI Development\ version=Version en développement Export\ selected\ entries=Exporter les entrées sélectionnées Export\ selected\ entries\ to\ clipboard=Exporter les entrées sélectionnées vers le presse-papiers @@ -2315,6 +2318,7 @@ Error\ connecting\ to\ Writer\ document=Erreur de connexion au document Writer You\ need\ to\ open\ Writer\ with\ a\ document\ before\ connecting=Vous devez ouvrir Writer avec un document avant de vous connecter Generate\ a\ new\ key\ for\ imported\ entries\ (overwriting\ their\ default)=Générer une nouvelle clef pour les entrées importées (en écrasant leur valeur par défaut) +Warn\ about\ duplicates\ on\ import=Avertir des doublons lors de l'importation Import\ and\ Export=Importation et exportation Custom\ DOI\ URI=URI DOI personnalisée Use\ custom\ DOI\ base\ URI\ for\ article\ access=Accéder aux articles par une URI personnalisée se basant sur le DOI @@ -2367,6 +2371,8 @@ Query=Requête Question=Question Select\ directory=Sélectionner un répertoire +Fulltext\ Index=Indexation des documents +Automatically\ index\ all\ linked\ files\ for\ fulltext\ search=Indexer automatiquement tous les fichiers liés pour la recherche dans les documents Rebuild\ fulltext\ search\ index=Reconstruire l'index de recherche sur les documents Rebuild\ fulltext\ search\ index\ for\ current\ library?=Reconstruire l'index de recherche sur les documents pour le fichier courant ? Rebuilding\ fulltext\ search\ index...=Reconstruction de l'index de recherche sur les documents... diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_id.properties similarity index 99% rename from src/main/resources/l10n/JabRef_in.properties rename to src/main/resources/l10n/JabRef_id.properties index 30f978c7e47..75a110ad084 100644 --- a/src/main/resources/l10n/JabRef_in.properties +++ b/src/main/resources/l10n/JabRef_id.properties @@ -145,6 +145,7 @@ Copied=Disalin Copy=Salin +Copy\ title=Kopi judul Copy\ to\ clipboard=Salin ke papan klip @@ -195,7 +196,7 @@ Library\ properties=Properti basisdata Default=Bawaan -Default\ encoding=Enkoding bawaan +The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=Enkoding yang dipilih '%0' tidak bisa digunakan untuk karakter berikut\: @@ -718,8 +719,6 @@ Status=Keadaan Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Menukar antara nama jurnal penuh dan singkatan jika nama jurnal diketahui. -The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=Enkoding yang dipilih '%0' tidak bisa digunakan untuk karakter berikut\: - the\ field\ %0=bidang %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Grup "%0" sudah mengandung pilihan. @@ -1102,7 +1101,7 @@ Save\ changes=Simpan perubahan Discard\ changes=Perubahan dibuang Library\ '%0'\ has\ changed.=Basisdata %0 telah berubah. Print\ entry\ preview=Cetak pratinjau entri -Copy\ title=Kopi judul + Invalid\ DOI\:\ '%0'.=DOI salah\: '%0'. should\ start\ with\ a\ name=harus bermula dengan nama should\ end\ with\ a\ name=harus berakhiran nama @@ -1556,7 +1555,6 @@ The\ group\ name\ contains\ the\ keyword\ separator\ "%0"\ and\ thus\ probably\ Blog=Blog Check\ integrity=Periksa Integritas Copy\ DOI\ url=Salin url DOI -Copy\ citation=Copy kutipan Development\ version=Versi pengembangan Export\ selected\ entries=Ekspor entri pilihan JabRef\ resources=Sumber JabRef diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties index 8d5381bce89..7f90c104d01 100644 --- a/src/main/resources/l10n/JabRef_it.properties +++ b/src/main/resources/l10n/JabRef_it.properties @@ -172,7 +172,13 @@ Copied=Copiato Copy=Copia +Copy\ title=Copia titolo +Copy\ \\cite{citation\ key}=Copia \\cite{citation key} +Copy\ citation\ (html)=Copia citazione (html) +Copy\ citation\ (text)=Copia citazione (testo) Copy\ citation\ key=Copia la chiave BibTeX +Copy\ citation\ key\ and\ link=Copia la chiave BibTeX ed il collegamento +Copy\ citation\ key\ and\ title=Copia la chiave BibTeX ed il titolo Copy\ to\ clipboard=Copia negli appunti @@ -227,7 +233,9 @@ Library\ properties=Proprietà della libreria Default=Predefinito -Default\ encoding=Codifica predefinita +Character\ encoding\ UTF-8\ is\ not\ supported.=La codifica dei caratteri UTF-8 non è supportata. +UTF-8\ could\ not\ be\ used\ to\ encode\ the\ following\ characters\:\ %0=UTF-8 non può essere usato per codificare i seguenti caratteri\: %0 +The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=La codifica scelta '%0' non può codificare i caratteri seguenti\: Downloading=Download in corso @@ -830,8 +838,6 @@ Sublibrary\ from\ AUX\ to\ BibTeX=Sotto-libreria da AUX a BibTeX Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Alterna nomi completi e nomi abbreviati per le riviste delle quali è noto il nome. -The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=La codifica scelta '%0' non può codificare i caratteri seguenti\: - the\ field\ %0=il campo %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Il gruppo "%0" contiene già la selezione. @@ -1297,9 +1303,7 @@ Save\ changes=Salva le modifiche Discard\ changes=Scarta le modifiche Library\ '%0'\ has\ changed.=La libreria '%0' è stato modificata. Print\ entry\ preview=Stampa l'anteprima della voce -Copy\ title=Copia titolo -Copy\ \\cite{citation\ key}=Copia \\cite{citation key} -Copy\ citation\ key\ and\ title=Copia la chiave BibTeX ed il titolo + Invalid\ DOI\:\ '%0'.=DOI non valido\: '%0'. Same\ DOI\ used\ in\ multiple\ entries=Stesso DOI usato in più voci should\ start\ with\ a\ name=deve cominciare con un nome @@ -1708,7 +1712,6 @@ should\ be\ normalized=dovrebbe essere normalizzato Empty\ search\ ID=ID della ricerca vuoto The\ given\ search\ ID\ was\ empty.=L'ID della ricerca usato era vuoto. -Copy\ citation\ key\ and\ link=Copia la chiave BibTeX ed il collegamento biblatex\ field\ only=campo solo biblatex Error\ while\ generating\ fetch\ URL=Errore generando l'URL per l'estrazione @@ -1851,8 +1854,8 @@ Blog=Blog Check\ integrity=Verifica di integrità Cleanup\ URL\ link=Pulisci URL Link Cleanup\ URL\ link\ by\ removing\ special\ symbols\ and\ extracting\ simple\ link=Pulisci l'URL rimuovendo simboli speciali ed estraendo un semplice link +Copy\ DOI=Copia DOI Copy\ DOI\ url=Copia l'url del DOI -Copy\ citation=Copia la citazione Development\ version=Versione di sviluppo Export\ selected\ entries=Esporta le voci selezionate Export\ selected\ entries\ to\ clipboard=Esportare le voci selezionate negli appunti @@ -2315,6 +2318,7 @@ Error\ connecting\ to\ Writer\ document=Errore nella connessione al documento Wr You\ need\ to\ open\ Writer\ with\ a\ document\ before\ connecting=Devi aprire Writer con un documento prima di connetterti Generate\ a\ new\ key\ for\ imported\ entries\ (overwriting\ their\ default)=Genera una nuova chiave per le voci importate (sovrascrivendo il valore predefinito) +Warn\ about\ duplicates\ on\ import=Avverti sui duplicati nell'importazione Import\ and\ Export=Importa ed Esporta Custom\ DOI\ URI=Uri DOI Personalizzato Use\ custom\ DOI\ base\ URI\ for\ article\ access=Usa l'URI di base DOI personalizzato per l'accesso agli articoli @@ -2367,6 +2371,8 @@ Query=Interrogazione Question=Domanda Select\ directory=Seleziona cartella +Fulltext\ Index=Indice di testo completo +Automatically\ index\ all\ linked\ files\ for\ fulltext\ search=Indicizza automaticamente tutti i file collegati per la ricerca di testo completo Rebuild\ fulltext\ search\ index=Ricostruisci l'indice di ricerca su tutto il testo Rebuild\ fulltext\ search\ index\ for\ current\ library?=Ricostruisci l'indice di ricerca su tutto il testo per la libreria corrente? Rebuilding\ fulltext\ search\ index...=Ricostruzione indice di ricerca su tutto il testo... diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties index a975c5b8f8f..a5869913f04 100644 --- a/src/main/resources/l10n/JabRef_ja.properties +++ b/src/main/resources/l10n/JabRef_ja.properties @@ -172,7 +172,11 @@ Copied=コピーしました Copy=コピー +Copy\ title=タイトルをコピー +Copy\ \\cite{citation\ key}=コピー \\文献{citation key} Copy\ citation\ key=文献キーをコピー +Copy\ citation\ key\ and\ link=文献キーとリンクをコピー +Copy\ citation\ key\ and\ title=文献キーとタイトルをコピー Copy\ to\ clipboard=クリップボードにコピーします. @@ -227,7 +231,7 @@ Library\ properties=ライブラリ特性 Default=既定値 -Default\ encoding=既定エンコーディング +The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=選択したエンコーディング「%0」は,以下の文字をエンコードすることができませんでした: Downloading=ダウンロードしています @@ -826,8 +830,6 @@ Sublibrary\ from\ AUX\ to\ BibTeX=AUXからBibTexへ変換した下位ライブ Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=学術誌名が既知の場合は,完全な学術誌名と短縮形を切り替える. -The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=選択したエンコーディング「%0」は,以下の文字をエンコードすることができませんでした: - the\ field\ %0=フィールド%0 The\ group\ "%0"\ already\ contains\ the\ selection.=グループ「%0」には既に選択したものが含まれています. @@ -1292,9 +1294,7 @@ Save\ changes=変更点を保存 Discard\ changes=変更を放棄 Library\ '%0'\ has\ changed.=ライブラリ「%0」に変更が加えられました. Print\ entry\ preview=項目プレビューを印刷 -Copy\ title=タイトルをコピー -Copy\ \\cite{citation\ key}=コピー \\文献{citation key} -Copy\ citation\ key\ and\ title=文献キーとタイトルをコピー + Invalid\ DOI\:\ '%0'.=無効なDOIです:'%0'. Same\ DOI\ used\ in\ multiple\ entries=複数のエントリーで同じDOIを使用 should\ start\ with\ a\ name=始まりは名前でなくてはなりません @@ -1703,7 +1703,6 @@ should\ be\ normalized=標準化されたものでなくてはなりません Empty\ search\ ID=検索IDが空 The\ given\ search\ ID\ was\ empty.=提示された検索IDが空です. -Copy\ citation\ key\ and\ link=文献キーとリンクをコピー biblatex\ field\ only=biblatexフィールドのみ Error\ while\ generating\ fetch\ URL=取得URLを生成中にエラー発生 @@ -1847,7 +1846,6 @@ Check\ integrity=整合性検査 Cleanup\ URL\ link=URLリンクを清掃 Cleanup\ URL\ link\ by\ removing\ special\ symbols\ and\ extracting\ simple\ link=特殊記号を削除し簡素化されたリンクを抽出してURLを清掃 Copy\ DOI\ url=DOIのURLをコピー -Copy\ citation=引用をコピー Development\ version=開発版 Export\ selected\ entries=選択した項目を書き出す Export\ selected\ entries\ to\ clipboard=選択した項目をクリップボードに書き出す diff --git a/src/main/resources/l10n/JabRef_ko.properties b/src/main/resources/l10n/JabRef_ko.properties index 65a3b9896b5..ada087a378d 100644 --- a/src/main/resources/l10n/JabRef_ko.properties +++ b/src/main/resources/l10n/JabRef_ko.properties @@ -172,7 +172,11 @@ Copied=복사 완료 Copy=복사 +Copy\ title=제목 복사 +Copy\ \\cite{citation\ key}=\\cite{citation key} 복사 Copy\ citation\ key=인용 키 복사 +Copy\ citation\ key\ and\ link=인용 키와 링크 복사 +Copy\ citation\ key\ and\ title=인용 키와 제목 복사 Copy\ to\ clipboard=클립보드에 복사 @@ -226,7 +230,7 @@ Library\ properties=라이브러리 속성 Default=기본값 -Default\ encoding=기본 인코딩 방식 +The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=선택한 인코딩 '%0'은 다음 문자를 인코딩할 수 없습니다. Downloading=다운로드 중 @@ -823,8 +827,6 @@ Sublibrary\ from\ AUX\ to\ BibTeX=AUX에서 BibTeX로의 서브 라이브러리 Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=저널 이름을 알고 있는 경우 전체 저널 이름과 약식 저널 이름 사이를 전환합니다. -The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=선택한 인코딩 '%0'은 다음 문자를 인코딩할 수 없습니다. - the\ field\ %0=필드 %0 The\ group\ "%0"\ already\ contains\ the\ selection.=그룹 "%0"에 이미 선택 항목이 포함되어 있습니다. @@ -1287,9 +1289,7 @@ Save\ changes=변경사항 저장 Discard\ changes=변경 내용 취소 Library\ '%0'\ has\ changed.=라이브러리 '%0'이 변경되었습니다. Print\ entry\ preview=항목 미리보기 인쇄 -Copy\ title=제목 복사 -Copy\ \\cite{citation\ key}=\\cite{citation key} 복사 -Copy\ citation\ key\ and\ title=인용 키와 제목 복사 + Invalid\ DOI\:\ '%0'.=유효하지 않은 DOI \: %0 Same\ DOI\ used\ in\ multiple\ entries=여러 항목에 동일한 DOI 사용 should\ start\ with\ a\ name=이름으로 시작해야 합니다 @@ -1698,7 +1698,6 @@ should\ be\ normalized=정규화되어야 합니다 Empty\ search\ ID=탐색 ID 없음 The\ given\ search\ ID\ was\ empty.=주어진 탐색 ID가 없습니다 -Copy\ citation\ key\ and\ link=인용 키와 링크 복사 biblatex\ field\ only=biblatex 필드만 Error\ while\ generating\ fetch\ URL=가져오기 URL을 생성하는 동안 오류가 발생했습니다. @@ -1841,7 +1840,6 @@ Check\ integrity=무결성 확인 Cleanup\ URL\ link=URL 링크 정리 Cleanup\ URL\ link\ by\ removing\ special\ symbols\ and\ extracting\ simple\ link=특수기호를 제거하고 단순링크를 추출하여 URL링크 정리 Copy\ DOI\ url=DOI URL 복사 -Copy\ citation=인용 복사 Development\ version=개발 버전 Export\ selected\ entries=선택한 항목 내보내기 Export\ selected\ entries\ to\ clipboard=선택한 항목을 클립보드로 내보내기 diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties index 88b01a3ad4e..4ee2f876fc0 100644 --- a/src/main/resources/l10n/JabRef_nl.properties +++ b/src/main/resources/l10n/JabRef_nl.properties @@ -156,6 +156,7 @@ Copied=Gekopieerd Copy=Kopiëren +Copy\ title=Titel kopiëren Copy\ citation\ key=Kopiëer citatiesleutel Copy\ to\ clipboard=Kopiëren naar klembord @@ -208,7 +209,7 @@ Library\ properties=Bibliotheek eigenschappen Default=Standaard -Default\ encoding=Standaard encodering +The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=De gekozen codering '%0' kan de volgende tekens niet coderen\: Downloading=Downloaden @@ -767,8 +768,6 @@ Status=Status Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Schakelt tussen volledige en afgekorte logboeknaam als het logboek bekend is. -The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=De gekozen codering '%0' kan de volgende tekens niet coderen\: - the\ field\ %0=het veld %0 The\ group\ "%0"\ already\ contains\ the\ selection.=De groep "%0" bevat reeds de selectie. @@ -1157,7 +1156,7 @@ Save\ changes=Wijzigingen opslaan Discard\ changes=Verwerp wijzigingen Library\ '%0'\ has\ changed.=Bibliotheek '%0' is veranderd. Print\ entry\ preview=Afdrukvoorbeeld printen -Copy\ title=Titel kopiëren + Invalid\ DOI\:\ '%0'.=Ongeldig DOI\: '%0'. should\ start\ with\ a\ name=moet beginnen met een naam should\ end\ with\ a\ name=moet eindigen met een naam @@ -1653,7 +1652,6 @@ Check\ integrity=Integriteitscontrole Cleanup\ URL\ link=Opschonen URL-koppeling Cleanup\ URL\ link\ by\ removing\ special\ symbols\ and\ extracting\ simple\ link=URL-koppeling opschonen door speciale symbolen te verwijderen en een eenvoudige koppeling te extraheren Copy\ DOI\ url=DOI url kopiëren -Copy\ citation=Citatie kopiëren Development\ version=Onwikkelingsversie Export\ selected\ entries=Exporteer geseleteerde records Export\ selected\ entries\ to\ clipboard=Exporteer geselecteerde invoergegevens naar het klembord diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties index a9833054749..6763920b849 100644 --- a/src/main/resources/l10n/JabRef_no.properties +++ b/src/main/resources/l10n/JabRef_no.properties @@ -197,7 +197,7 @@ Library\ properties=Egenskaper for bibliotek Default=Tilbakestill -Default\ encoding=Standard koding +The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=Den valgte tegnkodingen '%0' kunne ikke kode følgende tegn\: Execute\ default\ action\ in\ dialog=Utfør standardhandlingen i dialogen @@ -728,8 +728,6 @@ Status=Status Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Bytter mellom fullt og forkortet journalnavn dersom navnet er kjent. -The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=Den valgte tegnkodingen '%0' kunne ikke kode følgende tegn\: - the\ field\ %0=feltet %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Gruppen "%0" inneholder allerede de valgte enhetene. @@ -969,6 +967,7 @@ Path\ to\ %0=Sti til %0 Could\ not\ connect\ to\ %0=Kunne ikke koble til %0 + Invalid\ DOI\:\ '%0'.=Ugyldig DOI\: '%0'. diff --git a/src/main/resources/l10n/JabRef_pl.properties b/src/main/resources/l10n/JabRef_pl.properties index f9c0c9001cd..a8c87420c6c 100644 --- a/src/main/resources/l10n/JabRef_pl.properties +++ b/src/main/resources/l10n/JabRef_pl.properties @@ -114,6 +114,7 @@ Copied=Skopiowano Copy=Kopiuj +Copy\ title=Kopiuj tytuł Copy\ to\ clipboard=Skopiuj do schowka @@ -151,7 +152,6 @@ Library\ properties=Właściwości biblioteki Default=Domyślne -Default\ encoding=Domyślne kodowanie Downloading=Pobieranie @@ -571,7 +571,6 @@ Status=Status - Time\ stamp=Znacznik czasu @@ -747,7 +746,7 @@ No\ problems\ found.=Nie znaleziono problemów. Save\ changes=Zapisz zmiany Discard\ changes=Odrzuć zmiany Print\ entry\ preview=Drukuj podgląd wpisu -Copy\ title=Kopiuj tytuł + No\ results\ found.=Nie znaleziono wyników. plain\ text=czysty tekst @@ -953,7 +952,6 @@ Overwrite\ file=Nadpisz plik Open\ file\ %0=Otwórz plik %0 Blog=Blog -Copy\ citation=Kopiuj cytat Manage\ journal\ abbreviations=Zarządzaj skrótami czasopism Quit=Wyjdź diff --git a/src/main/resources/l10n/JabRef_pt.properties b/src/main/resources/l10n/JabRef_pt.properties index a1a78112486..3aece4aafd9 100644 --- a/src/main/resources/l10n/JabRef_pt.properties +++ b/src/main/resources/l10n/JabRef_pt.properties @@ -151,6 +151,7 @@ Copied=Copiado Copy=Copiar +Copy\ title=Copiar título Copy\ to\ clipboard=Copiar para a área de transferência @@ -202,7 +203,7 @@ Library\ properties=Propriedades da base de dados Default=Padrão -Default\ encoding=Codificação padrão +The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=A codificação '%0' não pode codificar os seguintes caracteres\: Execute\ default\ action\ in\ dialog=Executar a acão padrão na caixa de diálogo @@ -741,8 +742,6 @@ Statically\ group\ entries\ by\ manual\ assignment=Agrupar referências manualme Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Alterna entre nomes de periódicos abreviados e completos se o nome do periódico é conhecido. -The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=A codificação '%0' não pode codificar os seguintes caracteres\: - the\ field\ %0=o campo %0 The\ group\ "%0"\ already\ contains\ the\ selection.=O grupo "%0" já contém a seleção. @@ -1116,7 +1115,7 @@ Save\ changes=Salvar mudanças. Discard\ changes=Descartar mudanças Library\ '%0'\ has\ changed.=Base de dados '%0' mudou. Print\ entry\ preview=Imprimir preview da referência -Copy\ title=Copiar título + Invalid\ DOI\:\ '%0'.=DOI inválida\: '%0'. should\ start\ with\ a\ name=deve iniciar com um nome should\ end\ with\ a\ name=deve terminar com um nome @@ -1264,7 +1263,6 @@ Existing\ file=Arquivo existente Check\ integrity=Verificação de integridade Copy\ DOI\ url=Copiar URL do DOI -Copy\ citation=Copiar citação Development\ version=Versão de desenvolvimento Export\ selected\ entries=Exportar referências selecionadas JabRef\ resources=Recursos do JabRef diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties index 728fb357337..e75b7fd126d 100644 --- a/src/main/resources/l10n/JabRef_pt_BR.properties +++ b/src/main/resources/l10n/JabRef_pt_BR.properties @@ -66,6 +66,7 @@ Added\ string=Adicionada string All\ entries=Todas as referências +Also\ remove\ subgroups=Também remover subgrupos Always\ reformat\ BIB\ file\ on\ save\ and\ export=Reformatar sempre o arquivo BIB durante o salvar ou exportar @@ -171,7 +172,13 @@ Copied=Copiado Copy=Copiar +Copy\ title=Copiar título +Copy\ \\cite{citation\ key}=Copiar \\cite{citation key} +Copy\ citation\ (html)=Copiar citação (html) +Copy\ citation\ (text)=Copiar citação (texto) Copy\ citation\ key=Copiar chave de citação +Copy\ citation\ key\ and\ link=Copiar chave de citação e link +Copy\ citation\ key\ and\ title=Copiar chave de citação e título Copy\ to\ clipboard=Copiar para a área de transferência @@ -222,10 +229,13 @@ DOI\ not\ found=DOI não encontrado Library\ encoding=Codificação da base de dados Library\ properties=Propriedades da base de dados +%0\ -\ Library\ properties=%0 - Propriedades da biblioteca Default=Padrão -Default\ encoding=Codificação padrão +Character\ encoding\ UTF-8\ is\ not\ supported.=A codificação UTF-8 não é suportada. +UTF-8\ could\ not\ be\ used\ to\ encode\ the\ following\ characters\:\ %0=UTF-8 não pode ser usado para codificar os seguintes caracteres\: %0 +The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=A codificação '%0' não pode codificar os seguintes caracteres\: Downloading=Baixando @@ -273,6 +283,7 @@ Downloaded\ website\ as\ an\ HTML\ file.=Site baixado como arquivo HTML. duplicate\ removal=remoção de duplicatas +Duplicate\ fields=Duplicar campos Duplicate\ string\ name=Duplicar nome da string @@ -456,6 +467,7 @@ Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=Grupo I\ Agree=Concordo Indexing\ pdf\ files=Indexando arquivos pdf +Indexing\ for\ %0=Indexando %0 %0\ of\ %1\ linked\ files\ added\ to\ the\ index=%0 de %1 arquivos vinculados adicionados ao índice Invalid\ citation\ key=Chave de citação inválida @@ -507,6 +519,7 @@ Main\ file\ directory=Diretório de arquivos principal Manage\ custom\ exports=Gerenciar exportações personalizadas Manage\ custom\ imports=Gerenciar importações personalizadas +External\ file\ types=Tipos de arquivo externos Mark\ new\ entries\ with\ owner\ name=Marcar novas referências com o nome do usuário @@ -726,6 +739,8 @@ Replaces\ Unicode\ ligatures\ with\ their\ expanded\ form=Substitui caracteres e Required\ fields=Campos obrigatórios +Do\ not\ resolve\ BibTeX\ strings=Não resolver frases BibTeX +Resolve\ BibTeX\ strings\ for\ the\ following\ fields=Resolver textos BibTeX para os seguintes campos resolved=resolvido @@ -739,6 +754,7 @@ Review=Revisar Review\ changes=Revisar mudanças Review\ Field\ Migration=Revisar Migração de Campo +Loading=Carregando Save=Salvar Save\ all\ finished.=Salvar todos os concluídos. @@ -752,6 +768,7 @@ Save\ library\ as...=Salvar base de dados como... Saving=Salvando... Saving\ all\ libraries...=Salvando todas as bases de dados... Saving\ library=Salvando base de dados... +Library\ saved=Biblioteca salva Saved\ selected\ to\ '%0'.=Seleção salva para '%0'. Search=Pesquisar @@ -821,8 +838,6 @@ Sublibrary\ from\ AUX\ to\ BibTeX=Subbiblioteca de AUX para BibTeX Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Alterna entre nomes de periódicos abreviados e completos se o nome do periódico é conhecido. -The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=A codificação '%0' não pode codificar os seguintes caracteres\: - the\ field\ %0=o campo %0 The\ group\ "%0"\ already\ contains\ the\ selection.=O grupo "%0" já contém a seleção. @@ -839,6 +854,7 @@ The\ search\ is\ case\ insensitive.=A busca não é sensível ao caso. The\ search\ is\ case\ sensitive.=A busca é sensível ao caso. +There\ are\ possible\ duplicates\ that\ haven't\ been\ resolved.\ Continue?=Existem possíveis duplicatas que não foram resolvidas. Continuar? This\ operation\ requires\ all\ selected\ entries\ to\ have\ citation\ keys\ defined.=Esta operação requer que todas as referências selecionadas tenham chaves de citação definidas. @@ -896,12 +912,14 @@ Warning=Alerta Warnings=Alertas +Warning\:\ You\ added\ field\ "%0"\ twice.\ Only\ one\ will\ be\ kept.=Aviso\: Você adicionou o campo "%0" duas vezes. Apenas um será mantido. web\ link=link web What\ do\ you\ want\ to\ do?=O que você deseja fazer? Whatever\ option\ you\ choose,\ Mr.\ DLib\ may\ share\ its\ data\ with\ research\ partners\ to\ further\ improve\ recommendation\ quality\ as\ part\ of\ a\ 'living\ lab'.\ Mr.\ DLib\ may\ also\ release\ public\ datasets\ that\ may\ contain\ anonymized\ information\ about\ you\ and\ the\ recommendations\ (sensitive\ information\ such\ as\ metadata\ of\ your\ articles\ will\ be\ anonymised\ through\ e.g.\ hashing).\ Research\ partners\ are\ obliged\ to\ adhere\ to\ the\ same\ strict\ data\ protection\ policy\ as\ Mr.\ DLib.=Seja qual for a opção que você escolher, o Mr. DLib pode compartilhar seus dados com parceiros de pesquisa para melhorar a qualidade das recomendações como parte de um "laboratório vivo". O Mr. DLib também pode lançar conjuntos de dados públicos que possam conter informações anônimas sobre você e as recomendações (informações confidenciais, como os metadados dos seus artigos, serão anonimizados através de, por exemplo, hashing). Os parceiros de investigação são obrigados a respeitar a mesma política rigorosa de protecção de dados que o Mr. DLib. +Will\ write\ metadata\ to\ the\ PDFs\ linked\ from\ selected\ entries.=Irá gravar os metadados nos PDFs vinculados a partir de entradas selecionadas. Write\ BibTeXEntry\ as\ metadata\ to\ PDF.=Escrever BibTeXEntry como metadados para PDF. Write\ metadata\ for\ all\ PDFs\ in\ current\ library?=Escrever metadados para todos os PDFs na biblioteca atual? @@ -909,6 +927,7 @@ Writing\ metadata\ for\ selected\ entries...=Escrevendo metadados para as entrad Writing\ metadata...=Escrevendo metadados... Embed\ BibTeXEntry\ in\ PDF.=Incorporar BibTeXEntry ao PDF. +File\ '%0'\ is\ write\ protected.=O arquivo '%0' está protegido contra escrita. Write\ BibTeXEntry\ as\ XMP\ metadata\ to\ PDF.=Escrever o BibTeXEntry como metadado XMP no PDF. Write\ BibTeXEntry\ metadata\ to\ PDF.=Escrever metadados BibTeXEntry no PDF. Write\ metadata\ to\ PDF\ files=Escrever metadados para arquivos PDF @@ -921,6 +940,8 @@ You\ must\ restart\ JabRef\ for\ this\ to\ come\ into\ effect.=Você deve reinic The\ following\ fetchers\ are\ available\:=As seguintes ferramentas de pesquisa estão disponíveis\: Could\ not\ find\ fetcher\ '%0'=Não foi possível encontrar a ferramenta de pesquisa '%0' Running\ query\ '%0'\ with\ fetcher\ '%1'.=Executando consulta '%0' com ferramenta de pesquisa '%1'. +Invalid\ query.\ Check\ position\ %0.=Consulta inválida. Verifique a posição %0. +Invalid\ query\ element\ '%0'\ at\ position\ %1=Elemento de consulta '%0' na posição %1 inválido Move\ file=Mover arquivo Rename\ file=Renomear arquivo @@ -1105,6 +1126,7 @@ Collapse\ all=Reduzir todos Searches\ the\ selected\ directory\ for\ unlinked\ files.=Buscar arquivos não referenciados no diretório selecionado Starts\ the\ import\ of\ BibTeX\ entries.=Iniciar a importação de entradas BibTeX Last\ edited\:=Última edição\: +All\ time=Por todo o tempo last\ edited=última edição Last\ day=Dia anterior Last\ week=Semana anterior @@ -1171,12 +1193,15 @@ Please\ open\ or\ start\ a\ new\ library\ before\ searching=Por favor, abra ou i Canceled\ merging\ entries=União das referências cancelada Merge\ entries=Unir entradas +Merged\ entry=Referência mesclada Merged\ entries=Mesclou referências em uma nova e manteve a antiga None=Nenhum Parse=Interpretar Result=Resultado You\ have\ to\ choose\ exactly\ two\ entries\ to\ merge.=Você deve escolher exatamente duas referências para mesclar +Add\ timestamp\ to\ modified\ entries\ (field\ "modificationdate")=Adicionar timestamp nas entradas modificadas (campo "modificationdate") +Add\ timestamp\ to\ new\ entries\ (field\ "creationdate")=Adicionar timestamp às novas entradas (campo "modificationdate") All\ key\ bindings\ will\ be\ reset\ to\ their\ defaults.=Todas as teclas de atalho serão reconfiguradas para seus valores padrão. Automatically\ set\ file\ links=Definir links para os arquivos automaticamente @@ -1278,9 +1303,7 @@ Save\ changes=Salvar mudanças. Discard\ changes=Descartar mudanças Library\ '%0'\ has\ changed.=Base de dados '%0' mudou. Print\ entry\ preview=Imprimir preview da referência -Copy\ title=Copiar título -Copy\ \\cite{citation\ key}=Copiar \\cite{citation key} -Copy\ citation\ key\ and\ title=Copiar chave de citação e título + Invalid\ DOI\:\ '%0'.=DOI inválida\: '%0'. Same\ DOI\ used\ in\ multiple\ entries=Mesmo DOI usado em múltiplas entradas should\ start\ with\ a\ name=deve iniciar com um nome @@ -1366,6 +1389,7 @@ Display\ keywords\ appearing\ in\ ALL\ entries=Mostrar palavras-chave aparecendo Display\ keywords\ appearing\ in\ ANY\ entry=Exibir palavras-chave aparecendo em QUALQUER referência None\ of\ the\ selected\ entries\ have\ titles.=Nenhuma das entradas selecionadas tem títulos. None\ of\ the\ selected\ entries\ have\ citation\ keys.=Nenhuma das referências selecionadas tem chaves de citação. +None\ of\ the\ selected\ entries\ have\ DOIs.=Nenhuma das entradas selecionadas tem DOIs. Unabbreviate\ journal\ names=Reverter abreviações de nomes de periódicos Unabbreviating...=Revertendo abreviação Usage=Utilização @@ -1423,6 +1447,7 @@ Add\ enclosing\ braces=Adicionar chaves de fechamento Add\ braces\ encapsulating\ the\ complete\ field\ content.=Adicionar chaves encapsulando o conteúdo completo do campo. Remove\ enclosing\ braces=Remover chaves de fechamento Removes\ braces\ encapsulating\ the\ complete\ field\ content.=Remove chaves encapsulando o conteúdo completo do campo. +Removes\ all\ balanced\ {}\ braces\ around\ words.=Remove todas as chaves balanceadas {} em torno das palavras. Shorten\ DOI=Encurtar DOI Shortens\ DOI\ to\ more\ human\ readable\ form.=Encurta DOI para uma forma mais legível e humana. Sentence\ case=Muda Iniciais @@ -1435,7 +1460,10 @@ Does\ nothing.=Não faz nada. Identity=Identidade Clears\ the\ field\ completely.=Limpa completamente o campo. Directory\ not\ found=Diretório não encontrado +Main\ file\ directory\ not\ set.\ Check\ the\ preferences\ (linked\ files)\ or\ the\ library\ properties.=Diretório principal de arquivo não definido. Verifique as preferências (arquivos vinculados) ou as propriedades da biblioteca. This\ operation\ requires\ exactly\ one\ item\ to\ be\ selected.=Esta operação requer que exatamente um item seja selecionado. +Opening\ large\ number\ of\ files=Abrindo grande número de arquivos +You\ are\ about\ to\ open\ %0\ files.\ Continue?=Você está prestes a abrir %0 arquivos. Continuar? Continue=Continuar Importing\ in\ %0\ format=Importando no formato %0 Female\ name=Nome feminino @@ -1536,6 +1564,9 @@ Custom=Personalizar Export\ cited=Exportação citada Unable\ to\ generate\ new\ library=Não foi possível gerar nova biblioteca +Found\ identical\ ranges=Intervalos idênticos encontrados +Found\ overlapping\ ranges=Intervalos sobrepostos encontrados +Found\ touching\ ranges=Intervalos que se tocam foram encontrados Note\:\ Use\ the\ placeholder\ %DIR%\ for\ the\ location\ of\ the\ opened\ library\ file.=Nota\: Use o %DIR% para definir a localização do arquivo da biblioteca aberta. Error\ occured\ while\ executing\ the\ command\ "%0".=Ocorreu um erro ao executar o comando "%0". @@ -1545,6 +1576,7 @@ Countries\ and\ territories\ in\ English=Países e territórios em inglês Electrical\ engineering\ terms=Termos da engenharia elétrica Enabled=Ativado Internal\ list=Lista interna +Protected\ terms\ files=Arquivo de termos protegidos Months\ and\ weekdays\ in\ English=Meses e dias úteis em inglês The\ text\ after\ the\ last\ line\ starting\ with\ \#\ will\ be\ used=O texto após a última linha iniciando com \# será usado Add\ protected\ terms\ file=Adicionar arquivo de termos protegidos @@ -1636,6 +1668,7 @@ Style\ file=Arquivo de estilo Open\ OpenOffice/LibreOffice\ connection=Abrir conexão com OpenOffice/LibreOffice You\ must\ enter\ at\ least\ one\ field\ name=Você deve digitar pelo menos um nome de campo Non-ASCII\ encoded\ character\ found=Caractere não-ASCII encontrado +Non-UTF-8\ encoded\ field\ found=Campo não-UTF-8 encontrado Toggle\ web\ search\ interface=Alternar interface de busca na web Migration\ help\ information=Informação sobre ajuda para a migração @@ -1679,7 +1712,6 @@ should\ be\ normalized=deve ser normalizado Empty\ search\ ID=ID de pesquisa vazio The\ given\ search\ ID\ was\ empty.=O ID de pesquisa fornecido estava vazio. -Copy\ citation\ key\ and\ link=Copiar chave de citação e link biblatex\ field\ only=apenas campo biblatex Error\ while\ generating\ fetch\ URL=Erro ao gerar URL de busca @@ -1743,6 +1775,7 @@ Delete\ '%0'=Remover '%0' Delete\ from\ disk=Remover do disco Remove\ from\ entry=Remover da referência There\ exists\ already\ a\ group\ with\ the\ same\ name.=Já existe um grupo com o mesmo nome. +If\ you\ use\ it,\ it\ will\ inherit\ all\ entries\ from\ this\ other\ group.=Se você usá-lo, herdará todas as entradas deste outro grupo. Copy\ linked\ file=Copiar arquivo vinculado Copy\ linked\ file\ to\ folder...=Copiar arquivo vinculado para o diretório... @@ -1802,6 +1835,7 @@ Error\ pushing\ entries=Erro ao fazer push das referências Undefined\ character\ format=Formato de caractere indefinido Undefined\ paragraph\ format=Formato de parágrafo indefinido +Preamble=Preâmbulo Markings=Marcações Use\ selected\ instance=Usar instância selecionada @@ -1820,8 +1854,8 @@ Blog=Blog Check\ integrity=Verificação de integridade Cleanup\ URL\ link=Limpar URL Cleanup\ URL\ link\ by\ removing\ special\ symbols\ and\ extracting\ simple\ link=Limpar URL removendo símbolos especiais e extraindo um link simples +Copy\ DOI=Copiar DOI Copy\ DOI\ url=Copiar URL do DOI -Copy\ citation=Copiar citação Development\ version=Versão de desenvolvimento Export\ selected\ entries=Exportar referências selecionadas Export\ selected\ entries\ to\ clipboard=Exportar referências selecionadas para área de transferência @@ -1832,6 +1866,8 @@ Manage\ protected\ terms=Gerenciar palavras reservadas New\ entry\ from\ plain\ text=Nova referência a partir de texto simples Import\ by\ ID=Importar por ID Enter\ a\ valid\ ID=Insira um ID válido +Imported\ one\ entry=Uma entrada importada +Entry\ already\ exists=Entrada já existe New\ sublibrary\ based\ on\ AUX\ file=Nova subbiblioteca baseada em arquivo AUX Push\ entries\ to\ external\ application\ (%0)=Enviar referências para um aplicativo externo (%0) Quit=Sair @@ -1870,6 +1906,7 @@ Cancel\ import=Cancelar Importação Continue\ with\ import=Continuar com a importação Import\ canceled=Importação cancelada Select\ all\ new\ entries=Selecionar todas as novas referências +Select\ all\ entries=Selecionar todas as entradas Total\ items\ found\:=Total de itens encontrados\: Selected\ items\:=Itens selecionados\: Download\ linked\ online\ files=Baixar arquivos online vinculados @@ -1890,6 +1927,7 @@ Keyword\ separator=Separador da palavra-chave Remove\ keyword=Remover palavra-chave Are\ you\ sure\ you\ want\ to\ remove\ keyword\:\ "%0"?=Tem certeza que deseja remover a palavra-chave\: "%0"? Reset\ to\ default=Restaurar padrão +String\ constants=Constantes do texto Export\ all\ entries=Exportar todas as referências Generate\ citation\ keys=Gerar chaves de citação Manage\ field\ names\ &\ content=Gerenciar nomes e conteúdo dos campos @@ -2020,6 +2058,7 @@ Keyword\ delimiter=Delimitador de palavra-chave Hierarchical\ keyword\ delimiter=Delimitador hierárquico de palavra-chave Escape\ ampersands="Escapar" ampersands (&) +Hint\:\n\nTo\ search\ all\ fields\ for\ Smith,\ enter\:\nsmith\n\nTo\ search\ the\ field\ author\ for\ Smith\ and\ the\ field\ title\ for\ electrical,\ enter\:\nauthor\=Smith\ and\ title\=electrical=Dica\:\n\nPara pesquisar todos os campos por Smith, digite\:\nsmith\n\nPara procurar por Smith no campo autor e eletrico no campo título, digite\:\nauthor\=Ferreiro e title\=eletrico Copied\ '%0'\ to\ clipboard.='%0' copiado(s) para área de transferência. This\ operation\ requires\ an\ open\ library.=Esta operação requer uma biblioteca aberta. @@ -2140,8 +2179,22 @@ This\ field\ may\ be\ useful\ when\ implementing\ a\ style\ for\ annotated\ bibl Subtitle\ related\ to\ the\ "Booktitle".=Subtítulo relacionado ao "Booktitle". Annex\ to\ the\ "Booktitle",\ to\ be\ printed\ in\ a\ different\ font.=Anexo ao "Título do do livro" para ser impresso em uma fonte diferente. Comment\ to\ this\ entry.=Comentar esta referência. +Secondary\ editor\ performing\ a\ different\ editorial\ role,\ such\ as\ compiling,\ redacting,\ etc.=Editor secundário realizando uma função editorial diferente, como compilação, redação, etc. +Another\ secondary\ editor\ performing\ a\ different\ role.=Outro editor secundário realizando um papel diferente. +Type\ of\ editorial\ role\ performed\ by\ the\ "Editor".=Tipo de papel editorial desempenhado pelo "Editor". +Type\ of\ editorial\ role\ performed\ by\ the\ "Editora".=Tipo de papel editorial desempenhado pelo "EditorA". +Type\ of\ editorial\ role\ performed\ by\ the\ "Editorb".=Tipo de papel editorial desempenhado pelo "EditorB". +Type\ of\ editorial\ role\ performed\ by\ the\ "Editorc".=Tipo de papel editorial desempenhado pelo "EditorC". +Author(s)\ of\ a\ foreword\ to\ the\ work.=Autor(es) de um prefácio do trabalho. +International\ Standard\ Technical\ Report\ Number\ of\ a\ technical\ report.=Número de Relatório Técnico Padrão Internacional (International Standard Technical Report Number) de um Relatório Técnico. +International\ Standard\ Serial\ Number\ of\ a\ periodical.=International Standard Serial Number (ISBN) de um livro. +Subtitle\ of\ a\ journal,\ a\ newspaper,\ or\ some\ other\ periodical.=Subtítulo de uma revista, de um jornal ou de outro periódico. +Language(s)\ of\ the\ work.\ Languages\ may\ be\ specified\ literally\ or\ as\ localisation\ keys.=Idioma(s) do trabalho. Idiomas podem ser especificados literalmente ou como chaves de localização. Subtitle\ related\ to\ the\ "Maintitle".=Subtítulo relacionado ao "Maintitle". Annex\ to\ the\ "Maintitle",\ to\ be\ printed\ in\ a\ different\ font.=Anexo ao "Maintitle", a ser impresso em uma fonte diferente. +Addon\ to\ be\ printed\ immediately\ after\ the\ author\ name\ in\ the\ bibliography.=Addon a ser impresso imediatamente após o nome do autor na bibliografia. +If\ the\ work\ is\ a\ translation,\ a\ reprint,\ or\ something\ similar,\ the\ publication\ date\ of\ the\ original\ edition.=Se o trabalho é uma tradução, uma reimpressão, ou algo semelhante, a data de publicação da edição original. +If\ the\ work\ is\ a\ translation,\ the\ language(s)\ of\ the\ original\ work.=Se o trabalho é uma tradução, o(s) idioma(s) da(s) da obra original. Pagination\ of\ the\ work.\ The\ key\ should\ be\ given\ in\ the\ singular\ form.=Paginação do trabalho. A chave deve ser inserida de forma singular. Number\ of\ a\ partial\ volume.\ This\ field\ applies\ to\ books\ only,\ not\ to\ journals.\ It\ may\ be\ used\ when\ a\ logical\ volume\ consists\ of\ two\ or\ more\ physical\ ones.=Número de um volume parcial. Este campo se aplica somente aos livros, não aos periódicos. Pode ser usado quando um volume lógico consiste em dois ou mais volumes físicos. Title\ in\ an\ abridged\ form.=Título em forma abreviada. @@ -2149,23 +2202,61 @@ Annex\ to\ the\ "Title",\ to\ be\ printed\ in\ a\ different\ font.=Anexo ao "Tit Translator(s)\ of\ the\ "Title"\ or\ "Booktitle",\ depending\ on\ the\ entry\ type.\ If\ the\ translator\ is\ identical\ to\ the\ "Editor",\ the\ standard\ styles\ will\ automatically\ concatenate\ these\ fields\ in\ the\ bibliography.=Tradutores(s) do "Title" ou "Booktitle", dependendo do tipo de referência. Se o tradutor for idêntico ao "Editor", os estilos padrão concatenarão automaticamente esses campos na bibliografia. Type\ of\ a\ "Manual",\ "Patent",\ "Report",\ or\ "Thesis".=Tipo de "Manual", "Patent", "Report", or "Thesis". This\ field\ holds\ an\ entry\ key\ for\ the\ cross-referencing\ feature.\ Child\ entries\ with\ a\ "Crossref"\ field\ inherit\ data\ from\ the\ parent\ entry\ specified\ in\ the\ "Crossref"\ field.=Este campo contém uma chave de entrada para o recurso de referência cruzada. Referências filhas com um campo "Crossref" herdam dados da referência pai especificada no campo "Crossref". +Gender\ of\ the\ author\ or\ gender\ of\ the\ editor,\ if\ there\ is\ no\ author.=Gênero do autor ou gênero do editor, se não houver autor. Citation\ keys\ of\ other\ entries\ which\ have\ a\ relationship\ to\ this\ entry.=Chaves de citação de outras referências que tenham uma relação com esta referência. This\ field\ is\ an\ alternative\ cross-referencing\ mechanism.\ It\ differs\ from\ "Crossref"\ in\ that\ the\ child\ entry\ will\ not\ inherit\ any\ data\ from\ the\ parent\ entry\ specified\ in\ the\ "Xref"\ field.=Este campo é um mecanismo alternativo de referência cruzada. Difere de "Crossref" em que a referência filho não herdará nenhum dado da referência pai especificada no campo "Xref". Owner/creator\ of\ this\ entry.=Proprietário/criador desta referência. Timestamp\ of\ this\ entry,\ when\ it\ has\ been\ created\ or\ last\ modified.=Registro de data/hora desta referência, quando ela foi criada ou modificada pela última vez. User-specific\ printed\ flag,\ in\ case\ the\ entry\ has\ been\ printed.=Indicação impressa específica do usuário, no caso da referência ter sido impressa. +User-specific\ priority.=Prioridade específica do usuário. +User-specific\ quality\ flag,\ in\ case\ its\ quality\ is\ assured.=Sinalizador de qualidade específico do usuário, caso a qualidade seja garantida. +User-specific\ ranking.=Ranking específico do usuário. +User-specific\ read\ status.=Status de leitura específico do usuário. User-specific\ relevance\ flag,\ in\ case\ the\ entry\ is\ relevant.=Indicação de relevância específica do usuário, caso a referência seja relevante. - - +Auto\ complete\ disabled.=Auto completar desativado. +Auto\ complete\ enabled.=Auto completar ativado. + +Remove\ formatter\ for\ %0=Remover formatador para %0 +Remove\ formatter\ '%0'=Remover formatador '%0' + +An\ article\ in\ a\ journal,\ magazine,\ newspaper,\ or\ other\ periodical\ which\ forms\ a\ self-contained\ unit\ with\ its\ own\ title.=Um artigo de revista, jornal ou outro periódico que forma uma unidade auto-contida com seu próprio título. +A\ single-volume\ book\ with\ one\ or\ more\ authors\ where\ the\ authors\ share\ credit\ for\ the\ work\ as\ a\ whole.=Um livro de volume único com um ou mais autores em que os autores compartilham crédito pelo trabalho como um todo. +A\ book-like\ work\ without\ a\ formal\ publisher\ or\ sponsoring\ institution.=Um trabalho semelhante a um livro sem um editor formal ou uma instituição patrocinadora. +A\ single-volume\ collection\ with\ multiple,\ self-contained\ contributions\ by\ distinct\ authors\ which\ have\ their\ own\ title.\ The\ work\ as\ a\ whole\ has\ no\ overall\ author\ but\ it\ will\ usually\ have\ an\ editor.=Uma coleção de volume único com múltiplas contribuições auto-contidas de autores distintos que tenham seu próprio título. O trabalho como um todo não tem um autor, mas geralmente tem um editor. +A\ legacy\ alias\ for\ "InProceedings".=Um nome legado para "InProceedings". +A\ part\ of\ a\ book\ which\ forms\ a\ self-contained\ unit\ with\ its\ own\ title.=Uma parte de um livro que forma uma unidade auto-contida com seu próprio título. +A\ contribution\ to\ a\ collection\ which\ forms\ a\ self-contained\ unit\ with\ a\ distinct\ author\ and\ title.=Uma contribuição para uma coleção que forma uma unidade auto-contida, tendo um autor e título distintos. +An\ article\ in\ a\ conference\ proceedings.=Um artigo em anais de conferência. +Technical\ or\ other\ documentation,\ not\ necessarily\ in\ printed\ form.=Documentação técnica não necessariamente na forma impressa. +A\ fallback\ type\ for\ entries\ which\ do\ not\ fit\ into\ any\ other\ category.=Um tipo para entradas que não se encaixam em nenhuma outra categoria. +Similar\ to\ "Thesis"\ except\ that\ the\ type\ field\ is\ optional\ and\ defaults\ to\ the\ localised\ term\ \ Master's\ thesis.=Semelhante a "Thesis", exceto que o campo 'type' é opcional e o padrão é a Dissertação de Mestrado. +Similar\ to\ "Thesis"\ except\ that\ the\ type\ field\ is\ optional\ and\ defaults\ to\ the\ localised\ term\ PhD\ thesis.=Semelhante a "Thesis", exceto que o campo 'type' é opcional e o padrão é a Tese de Doutorado. +A\ single-volume\ conference\ proceedings.\ This\ type\ is\ very\ similar\ to\ "Collection".=Anais de conferência de volume único. Este tipo é muito semelhante à "Collection". +Similar\ to\ "Report"\ except\ that\ the\ type\ field\ is\ optional\ and\ defaults\ to\ the\ localised\ term\ technical\ report.=Semelhante a "Report", exceto que o campo 'type' é opcional e o padrão é Technical Report. +A\ work\ with\ an\ author\ and\ a\ title\ which\ has\ not\ been\ formally\ published,\ such\ as\ a\ manuscript\ or\ the\ script\ of\ a\ talk.=Um trabalho com um autor e um título que não foi formalmente publicado, como um manuscrito ou o script de uma conversa. +This\ type\ is\ similar\ to\ "InBook"\ but\ intended\ for\ works\ originally\ published\ as\ a\ stand-alone\ book.=Este tipo é semelhante ao "InBook", mas destinado a trabalhos originalmente publicados como um livro independente. An\ article\ in\ a\ work\ of\ reference.\ This\ is\ a\ more\ specific\ variant\ of\ the\ generic\ "InCollection"\ entry\ type.=Um artigo em um trabalho de referência. Esta é uma variante mais específica do tipo de referência genérico de "InCollection". +A\ multi-volume\ "Book".=Um livro (Book) de vários volumes. +A\ multi-volume\ "Collection".=Uma "Collection" de vários volumes. A\ multi-volume\ "Proceedings"\ entry.=Uma referência "Proceedings" com vários volumes. A\ multi-volume\ "Reference"\ entry.\ The\ standard\ styles\ will\ treat\ this\ entry\ type\ as\ an\ alias\ for\ "MvCollection".=Uma referência "Reference" de vários volumes. Os estilos padrão tratarão este tipo de referência como um apelido para "MvCollection". This\ entry\ type\ is\ intended\ for\ sources\ such\ as\ web\ sites\ which\ are\ intrinsically\ online\ resources.=Este tipo de referência é destinado a fontes como sites que são recursos intrinsecamente on-line. +A\ single-volume\ work\ of\ reference\ such\ as\ an\ encyclopedia\ or\ a\ dictionary.=Uma obra de referência em volume único, como uma enciclopédia ou um dicionário. +A\ technical\ report,\ research\ report,\ or\ white\ paper\ published\ by\ a\ university\ or\ some\ other\ institution.=Um relatório técnico, um relatório de pesquisa ou "White Paper" publicado por uma universidade ou outra instituição. An\ entry\ set\ is\ a\ group\ of\ entries\ which\ are\ cited\ as\ a\ single\ reference\ and\ listed\ as\ a\ single\ item\ in\ the\ bibliography.=Um conjunto de referências é um grupo de referências que são citadas como uma única referência e listadas como um único item na bibliografia. +Supplemental\ material\ in\ a\ "Book".\ This\ type\ is\ provided\ for\ elements\ such\ as\ prefaces,\ introductions,\ forewords,\ afterwords,\ etc.\ which\ often\ have\ a\ generic\ title\ only.=Material suplementar em um Livro. Este tipo é fornecido para elementos como prefácios, introduções, posfácios, etc. que muitas vezes têm um título genérico apenas. +Supplemental\ material\ in\ a\ "Collection".=Material suplementar em uma "Collection". Supplemental\ material\ in\ a\ "Periodical".\ This\ type\ may\ be\ useful\ when\ referring\ to\ items\ such\ as\ regular\ columns,\ obituaries,\ letters\ to\ the\ editor,\ etc.\ which\ only\ have\ a\ generic\ title.=Material suplementar em um "Periodical". Este tipo pode ser útil quando se refere a itens como colunas regulares, obituários, cartas para o editor, etc. que têm apenas um título genérico. +A\ thesis\ written\ for\ an\ educational\ institution\ to\ satisfy\ the\ requirements\ for\ a\ degree.=Uma tese escrita para uma instituição educacional para satisfazer os requisitos para graduação +An\ alias\ for\ "Online",\ provided\ for\ jurabib\ compatibility.=Um apelido para "Online", fornecido para a compatibilidade com jurabib. Computer\ software.\ The\ standard\ styles\ will\ treat\ this\ entry\ type\ as\ an\ alias\ for\ "Misc".=Software de computador. Os estilos padrão tratarão esse tipo de entrada como um apelido para "Misc". +A\ data\ set\ or\ a\ similar\ collection\ of\ (mostly)\ raw\ data.=Um conjunto de dados ou uma coleção semelhante de dados (na maioria) brutos. +Display\ count\ of\ items\ in\ group=Mostrar a contagem de itens no grupo +Remove\ the\ following\ characters\:=Remover os seguintes caracteres\: +Truncate=Truncar +Truncates\ a\ string\ after\ a\ given\ index.=Trunca uma sequência de caracteres após um determinado índice. Close=Fechar Close\ all=Fechar Tudo Close\ all\ libraries=Fechar todas as bibliotecas @@ -2173,11 +2264,22 @@ Close\ other\ libraries=Fechar outras bibliotecas Close\ others=Fechar outros Reveal\ in\ file\ explorer=Mostrar no explorador de arquivos +Autolink\ files=Autovincular arquivos +Custom\ editor\ tabs=Guias do editor personalizadas +Custom\ export\ formats=Formatos de exportação personalizados +Custom\ import\ formats=Formatos de importação personalizados +No\ list\ enabled=Nenhuma lista habilitada +Protect\ selection=Proteger a seleção +Customized\ preview\ style=Estilo de visualização personalizado +Next\ preview\ style=Próximo estilo de preview +Previous\ preview\ style=Estilo de preview anterior +(\ Note\:\ Press\ return\ to\ commit\ changes\ in\ the\ table\!\ )=( Nota\: Pressione enter para fazer commit das alterações na tabela) Reset=Reset +New\ inproceedings=Novo anais Reset\ entry\ types\ and\ fields\ to\ defaults=Redefinir tipos de entrada e campos para o padrão This\ will\ reset\ all\ entry\ types\ to\ their\ default\ values\ and\ remove\ all\ custom\ entry\ types=Isso redefinirá todos os tipos de referências aos seus valores padrão e removerá todos os tipos de entrada personalizados Replace\ tabs\ with\ space=Substituir tabs por espaços @@ -2193,30 +2295,66 @@ Check\ Proxy\ Setting=Verificar Configuração de Proxy Check\ connection=Verificar conexão Connection\ failed\!=Falha na conexão\! Connection\ successful\!=Conexão bem-sucedida\! - - +Generate\ groups\ from\ keywords\ in\ the\ following\ field=Gerar grupos de palavras-chave no campo seguinte +Generate\ groups\ for\ author\ last\ names=Gerar grupos para os últimos nomes dos autores +Regular\ expression=Expressão regular + +Error\ importing.\ See\ the\ error\ log\ for\ details.=Erro ao importar. Veja o log de erros para detalhes. + +Error\ from\ import\:\ %0=Erro de importação\: %0 +Error\ reading\ PDF\ content\:\ %0=Erro ao ler conteúdo do PDF\: %0 +Importing\ bib\ entry=Importando entrada bib +Importing\ using\ extracted\ PDF\ data=Importando usando dados extraídos do PDF +No\ BibTeX\ data\ found.\ Creating\ empty\ entry\ with\ file\ link=Nenhum dado BibTeX encontrado. Criando uma referência vazia com link do arquivo +No\ metadata\ found.\ Creating\ empty\ entry\ with\ file\ link=Nenhum metadado encontrado. Criando uma entrada vazia com link de arquivo +Processing\ file\ %0=Processando arquivo %0 Export\ selected=Exportar selecionado +Separate\ merged\ citations=Separar citações mescladas Separate\ citations=Separar citações Unprotect\ terms=Desproteger termos +Error\ connecting\ to\ Writer\ document=Erro ao conectar com o documento Writer +You\ need\ to\ open\ Writer\ with\ a\ document\ before\ connecting=Você precisa abrir o Writer com um documento antes de se conectar +Generate\ a\ new\ key\ for\ imported\ entries\ (overwriting\ their\ default)=Gerar uma nova chave para entradas importadas (sobrescrevendo o padrão) +Warn\ about\ duplicates\ on\ import=Avisar sobre duplicatas na importação Import\ and\ Export=Importar e Exportar +Custom\ DOI\ URI=URI DOI personalizado +Use\ custom\ DOI\ base\ URI\ for\ article\ access=Acessar o artigo utilizando uma URI personalizada baseada no DOI Cited\ on\ pages=Citado nas páginas +Unable\ to\ find\ valid\ certification\ path\ to\ requested\ target(%0),\ download\ anyway?=Não foi possível encontrar um caminho de certificação válido para o destino solicitado (%0), baixar mesmo assim? +Download\ operation\ canceled.=Operação de download cancelada. +Convert\ timestamp\ field\ to\ field\ 'creationdate'=Converter campo timestamp para o campo 'creationdate' +Convert\ timestamp\ field\ to\ field\ 'modificationdate'=Converter campo timestamp para campo 'modificationdate' +New\ entry\ by\ type=Nova entrada por tipo +File\ '%1'\ is\ a\ duplicate\ of\ '%0'.\ Keeping\ '%0'=Arquivo '%1' é uma duplicata de '%0'. Mantendo '%0' +File\ '%1'\ is\ a\ duplicate\ of\ '%0'.\ Keeping\ both\ due\ to\ deletion\ error=Arquivo '%1' é uma duplicata de '%0'. Mantendo ambos devido a um erro de exclusão +Enable\ field\ formatters=Ativar formatadores de campo +Entry\ Type=Tipo de referência +Entry\ types=Tipos de referência +Field\ names=Nomes dos campos +Others=Outros +Overwrite\ existing\ field\ values=Sobrescrever valores de campos existentes +Recommended=Recomendado +Authors\ and\ Title=Autores e Título Database=Banco de dados Databases=Bancos de dados +Manage\ study\ definition=Gerenciar definição de estudo Add\ Author\:=Adicionar Autor\: Add\ Database\:=Adicionar banco de dados\: Searching=Buscando Finalize=Finalizar +Fulltext\ Index=Índices para texto completo +Automatically\ index\ all\ linked\ files\ for\ fulltext\ search=Indexar automaticamente todos os arquivos vinculados para pesquisa em texto completo Word\ by\ word=Palavra por palavra diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties index 1bdaaa94975..66970d8eb33 100644 --- a/src/main/resources/l10n/JabRef_ru.properties +++ b/src/main/resources/l10n/JabRef_ru.properties @@ -172,7 +172,11 @@ Copied=Скопированное Copy=Копировать +Copy\ title=Копировать заглавие +Copy\ \\cite{citation\ key}=Копировать \\ цитировать{citation key} Copy\ citation\ key=Копировать ключ цитаты +Copy\ citation\ key\ and\ link=Скопировать ключ цитаты и ссылку +Copy\ citation\ key\ and\ title=Копировать ключ цитаты и заголовок Copy\ to\ clipboard=Копировать в буфер обмена @@ -227,7 +231,7 @@ Library\ properties=Свойства БД Default=По умолчанию -Default\ encoding=Кодировка по умолчанию +The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=В выбранной кодировке '%0' невозможно прочитать следующие символы\: Downloading=Загрузка … @@ -825,8 +829,6 @@ Sublibrary\ from\ AUX\ to\ BibTeX=Библиотека для перехода Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Переключение полного/сокращенного имени журнала для известных имен журналов. -The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=В выбранной кодировке '%0' невозможно прочитать следующие символы\: - the\ field\ %0=поле %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Группа "%0" уже содержит выбранное. @@ -1289,9 +1291,7 @@ Save\ changes=Сохранить изменения Discard\ changes=Отменить изменения Library\ '%0'\ has\ changed.=БД '%0' изменена. Print\ entry\ preview=Предварительный просмотр записи для печати -Copy\ title=Копировать заглавие -Copy\ \\cite{citation\ key}=Копировать \\ цитировать{citation key} -Copy\ citation\ key\ and\ title=Копировать ключ цитаты и заголовок + Invalid\ DOI\:\ '%0'.=Недопустимый DOI-адрес\: '%0'. Same\ DOI\ used\ in\ multiple\ entries=Один и тот же DOI используется в нескольких записях should\ start\ with\ a\ name=должно начинаться с имени @@ -1700,7 +1700,6 @@ should\ be\ normalized=должно быть нормализовано Empty\ search\ ID=Пустой поисковый запрос The\ given\ search\ ID\ was\ empty.=Указанный поисковый ID был пустым. -Copy\ citation\ key\ and\ link=Скопировать ключ цитаты и ссылку biblatex\ field\ only=только поле типа biblatex Error\ while\ generating\ fetch\ URL=Ошибка генерации URL адреса загрузки @@ -1843,7 +1842,6 @@ Check\ integrity=Проверка целостности Cleanup\ URL\ link=Очистить URL ссылку Cleanup\ URL\ link\ by\ removing\ special\ symbols\ and\ extracting\ simple\ link=Очистка URL ссылку, удалив специальные символы, чтобы получился простой URL Copy\ DOI\ url=Копировать URL-адрес DOI -Copy\ citation=Копировать цитату Development\ version=Версия для разработчиков Export\ selected\ entries=Экспорт выбранных записей Export\ selected\ entries\ to\ clipboard=Копировать выбранные записи в буфер обмена diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties index 5e9c6f1c023..f64e15903a9 100644 --- a/src/main/resources/l10n/JabRef_sv.properties +++ b/src/main/resources/l10n/JabRef_sv.properties @@ -152,7 +152,9 @@ Copied=Kopierade Copy=Kopiera +Copy\ title=Kopiera titel Copy\ citation\ key=Kopiera referensnyckel +Copy\ citation\ key\ and\ title=Kopiera referensnyckel och titel Copy\ to\ clipboard=Kopiera till urklipp @@ -203,7 +205,7 @@ Library\ properties=Bibliotekets egenskaper Default=Standard -Default\ encoding=Standardteckenkodning +The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=Den valde teckenkodningen '%0' kan inte representera följande tecken Downloading=Laddar ner @@ -720,8 +722,6 @@ Statically\ group\ entries\ by\ manual\ assignment=Gruppera poster genom att man Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Växlar mellan fullt och förkortat tidskiftsnamn om tidskriften är känd. -The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=Den valde teckenkodningen '%0' kan inte representera följande tecken - the\ field\ %0=fältet %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Gruppen "%0" innehåller redan de valda posterna. @@ -1078,8 +1078,7 @@ Save\ changes=Spara ändringar Discard\ changes=Ignorera ändringar Library\ '%0'\ has\ changed.=Biblioteket '%0' har ändrats. Print\ entry\ preview=Skriv ut postvisning -Copy\ title=Kopiera titel -Copy\ citation\ key\ and\ title=Kopiera referensnyckel och titel + Invalid\ DOI\:\ '%0'.=Ogiltig DOI\: '%0'. Same\ DOI\ used\ in\ multiple\ entries=Samma DOI används i flera poster should\ start\ with\ a\ name=ska börja med ett namn diff --git a/src/main/resources/l10n/JabRef_tl.properties b/src/main/resources/l10n/JabRef_tl.properties index 3daa7c12be8..b79b4ff13e6 100644 --- a/src/main/resources/l10n/JabRef_tl.properties +++ b/src/main/resources/l10n/JabRef_tl.properties @@ -147,6 +147,7 @@ Copied=Na kopya Copy=Kopya +Copy\ title=Kopyahin ang pamagat Copy\ to\ clipboard=Kopyahin sa clipboad @@ -197,7 +198,7 @@ Library\ properties=Katangian ng library Default=Default -Default\ encoding=Default encoding +The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=Ang napiling encoding na '%0' ay hindi ma-encode ang mga sumusunod na character\: @@ -719,8 +720,6 @@ Status=Katayuan Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Lilipat sa pagitan ng buong at dinaglat na pangalan ng journal kung kulala ang pangalan ng journal. -The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=Ang napiling encoding na '%0' ay hindi ma-encode ang mga sumusunod na character\: - the\ field\ %0=ang patlang na %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Ang grupo na '%0' ay naglalaman na ng pagpili. @@ -1098,7 +1097,7 @@ Save\ changes=I-save ang mga pagbabago Discard\ changes=Itapon ang mga pagbabago Library\ '%0'\ has\ changed.=Binago ang Library '%0'. Print\ entry\ preview=I-print ang preview ng entry -Copy\ title=Kopyahin ang pamagat + Invalid\ DOI\:\ '%0'.=Di-wastong DOI\: '%0'. should\ start\ with\ a\ name=dapat magsimula sa isang pangalan should\ end\ with\ a\ name=dapat magtapos sa isang pangalan diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties index d0cd850d335..75b2606d4b5 100644 --- a/src/main/resources/l10n/JabRef_tr.properties +++ b/src/main/resources/l10n/JabRef_tr.properties @@ -172,7 +172,11 @@ Copied=Kopyalandı Copy=Kopyala +Copy\ title=Başlığı kopyala +Copy\ \\cite{citation\ key}=\\cite{citation key}''nı kopyala Copy\ citation\ key=Atıf anahtarını kopyala +Copy\ citation\ key\ and\ link=Atıf anahtarı ve bağlantısını kopyala +Copy\ citation\ key\ and\ title=Atıf anahtarı ve başlığını kopyala Copy\ to\ clipboard=Panoya kopyala @@ -227,7 +231,7 @@ Library\ properties=Veritabanı özellikleri Default=Öntanımlı -Default\ encoding=Öntanımlı kodlama +The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=Seçilen '%0' kodlaması şu karakterleri kodlayamıyor\: Downloading=İndiriliyor @@ -275,6 +279,7 @@ Downloaded\ website\ as\ an\ HTML\ file.=Web sitesi bir HTML dosyası olarak ind duplicate\ removal=çift nüsha silme +Duplicate\ fields=Yinelenen Alan Duplicate\ string\ name=Çift nüsha dizge adı @@ -730,6 +735,8 @@ Replaces\ Unicode\ ligatures\ with\ their\ expanded\ form=Unicode bitişik harfl Required\ fields=Zorunlu alanlar +Do\ not\ resolve\ BibTeX\ strings=BibTeX dizgelerini çözümleme +Resolve\ BibTeX\ strings\ for\ the\ following\ fields=BibTeX dizgelerini aşağıdaki alanlar için çözümle resolved=çözümlendi @@ -743,6 +750,7 @@ Review=Gözden geçir Review\ changes=Değişklikleri incele Review\ Field\ Migration=Alan Birleştirmeyi İncele +Loading=Yükleniyor Save=Kaydet Save\ all\ finished.=Tüm bitenleri kaydet. @@ -826,8 +834,6 @@ Sublibrary\ from\ AUX\ to\ BibTeX=AUX'tan BibTeX'e alt-kütüphane Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Dergi adı biliniyorsa tam ve kısaltılmış dergi adı arasında geçiş yapar. -The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=Seçilen '%0' kodlaması şu karakterleri kodlayamıyor\: - the\ field\ %0=alan %0 The\ group\ "%0"\ already\ contains\ the\ selection.="%0" grubu seçimi zaten kapsıyor. @@ -902,6 +908,7 @@ Warning=Uyarı Warnings=Uyarılar +Warning\:\ You\ added\ field\ "%0"\ twice.\ Only\ one\ will\ be\ kept.=Uyarı\: "%0" alanını iki kez eklediniz. Yalnızca bir tanesi tutulacak. web\ link=sanaldoku linki @@ -1292,9 +1299,7 @@ Save\ changes=Değişiklikleri kaydet Discard\ changes=Değişiklikleri sil Library\ '%0'\ has\ changed.=Veri tabanı '%0' değişti. Print\ entry\ preview=Girdi yazdırma önizleme -Copy\ title=Başlığı kopyala -Copy\ \\cite{citation\ key}=\\cite{citation key}''nı kopyala -Copy\ citation\ key\ and\ title=Atıf anahtarı ve başlığını kopyala + Invalid\ DOI\:\ '%0'.=Geçersiz DOI\: '%0'. Same\ DOI\ used\ in\ multiple\ entries=Aynı DOI birçok girdide kullanıldı should\ start\ with\ a\ name=bir isimle başlamalı @@ -1703,7 +1708,6 @@ should\ be\ normalized=normalleştirilmelidir Empty\ search\ ID=Boş arama IDsi The\ given\ search\ ID\ was\ empty.=Verilen arama IDsi boştu. -Copy\ citation\ key\ and\ link=Atıf anahtarı ve bağlantısını kopyala biblatex\ field\ only=Yalnızca biblatex alanı Error\ while\ generating\ fetch\ URL=URL'den getirme oluşturulurken hata @@ -1847,7 +1851,6 @@ Check\ integrity=Bütünlük kontrolü Cleanup\ URL\ link=URL bağlantısını temizle Cleanup\ URL\ link\ by\ removing\ special\ symbols\ and\ extracting\ simple\ link=URL bağlantısını özel simgeleri kaldırarak ve basit bağlantı çıkararak temizle Copy\ DOI\ url=DOI url'sini kopyala -Copy\ citation=Atıf'ı kopyala Development\ version=Geliştirme sürümü Export\ selected\ entries=Seçili girdileri dışa aktar Export\ selected\ entries\ to\ clipboard=Seçili girdileri panoya aktar diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties index d81484184dd..4482b5b1809 100644 --- a/src/main/resources/l10n/JabRef_vi.properties +++ b/src/main/resources/l10n/JabRef_vi.properties @@ -205,7 +205,7 @@ Library\ properties=Tính chất của CSDL Default=Mặc định -Default\ encoding=Mã hóa mặc định +The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=Mã hóa đã chọn '%0' không thể mã hóa được các ký tự sau\: @@ -726,8 +726,6 @@ Status=Trạng thái Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=Chuyển đổi giữa tên đầy đủ và tên viết tắt tạp chí nếu biết tên tạp chí đó. -The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=Mã hóa đã chọn '%0' không thể mã hóa được các ký tự sau\: - the\ field\ %0=dữ liệu %0 The\ group\ "%0"\ already\ contains\ the\ selection.=Nhóm "%0" đã chứa phép chọn. @@ -905,6 +903,7 @@ Path\ to\ %0=Đường dẫn đến %0 Could\ not\ connect\ to\ %0=Không thể kết nối đến %0 + Invalid\ DOI\:\ '%0'.=DOI không hợp lệ\: '%0'. diff --git a/src/main/resources/l10n/JabRef_zh_CN.properties b/src/main/resources/l10n/JabRef_zh_CN.properties index 7a090bb2e84..baa7f8f9e9d 100644 --- a/src/main/resources/l10n/JabRef_zh_CN.properties +++ b/src/main/resources/l10n/JabRef_zh_CN.properties @@ -172,7 +172,11 @@ Copied=已复制 Copy=复制 -Copy\ citation\ key=复制Citationkey +Copy\ title=复制标题 +Copy\ \\cite{citation\ key}=复制 \\cite{citation key} +Copy\ citation\ key=复制 citationkey +Copy\ citation\ key\ and\ link=复制 citationkey 和链接 +Copy\ citation\ key\ and\ title=复制 citationkey 和标题 Copy\ to\ clipboard=复制到剪贴板 @@ -227,7 +231,7 @@ Library\ properties=文献库属性 Default=默认 -Default\ encoding=默认编码 +The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=选择的编码 '%0' 无法支持下列字符\: Downloading=正在下载 @@ -830,8 +834,6 @@ Sublibrary\ from\ AUX\ to\ BibTeX=Sublibrary from AUX to BibTeX Switches\ between\ full\ and\ abbreviated\ journal\ name\ if\ the\ journal\ name\ is\ known.=在已知的期刊名简写和全称之间切换。 -The\ chosen\ encoding\ '%0'\ could\ not\ encode\ the\ following\ characters\:=选择的编码 '%0' 无法支持下列字符\: - the\ field\ %0=字段 %0 The\ group\ "%0"\ already\ contains\ the\ selection.=分组 "%0" 中已经包含选中的项。 @@ -1297,9 +1299,7 @@ Save\ changes=保存修改 Discard\ changes=放弃修改 Library\ '%0'\ has\ changed.=文献库 '%0' 已修改。 Print\ entry\ preview=打印记录预览 -Copy\ title=复制标题 -Copy\ \\cite{citation\ key}=复制 \\cite{citation key} -Copy\ citation\ key\ and\ title=复制 ciationkey 和标题 + Invalid\ DOI\:\ '%0'.=不合法的 DOI\: Same\ DOI\ used\ in\ multiple\ entries=多个条目重复使用了相同的 DOI should\ start\ with\ a\ name=请以名称开头 @@ -1708,7 +1708,6 @@ should\ be\ normalized=应当被规范化 Empty\ search\ ID=清空搜索ID The\ given\ search\ ID\ was\ empty.=给定的搜索 ID 为空。 -Copy\ citation\ key\ and\ link=复制 citationkey 和链接 biblatex\ field\ only=仅限 biblatex 字段 Error\ while\ generating\ fetch\ URL=生成提取 URL 时出错 @@ -1852,7 +1851,6 @@ Check\ integrity=检查完整性 Cleanup\ URL\ link=清理 URL 链接 Cleanup\ URL\ link\ by\ removing\ special\ symbols\ and\ extracting\ simple\ link=通过删除特殊符号和提取简单链接来清理 URL 链接 Copy\ DOI\ url=复制 DOI -Copy\ citation=复制引用 Development\ version=开发中版本 Export\ selected\ entries=导出选中记录 Export\ selected\ entries\ to\ clipboard=将选定条目导出到剪贴板 diff --git a/src/main/resources/l10n/JabRef_zh_TW.properties b/src/main/resources/l10n/JabRef_zh_TW.properties index b1b41eccd0b..7cbee6f4d00 100644 --- a/src/main/resources/l10n/JabRef_zh_TW.properties +++ b/src/main/resources/l10n/JabRef_zh_TW.properties @@ -163,7 +163,11 @@ Copied=已複製 Copy=複製 +Copy\ title=複製標題 +Copy\ \\cite{citation\ key}=複製 \\cite{citation key} Copy\ citation\ key=複製引用鍵值(citation key) +Copy\ citation\ key\ and\ link=複製引用鍵與連結 +Copy\ citation\ key\ and\ title=複製引用鍵與標題 Copy\ to\ clipboard=複製到剪貼簿 @@ -215,7 +219,6 @@ Library\ properties=文獻倉庫屬性 Default=預設 -Default\ encoding=預設編碼 Downloading=正在下載 @@ -657,7 +660,6 @@ Status=狀態 - the\ field\ %0=欄位 %0 The\ group\ "%0"\ already\ contains\ the\ selection.=群組「%0」中已經包含選取的內容。 @@ -816,9 +818,7 @@ Opens\ JabRef's\ website=開啟 JabRef 的網站 Select\ at\ least\ one\ entry\ to\ manage\ keywords.=選中至少一則條目來管理關鍵詞 Select\ export\ format=選擇匯出格式 -Copy\ title=複製標題 -Copy\ \\cite{citation\ key}=複製 \\cite{citation key} -Copy\ citation\ key\ and\ title=複製引用鍵與標題 + Push\ to\ application=推送到應用程式 @@ -892,7 +892,6 @@ Used\ libraries=使用的函式庫 -Copy\ citation\ key\ and\ link=複製引用鍵與連結 @@ -926,7 +925,6 @@ Move\ panel\ up=上移面板 Move\ panel\ down=下移面板 Linked\ files=聯動檔案 Blog=部落格 -Copy\ citation=複製引用 Development\ version=開發版本 Export\ selected\ entries=匯出選取條目 Export\ selected\ entries\ to\ clipboard=匯出選取條目到剪貼簿 diff --git a/src/test/java/org/jabref/JabRefPreferencesTest.java b/src/test/java/org/jabref/JabRefPreferencesTest.java deleted file mode 100644 index 27f00b68298..00000000000 --- a/src/test/java/org/jabref/JabRefPreferencesTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.jabref; - -import java.nio.charset.StandardCharsets; - -import org.jabref.preferences.GeneralPreferences; -import org.jabref.preferences.JabRefPreferences; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Answers; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -class JabRefPreferencesTest { - - private JabRefPreferences prefs; - - @BeforeEach - void setUp() { - prefs = mock(JabRefPreferences.class); - GeneralPreferences generalPreferences = mock(GeneralPreferences.class, Answers.RETURNS_DEEP_STUBS); - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.UTF_8); - when(prefs.getGeneralPreferences()).thenReturn(generalPreferences); - } - - // FIXME: This test is not testing anything. prefs.getDefaultEncoding() will always return StandardCharsets.UTF_8 - // because of setUp(): when(prefs.getDefaultEnconding()).thenReturn(StandardCharsets.UTF_8); - @Test - void getDefaultEncodingReturnsPreviouslyStoredEncoding() { - // prefs.setDefaultEncoding(StandardCharsets.UTF_8); - // assertEquals(StandardCharsets.UTF_8, prefs.getDefaultEncoding()); - } -} diff --git a/src/test/java/org/jabref/gui/exporter/ExportToClipboardActionTest.java b/src/test/java/org/jabref/gui/exporter/ExportToClipboardActionTest.java index f0d1be6933d..e1f400630b9 100644 --- a/src/test/java/org/jabref/gui/exporter/ExportToClipboardActionTest.java +++ b/src/test/java/org/jabref/gui/exporter/ExportToClipboardActionTest.java @@ -1,7 +1,5 @@ package org.jabref.gui.exporter; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -94,10 +92,9 @@ public void testExecuteIfNoSelectedEntries() { @Test public void testExecuteOnSuccess() { - Exporter selectedExporter = new Exporter("html", "HTML", StandardFileType.HTML) { @Override - public void export(BibDatabaseContext databaseContext, Path file, Charset encoding, List entries) { + public void export(BibDatabaseContext databaseContext, Path file, List entries) { } }; @@ -105,7 +102,6 @@ public void export(BibDatabaseContext databaseContext, Path file, Charset encodi when(preferences.getImportExportPreferences()).thenReturn(importExportPrefs); GeneralPreferences generalPreferences = mock(GeneralPreferences.class, Answers.RETURNS_DEEP_STUBS); FilePreferences filePreferences = mock(FilePreferences.class, Answers.RETURNS_DEEP_STUBS); - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.UTF_8); when(preferences.getFilePreferences()).thenReturn(filePreferences); when(preferences.getGeneralPreferences()).thenReturn(generalPreferences); when(stateManager.getSelectedEntries()).thenReturn(selectedEntries); diff --git a/src/test/java/org/jabref/gui/exporter/SaveDatabaseActionTest.java b/src/test/java/org/jabref/gui/exporter/SaveDatabaseActionTest.java index 978867dfd28..e53ec0be4df 100644 --- a/src/test/java/org/jabref/gui/exporter/SaveDatabaseActionTest.java +++ b/src/test/java/org/jabref/gui/exporter/SaveDatabaseActionTest.java @@ -1,7 +1,6 @@ package org.jabref.gui.exporter; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.Collections; @@ -112,7 +111,6 @@ private SaveDatabaseAction createSaveDatabaseActionForBibDatabase(BibDatabase da libraryTab = mock(LibraryTab.class); MetaData metaData = mock(MetaData.class); when(savePreferences.withSaveType(any(SavePreferences.DatabaseSaveType.class))).thenReturn(savePreferences); - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.UTF_8); when(savePreferences.getFieldWriterPreferences()).thenReturn(fieldWriterPreferences); GlobalCitationKeyPattern emptyGlobalCitationKeyPattern = GlobalCitationKeyPattern.fromPattern(""); when(metaData.getCiteKeyPattern(any(GlobalCitationKeyPattern.class))).thenReturn(emptyGlobalCitationKeyPattern); diff --git a/src/test/java/org/jabref/logic/auxparser/AuxParserTest.java b/src/test/java/org/jabref/logic/auxparser/AuxParserTest.java index e171fb56ccd..7b1ecb29e4f 100644 --- a/src/test/java/org/jabref/logic/auxparser/AuxParserTest.java +++ b/src/test/java/org/jabref/logic/auxparser/AuxParserTest.java @@ -64,6 +64,33 @@ void testNormal() throws URISyntaxException, IOException { } } + @Test + void testTwoArgMacro() throws URISyntaxException, IOException { + // Result should be identical to that of testNormal + + InputStream originalStream = AuxParserTest.class.getResourceAsStream("origin.bib"); + Path auxFile = Path.of(AuxParserTest.class.getResource("papertwoargmacro.aux").toURI()); + try (InputStreamReader originalReader = new InputStreamReader(originalStream, StandardCharsets.UTF_8)) { + ParserResult result = new BibtexParser(importFormatPreferences, new DummyFileUpdateMonitor()).parse(originalReader); + + AuxParser auxParser = new DefaultAuxParser(result.getDatabase()); + AuxParserResult auxResult = auxParser.parse(auxFile); + + assertTrue(auxResult.getGeneratedBibDatabase().hasEntries()); + assertEquals(0, auxResult.getUnresolvedKeysCount()); + BibDatabase newDB = auxResult.getGeneratedBibDatabase(); + List newEntries = newDB.getEntries(); + assertEquals(2, newEntries.size()); + assertTrue(newEntries.get(0).hasChanged()); + assertTrue(newEntries.get(1).hasChanged()); + assertEquals(2, auxResult.getResolvedKeysCount()); + assertEquals(2, auxResult.getFoundKeysInAux()); + assertEquals(auxResult.getFoundKeysInAux() + auxResult.getCrossRefEntriesCount(), + auxResult.getResolvedKeysCount() + auxResult.getUnresolvedKeysCount()); + assertEquals(0, auxResult.getCrossRefEntriesCount()); + } + } + @Test void testNotAllFound() throws URISyntaxException, IOException { InputStream originalStream = AuxParserTest.class.getResourceAsStream("origin.bib"); diff --git a/src/test/java/org/jabref/logic/bibtex/BibEntryAssert.java b/src/test/java/org/jabref/logic/bibtex/BibEntryAssert.java index 4de24b84d50..360371f7142 100644 --- a/src/test/java/org/jabref/logic/bibtex/BibEntryAssert.java +++ b/src/test/java/org/jabref/logic/bibtex/BibEntryAssert.java @@ -138,7 +138,7 @@ public static void assertEquals(InputStream expectedIs, URL fileToImport, Import */ public static void assertEquals(List expected, Path fileToImport, Importer importer) throws IOException { - List actualEntries = importer.importDatabase(fileToImport, StandardCharsets.UTF_8) + List actualEntries = importer.importDatabase(fileToImport) .getDatabase().getEntries(); // explicit reference of Assertions is needed here to disambiguate from the methods defined by this class Assertions.assertEquals(expected, actualEntries); diff --git a/src/test/java/org/jabref/logic/crawler/CrawlerTest.java b/src/test/java/org/jabref/logic/crawler/CrawlerTest.java index f41c82be17e..13123472f18 100644 --- a/src/test/java/org/jabref/logic/crawler/CrawlerTest.java +++ b/src/test/java/org/jabref/logic/crawler/CrawlerTest.java @@ -1,7 +1,6 @@ package org.jabref.logic.crawler; import java.net.URL; -import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; @@ -89,7 +88,6 @@ private void setUp() throws Exception { when(savePreferences.getSaveOrder()).thenReturn(new SaveOrderConfig()); when(savePreferences.takeMetadataSaveOrderInAccount()).thenReturn(true); when(savePreferences.getCitationKeyPatternPreferences()).thenReturn(citationKeyPatternPreferences); - when(generalPreferences.getDefaultEncoding()).thenReturn(Charset.defaultCharset()); when(importFormatPreferences.getKeywordSeparator()).thenReturn(','); when(importFormatPreferences.getFieldContentFormatterPreferences()).thenReturn(new FieldContentFormatterPreferences()); entryTypesManager = new BibEntryTypesManager(); diff --git a/src/test/java/org/jabref/logic/crawler/StudyDatabaseToFetcherConverterTest.java b/src/test/java/org/jabref/logic/crawler/StudyDatabaseToFetcherConverterTest.java index 55ef69a9c62..7151bd83f77 100644 --- a/src/test/java/org/jabref/logic/crawler/StudyDatabaseToFetcherConverterTest.java +++ b/src/test/java/org/jabref/logic/crawler/StudyDatabaseToFetcherConverterTest.java @@ -1,7 +1,6 @@ package org.jabref.logic.crawler; import java.net.URL; -import java.nio.charset.Charset; import java.nio.file.Path; import java.util.List; @@ -42,7 +41,6 @@ void setUpMocks() { importFormatPreferences = mock(ImportFormatPreferences.class, Answers.RETURNS_DEEP_STUBS); savePreferences = mock(SavePreferences.class, Answers.RETURNS_DEEP_STUBS); timestampPreferences = mock(TimestampPreferences.class); - when(generalPreferences.getDefaultEncoding()).thenReturn(Charset.defaultCharset()); when(savePreferences.getSaveOrder()).thenReturn(new SaveOrderConfig()); when(savePreferences.takeMetadataSaveOrderInAccount()).thenReturn(true); when(importFormatPreferences.getKeywordSeparator()).thenReturn(','); diff --git a/src/test/java/org/jabref/logic/crawler/StudyRepositoryTest.java b/src/test/java/org/jabref/logic/crawler/StudyRepositoryTest.java index 587e68949ed..5805fe73ad8 100644 --- a/src/test/java/org/jabref/logic/crawler/StudyRepositoryTest.java +++ b/src/test/java/org/jabref/logic/crawler/StudyRepositoryTest.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.net.URL; -import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.time.LocalDate; @@ -79,7 +78,6 @@ public void setUpMocks() throws Exception { DEFAULT_UNWANTED_CHARACTERS, GlobalCitationKeyPattern.fromPattern("[auth][year]"), ','); - when(generalPreferences.getDefaultEncoding()).thenReturn(Charset.defaultCharset()); when(savePreferences.getSaveOrder()).thenReturn(new SaveOrderConfig()); when(savePreferences.takeMetadataSaveOrderInAccount()).thenReturn(true); when(savePreferences.getCitationKeyPatternPreferences()).thenReturn(citationKeyPatternPreferences); diff --git a/src/test/java/org/jabref/logic/exporter/BibTeXMLExporterTestFiles.java b/src/test/java/org/jabref/logic/exporter/BibTeXMLExporterTestFiles.java index 2e8bfa1d5a5..8dbbd117221 100644 --- a/src/test/java/org/jabref/logic/exporter/BibTeXMLExporterTestFiles.java +++ b/src/test/java/org/jabref/logic/exporter/BibTeXMLExporterTestFiles.java @@ -2,8 +2,6 @@ import java.io.IOException; import java.net.URISyntaxException; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; @@ -34,7 +32,6 @@ public class BibTeXMLExporterTestFiles { private static Path resourceDir; public BibDatabaseContext databaseContext; - public Charset charset; public Path tempFile; public BibTeXMLExporter bibtexmlExportFormat; public BibtexImporter testImporter; @@ -51,7 +48,6 @@ public static Stream fileNames() throws IOException, URISyntaxException @BeforeEach public void setUp(@TempDir Path testFolder) throws Exception { databaseContext = new BibDatabaseContext(); - charset = StandardCharsets.UTF_8; bibtexmlExportFormat = new BibTeXMLExporter(); Files.createFile(testFolder.resolve("ARandomlyNamedFile.tmp")); tempFile = testFolder.resolve("ARandomlyNamedFile.tmp"); @@ -65,10 +61,10 @@ public final void testPerformExport(String filename) throws IOException, SaveExc Path importFile = resourceDir.resolve(filename); String tempFilePath = tempFile.toAbsolutePath().toString(); - List entries = testImporter.importDatabase(importFile, StandardCharsets.UTF_8).getDatabase() + List entries = testImporter.importDatabase(importFile).getDatabase() .getEntries(); - bibtexmlExportFormat.export(databaseContext, tempFile, charset, entries); + bibtexmlExportFormat.export(databaseContext, tempFile, entries); Builder control = Input.from(Files.newInputStream(resourceDir.resolve(xmlFileName))); Builder test = Input.from(Files.newInputStream(Path.of(tempFilePath))); diff --git a/src/test/java/org/jabref/logic/exporter/BibtexDatabaseWriterTest.java b/src/test/java/org/jabref/logic/exporter/BibtexDatabaseWriterTest.java index 0a298d3d32c..648d68bcd2f 100644 --- a/src/test/java/org/jabref/logic/exporter/BibtexDatabaseWriterTest.java +++ b/src/test/java/org/jabref/logic/exporter/BibtexDatabaseWriterTest.java @@ -82,7 +82,6 @@ public class BibtexDatabaseWriterTest { @BeforeEach void setUp() { generalPreferences = mock(GeneralPreferences.class); - when(generalPreferences.getDefaultEncoding()).thenReturn(null); savePreferences = mock(SavePreferences.class, Answers.RETURNS_DEEP_STUBS); when(savePreferences.getSaveOrder()).thenReturn(new SaveOrderConfig()); when(savePreferences.takeMetadataSaveOrderInAccount()).thenReturn(true); @@ -107,18 +106,8 @@ void writeWithNullEntriesThrowsException() throws Exception { assertThrows(NullPointerException.class, () -> databaseWriter.savePartOfDatabase(bibtexContext, null)); } - @Test - void writeEncodingUsAsciiWhenSetInPreferences() throws Exception { - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.US_ASCII); - - databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList()); - - assertEquals("% Encoding: US-ASCII" + OS.NEWLINE, stringWriter.toString()); - } - @Test void writeEncodingUsAsciiWhenSetInPreferencesAndHeader() throws Exception { - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.US_ASCII); metaData.setEncoding(StandardCharsets.US_ASCII); databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList()); @@ -126,21 +115,9 @@ void writeEncodingUsAsciiWhenSetInPreferencesAndHeader() throws Exception { assertEquals("% Encoding: US-ASCII" + OS.NEWLINE, stringWriter.toString()); } - @Test - void writeEncodingWindows1252WhenSetInPreferences() throws Exception { - Charset charsetWindows1252 = Charset.forName("windows-1252"); - when(generalPreferences.getDefaultEncoding()).thenReturn(charsetWindows1252); - - databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList()); - - assertEquals("% Encoding: windows-1252" + OS.NEWLINE, stringWriter.toString()); - } - @Test void writeEncodingWindows1252WhenSetInPreferencesAndHeader() throws Exception { - Charset charsetWindows1252 = Charset.forName("windows-1252"); - when(generalPreferences.getDefaultEncoding()).thenReturn(charsetWindows1252); - metaData.setEncoding(charsetWindows1252); + metaData.setEncoding(Charset.forName("windows-1252")); databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList()); @@ -158,7 +135,7 @@ void writePreamble() throws Exception { @Test void writePreambleAndEncoding() throws Exception { - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.US_ASCII); + metaData.setEncoding(StandardCharsets.US_ASCII); database.setPreamble("Test preamble"); databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList()); @@ -182,10 +159,10 @@ void writeEntry() throws Exception { @Test void writeEncodingAndEntry() throws Exception { - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.US_ASCII); BibEntry entry = new BibEntry(); entry.setType(StandardEntryType.Article); database.insertEntry(entry); + metaData.setEncoding(StandardCharsets.US_ASCII); databaseWriter.savePartOfDatabase(bibtexContext, Collections.singletonList(entry)); @@ -207,8 +184,8 @@ void writeEpilogue() throws Exception { @Test void writeEpilogueAndEncoding() throws Exception { - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.US_ASCII); database.setEpilog("Test epilog"); + metaData.setEncoding(StandardCharsets.US_ASCII); databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList()); @@ -230,10 +207,10 @@ void writeMetadata() throws Exception { @Test void writeMetadataAndEncoding() throws Exception { - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.US_ASCII); DatabaseCitationKeyPattern bibtexKeyPattern = new DatabaseCitationKeyPattern(mock(GlobalCitationKeyPattern.class)); bibtexKeyPattern.setDefaultValue("test"); metaData.setCiteKeyPattern(bibtexKeyPattern); + metaData.setEncoding(StandardCharsets.US_ASCII); databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList()); @@ -260,11 +237,10 @@ void writeGroups() throws Exception { @Test void writeGroupsAndEncoding() throws Exception { - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.US_ASCII); - GroupTreeNode groupRoot = GroupTreeNode.fromGroup(new AllEntriesGroup("")); groupRoot.addChild(GroupTreeNode.fromGroup(new ExplicitGroup("test", GroupHierarchyType.INCLUDING, ','))); metaData.setGroups(groupRoot); + metaData.setEncoding(StandardCharsets.US_ASCII); databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList()); @@ -290,7 +266,7 @@ void writeString() throws Exception { @Test void writeStringAndEncoding() throws Exception { - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.US_ASCII); + metaData.setEncoding(StandardCharsets.US_ASCII); database.addString(new BibtexString("name", "content")); databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList()); @@ -301,7 +277,6 @@ void writeStringAndEncoding() throws Exception { @Test void doNotWriteUtf8StringAndEncoding() throws Exception { - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.UTF_8); database.addString(new BibtexString("name", "content")); databaseWriter.savePartOfDatabase(bibtexContext, Collections.emptyList()); @@ -375,9 +350,8 @@ void writeCustomizedTypesInAlphabeticalOrder() throws Exception { void roundtripWithArticleMonths() throws Exception { Path testBibtexFile = Path.of("src/test/resources/testbib/articleWithMonths.bib"); Charset encoding = StandardCharsets.UTF_8; - ParserResult result = new BibtexParser(importFormatPreferences, fileMonitor).parse(Importer.getReader(testBibtexFile, encoding)); + ParserResult result = new BibtexParser(importFormatPreferences, fileMonitor).parse(Importer.getReader(testBibtexFile)); - when(generalPreferences.getDefaultEncoding()).thenReturn(encoding); when(savePreferences.shouldSaveInOriginalOrder()).thenReturn(true); BibDatabaseContext context = new BibDatabaseContext(result.getDatabase(), result.getMetaData()); @@ -387,7 +361,6 @@ void roundtripWithArticleMonths() throws Exception { @Test void roundtripUtf8EncodingHeaderRemoved() throws Exception { - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.UTF_8); // @formatter:off String bibtexEntry = OS.NEWLINE + "% Encoding: UTF8" + OS.NEWLINE + OS.NEWLINE + @@ -414,9 +387,8 @@ void roundtripUtf8EncodingHeaderRemoved() throws Exception { @Test void roundtripWin1252HeaderKept(@TempDir Path bibFolder) throws Exception { - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.UTF_8); Path testFile = Path.of(BibtexImporterTest.class.getResource("encoding-windows-1252-with-header.bib").toURI()); - ParserResult result = new BibtexImporter(importFormatPreferences, fileMonitor).importDatabase(testFile, StandardCharsets.UTF_8); + ParserResult result = new BibtexImporter(importFormatPreferences, fileMonitor).importDatabase(testFile); BibDatabaseContext context = new BibDatabaseContext(result.getDatabase(), result.getMetaData()); Path pathToFile = bibFolder.resolve("JabRef.bib"); @@ -436,9 +408,8 @@ void roundtripWin1252HeaderKept(@TempDir Path bibFolder) throws Exception { void roundtripWithComplexBib() throws Exception { Path testBibtexFile = Path.of("src/test/resources/testbib/complex.bib"); Charset encoding = StandardCharsets.UTF_8; - ParserResult result = new BibtexParser(importFormatPreferences, fileMonitor).parse(Importer.getReader(testBibtexFile, encoding)); + ParserResult result = new BibtexParser(importFormatPreferences, fileMonitor).parse(Importer.getReader(testBibtexFile)); - when(generalPreferences.getDefaultEncoding()).thenReturn(encoding); when(savePreferences.shouldSaveInOriginalOrder()).thenReturn(true); BibDatabaseContext context = new BibDatabaseContext(result.getDatabase(), result.getMetaData()); @@ -450,9 +421,8 @@ void roundtripWithComplexBib() throws Exception { void roundtripWithUserComment() throws Exception { Path testBibtexFile = Path.of("src/test/resources/testbib/bibWithUserComments.bib"); Charset encoding = StandardCharsets.UTF_8; - ParserResult result = new BibtexParser(importFormatPreferences, fileMonitor).parse(Importer.getReader(testBibtexFile, encoding)); + ParserResult result = new BibtexParser(importFormatPreferences, fileMonitor).parse(Importer.getReader(testBibtexFile)); - when(generalPreferences.getDefaultEncoding()).thenReturn(encoding); when(savePreferences.shouldSaveInOriginalOrder()).thenReturn(true); BibDatabaseContext context = new BibDatabaseContext(result.getDatabase(), result.getMetaData()); @@ -477,7 +447,6 @@ void roundtripWithOneUserCommentAndEntryChange() throws Exception { BibEntry entry = result.getDatabase().getEntryByCitationKey("1137631").get(); entry.setField(StandardField.AUTHOR, "Mr. Author"); - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.UTF_8); when(savePreferences.shouldSaveInOriginalOrder()).thenReturn(true); BibDatabaseContext context = new BibDatabaseContext(result.getDatabase(), result.getMetaData()); @@ -507,7 +476,6 @@ void roundtripWithTwoEntriesAndOneUserCommentAndEntryChange() throws Exception { BibEntry entry = result.getDatabase().getEntryByCitationKey("1137631").get(); entry.setField(StandardField.AUTHOR, "Mr. Author"); - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.UTF_8); when(savePreferences.shouldSaveInOriginalOrder()).thenReturn(true); BibDatabaseContext context = new BibDatabaseContext(result.getDatabase(), result.getMetaData()); @@ -522,12 +490,11 @@ void roundtripWithTwoEntriesAndOneUserCommentAndEntryChange() throws Exception { void roundtripWithUserCommentAndEntryChange() throws Exception { Path testBibtexFile = Path.of("src/test/resources/testbib/bibWithUserComments.bib"); Charset encoding = StandardCharsets.UTF_8; - ParserResult result = new BibtexParser(importFormatPreferences, fileMonitor).parse(Importer.getReader(testBibtexFile, encoding)); + ParserResult result = new BibtexParser(importFormatPreferences, fileMonitor).parse(Importer.getReader(testBibtexFile)); BibEntry entry = result.getDatabase().getEntryByCitationKey("1137631").get(); entry.setField(StandardField.AUTHOR, "Mr. Author"); - when(generalPreferences.getDefaultEncoding()).thenReturn(encoding); when(savePreferences.shouldSaveInOriginalOrder()).thenReturn(true); BibDatabaseContext context = new BibDatabaseContext(result.getDatabase(), result.getMetaData()); @@ -539,14 +506,13 @@ void roundtripWithUserCommentAndEntryChange() throws Exception { void roundtripWithUserCommentBeforeStringAndChange() throws Exception { Path testBibtexFile = Path.of("src/test/resources/testbib/complex.bib"); Charset encoding = StandardCharsets.UTF_8; - ParserResult result = new BibtexParser(importFormatPreferences, fileMonitor).parse(Importer.getReader(testBibtexFile, encoding)); + ParserResult result = new BibtexParser(importFormatPreferences, fileMonitor).parse(Importer.getReader(testBibtexFile)); for (BibtexString string : result.getDatabase().getStringValues()) { // Mark them as changed string.setContent(string.getContent()); } - when(generalPreferences.getDefaultEncoding()).thenReturn(encoding); when(savePreferences.shouldSaveInOriginalOrder()).thenReturn(true); BibDatabaseContext context = new BibDatabaseContext(result.getDatabase(), result.getMetaData()); @@ -559,9 +525,8 @@ void roundtripWithUserCommentBeforeStringAndChange() throws Exception { void roundtripWithUnknownMetaData() throws Exception { Path testBibtexFile = Path.of("src/test/resources/testbib/unknownMetaData.bib"); Charset encoding = StandardCharsets.UTF_8; - ParserResult result = new BibtexParser(importFormatPreferences, fileMonitor).parse(Importer.getReader(testBibtexFile, encoding)); + ParserResult result = new BibtexParser(importFormatPreferences, fileMonitor).parse(Importer.getReader(testBibtexFile)); - when(generalPreferences.getDefaultEncoding()).thenReturn(encoding); when(savePreferences.shouldSaveInOriginalOrder()).thenReturn(true); BibDatabaseContext context = new BibDatabaseContext(result.getDatabase(), result.getMetaData()); @@ -829,7 +794,6 @@ void roundtripWithContentSelectorsAndUmlauts() throws Exception { ParserResult firstParse = new BibtexParser(importFormatPreferences, fileMonitor).parse(new StringReader(fileContent)); - when(generalPreferences.getDefaultEncoding()).thenReturn(encoding); when(savePreferences.shouldSaveInOriginalOrder()).thenReturn(true); BibDatabaseContext context = new BibDatabaseContext(firstParse.getDatabase(), firstParse.getMetaData()); diff --git a/src/test/java/org/jabref/logic/exporter/CsvExportFormatTest.java b/src/test/java/org/jabref/logic/exporter/CsvExportFormatTest.java index d641b1a7e59..584f73e109f 100644 --- a/src/test/java/org/jabref/logic/exporter/CsvExportFormatTest.java +++ b/src/test/java/org/jabref/logic/exporter/CsvExportFormatTest.java @@ -1,8 +1,6 @@ package org.jabref.logic.exporter; import java.io.File; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -29,7 +27,6 @@ public class CsvExportFormatTest { public BibDatabaseContext databaseContext; - public Charset charset; private Exporter exportFormat; @BeforeEach @@ -44,7 +41,6 @@ public void setUp() { exportFormat = exporterFactory.getExporterByName("oocsv").get(); databaseContext = new BibDatabaseContext(); - charset = StandardCharsets.UTF_8; } @AfterEach @@ -60,7 +56,7 @@ public void testPerformExportForSingleAuthor(@TempDir Path testFolder) throws Ex entry.setField(StandardField.AUTHOR, "Someone, Van Something"); List entries = Arrays.asList(entry); - exportFormat.export(databaseContext, path, charset, entries); + exportFormat.export(databaseContext, path, entries); List lines = Files.readAllLines(path); assertEquals(2, lines.size()); @@ -77,7 +73,7 @@ public void testPerformExportForMultipleAuthors(@TempDir Path testFolder) throws entry.setField(StandardField.AUTHOR, "von Neumann, John and Smith, John and Black Brown, Peter"); List entries = Arrays.asList(entry); - exportFormat.export(databaseContext, path, charset, entries); + exportFormat.export(databaseContext, path, entries); List lines = Files.readAllLines(path); assertEquals(2, lines.size()); @@ -94,7 +90,7 @@ public void testPerformExportForSingleEditor(@TempDir Path testFolder) throws Ex entry.setField(StandardField.EDITOR, "Someone, Van Something"); List entries = Arrays.asList(entry); - exportFormat.export(databaseContext, tmpFile.toPath(), charset, entries); + exportFormat.export(databaseContext, tmpFile.toPath(), entries); List lines = Files.readAllLines(tmpFile.toPath()); assertEquals(2, lines.size()); @@ -111,7 +107,7 @@ public void testPerformExportForMultipleEditors(@TempDir Path testFolder) throws entry.setField(StandardField.EDITOR, "von Neumann, John and Smith, John and Black Brown, Peter"); List entries = Arrays.asList(entry); - exportFormat.export(databaseContext, tmpFile.toPath(), charset, entries); + exportFormat.export(databaseContext, tmpFile.toPath(), entries); List lines = Files.readAllLines(tmpFile.toPath()); assertEquals(2, lines.size()); diff --git a/src/test/java/org/jabref/logic/exporter/DocBook5ExporterTest.java b/src/test/java/org/jabref/logic/exporter/DocBook5ExporterTest.java index e6baf19f1cb..34e6838a8ab 100644 --- a/src/test/java/org/jabref/logic/exporter/DocBook5ExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/DocBook5ExporterTest.java @@ -71,7 +71,7 @@ void setUp() throws URISyntaxException { void testPerformExportForSingleEntry(@TempDir Path testFolder) throws Exception { Path path = testFolder.resolve("ThisIsARandomlyNamedFile"); - exporter.export(databaseContext, path, charset, entries); + exporter.export(databaseContext, path, entries); Builder control = Input.from(Files.newInputStream(xmlFile)); Builder test = Input.from(Files.newInputStream(path)); diff --git a/src/test/java/org/jabref/logic/exporter/DocbookExporterTest.java b/src/test/java/org/jabref/logic/exporter/DocbookExporterTest.java index 39246058eeb..83f40656623 100644 --- a/src/test/java/org/jabref/logic/exporter/DocbookExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/DocbookExporterTest.java @@ -52,7 +52,7 @@ public void testCorruptedTitleBraces(@TempDir Path testFolder) throws Exception List entries = Arrays.asList(entry); - exportFormat.export(databaseContext, tmpFile, charset, entries); + exportFormat.export(databaseContext, tmpFile, entries); List lines = Files.readAllLines(tmpFile); assertEquals(20, lines.size()); @@ -68,7 +68,7 @@ public void testCorruptedTitleUnicode(@TempDir Path testFolder) throws Exception List entries = Arrays.asList(entry); - exportFormat.export(databaseContext, tmpFile, charset, entries); + exportFormat.export(databaseContext, tmpFile, entries); List lines = Files.readAllLines(tmpFile); assertEquals(20, lines.size()); diff --git a/src/test/java/org/jabref/logic/exporter/EmbeddedBibFilePdfExporterTest.java b/src/test/java/org/jabref/logic/exporter/EmbeddedBibFilePdfExporterTest.java index 5ec6811977a..e2e4ee62323 100644 --- a/src/test/java/org/jabref/logic/exporter/EmbeddedBibFilePdfExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/EmbeddedBibFilePdfExporterTest.java @@ -132,13 +132,13 @@ void setUp() throws IOException { @ParameterizedTest @MethodSource("provideBibEntriesWithValidPdfFileLinks") void successfulExportToAllFilesOfEntry(BibEntry bibEntryWithValidPdfFileLink) throws Exception { - assertTrue(exporter.exportToAllFilesOfEntry(databaseContext, encoding, filePreferences, bibEntryWithValidPdfFileLink, Arrays.asList(olly2018))); + assertTrue(exporter.exportToAllFilesOfEntry(databaseContext, filePreferences, bibEntryWithValidPdfFileLink, Arrays.asList(olly2018))); } @ParameterizedTest @MethodSource("provideBibEntriesWithInvalidPdfFileLinks") void unsuccessfulExportToAllFilesOfEntry(BibEntry bibEntryWithValidPdfFileLink) throws Exception { - assertFalse(exporter.exportToAllFilesOfEntry(databaseContext, encoding, filePreferences, bibEntryWithValidPdfFileLink, Arrays.asList(olly2018))); + assertFalse(exporter.exportToAllFilesOfEntry(databaseContext, filePreferences, bibEntryWithValidPdfFileLink, Arrays.asList(olly2018))); } public static Stream provideBibEntriesWithValidPdfFileLinks() { @@ -152,13 +152,13 @@ public static Stream provideBibEntriesWithInvalidPdfFileLinks() { @ParameterizedTest @MethodSource("providePathsToValidPDFs") void successfulExportToFileByPath(Path path) throws Exception { - assertTrue(exporter.exportToFileByPath(databaseContext, dataBase, encoding, filePreferences, path)); + assertTrue(exporter.exportToFileByPath(databaseContext, dataBase, filePreferences, path)); } @ParameterizedTest @MethodSource("providePathsToInvalidPDFs") void unsuccessfulExportToFileByPath(Path path) throws Exception { - assertFalse(exporter.exportToFileByPath(databaseContext, dataBase, encoding, filePreferences, path)); + assertFalse(exporter.exportToFileByPath(databaseContext, dataBase, filePreferences, path)); } public static Stream providePathsToValidPDFs() { diff --git a/src/test/java/org/jabref/logic/exporter/ExporterTest.java b/src/test/java/org/jabref/logic/exporter/ExporterTest.java index 34d1d5b1477..fddc690af10 100644 --- a/src/test/java/org/jabref/logic/exporter/ExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/ExporterTest.java @@ -66,7 +66,7 @@ private static Stream exportFormats() { public void testExportingEmptyDatabaseYieldsEmptyFile(Exporter exportFormat, String name, @TempDir Path testFolder) throws Exception { Path tmpFile = testFolder.resolve("ARandomlyNamedFile"); Files.createFile(tmpFile); - exportFormat.export(databaseContext, tmpFile, charset, entries); + exportFormat.export(databaseContext, tmpFile, entries); assertEquals(Collections.emptyList(), Files.readAllLines(tmpFile)); } @@ -76,17 +76,7 @@ public void testExportingNullDatabaseThrowsNPE(Exporter exportFormat, String nam assertThrows(NullPointerException.class, () -> { Path tmpFile = testFolder.resolve("ARandomlyNamedFile"); Files.createFile(tmpFile); - exportFormat.export(null, tmpFile, charset, entries); - }); - } - - @ParameterizedTest - @MethodSource("exportFormats") - public void testExportingNullEntriesThrowsNPE(Exporter exportFormat, String name, @TempDir Path testFolder) { - assertThrows(NullPointerException.class, () -> { - Path tmpFile = testFolder.resolve("ARandomlyNamedFile"); - Files.createFile(tmpFile); - exportFormat.export(databaseContext, tmpFile, charset, null); + exportFormat.export(null, tmpFile, entries); }); } } diff --git a/src/test/java/org/jabref/logic/exporter/HtmlExportFormatTest.java b/src/test/java/org/jabref/logic/exporter/HtmlExportFormatTest.java index 821b9f4933b..b0157678ecd 100644 --- a/src/test/java/org/jabref/logic/exporter/HtmlExportFormatTest.java +++ b/src/test/java/org/jabref/logic/exporter/HtmlExportFormatTest.java @@ -59,7 +59,7 @@ public void tearDown() { @Test public void emitWellFormedHtml(@TempDir Path testFolder) throws Exception { Path path = testFolder.resolve("ThisIsARandomlyNamedFile"); - exportFormat.export(databaseContext, path, charset, entries); + exportFormat.export(databaseContext, path, entries); List lines = Files.readAllLines(path); assertEquals("", lines.get(lines.size() - 1)); } diff --git a/src/test/java/org/jabref/logic/exporter/MSBibExportFormatTestFiles.java b/src/test/java/org/jabref/logic/exporter/MSBibExportFormatTestFiles.java index b5791ce3076..11de4f34588 100644 --- a/src/test/java/org/jabref/logic/exporter/MSBibExportFormatTestFiles.java +++ b/src/test/java/org/jabref/logic/exporter/MSBibExportFormatTestFiles.java @@ -66,11 +66,11 @@ void testPerformExport(String filename) throws IOException, SaveException { Path expectedFile = resourceDir.resolve(xmlFileName); Path importFile = resourceDir.resolve(filename); - List entries = testImporter.importDatabase(importFile, StandardCharsets.UTF_8) + List entries = testImporter.importDatabase(importFile) .getDatabase() .getEntries(); - exporter.export(databaseContext, exportedFile, charset, entries); + exporter.export(databaseContext, exportedFile, entries); String expected = String.join("\n", Files.readAllLines(expectedFile)); String actual = String.join("\n", Files.readAllLines(exportedFile)); diff --git a/src/test/java/org/jabref/logic/exporter/ModsExportFormatTest.java b/src/test/java/org/jabref/logic/exporter/ModsExportFormatTest.java index d205b4ce235..cf98c1764af 100644 --- a/src/test/java/org/jabref/logic/exporter/ModsExportFormatTest.java +++ b/src/test/java/org/jabref/logic/exporter/ModsExportFormatTest.java @@ -1,7 +1,5 @@ package org.jabref.logic.exporter; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.Collections; @@ -21,14 +19,12 @@ public class ModsExportFormatTest { - public Charset charset; private ModsExporter modsExportFormat; private BibDatabaseContext databaseContext; @BeforeEach public void setUp() throws Exception { databaseContext = new BibDatabaseContext(); - charset = StandardCharsets.UTF_8; modsExportFormat = new ModsExporter(); new BibtexImporter(mock(ImportFormatPreferences.class, Answers.RETURNS_DEEP_STUBS), new DummyFileUpdateMonitor()); Path.of(ModsExportFormatTest.class.getResource("ModsExportFormatTestAllFields.bib").toURI()); @@ -38,7 +34,7 @@ public void setUp() throws Exception { public final void exportForNoEntriesWritesNothing(@TempDir Path tempFile) throws Exception { Path file = tempFile.resolve("ThisIsARandomlyNamedFile"); Files.createFile(file); - modsExportFormat.export(databaseContext, tempFile, charset, Collections.emptyList()); + modsExportFormat.export(databaseContext, tempFile, Collections.emptyList()); assertEquals(Collections.emptyList(), Files.readAllLines(file)); } } diff --git a/src/test/java/org/jabref/logic/exporter/ModsExportFormatTestFiles.java b/src/test/java/org/jabref/logic/exporter/ModsExportFormatTestFiles.java index 5820f344daa..22f33319112 100644 --- a/src/test/java/org/jabref/logic/exporter/ModsExportFormatTestFiles.java +++ b/src/test/java/org/jabref/logic/exporter/ModsExportFormatTestFiles.java @@ -67,10 +67,10 @@ public void setUp(@TempDir Path testFolder) throws Exception { public final void testPerformExport(String filename) throws Exception { importFile = Path.of(ModsExportFormatTestFiles.class.getResource(filename).toURI()); String xmlFileName = filename.replace(".bib", ".xml"); - List entries = bibtexImporter.importDatabase(importFile, charset).getDatabase().getEntries(); + List entries = bibtexImporter.importDatabase(importFile).getDatabase().getEntries(); Path expectedFile = Path.of(ModsExportFormatTestFiles.class.getResource(xmlFileName).toURI()); - exporter.export(databaseContext, exportedFile, charset, entries); + exporter.export(databaseContext, exportedFile, entries); assertEquals( String.join("\n", Files.readAllLines(expectedFile)), @@ -81,9 +81,9 @@ public final void testPerformExport(String filename) throws Exception { @MethodSource("fileNames") public final void testExportAsModsAndThenImportAsMods(String filename) throws Exception { importFile = Path.of(ModsExportFormatTestFiles.class.getResource(filename).toURI()); - List entries = bibtexImporter.importDatabase(importFile, charset).getDatabase().getEntries(); + List entries = bibtexImporter.importDatabase(importFile).getDatabase().getEntries(); - exporter.export(databaseContext, exportedFile, charset, entries); + exporter.export(databaseContext, exportedFile, entries); BibEntryAssert.assertEquals(entries, exportedFile, modsImporter); } @@ -94,9 +94,9 @@ public final void testImportAsModsAndExportAsMods(String filename) throws Except String xmlFileName = filename.replace(".bib", ".xml"); Path xmlFile = Path.of(ModsExportFormatTestFiles.class.getResource(xmlFileName).toURI()); - List entries = modsImporter.importDatabase(xmlFile, charset).getDatabase().getEntries(); + List entries = modsImporter.importDatabase(xmlFile).getDatabase().getEntries(); - exporter.export(databaseContext, exportedFile, charset, entries); + exporter.export(databaseContext, exportedFile, entries); assertEquals( String.join("\n", Files.readAllLines(xmlFile)), diff --git a/src/test/java/org/jabref/logic/exporter/MsBibExportFormatTest.java b/src/test/java/org/jabref/logic/exporter/MsBibExportFormatTest.java index 9ddbe119d73..7be464fc9a6 100644 --- a/src/test/java/org/jabref/logic/exporter/MsBibExportFormatTest.java +++ b/src/test/java/org/jabref/logic/exporter/MsBibExportFormatTest.java @@ -1,8 +1,6 @@ package org.jabref.logic.exporter; import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.Collections; @@ -20,13 +18,11 @@ public class MsBibExportFormatTest { public BibDatabaseContext databaseContext; - public Charset charset; public MSBibExporter msBibExportFormat; @BeforeEach public void setUp() throws Exception { databaseContext = new BibDatabaseContext(); - charset = StandardCharsets.UTF_8; msBibExportFormat = new MSBibExporter(); } @@ -35,7 +31,7 @@ public final void testPerformExportWithNoEntry(@TempDir Path tempFile) throws IO Path path = tempFile.resolve("ThisIsARandomlyNamedFile"); Files.createFile(path); List entries = Collections.emptyList(); - msBibExportFormat.export(databaseContext, path, charset, entries); + msBibExportFormat.export(databaseContext, path, entries); assertEquals(Collections.emptyList(), Files.readAllLines(path)); } } diff --git a/src/test/java/org/jabref/logic/exporter/OpenOfficeDocumentCreatorTest.java b/src/test/java/org/jabref/logic/exporter/OpenOfficeDocumentCreatorTest.java index 95d1994e607..1c5ebf0cbc8 100644 --- a/src/test/java/org/jabref/logic/exporter/OpenOfficeDocumentCreatorTest.java +++ b/src/test/java/org/jabref/logic/exporter/OpenOfficeDocumentCreatorTest.java @@ -81,7 +81,7 @@ void setUp() throws URISyntaxException { void testPerformExportForSingleEntry(@TempDir Path testFolder) throws Exception { Path zipPath = testFolder.resolve("OpenOfficeRandomNamedFile"); - exporter.export(databaseContext, zipPath, charset, entries); + exporter.export(databaseContext, zipPath, entries); Path unzipFolder = testFolder.resolve("unzipFolder"); unzipContentXml(zipPath, testFolder.resolve(unzipFolder)); diff --git a/src/test/java/org/jabref/logic/exporter/XmpExporterTest.java b/src/test/java/org/jabref/logic/exporter/XmpExporterTest.java index fa316547047..84af17aed90 100644 --- a/src/test/java/org/jabref/logic/exporter/XmpExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/XmpExporterTest.java @@ -1,7 +1,5 @@ package org.jabref.logic.exporter; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; @@ -27,7 +25,6 @@ public class XmpExporterTest { private Exporter exporter; private BibDatabaseContext databaseContext; - private Charset encoding; private final XmpPreferences xmpPreferences = mock(XmpPreferences.class); @BeforeEach @@ -35,7 +32,6 @@ public void setUp() { exporter = new XmpExporter(xmpPreferences); databaseContext = new BibDatabaseContext(); - encoding = StandardCharsets.UTF_8; } @Test @@ -46,7 +42,7 @@ public void exportSingleEntry(@TempDir Path testFolder) throws Exception { BibEntry entry = new BibEntry(); entry.setField(StandardField.AUTHOR, "Alan Turing"); - exporter.export(databaseContext, file, encoding, Collections.singletonList(entry)); + exporter.export(databaseContext, file, Collections.singletonList(entry)); String actual = String.join("\n", Files.readAllLines(file)); // we are using \n to join, so we need it in the expected string as well, \r\n would fail String expected = " \n" + " \n" + @@ -78,7 +74,7 @@ public void writeMultipleEntriesInASingleFile(@TempDir Path testFolder) throws E entryArmbrust.setField(StandardField.AUTHOR, "Michael Armbrust"); entryArmbrust.setCitationKey("Armbrust2010"); - exporter.export(databaseContext, file, encoding, Arrays.asList(entryTuring, entryArmbrust)); + exporter.export(databaseContext, file, Arrays.asList(entryTuring, entryArmbrust)); String actual = String.join("\n", Files.readAllLines(file)); // we are using \n to join, so we need it in the expected string as well, \r\n would fail @@ -131,7 +127,7 @@ public void writeMultipleEntriesInDifferentFiles(@TempDir Path testFolder) throw .withField(StandardField.AUTHOR, "Michael Armbrust") .withCitationKey("Armbrust2010"); - exporter.export(databaseContext, file, encoding, List.of(entryTuring, entryArmbrust)); + exporter.export(databaseContext, file, List.of(entryTuring, entryArmbrust)); List lines = Files.readAllLines(file); assertEquals(Collections.emptyList(), lines); @@ -195,7 +191,7 @@ public void exportSingleEntryWithPrivacyFilter(@TempDir Path testFolder) throws BibEntry entry = new BibEntry(); entry.setField(StandardField.AUTHOR, "Alan Turing"); - exporter.export(databaseContext, file, encoding, Collections.singletonList(entry)); + exporter.export(databaseContext, file, Collections.singletonList(entry)); String actual = String.join("\n", Files.readAllLines(file)); String expected = " \n" + " \n" + diff --git a/src/test/java/org/jabref/logic/exporter/XmpPdfExporterTest.java b/src/test/java/org/jabref/logic/exporter/XmpPdfExporterTest.java index c6eee8dcd82..acfe7457bed 100644 --- a/src/test/java/org/jabref/logic/exporter/XmpPdfExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/XmpPdfExporterTest.java @@ -121,13 +121,13 @@ void setUp() throws IOException { @ParameterizedTest @MethodSource("provideBibEntriesWithValidPdfFileLinks") void successfulExportToAllFilesOfEntry(BibEntry bibEntryWithValidPdfFileLink) throws Exception { - assertTrue(exporter.exportToAllFilesOfEntry(databaseContext, encoding, filePreferences, bibEntryWithValidPdfFileLink, List.of(olly2018))); + assertTrue(exporter.exportToAllFilesOfEntry(databaseContext, filePreferences, bibEntryWithValidPdfFileLink, List.of(olly2018))); } @ParameterizedTest @MethodSource("provideBibEntriesWithInvalidPdfFileLinks") void unsuccessfulExportToAllFilesOfEntry(BibEntry bibEntryWithValidPdfFileLink) throws Exception { - assertFalse(exporter.exportToAllFilesOfEntry(databaseContext, encoding, filePreferences, bibEntryWithValidPdfFileLink, List.of(olly2018))); + assertFalse(exporter.exportToAllFilesOfEntry(databaseContext, filePreferences, bibEntryWithValidPdfFileLink, List.of(olly2018))); } public static Stream provideBibEntriesWithValidPdfFileLinks() { @@ -141,13 +141,13 @@ public static Stream provideBibEntriesWithInvalidPdfFileLinks() { @ParameterizedTest @MethodSource("providePathsToValidPDFs") void successfulExportToFileByPath(Path path) throws Exception { - assertTrue(exporter.exportToFileByPath(databaseContext, dataBase, encoding, filePreferences, path)); + assertTrue(exporter.exportToFileByPath(databaseContext, dataBase, filePreferences, path)); } @ParameterizedTest @MethodSource("providePathsToInvalidPDFs") void unsuccessfulExportToFileByPath(Path path) throws Exception { - assertFalse(exporter.exportToFileByPath(databaseContext, dataBase, encoding, filePreferences, path)); + assertFalse(exporter.exportToFileByPath(databaseContext, dataBase, filePreferences, path)); } public static Stream providePathsToValidPDFs() { diff --git a/src/test/java/org/jabref/logic/exporter/YamlExporterTest.java b/src/test/java/org/jabref/logic/exporter/YamlExporterTest.java index dcef2c1e12e..6474a97d490 100644 --- a/src/test/java/org/jabref/logic/exporter/YamlExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/YamlExporterTest.java @@ -49,7 +49,7 @@ static void setUp() { public final void exportForNoEntriesWritesNothing(@TempDir Path tempFile) throws Exception { Path file = tempFile.resolve("ThisIsARandomlyNamedFile"); Files.createFile(file); - yamlExporter.export(databaseContext, tempFile, charset, Collections.emptyList()); + yamlExporter.export(databaseContext, tempFile, Collections.emptyList()); assertEquals(Collections.emptyList(), Files.readAllLines(file)); } @@ -64,7 +64,7 @@ public final void exportsCorrectContent(@TempDir Path tempFile) throws Exception Path file = tempFile.resolve("RandomFileName"); Files.createFile(file); - yamlExporter.export(databaseContext, file, charset, Collections.singletonList(entry)); + yamlExporter.export(databaseContext, file, Collections.singletonList(entry)); List expected = List.of( "---", @@ -92,7 +92,7 @@ public final void formatsContentCorrect(@TempDir Path tempFile) throws Exception Path file = tempFile.resolve("RandomFileName"); Files.createFile(file); - yamlExporter.export(databaseContext, file, charset, Collections.singletonList(entry)); + yamlExporter.export(databaseContext, file, Collections.singletonList(entry)); List expected = List.of( "---", @@ -120,7 +120,7 @@ void passesModifiedCharset(@TempDir Path tempFile) throws Exception { Path file = tempFile.resolve("RandomFileName"); Files.createFile(file); - yamlExporter.export(databaseContext, file, StandardCharsets.UTF_8, Collections.singletonList(entry)); + yamlExporter.export(databaseContext, file, Collections.singletonList(entry)); List expected = List.of( "---", @@ -148,7 +148,7 @@ void passesModifiedCharsetNull(@TempDir Path tempFile) throws Exception { Path file = tempFile.resolve("RandomFileName"); Files.createFile(file); - yamlExporter.export(databaseContext, file, null, Collections.singletonList(entry)); + yamlExporter.export(databaseContext, file, Collections.singletonList(entry)); List expected = List.of( "---", @@ -161,36 +161,6 @@ void passesModifiedCharsetNull(@TempDir Path tempFile) throws Exception { " issued: 2020-10-14", " url: http://example.com", "---"); - - assertEquals(expected, Files.readAllLines(file)); - } - - @Test - void passesModifiedCharsetASCII(@TempDir Path tempFile) throws Exception { - BibEntry entry = new BibEntry(StandardEntryType.Article) - .withCitationKey("test") - .withField(StandardField.AUTHOR, "谷崎 潤一郎") - .withField(StandardField.TITLE, "細雪") - .withField(StandardField.URL, "http://example.com") - .withField(StandardField.DATE, "2020-10-14"); - - Path file = tempFile.resolve("RandomFileName"); - Files.createFile(file); - yamlExporter.export(databaseContext, file, StandardCharsets.US_ASCII, Collections.singletonList(entry)); - - List expected = List.of( - "---", - "references:", - "- id: test", - " type: article", - " author:", - " - literal: \"?? ???\"", - " title: \"??\"", - " issued: 2020-10-14", - " url: http://example.com", - "---"); - assertEquals(expected, Files.readAllLines(file)); - } } diff --git a/src/test/java/org/jabref/logic/importer/DatabaseFileLookupTest.java b/src/test/java/org/jabref/logic/importer/DatabaseFileLookupTest.java index 330d2dd22ba..e4990202d1e 100644 --- a/src/test/java/org/jabref/logic/importer/DatabaseFileLookupTest.java +++ b/src/test/java/org/jabref/logic/importer/DatabaseFileLookupTest.java @@ -1,6 +1,5 @@ package org.jabref.logic.importer; -import java.nio.charset.StandardCharsets; import java.util.Collection; import org.jabref.logic.importer.fileformat.BibtexImporter; @@ -27,7 +26,7 @@ class DatabaseFileLookupTest { @BeforeEach void setUp() throws Exception { ParserResult result = new BibtexImporter(mock(ImportFormatPreferences.class, Answers.RETURNS_DEEP_STUBS), new DummyFileUpdateMonitor()) - .importDatabase(ImportDataTest.UNLINKED_FILES_TEST_BIB, StandardCharsets.UTF_8); + .importDatabase(ImportDataTest.UNLINKED_FILES_TEST_BIB); database = result.getDatabase(); entries = database.getEntries(); diff --git a/src/test/java/org/jabref/logic/importer/ImportFormatReaderIntegrationTest.java b/src/test/java/org/jabref/logic/importer/ImportFormatReaderIntegrationTest.java index 16f7dfd36c0..e7f45023830 100644 --- a/src/test/java/org/jabref/logic/importer/ImportFormatReaderIntegrationTest.java +++ b/src/test/java/org/jabref/logic/importer/ImportFormatReaderIntegrationTest.java @@ -1,6 +1,5 @@ package org.jabref.logic.importer; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -31,7 +30,6 @@ void setUp() { ImportFormatPreferences importFormatPreferences = mock(ImportFormatPreferences.class, Answers.RETURNS_DEEP_STUBS); when(importFormatPreferences.getCustomImportList()).thenReturn(Set.of()); GeneralPreferences generalPreferences = mock(GeneralPreferences.class, Answers.RETURNS_DEEP_STUBS); - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.UTF_8); reader.resetImportFormats(mock(ImporterPreferences.class), generalPreferences, importFormatPreferences, mock(XmpPreferences.class), new DummyFileUpdateMonitor()); } diff --git a/src/test/java/org/jabref/logic/importer/ImportFormatReaderTestParameterless.java b/src/test/java/org/jabref/logic/importer/ImportFormatReaderTestParameterless.java index 7cd43538bc6..4f867e05141 100644 --- a/src/test/java/org/jabref/logic/importer/ImportFormatReaderTestParameterless.java +++ b/src/test/java/org/jabref/logic/importer/ImportFormatReaderTestParameterless.java @@ -1,6 +1,5 @@ package org.jabref.logic.importer; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Set; @@ -26,7 +25,6 @@ class ImportFormatReaderTestParameterless { void setUp() { reader = new ImportFormatReader(); GeneralPreferences generalPreferences = mock(GeneralPreferences.class, Answers.RETURNS_DEEP_STUBS); - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.UTF_8); ImportFormatPreferences importFormatPreferences = mock(ImportFormatPreferences.class, Answers.RETURNS_DEEP_STUBS); when(importFormatPreferences.getCustomImportList()).thenReturn(Set.of()); reader.resetImportFormats(mock(ImporterPreferences.class), generalPreferences, importFormatPreferences, mock(XmpPreferences.class), fileMonitor); diff --git a/src/test/java/org/jabref/logic/importer/OpenDatabaseTest.java b/src/test/java/org/jabref/logic/importer/OpenDatabaseTest.java index 222f68e809a..d5fe3876d4b 100644 --- a/src/test/java/org/jabref/logic/importer/OpenDatabaseTest.java +++ b/src/test/java/org/jabref/logic/importer/OpenDatabaseTest.java @@ -21,7 +21,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; class OpenDatabaseTest { @@ -46,39 +45,36 @@ class OpenDatabaseTest { @BeforeEach void setUp() { generalPreferences = mock(GeneralPreferences.class, Answers.RETURNS_DEEP_STUBS); - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.UTF_8); importFormatPreferences = mock(ImportFormatPreferences.class, Answers.RETURNS_DEEP_STUBS); } @Test void useFallbackEncodingIfNoHeader() throws IOException { - ParserResult result = OpenDatabase.loadDatabase(bibNoHeader, generalPreferences, importFormatPreferences, fileMonitor); + ParserResult result = OpenDatabase.loadDatabase(bibNoHeader, importFormatPreferences, fileMonitor); assertEquals(defaultEncoding, result.getMetaData().getEncoding().get()); } @Test void useFallbackEncodingIfUnknownHeader() throws IOException { - ParserResult result = OpenDatabase.loadDatabase(bibWrongHeader, generalPreferences, importFormatPreferences, fileMonitor); + ParserResult result = OpenDatabase.loadDatabase(bibWrongHeader, importFormatPreferences, fileMonitor); assertEquals(defaultEncoding, result.getMetaData().getEncoding().get()); } @Test void useSpecifiedEncoding() throws IOException { - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.US_ASCII); - ParserResult result = OpenDatabase.loadDatabase(bibHeader, generalPreferences, importFormatPreferences, fileMonitor); + ParserResult result = OpenDatabase.loadDatabase(bibHeader, importFormatPreferences, fileMonitor); assertEquals(defaultEncoding, result.getMetaData().getEncoding().get()); } @Test void useSpecifiedEncodingWithSignature() throws IOException { - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.US_ASCII); - ParserResult result = OpenDatabase.loadDatabase(bibHeaderAndSignature, generalPreferences, importFormatPreferences, fileMonitor); + ParserResult result = OpenDatabase.loadDatabase(bibHeaderAndSignature, importFormatPreferences, fileMonitor); assertEquals(defaultEncoding, result.getMetaData().getEncoding().get()); } @Test void entriesAreParsedNoHeader() throws IOException { - ParserResult result = OpenDatabase.loadDatabase(bibNoHeader, generalPreferences, importFormatPreferences, fileMonitor); + ParserResult result = OpenDatabase.loadDatabase(bibNoHeader, importFormatPreferences, fileMonitor); BibDatabase db = result.getDatabase(); // Entry @@ -88,7 +84,7 @@ void entriesAreParsedNoHeader() throws IOException { @Test void entriesAreParsedHeader() throws IOException { - ParserResult result = OpenDatabase.loadDatabase(bibHeader, generalPreferences, importFormatPreferences, fileMonitor); + ParserResult result = OpenDatabase.loadDatabase(bibHeader, importFormatPreferences, fileMonitor); BibDatabase db = result.getDatabase(); // Entry @@ -98,7 +94,7 @@ void entriesAreParsedHeader() throws IOException { @Test void entriesAreParsedHeaderAndSignature() throws IOException { - ParserResult result = OpenDatabase.loadDatabase(bibHeaderAndSignature, generalPreferences, importFormatPreferences, fileMonitor); + ParserResult result = OpenDatabase.loadDatabase(bibHeaderAndSignature, importFormatPreferences, fileMonitor); BibDatabase db = result.getDatabase(); // Entry @@ -111,7 +107,7 @@ void entriesAreParsedHeaderAndSignature() throws IOException { */ @Test void correctlyParseEncodingWithoutNewline() throws IOException { - ParserResult result = OpenDatabase.loadDatabase(bibEncodingWithoutNewline, generalPreferences, importFormatPreferences, fileMonitor); + ParserResult result = OpenDatabase.loadDatabase(bibEncodingWithoutNewline, importFormatPreferences, fileMonitor); assertEquals(StandardCharsets.US_ASCII, result.getMetaData().getEncoding().get()); BibDatabase db = result.getDatabase(); diff --git a/src/test/java/org/jabref/logic/importer/WebFetchersTest.java b/src/test/java/org/jabref/logic/importer/WebFetchersTest.java index 6c1aa5aeb4d..ca9ca27c716 100644 --- a/src/test/java/org/jabref/logic/importer/WebFetchersTest.java +++ b/src/test/java/org/jabref/logic/importer/WebFetchersTest.java @@ -1,6 +1,5 @@ package org.jabref.logic.importer; -import java.nio.charset.Charset; import java.util.Collection; import java.util.HashSet; import java.util.Set; @@ -65,7 +64,7 @@ void getIdBasedFetchersReturnsAllFetcherDerivingFromIdBasedFetcher() throws Exce @Test void getEntryBasedFetchersReturnsAllFetcherDerivingFromEntryBasedFetcher() throws Exception { - Set idFetchers = WebFetchers.getEntryBasedFetchers(mock(ImporterPreferences.class), importFormatPreferences, mock(FilePreferences.class), mock(BibDatabaseContext.class), Charset.defaultCharset()); + Set idFetchers = WebFetchers.getEntryBasedFetchers(mock(ImporterPreferences.class), importFormatPreferences, mock(FilePreferences.class), mock(BibDatabaseContext.class)); try (ScanResult scanResult = classGraph.scan()) { ClassInfoList controlClasses = scanResult.getClassesImplementing(EntryBasedFetcher.class.getCanonicalName()); diff --git a/src/test/java/org/jabref/logic/importer/fileformat/BiblioscapeImporterTest.java b/src/test/java/org/jabref/logic/importer/fileformat/BiblioscapeImporterTest.java index 5fa5ab65a1e..d83d80e5a0d 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/BiblioscapeImporterTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/BiblioscapeImporterTest.java @@ -1,6 +1,5 @@ package org.jabref.logic.importer.fileformat; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Collections; @@ -45,6 +44,6 @@ public void testGetCLIID() { public void testImportEntriesAbortion() throws Throwable { Path file = Path.of(BiblioscapeImporter.class.getResource("BiblioscapeImporterTestCorrupt.txt").toURI()); assertEquals(Collections.emptyList(), - importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries()); + importer.importDatabase(file).getDatabase().getEntries()); } } diff --git a/src/test/java/org/jabref/logic/importer/fileformat/BibtexImporterTest.java b/src/test/java/org/jabref/logic/importer/fileformat/BibtexImporterTest.java index 12c9d381a2f..323866d51c1 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/BibtexImporterTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/BibtexImporterTest.java @@ -7,6 +7,7 @@ import java.nio.file.Path; import java.util.List; import java.util.Optional; +import java.util.stream.Stream; import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.logic.importer.ParserResult; @@ -19,6 +20,10 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.Answers; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -42,13 +47,13 @@ public void setUp() { @Test public void testIsRecognizedFormat() throws IOException, URISyntaxException { Path file = Path.of(BibtexImporterTest.class.getResource("BibtexImporter.examples.bib").toURI()); - assertTrue(importer.isRecognizedFormat(file, StandardCharsets.UTF_8)); + assertTrue(importer.isRecognizedFormat(file)); } @Test public void testImportEntries() throws IOException, URISyntaxException { Path file = Path.of(BibtexImporterTest.class.getResource("BibtexImporter.examples.bib").toURI()); - List bibEntries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List bibEntries = importer.importDatabase(file).getDatabase().getEntries(); assertEquals(4, bibEntries.size()); @@ -125,26 +130,43 @@ public void testGetDescription() { @Test public void testRecognizesDatabaseID() throws Exception { Path file = Path.of(BibtexImporterTest.class.getResource("AutosavedSharedDatabase.bib").toURI()); - String sharedDatabaseID = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getSharedDatabaseID().get(); + String sharedDatabaseID = importer.importDatabase(file).getDatabase().getSharedDatabaseID().get(); assertEquals("13ceoc8dm42f5g1iitao3dj2ap", sharedDatabaseID); } - @Test - public void testParsingOfWindows1252EncodedFileReturnsCorrectHeader() throws Exception { + static Stream testParsingOfEncodedFileWithHeader() { + return Stream.of( + Arguments.of(StandardCharsets.US_ASCII, "encoding-us-ascii-with-header.bib"), + Arguments.of(StandardCharsets.UTF_8, "encoding-utf-8-with-header.bib"), + Arguments.of(Charset.forName("Windows-1252"), "encoding-windows-1252-with-header.bib") + ); + } + + @ParameterizedTest + @MethodSource + public void testParsingOfEncodedFileWithHeader(Charset charset, String fileName) throws Exception { ParserResult parserResult = importer.importDatabase( - Path.of(BibtexImporterTest.class.getResource("encoding-windows-1252-with-header.bib").toURI()), - StandardCharsets.UTF_8); - assertEquals(Optional.of(Charset.forName("Windows-1252")), parserResult.getMetaData().getEncoding()); + Path.of(BibtexImporterTest.class.getResource(fileName).toURI())); + assertEquals(Optional.of(charset), parserResult.getMetaData().getEncoding()); } - @Test - public void testParsingOfWindows1252EncodedFileReadsDegreeCharacterCorrectly() throws Exception { + @ParameterizedTest + @CsvSource({"encoding-windows-1252-with-header.bib", "encoding-windows-1252-without-header.bib"}) + public void testParsingOfWindows1252EncodedFileReadsDegreeCharacterCorrectly(String filename) throws Exception { ParserResult parserResult = importer.importDatabase( - Path.of(BibtexImporterTest.class.getResource("encoding-windows-1252-with-header.bib").toURI()), - StandardCharsets.UTF_8); - List bibEntries = parserResult.getDatabase().getEntries(); + Path.of(BibtexImporterTest.class.getResource(filename).toURI())); assertEquals( List.of(new BibEntry(StandardEntryType.Article).withField(StandardField.ABSTRACT, "25° C")), - bibEntries); + parserResult.getDatabase().getEntries()); + } + + @ParameterizedTest + @CsvSource({"encoding-utf-8-with-header.bib", "encoding-utf-8-without-header.bib"}) + public void testParsingOfUtf8EncodedFileReadsUmlatCharacterCorrectly(String filename) throws Exception { + ParserResult parserResult = importer.importDatabase( + Path.of(BibtexImporterTest.class.getResource(filename).toURI())); + assertEquals( + List.of(new BibEntry(StandardEntryType.Article).withField(StandardField.TITLE, "Ü ist ein Umlaut")), + parserResult.getDatabase().getEntries()); } } diff --git a/src/test/java/org/jabref/logic/importer/fileformat/CffImporterTest.java b/src/test/java/org/jabref/logic/importer/fileformat/CffImporterTest.java index 5dd61a6d262..76cb13af355 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/CffImporterTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/CffImporterTest.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Arrays; import java.util.List; @@ -53,7 +52,7 @@ public void testGetDescription() { @Test public void testIsRecognizedFormat() throws IOException, URISyntaxException { Path file = Path.of(CffImporterTest.class.getResource("CffImporterTestValid.cff").toURI()); - assertTrue(importer.isRecognizedFormat(file, StandardCharsets.UTF_8)); + assertTrue(importer.isRecognizedFormat(file)); } @Test @@ -62,14 +61,14 @@ public void testIsRecognizedFormatReject() throws IOException, URISyntaxExceptio for (String string : list) { Path file = Path.of(CffImporterTest.class.getResource(string).toURI()); - assertFalse(importer.isRecognizedFormat(file, StandardCharsets.UTF_8)); + assertFalse(importer.isRecognizedFormat(file)); } } @Test public void testImportEntriesBasic() throws IOException, URISyntaxException { Path file = Path.of(CffImporterTest.class.getResource("CffImporterTestValid.cff").toURI()); - List bibEntries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List bibEntries = importer.importDatabase(file).getDatabase().getEntries(); BibEntry entry = bibEntries.get(0); BibEntry expected = getPopulatedEntry().withField(StandardField.AUTHOR, "Joe van Smith"); @@ -80,7 +79,7 @@ public void testImportEntriesBasic() throws IOException, URISyntaxException { @Test public void testImportEntriesMultipleAuthors() throws IOException, URISyntaxException { Path file = Path.of(CffImporterTest.class.getResource("CffImporterTestValidMultAuthors.cff").toURI()); - List bibEntries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List bibEntries = importer.importDatabase(file).getDatabase().getEntries(); BibEntry entry = bibEntries.get(0); BibEntry expected = getPopulatedEntry(); @@ -92,7 +91,7 @@ public void testImportEntriesMultipleAuthors() throws IOException, URISyntaxExce @Test public void testImportEntriesSwhIdSelect1() throws IOException, URISyntaxException { Path file = Path.of(CffImporterTest.class.getResource("CffImporterTestValidSwhIdSelect1.cff").toURI()); - List bibEntries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List bibEntries = importer.importDatabase(file).getDatabase().getEntries(); BibEntry entry = bibEntries.get(0); BibEntry expected = getPopulatedEntry().withField(StandardField.SWHID, "swh:1:rel:22ece559cc7cc2364edc5e5593d63ae8bd229f9f"); @@ -103,7 +102,7 @@ public void testImportEntriesSwhIdSelect1() throws IOException, URISyntaxExcepti @Test public void testImportEntriesSwhIdSelect2() throws IOException, URISyntaxException { Path file = Path.of(CffImporterTest.class.getResource("CffImporterTestValidSwhIdSelect2.cff").toURI()); - List bibEntries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List bibEntries = importer.importDatabase(file).getDatabase().getEntries(); BibEntry entry = bibEntries.get(0); BibEntry expected = getPopulatedEntry().withField(StandardField.SWHID, "swh:1:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2"); @@ -114,7 +113,7 @@ public void testImportEntriesSwhIdSelect2() throws IOException, URISyntaxExcepti @Test public void testImportEntriesDataset() throws IOException, URISyntaxException { Path file = Path.of(CffImporterTest.class.getResource("CffImporterTestDataset.cff").toURI()); - List bibEntries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List bibEntries = importer.importDatabase(file).getDatabase().getEntries(); BibEntry entry = bibEntries.get(0); BibEntry expected = getPopulatedEntry(); @@ -126,7 +125,7 @@ public void testImportEntriesDataset() throws IOException, URISyntaxException { @Test public void testImportEntriesDoiSelect() throws IOException, URISyntaxException { Path file = Path.of(CffImporterTest.class.getResource("CffImporterTestDoiSelect.cff").toURI()); - List bibEntries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List bibEntries = importer.importDatabase(file).getDatabase().getEntries(); BibEntry entry = bibEntries.get(0); BibEntry expected = getPopulatedEntry(); @@ -137,7 +136,7 @@ public void testImportEntriesDoiSelect() throws IOException, URISyntaxException @Test public void testImportEntriesUnknownFields() throws IOException, URISyntaxException { Path file = Path.of(CffImporterTest.class.getResource("CffImporterTestUnknownFields.cff").toURI()); - List bibEntries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List bibEntries = importer.importDatabase(file).getDatabase().getEntries(); BibEntry entry = bibEntries.get(0); BibEntry expected = getPopulatedEntry().withField(new UnknownField("commit"), "10ad"); diff --git a/src/test/java/org/jabref/logic/importer/fileformat/CopacImporterTest.java b/src/test/java/org/jabref/logic/importer/fileformat/CopacImporterTest.java index 9955c85fa76..3ecf3760a49 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/CopacImporterTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/CopacImporterTest.java @@ -1,6 +1,5 @@ package org.jabref.logic.importer.fileformat; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Collections; import java.util.List; @@ -35,7 +34,7 @@ public void testGetDescription() { @Test public void testImportEmptyEntries() throws Exception { Path path = Path.of(CopacImporterTest.class.getResource("Empty.txt").toURI()); - List entries = importer.importDatabase(path, StandardCharsets.UTF_8).getDatabase().getEntries(); + List entries = importer.importDatabase(path).getDatabase().getEntries(); assertEquals(Collections.emptyList(), entries); } } diff --git a/src/test/java/org/jabref/logic/importer/fileformat/EndnoteImporterTest.java b/src/test/java/org/jabref/logic/importer/fileformat/EndnoteImporterTest.java index 74bdbe43ca3..37e163a87e3 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/EndnoteImporterTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/EndnoteImporterTest.java @@ -4,8 +4,6 @@ import java.io.IOException; import java.io.StringReader; import java.net.URISyntaxException; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Arrays; import java.util.List; @@ -62,7 +60,7 @@ public void testIsRecognizedFormat() throws IOException, URISyntaxException { for (String string : list) { Path file = Path.of(EndnoteImporterTest.class.getResource(string).toURI()); - assertTrue(importer.isRecognizedFormat(file, StandardCharsets.UTF_8)); + assertTrue(importer.isRecognizedFormat(file)); } } @@ -74,14 +72,14 @@ public void testIsRecognizedFormatReject() throws IOException, URISyntaxExceptio for (String string : list) { Path file = Path.of(EndnoteImporterTest.class.getResource(string).toURI()); - assertFalse(importer.isRecognizedFormat(file, Charset.defaultCharset())); + assertFalse(importer.isRecognizedFormat(file)); } } @Test public void testImportEntries0() throws IOException, URISyntaxException { Path file = Path.of(EndnoteImporterTest.class.getResource("Endnote.entries.enw").toURI()); - List bibEntries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List bibEntries = importer.importDatabase(file).getDatabase().getEntries(); assertEquals(5, bibEntries.size()); @@ -141,7 +139,7 @@ public void testImportEntries1() throws IOException { @Test public void testImportEntriesBookExample() throws IOException, URISyntaxException { Path file = Path.of(EndnoteImporterTest.class.getResource("Endnote.book.example.enw").toURI()); - List bibEntries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List bibEntries = importer.importDatabase(file).getDatabase().getEntries(); BibEntry entry = bibEntries.get(0); diff --git a/src/test/java/org/jabref/logic/importer/fileformat/ImporterTestEngine.java b/src/test/java/org/jabref/logic/importer/fileformat/ImporterTestEngine.java index 010ad110236..9d24b9c96d7 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/ImporterTestEngine.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/ImporterTestEngine.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -41,15 +40,15 @@ public static Collection getTestFiles(Predicate fileNamePredicat } public static void testIsRecognizedFormat(Importer importer, String fileName) throws IOException { - Assertions.assertTrue(importer.isRecognizedFormat(getPath(fileName), StandardCharsets.UTF_8)); + Assertions.assertTrue(importer.isRecognizedFormat(getPath(fileName))); } public static void testIsNotRecognizedFormat(Importer importer, String fileName) throws IOException { - Assertions.assertFalse(importer.isRecognizedFormat(getPath(fileName), StandardCharsets.UTF_8)); + Assertions.assertFalse(importer.isRecognizedFormat(getPath(fileName))); } public static void testImportEntries(Importer importer, String fileName, String fileType) throws IOException, ImportException { - ParserResult parserResult = importer.importDatabase(getPath(fileName), StandardCharsets.UTF_8); + ParserResult parserResult = importer.importDatabase(getPath(fileName)); if (parserResult.isInvalid()) { throw new ImportException(parserResult.getErrorMessage()); } @@ -67,7 +66,7 @@ private static Path getPath(String fileName) throws IOException { } public static void testImportMalformedFiles(Importer importer, String fileName) throws IOException { - List entries = importer.importDatabase(getPath(fileName), StandardCharsets.UTF_8).getDatabase() + List entries = importer.importDatabase(getPath(fileName)).getDatabase() .getEntries(); assertEquals(entries, new ArrayList()); } diff --git a/src/test/java/org/jabref/logic/importer/fileformat/IsiImporterTest.java b/src/test/java/org/jabref/logic/importer/fileformat/IsiImporterTest.java index f71618c1afb..f0b385f74d4 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/IsiImporterTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/IsiImporterTest.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.HashMap; import java.util.List; @@ -127,7 +126,7 @@ public void testProcessSubSup() { @Test public void testImportEntries1() throws IOException, URISyntaxException { Path file = Path.of(IsiImporterTest.class.getResource("IsiImporterTest1.isi").toURI()); - List entries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List entries = importer.importDatabase(file).getDatabase().getEntries(); BibEntry entry = entries.get(0); assertEquals(1, entries.size()); @@ -148,7 +147,7 @@ public void testImportEntries1() throws IOException, URISyntaxException { @Test public void testImportEntries2() throws IOException, URISyntaxException { Path file = Path.of(IsiImporterTest.class.getResource("IsiImporterTest2.isi").toURI()); - List entries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List entries = importer.importDatabase(file).getDatabase().getEntries(); BibEntry entry = entries.get(0); assertEquals(3, entries.size()); @@ -165,7 +164,7 @@ public void testImportEntries2() throws IOException, URISyntaxException { @Test public void testImportEntriesINSPEC() throws IOException, URISyntaxException { Path file = Path.of(IsiImporterTest.class.getResource("IsiImporterTestInspec.isi").toURI()); - List entries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List entries = importer.importDatabase(file).getDatabase().getEntries(); BibEntry first = entries.get(0); BibEntry second = entries.get(1); @@ -202,7 +201,7 @@ public void testImportEntriesINSPEC() throws IOException, URISyntaxException { @Test public void testImportEntriesWOS() throws IOException, URISyntaxException { Path file = Path.of(IsiImporterTest.class.getResource("IsiImporterTestWOS.isi").toURI()); - List entries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List entries = importer.importDatabase(file).getDatabase().getEntries(); BibEntry first = entries.get(0); BibEntry second = entries.get(1); @@ -258,7 +257,7 @@ public void testIsiAuthorConvert() { @Test public void testImportIEEEExport() throws IOException, URISyntaxException { Path file = Path.of(IsiImporterTest.class.getResource("IEEEImport1.txt").toURI()); - List entries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List entries = importer.importDatabase(file).getDatabase().getEntries(); BibEntry entry = entries.get(0); assertEquals(1, entries.size()); @@ -281,7 +280,7 @@ public void testImportIEEEExport() throws IOException, URISyntaxException { @Test public void testIEEEImport() throws IOException, URISyntaxException { Path file = Path.of(IsiImporterTest.class.getResource("IEEEImport1.txt").toURI()); - List entries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List entries = importer.importDatabase(file).getDatabase().getEntries(); BibEntry entry = entries.get(0); assertEquals(1, entries.size()); @@ -305,7 +304,7 @@ public void testIEEEImport() throws IOException, URISyntaxException { @Test public void testImportEntriesMedline() throws IOException, URISyntaxException { Path file = Path.of(IsiImporterTest.class.getResource("IsiImporterTestMedline.isi").toURI()); - List entries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List entries = importer.importDatabase(file).getDatabase().getEntries(); BibEntry first = entries.get(0); BibEntry second = entries.get(1); @@ -342,7 +341,7 @@ public void testImportEntriesMedline() throws IOException, URISyntaxException { public void testImportEntriesEmpty() throws IOException, URISyntaxException { Path file = Path.of(IsiImporterTest.class.getResource("IsiImporterTestEmpty.isi").toURI()); - List entries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List entries = importer.importDatabase(file).getDatabase().getEntries(); assertEquals(1, entries.size()); } diff --git a/src/test/java/org/jabref/logic/importer/fileformat/MedlinePlainImporterTest.java b/src/test/java/org/jabref/logic/importer/fileformat/MedlinePlainImporterTest.java index fe48bcb86ca..bc25e3359eb 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/MedlinePlainImporterTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/MedlinePlainImporterTest.java @@ -5,7 +5,6 @@ import java.io.InputStream; import java.io.StringReader; import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Arrays; import java.util.Collections; @@ -20,7 +19,6 @@ import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.types.StandardEntryType; -import org.apache.commons.codec.Charsets; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; @@ -78,7 +76,7 @@ void doesNotRecognizeEmptyFiles() throws IOException { void testImportMultipleEntriesInSingleFile() throws IOException, URISyntaxException { Path inputFile = Path.of(MedlinePlainImporter.class.getResource("MedlinePlainImporterTestMultipleEntries.txt").toURI()); - List entries = importer.importDatabase(inputFile, StandardCharsets.UTF_8).getDatabase() + List entries = importer.importDatabase(inputFile).getDatabase() .getEntries(); BibEntry testEntry = entries.get(0); @@ -147,7 +145,7 @@ private void assertImportOfMedlineFileEqualsBibtexFile(String medlineFile, Strin Path file = Path.of(MedlinePlainImporter.class.getResource(medlineFile).toURI()); try (InputStream nis = MedlinePlainImporter.class.getResourceAsStream(bibtexFile)) { - List entries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List entries = importer.importDatabase(file).getDatabase().getEntries(); assertNotNull(entries); assertEquals(1, entries.size()); BibEntryAssert.assertEquals(nis, entries.get(0)); @@ -189,7 +187,7 @@ void testKeyWords() throws IOException { void testWithNbibFile() throws IOException, URISyntaxException { Path file = Path.of(MedlinePlainImporter.class.getResource("NbibImporterTest.nbib").toURI()); - List entries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List entries = importer.importDatabase(file).getDatabase().getEntries(); BibEntryAssert.assertEquals(MedlinePlainImporter.class, "NbibImporterTest.bib", entries); } @@ -198,7 +196,7 @@ void testWithNbibFile() throws IOException, URISyntaxException { void testWithMultipleEntries() throws IOException, URISyntaxException { Path file = Path.of(MedlinePlainImporter.class.getResource("MedlinePlainImporterStringOutOfBounds.txt").toURI()); - List entries = importer.importDatabase(file, Charsets.UTF_8).getDatabase().getEntries(); + List entries = importer.importDatabase(file).getDatabase().getEntries(); BibEntryAssert.assertEquals(MedlinePlainImporter.class, "MedlinePlainImporterStringOutOfBounds.bib", entries); } @@ -207,7 +205,7 @@ void testWithMultipleEntries() throws IOException, URISyntaxException { void testInvalidFormat() throws URISyntaxException, IOException { Path file = Path.of(MedlinePlainImporter.class.getResource("MedlinePlainImporterTestInvalidFormat.xml").toURI()); - List entries = importer.importDatabase(file, Charsets.UTF_8).getDatabase().getEntries(); + List entries = importer.importDatabase(file).getDatabase().getEntries(); assertEquals(Collections.emptyList(), entries); } diff --git a/src/test/java/org/jabref/logic/importer/fileformat/MsBibImporterTest.java b/src/test/java/org/jabref/logic/importer/fileformat/MsBibImporterTest.java index beaeb16c49f..c87c3d77cc0 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/MsBibImporterTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/MsBibImporterTest.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.net.URISyntaxException; -import java.nio.charset.Charset; import java.nio.file.Path; import java.util.Arrays; import java.util.Collections; @@ -37,7 +36,7 @@ public final void testIsNotRecognizedFormat() throws Exception { "IsiImporterTestInspec.isi", "emptyFile.xml", "IsiImporterTestWOS.isi"); for (String s : notAccepted) { Path file = Path.of(MsBibImporter.class.getResource(s).toURI()); - assertFalse(testImporter.isRecognizedFormat(file, Charset.defaultCharset())); + assertFalse(testImporter.isRecognizedFormat(file)); } } @@ -45,7 +44,7 @@ public final void testIsNotRecognizedFormat() throws Exception { public final void testImportEntriesEmpty() throws IOException, URISyntaxException { MsBibImporter testImporter = new MsBibImporter(); Path file = Path.of(MsBibImporter.class.getResource("EmptyMsBib_Test.xml").toURI()); - List entries = testImporter.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); + List entries = testImporter.importDatabase(file).getDatabase().getEntries(); assertEquals(Collections.emptyList(), entries); } @@ -53,7 +52,7 @@ public final void testImportEntriesEmpty() throws IOException, URISyntaxExceptio public final void testImportEntriesNotRecognizedFormat() throws IOException, URISyntaxException { MsBibImporter testImporter = new MsBibImporter(); Path file = Path.of(MsBibImporter.class.getResource("CopacImporterTest1.txt").toURI()); - List entries = testImporter.importDatabase(file, Charset.defaultCharset()).getDatabase().getEntries(); + List entries = testImporter.importDatabase(file).getDatabase().getEntries(); assertEquals(0, entries.size()); } diff --git a/src/test/java/org/jabref/logic/importer/fileformat/OvidImporterTest.java b/src/test/java/org/jabref/logic/importer/fileformat/OvidImporterTest.java index 695ca2e9d7b..a948ecf75b0 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/OvidImporterTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/OvidImporterTest.java @@ -3,7 +3,6 @@ import java.io.IOException; import java.io.InputStream; import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Collections; import java.util.List; @@ -83,14 +82,14 @@ public void testIsRecognizedFormatRejected(String fileName) throws IOException, @Test public void testImportEmpty() throws IOException, URISyntaxException { Path file = Path.of(OvidImporter.class.getResource("Empty.txt").toURI()); - List entries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List entries = importer.importDatabase(file).getDatabase().getEntries(); assertEquals(Collections.emptyList(), entries); } @Test public void testImportEntries1() throws IOException, URISyntaxException { Path file = Path.of(OvidImporter.class.getResource("OvidImporterTest1.txt").toURI()); - List entries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List entries = importer.importDatabase(file).getDatabase().getEntries(); assertEquals(5, entries.size()); BibEntry entry = entries.get(0); @@ -143,7 +142,7 @@ public void testImportEntries1() throws IOException, URISyntaxException { @Test public void testImportEntries2() throws IOException, URISyntaxException { Path file = Path.of(OvidImporter.class.getResource("OvidImporterTest2Invalid.txt").toURI()); - List entries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List entries = importer.importDatabase(file).getDatabase().getEntries(); assertEquals(Collections.emptyList(), entries); } @@ -153,7 +152,7 @@ public void testImportSingleEntries() throws IOException, URISyntaxException { for (int n = 3; n <= 7; n++) { Path file = Path.of(OvidImporter.class.getResource("OvidImporterTest" + n + ".txt").toURI()); try (InputStream nis = OvidImporter.class.getResourceAsStream("OvidImporterTestBib" + n + ".bib")) { - List entries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase() + List entries = importer.importDatabase(file).getDatabase() .getEntries(); assertNotNull(entries); assertEquals(1, entries.size()); diff --git a/src/test/java/org/jabref/logic/importer/fileformat/PdfContentImporterTest.java b/src/test/java/org/jabref/logic/importer/fileformat/PdfContentImporterTest.java index faf37949972..55c2e1413aa 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/PdfContentImporterTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/PdfContentImporterTest.java @@ -1,6 +1,5 @@ package org.jabref.logic.importer.fileformat; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Collections; import java.util.List; @@ -42,21 +41,21 @@ void testGetDescription() { @Test void doesNotHandleEncryptedPdfs() throws Exception { Path file = Path.of(PdfContentImporter.class.getResource("/pdfs/encrypted.pdf").toURI()); - List result = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List result = importer.importDatabase(file).getDatabase().getEntries(); assertEquals(Collections.emptyList(), result); } @Test void importTwiceWorksAsExpected() throws Exception { Path file = Path.of(PdfContentImporter.class.getResource("/pdfs/minimal.pdf").toURI()); - List result = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List result = importer.importDatabase(file).getDatabase().getEntries(); BibEntry expected = new BibEntry(StandardEntryType.InProceedings); expected.setField(StandardField.AUTHOR, "1 "); expected.setField(StandardField.TITLE, "Hello World"); expected.setFiles(Collections.singletonList(new LinkedFile("", file.toAbsolutePath(), "PDF"))); - List resultSecondImport = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List resultSecondImport = importer.importDatabase(file).getDatabase().getEntries(); assertEquals(Collections.singletonList(expected), result); assertEquals(Collections.singletonList(expected), resultSecondImport); } diff --git a/src/test/java/org/jabref/logic/importer/fileformat/PdfEmbeddedBibFileImporterTest.java b/src/test/java/org/jabref/logic/importer/fileformat/PdfEmbeddedBibFileImporterTest.java index dc5dc085672..b00746f8eb8 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/PdfEmbeddedBibFileImporterTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/PdfEmbeddedBibFileImporterTest.java @@ -1,6 +1,5 @@ package org.jabref.logic.importer.fileformat; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Collections; import java.util.List; @@ -45,14 +44,14 @@ void testGetDescription() { @Test void doesNotHandleEncryptedPdfs() throws Exception { Path file = Path.of(PdfEmbeddedBibFileImporter.class.getResource("/pdfs/encrypted.pdf").toURI()); - List result = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List result = importer.importDatabase(file).getDatabase().getEntries(); assertEquals(Collections.emptyList(), result); } @Test void importWorksAsExpected() throws Exception { Path file = Path.of(PdfEmbeddedBibFileImporterTest.class.getResource("mixedMetadata.pdf").toURI()); - List result = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List result = importer.importDatabase(file).getDatabase().getEntries(); BibEntry expected = new BibEntry(StandardEntryType.Misc); expected.setCitationKey("jabreftext2021"); diff --git a/src/test/java/org/jabref/logic/importer/fileformat/PdfGrobidImporterTest.java b/src/test/java/org/jabref/logic/importer/fileformat/PdfGrobidImporterTest.java index 296fd455c68..e9749aca122 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/PdfGrobidImporterTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/PdfGrobidImporterTest.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.List; import java.util.Optional; @@ -48,7 +47,7 @@ public void testsGetExtensions() { @Test public void testImportEntries() throws URISyntaxException { Path file = Path.of(PdfGrobidImporterTest.class.getResource("LNCS-minimal.pdf").toURI()); - List bibEntries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List bibEntries = importer.importDatabase(file).getDatabase().getEntries(); assertEquals(1, bibEntries.size()); @@ -60,13 +59,13 @@ public void testImportEntries() throws URISyntaxException { @Test public void testIsRecognizedFormat() throws IOException, URISyntaxException { Path file = Path.of(PdfGrobidImporterTest.class.getResource("annotated.pdf").toURI()); - assertTrue(importer.isRecognizedFormat(file, StandardCharsets.UTF_8)); + assertTrue(importer.isRecognizedFormat(file)); } @Test public void testIsRecognizedFormatReject() throws IOException, URISyntaxException { Path file = Path.of(PdfGrobidImporterTest.class.getResource("BibtexImporter.examples.bib").toURI()); - assertFalse(importer.isRecognizedFormat(file, StandardCharsets.UTF_8)); + assertFalse(importer.isRecognizedFormat(file)); } @Test diff --git a/src/test/java/org/jabref/logic/importer/fileformat/PdfMergeMetadataImporterTest.java b/src/test/java/org/jabref/logic/importer/fileformat/PdfMergeMetadataImporterTest.java index fbf2eb763dd..54b112bb247 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/PdfMergeMetadataImporterTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/PdfMergeMetadataImporterTest.java @@ -1,6 +1,5 @@ package org.jabref.logic.importer.fileformat; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Collections; import java.util.List; @@ -53,14 +52,14 @@ void testGetDescription() { @Test void doesNotHandleEncryptedPdfs() throws Exception { Path file = Path.of(PdfMergeMetadataImporter.class.getResource("/pdfs/encrypted.pdf").toURI()); - List result = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List result = importer.importDatabase(file).getDatabase().getEntries(); assertEquals(Collections.emptyList(), result); } @Test void importWorksAsExpected() throws Exception { Path file = Path.of(PdfMergeMetadataImporterTest.class.getResource("mixedMetadata.pdf").toURI()); - List result = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List result = importer.importDatabase(file).getDatabase().getEntries(); // From DOI (contained in embedded bib file) BibEntry expected = new BibEntry(StandardEntryType.Book); diff --git a/src/test/java/org/jabref/logic/importer/fileformat/PdfVerbatimBibTextImporterTest.java b/src/test/java/org/jabref/logic/importer/fileformat/PdfVerbatimBibTextImporterTest.java index 334f0cb76c0..404427a7207 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/PdfVerbatimBibTextImporterTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/PdfVerbatimBibTextImporterTest.java @@ -1,6 +1,5 @@ package org.jabref.logic.importer.fileformat; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Collections; import java.util.List; @@ -46,14 +45,14 @@ void testGetDescription() { @Test void doesNotHandleEncryptedPdfs() throws Exception { Path file = Path.of(PdfVerbatimBibTextImporter.class.getResource("/pdfs/encrypted.pdf").toURI()); - List result = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List result = importer.importDatabase(file).getDatabase().getEntries(); assertEquals(Collections.emptyList(), result); } @Test void importTwiceWorksAsExpected() throws Exception { Path file = Path.of(PdfVerbatimBibTextImporterTest.class.getResource("mixedMetadata.pdf").toURI()); - List result = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List result = importer.importDatabase(file).getDatabase().getEntries(); BibEntry expected = new BibEntry(StandardEntryType.Article); expected.setCitationKey("jabreftest2021"); @@ -65,7 +64,7 @@ void importTwiceWorksAsExpected() throws Exception { expected.setField(StandardField.ISBN, "0134685997"); expected.setFiles(Collections.singletonList(new LinkedFile("", file.toAbsolutePath(), "PDF"))); - List resultSecondImport = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List resultSecondImport = importer.importDatabase(file).getDatabase().getEntries(); assertEquals(Collections.singletonList(expected), result); assertEquals(Collections.singletonList(expected), resultSecondImport); } diff --git a/src/test/java/org/jabref/logic/importer/fileformat/PdfXmpImporterTest.java b/src/test/java/org/jabref/logic/importer/fileformat/PdfXmpImporterTest.java index fc7a9b53d13..b6a530ff29f 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/PdfXmpImporterTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/PdfXmpImporterTest.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.List; import java.util.Optional; @@ -58,14 +57,14 @@ public void testGetDescription() { @Test public void importEncryptedFileReturnsError() throws URISyntaxException { Path file = Path.of(PdfXmpImporterTest.class.getResource("/pdfs/encrypted.pdf").toURI()); - ParserResult result = importer.importDatabase(file, StandardCharsets.UTF_8); + ParserResult result = importer.importDatabase(file); assertTrue(result.hasWarnings()); } @Test public void testImportEntries() throws URISyntaxException { Path file = Path.of(PdfXmpImporterTest.class.getResource("annotated.pdf").toURI()); - List bibEntries = importer.importDatabase(file, StandardCharsets.UTF_8).getDatabase().getEntries(); + List bibEntries = importer.importDatabase(file).getDatabase().getEntries(); assertEquals(1, bibEntries.size()); @@ -79,7 +78,7 @@ public void testImportEntries() throws URISyntaxException { @Test public void testIsRecognizedFormat() throws IOException, URISyntaxException { Path file = Path.of(PdfXmpImporterTest.class.getResource("annotated.pdf").toURI()); - assertTrue(importer.isRecognizedFormat(file, StandardCharsets.UTF_8)); + assertTrue(importer.isRecognizedFormat(file)); } @ParameterizedTest diff --git a/src/test/java/org/jabref/logic/importer/fileformat/RISImporterTest.java b/src/test/java/org/jabref/logic/importer/fileformat/RISImporterTest.java index c086370b0ae..11ad5bb9782 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/RISImporterTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/RISImporterTest.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import org.jabref.logic.util.StandardFileType; @@ -45,6 +44,6 @@ public void testGetDescription() { @Test public void testIfNotRecognizedFormat() throws IOException, URISyntaxException { Path file = Path.of(RISImporterTest.class.getResource("RisImporterCorrupted.ris").toURI()); - assertFalse(importer.isRecognizedFormat(file, StandardCharsets.UTF_8)); + assertFalse(importer.isRecognizedFormat(file)); } } diff --git a/src/test/java/org/jabref/logic/importer/util/FileFieldParserTest.java b/src/test/java/org/jabref/logic/importer/util/FileFieldParserTest.java index 4ccf9a150b6..cfe53630acb 100644 --- a/src/test/java/org/jabref/logic/importer/util/FileFieldParserTest.java +++ b/src/test/java/org/jabref/logic/importer/util/FileFieldParserTest.java @@ -138,17 +138,34 @@ private static Stream stringsToParseTestData() throws Exception { "desc:file.pdf:PDF:asdf" ), + // www inside filename + Arguments.of( + Collections.singletonList(new LinkedFile("", Path.of("/home/www.google.de.pdf"), "")), + ":/home/www.google.de.pdf" + ), + // url Arguments.of( Collections.singletonList(new LinkedFile(new URL("https://books.google.de/"), "")), "https://books.google.de/" ), + // url with www + Arguments.of( + Collections.singletonList(new LinkedFile(new URL("https://www.google.de/"), "")), + "https://www.google.de/" + ), + // url as file Arguments.of( Collections.singletonList(new LinkedFile("", new URL("http://ceur-ws.org/Vol-438"), "URL")), ":http\\://ceur-ws.org/Vol-438:URL" - ) + ), + // url as file with desc + Arguments.of( + Collections.singletonList(new LinkedFile("desc", new URL("http://ceur-ws.org/Vol-438"), "URL")), + "desc:http\\://ceur-ws.org/Vol-438:URL" + ) ); } diff --git a/src/test/java/org/jabref/logic/integrity/IntegrityCheckTest.java b/src/test/java/org/jabref/logic/integrity/IntegrityCheckTest.java index a35bbb4a490..8f0a1cac867 100644 --- a/src/test/java/org/jabref/logic/integrity/IntegrityCheckTest.java +++ b/src/test/java/org/jabref/logic/integrity/IntegrityCheckTest.java @@ -1,7 +1,6 @@ package org.jabref.logic.integrity; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.Collections; @@ -140,7 +139,6 @@ void testEntryIsUnchangedAfterChecks() { new IntegrityCheck(context, mock(FilePreferences.class), createCitationKeyPatternPreferences(), - StandardCharsets.UTF_8, JournalAbbreviationLoader.loadBuiltInRepository(), false) .check(); @@ -174,7 +172,6 @@ private void assertWrong(BibDatabaseContext context) { List messages = new IntegrityCheck(context, mock(FilePreferences.class), createCitationKeyPatternPreferences(), - StandardCharsets.UTF_8, JournalAbbreviationLoader.loadBuiltInRepository(), false) .check(); assertNotEquals(Collections.emptyList(), messages); @@ -186,7 +183,6 @@ private void assertCorrect(BibDatabaseContext context) { List messages = new IntegrityCheck(context, filePreferencesMock, createCitationKeyPatternPreferences(), - StandardCharsets.UTF_8, JournalAbbreviationLoader.loadBuiltInRepository(), false ).check(); assertEquals(Collections.emptyList(), messages); diff --git a/src/test/java/org/jabref/logic/openoffice/style/OOBibStyleTest.java b/src/test/java/org/jabref/logic/openoffice/style/OOBibStyleTest.java index 82d7888afd8..a76c9ae91b3 100644 --- a/src/test/java/org/jabref/logic/openoffice/style/OOBibStyleTest.java +++ b/src/test/java/org/jabref/logic/openoffice/style/OOBibStyleTest.java @@ -1,12 +1,9 @@ package org.jabref.logic.openoffice.style; -import java.io.File; import java.io.IOException; import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -62,9 +59,9 @@ void testAuthorYear() throws IOException { @Test void testAuthorYearAsFile() throws URISyntaxException, IOException { - File defFile = Path.of(OOBibStyleTest.class.getResource(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH).toURI()) - .toFile(); - OOBibStyle style = new OOBibStyle(defFile, layoutFormatterPreferences, StandardCharsets.UTF_8); + Path defFile = Path.of(OOBibStyleTest.class.getResource(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH).toURI()); + + OOBibStyle style = new OOBibStyle(defFile, layoutFormatterPreferences); assertTrue(style.isValid()); assertFalse(style.isInternalStyle()); assertFalse(style.isCitationKeyCiteMarkers()); @@ -118,10 +115,10 @@ static CitationMarkerEntry makeCitationMarkerEntry(BibEntry entry, String pageInfoQ, boolean isFirstAppearanceOfSource) { return OOBibStyleTestHelper.makeCitationMarkerEntry(entry, - database, - uniqueLetterQ, - pageInfoQ, - isFirstAppearanceOfSource); + database, + uniqueLetterQ, + pageInfoQ, + isFirstAppearanceOfSource); } /* @@ -136,12 +133,28 @@ static String getCitationMarker2(OOBibStyle style, Boolean[] isFirstAppearanceOfSource, String[] pageInfo) { return OOBibStyleTestHelper.getCitationMarker2(style, - entries, - entryDBMap, - inParenthesis, - uniquefiers, - isFirstAppearanceOfSource, - pageInfo); + entries, + entryDBMap, + inParenthesis, + uniquefiers, + isFirstAppearanceOfSource, + pageInfo); + } + + static String getCitationMarker2b(OOBibStyle style, + List entries, + Map entryDBMap, + boolean inParenthesis, + String[] uniquefiers, + Boolean[] isFirstAppearanceOfSource, + String[] pageInfo) { + return OOBibStyleTestHelper.getCitationMarker2b(style, + entries, + entryDBMap, + inParenthesis, + uniquefiers, + isFirstAppearanceOfSource, + pageInfo); } /* @@ -152,35 +165,16 @@ static String getCitationMarker2(OOBibStyle style, void testGetNumCitationMarker() throws IOException { OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, layoutFormatterPreferences); - assertEquals("[1] ", style.getNumCitationMarker(Arrays.asList(1), -1, true)); - assertEquals("[1] ", runGetNumCitationMarker2a(style, Arrays.asList(1), -1, true)); + assertEquals("[1] ", runGetNumCitationMarker2a(style, List.of(1), -1, true)); - assertEquals("[1]", style.getNumCitationMarker(Arrays.asList(1), -1, false)); - assertEquals("[1]", runGetNumCitationMarker2a(style, Arrays.asList(1), -1, false)); + assertEquals("[1]", runGetNumCitationMarker2a(style, List.of(1), -1, false)); assertEquals("[1]", runGetNumCitationMarker2b(style, -1, numEntry("key", 1, null))); - assertEquals("[1] ", style.getNumCitationMarker(Arrays.asList(1), 0, true)); - assertEquals("[1] ", runGetNumCitationMarker2a(style, Arrays.asList(1), 0, true)); - - /* - * The following tests as for a numeric label for a - * bibliography entry containing more than one numbers. - * We do not need this, not reproduced. - */ - assertEquals("[1-3] ", style.getNumCitationMarker(Arrays.asList(1, 2, 3), 1, true)); - assertEquals("[1; 2; 3] ", style.getNumCitationMarker(Arrays.asList(1, 2, 3), 5, true)); - assertEquals("[1; 2; 3] ", style.getNumCitationMarker(Arrays.asList(1, 2, 3), -1, true)); - assertEquals("[1; 3; 12] ", style.getNumCitationMarker(Arrays.asList(1, 12, 3), 1, true)); - assertEquals("[3-5; 7; 10-12] ", style.getNumCitationMarker(Arrays.asList(12, 7, 3, 4, 11, 10, 5), 1, true)); - - String citation = style.getNumCitationMarker(Arrays.asList(1), -1, false); - assertEquals("[1; pp. 55-56]", style.insertPageInfo(citation, "pp. 55-56")); + assertEquals("[1] ", runGetNumCitationMarker2a(style, List.of(1), 0, true)); CitationMarkerNumericEntry e2 = numEntry("key", 1, "pp. 55-56"); - assertEquals(true, e2.getPageInfo().isPresent()); + assertTrue(e2.getPageInfo().isPresent()); assertEquals("pp. 55-56", e2.getPageInfo().get().toString()); - citation = runGetNumCitationMarker2b(style, -1, e2); - assertEquals("[1; pp. 55-56]", citation); OOBibStyleTestHelper.testGetNumCitationMarkerExtra(style); } @@ -189,68 +183,48 @@ void testGetNumCitationMarker() throws IOException { void testGetNumCitationMarkerUndefined() throws IOException { OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, layoutFormatterPreferences); - /* - * Testing bibliography labels with multiple numbers again. - * Not reproduced. - */ - assertEquals("[" + OOBibStyle.UNDEFINED_CITATION_MARKER + "; 2-4] ", - style.getNumCitationMarker(Arrays.asList(4, 2, 3, 0), 1, true)); - - assertEquals("[" + OOBibStyle.UNDEFINED_CITATION_MARKER + "] ", - style.getNumCitationMarker(Arrays.asList(0), 1, true)); - - assertEquals("[" + OOBibStyle.UNDEFINED_CITATION_MARKER + "; 1-3] ", - style.getNumCitationMarker(Arrays.asList(1, 2, 3, 0), 1, true)); - - assertEquals("[" + OOBibStyle.UNDEFINED_CITATION_MARKER + "; " + OOBibStyle.UNDEFINED_CITATION_MARKER + "; " - + OOBibStyle.UNDEFINED_CITATION_MARKER + "] ", - style.getNumCitationMarker(Arrays.asList(0, 0, 0), 1, true)); - - /* - * We have these instead: - */ // unresolved citations look like [??key] assertEquals("[" + OOBibStyle.UNDEFINED_CITATION_MARKER + "key" + "]", - runGetNumCitationMarker2b(style, 1, - numEntry("key", 0, null))); + runGetNumCitationMarker2b(style, 1, + numEntry("key", 0, null))); // pageInfo is shown for unresolved citations assertEquals("[" + OOBibStyle.UNDEFINED_CITATION_MARKER + "key" + "; p1]", - runGetNumCitationMarker2b(style, 1, - numEntry("key", 0, "p1"))); + runGetNumCitationMarker2b(style, 1, + numEntry("key", 0, "p1"))); // unresolved citations sorted to the front assertEquals("[" + OOBibStyle.UNDEFINED_CITATION_MARKER + "key" + "; 2-4]", - runGetNumCitationMarker2b(style, 1, - numEntry("x4", 4, ""), - numEntry("x2", 2, ""), - numEntry("x3", 3, ""), - numEntry("key", 0, ""))); + runGetNumCitationMarker2b(style, 1, + numEntry("x4", 4, ""), + numEntry("x2", 2, ""), + numEntry("x3", 3, ""), + numEntry("key", 0, ""))); assertEquals("[" + OOBibStyle.UNDEFINED_CITATION_MARKER + "key" + "; 1-3]", - runGetNumCitationMarker2b(style, 1, - numEntry("x1", 1, ""), - numEntry("x2", 2, ""), - numEntry("y3", 3, ""), - numEntry("key", 0, ""))); + runGetNumCitationMarker2b(style, 1, + numEntry("x1", 1, ""), + numEntry("x2", 2, ""), + numEntry("y3", 3, ""), + numEntry("key", 0, ""))); // multiple unresolved citations are not collapsed assertEquals("[" - + OOBibStyle.UNDEFINED_CITATION_MARKER + "x1" + "; " - + OOBibStyle.UNDEFINED_CITATION_MARKER + "x2" + "; " - + OOBibStyle.UNDEFINED_CITATION_MARKER + "x3" + "]", - runGetNumCitationMarker2b(style, 1, - numEntry("x1", 0, ""), - numEntry("x2", 0, ""), - numEntry("x3", 0, ""))); + + OOBibStyle.UNDEFINED_CITATION_MARKER + "x1" + "; " + + OOBibStyle.UNDEFINED_CITATION_MARKER + "x2" + "; " + + OOBibStyle.UNDEFINED_CITATION_MARKER + "x3" + "]", + runGetNumCitationMarker2b(style, 1, + numEntry("x1", 0, ""), + numEntry("x2", 0, ""), + numEntry("x3", 0, ""))); /* * BIBLIOGRAPHY */ CitationMarkerNumericBibEntry x = numBibEntry("key", Optional.empty()); assertEquals("[" + OOBibStyle.UNDEFINED_CITATION_MARKER + "key" + "] ", - style.getNumCitationMarkerForBibliography(x).toString()); + style.getNumCitationMarkerForBibliography(x).toString()); } @Test @@ -293,28 +267,22 @@ void testGetCitationMarker() throws IOException { assertEquals(-1, style.getMaxAuthorsFirst()); assertEquals("[Boström et al., 2006]", - style.getCitationMarker(Collections.singletonList(entry), entryDBMap, true, null, null)); - assertEquals("[Boström et al., 2006]", - getCitationMarker2(style, - Collections.singletonList(entry), entryDBMap, - true, null, null, null)); + getCitationMarker2(style, + Collections.singletonList(entry), entryDBMap, + true, null, null, null)); assertEquals("Boström et al. [2006]", - style.getCitationMarker(Collections.singletonList(entry), entryDBMap, false, null, new int[]{3})); - assertEquals("Boström et al. [2006]", - getCitationMarker2(style, - Collections.singletonList(entry), entryDBMap, - false, null, new Boolean[]{false}, null)); + getCitationMarker2(style, + Collections.singletonList(entry), entryDBMap, + false, null, new Boolean[] {false}, null)); assertEquals("[Boström, Wäyrynen, Bodén, Beznosov & Kruchten, 2006]", - style.getCitationMarker(Collections.singletonList(entry), entryDBMap, true, null, new int[]{5})); - assertEquals("[Boström, Wäyrynen, Bodén, Beznosov & Kruchten, 2006]", - getCitationMarker2(style, - Collections.singletonList(entry), entryDBMap, - true, - null, - new Boolean[]{true} /* corresponds to -1, not 5 */, - null)); + getCitationMarker2(style, + Collections.singletonList(entry), entryDBMap, + true, + null, + new Boolean[] {true}, + null)); } @Test @@ -399,11 +367,10 @@ void testInstitutionAuthorMarker() throws IOException { database.insertEntry(entry); entries.add(entry); entryDBMap.put(entry, database); - assertEquals("[JabRef Development Team, 2016]", style.getCitationMarker(entries, entryDBMap, true, null, null)); assertEquals("[JabRef Development Team, 2016]", - getCitationMarker2(style, - entries, entryDBMap, true, null, null, null)); + getCitationMarker2(style, + entries, entryDBMap, true, null, null, null)); } @Test @@ -420,10 +387,11 @@ void testVonAuthorMarker() throws IOException { entry.setField(StandardField.AUTHOR, "Alpha von Beta"); entry.setField(StandardField.TITLE, "JabRef Manual"); entry.setField(StandardField.YEAR, "2016"); + entry.setCitationKey("a1"); database.insertEntry(entry); entries.add(entry); entryDBMap.put(entry, database); - assertEquals("[von Beta, 2016]", style.getCitationMarker(entries, entryDBMap, true, null, null)); + assertEquals("[von Beta, 2016]", getCitationMarker2(style, entries, entryDBMap, true, null, null, null)); } @Test @@ -438,10 +406,11 @@ void testNullAuthorMarker() throws IOException { BibEntry entry = new BibEntry(); entry.setType(StandardEntryType.Article); entry.setField(StandardField.YEAR, "2016"); + entry.setCitationKey("a1"); database.insertEntry(entry); entries.add(entry); entryDBMap.put(entry, database); - assertEquals("[, 2016]", style.getCitationMarker(entries, entryDBMap, true, null, null)); + assertEquals("[, 2016]", getCitationMarker2(style, entries, entryDBMap, true, null, null, null)); } @Test @@ -456,10 +425,11 @@ void testNullYearMarker() throws IOException { BibEntry entry = new BibEntry(); entry.setType(StandardEntryType.Article); entry.setField(StandardField.AUTHOR, "Alpha von Beta"); + entry.setCitationKey("a1"); database.insertEntry(entry); entries.add(entry); entryDBMap.put(entry, database); - assertEquals("[von Beta, ]", style.getCitationMarker(entries, entryDBMap, true, null, null)); + assertEquals("[von Beta, ]", getCitationMarker2(style, entries, entryDBMap, true, null, null, null)); } @Test @@ -473,10 +443,11 @@ void testEmptyEntryMarker() throws IOException { BibEntry entry = new BibEntry(); entry.setType(StandardEntryType.Article); + entry.setCitationKey("a1"); database.insertEntry(entry); entries.add(entry); entryDBMap.put(entry, database); - assertEquals("[, ]", style.getCitationMarker(entries, entryDBMap, true, null, null)); + assertEquals("[, ]", getCitationMarker2(style, entries, entryDBMap, true, null, null, null)); } @Test @@ -492,17 +463,20 @@ void testGetCitationMarkerInParenthesisUniquefiers() throws IOException { entry1.setField(StandardField.AUTHOR, "Alpha Beta"); entry1.setField(StandardField.TITLE, "Paper 1"); entry1.setField(StandardField.YEAR, "2000"); + entry1.setCitationKey("a1"); entries.add(entry1); database.insertEntry(entry1); BibEntry entry3 = new BibEntry(); entry3.setField(StandardField.AUTHOR, "Alpha Beta"); entry3.setField(StandardField.TITLE, "Paper 2"); entry3.setField(StandardField.YEAR, "2000"); + entry3.setCitationKey("a3"); entries.add(entry3); database.insertEntry(entry3); BibEntry entry2 = new BibEntry(); entry2.setField(StandardField.AUTHOR, "Gamma Epsilon"); entry2.setField(StandardField.YEAR, "2001"); + entry2.setCitationKey("a2"); entries.add(entry2); database.insertEntry(entry2); for (BibEntry entry : database.getEntries()) { @@ -510,9 +484,12 @@ void testGetCitationMarkerInParenthesisUniquefiers() throws IOException { } assertEquals("[Beta, 2000; Beta, 2000; Epsilon, 2001]", - style.getCitationMarker(entries, entryDBMap, true, null, null)); + getCitationMarker2b(style, entries, entryDBMap, true, null, null, null)); assertEquals("[Beta, 2000a,b; Epsilon, 2001]", - style.getCitationMarker(entries, entryDBMap, true, new String[]{"a", "b", ""}, new int[]{1, 1, 1})); + getCitationMarker2(style, entries, entryDBMap, true, + new String[] {"a", "b", ""}, + new Boolean[] {false, false, false}, + null)); } @Test @@ -528,27 +505,33 @@ void testGetCitationMarkerInTextUniquefiers() throws IOException { entry1.setField(StandardField.AUTHOR, "Alpha Beta"); entry1.setField(StandardField.TITLE, "Paper 1"); entry1.setField(StandardField.YEAR, "2000"); + entry1.setCitationKey("a1"); entries.add(entry1); database.insertEntry(entry1); BibEntry entry3 = new BibEntry(); entry3.setField(StandardField.AUTHOR, "Alpha Beta"); entry3.setField(StandardField.TITLE, "Paper 2"); entry3.setField(StandardField.YEAR, "2000"); + entry3.setCitationKey("a3"); entries.add(entry3); database.insertEntry(entry3); BibEntry entry2 = new BibEntry(); entry2.setField(StandardField.AUTHOR, "Gamma Epsilon"); entry2.setField(StandardField.YEAR, "2001"); entries.add(entry2); + entry2.setCitationKey("a2"); database.insertEntry(entry2); for (BibEntry entry : database.getEntries()) { entryDBMap.put(entry, database); } assertEquals("Beta [2000]; Beta [2000]; Epsilon [2001]", - style.getCitationMarker(entries, entryDBMap, false, null, null)); + getCitationMarker2b(style, entries, entryDBMap, false, null, null, null)); assertEquals("Beta [2000a,b]; Epsilon [2001]", - style.getCitationMarker(entries, entryDBMap, false, new String[]{"a", "b", ""}, new int[]{1, 1, 1})); + getCitationMarker2(style, entries, entryDBMap, false, + new String[] {"a", "b", ""}, + new Boolean[] {false, false, false}, + null)); } @Test @@ -564,18 +547,21 @@ void testGetCitationMarkerInParenthesisUniquefiersThreeSameAuthor() throws IOExc entry1.setField(StandardField.AUTHOR, "Alpha Beta"); entry1.setField(StandardField.TITLE, "Paper 1"); entry1.setField(StandardField.YEAR, "2000"); + entry1.setCitationKey("a1"); entries.add(entry1); database.insertEntry(entry1); BibEntry entry2 = new BibEntry(); entry2.setField(StandardField.AUTHOR, "Alpha Beta"); entry2.setField(StandardField.TITLE, "Paper 2"); entry2.setField(StandardField.YEAR, "2000"); + entry2.setCitationKey("a2"); entries.add(entry2); database.insertEntry(entry2); BibEntry entry3 = new BibEntry(); entry3.setField(StandardField.AUTHOR, "Alpha Beta"); entry3.setField(StandardField.TITLE, "Paper 3"); entry3.setField(StandardField.YEAR, "2000"); + entry3.setCitationKey("a3"); entries.add(entry3); database.insertEntry(entry3); for (BibEntry entry : database.getEntries()) { @@ -583,7 +569,10 @@ void testGetCitationMarkerInParenthesisUniquefiersThreeSameAuthor() throws IOExc } assertEquals("[Beta, 2000a,b,c]", - style.getCitationMarker(entries, entryDBMap, true, new String[]{"a", "b", "c"}, new int[]{1, 1, 1})); + getCitationMarker2(style, entries, entryDBMap, true, + new String[] {"a", "b", "c"}, + new Boolean[] {false, false, false}, + null)); } @Test @@ -599,18 +588,21 @@ void testGetCitationMarkerInTextUniquefiersThreeSameAuthor() throws IOException entry1.setField(StandardField.AUTHOR, "Alpha Beta"); entry1.setField(StandardField.TITLE, "Paper 1"); entry1.setField(StandardField.YEAR, "2000"); + entry1.setCitationKey("a1"); entries.add(entry1); database.insertEntry(entry1); BibEntry entry2 = new BibEntry(); entry2.setField(StandardField.AUTHOR, "Alpha Beta"); entry2.setField(StandardField.TITLE, "Paper 2"); entry2.setField(StandardField.YEAR, "2000"); + entry2.setCitationKey("a2"); entries.add(entry2); database.insertEntry(entry2); BibEntry entry3 = new BibEntry(); entry3.setField(StandardField.AUTHOR, "Alpha Beta"); entry3.setField(StandardField.TITLE, "Paper 3"); entry3.setField(StandardField.YEAR, "2000"); + entry3.setCitationKey("a3"); entries.add(entry3); database.insertEntry(entry3); for (BibEntry entry : database.getEntries()) { @@ -618,11 +610,14 @@ void testGetCitationMarkerInTextUniquefiersThreeSameAuthor() throws IOException } assertEquals("Beta [2000a,b,c]", - style.getCitationMarker(entries, entryDBMap, false, new String[]{"a", "b", "c"}, new int[]{1, 1, 1})); + getCitationMarker2(style, entries, entryDBMap, false, + new String[] {"a", "b", "c"}, + new Boolean[] {false, false, false}, + null)); } @Test - // TODO: equals only work when initialized from file, not from reader + // TODO: equals only work when initialized from file, not from reader void testEquals() throws IOException { OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, layoutFormatterPreferences); @@ -632,7 +627,7 @@ void testEquals() throws IOException { } @Test - // TODO: equals only work when initialized from file, not from reader + // TODO: equals only work when initialized from file, not from reader void testNotEquals() throws IOException { OOBibStyle style1 = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, layoutFormatterPreferences); @@ -672,11 +667,12 @@ void testEmptyStringPropertyAndOxfordComma() throws Exception { entry.setField(StandardField.AUTHOR, "Alpha von Beta and Gamma Epsilon and Ypsilon Tau"); entry.setField(StandardField.TITLE, "JabRef Manual"); entry.setField(StandardField.YEAR, "2016"); + entry.setCitationKey("a1"); database.insertEntry(entry); entries.add(entry); entryDBMap.put(entry, database); assertEquals("von Beta, Epsilon, & Tau, 2016", - style.getCitationMarker(entries, entryDBMap, true, null, null)); + getCitationMarker2(style, entries, entryDBMap, true, null, null, null)); } @Test @@ -688,20 +684,20 @@ void testIsValidWithDefaultSectionAtTheStart() throws Exception { @Test void testGetCitationMarkerJoinFirst() throws IOException { OOBibStyle style = new OOBibStyle(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, - layoutFormatterPreferences); + layoutFormatterPreferences); - // Question: What should happen if some of the sources is + // Question: What should happen if some sources are // marked as isFirstAppearanceOfSource? // This test documents what is happening now. // Two entries with identical normalizedMarkers and many authors. BibEntry entry1 = new BibEntry() .withField(StandardField.AUTHOR, - "Gustav Bostr\\\"{o}m" - + " and Jaana W\\\"{a}yrynen" - + " and Marine Bod\\'{e}n" - + " and Konstantin Beznosov" - + " and Philippe Kruchten") + "Gustav Bostr\\\"{o}m" + + " and Jaana W\\\"{a}yrynen" + + " and Marine Bod\\'{e}n" + + " and Konstantin Beznosov" + + " and Philippe Kruchten") .withField(StandardField.YEAR, "2006") .withField(StandardField.BOOKTITLE, "A book 1") .withField(StandardField.PUBLISHER, "ACM") @@ -711,11 +707,11 @@ void testGetCitationMarkerJoinFirst() throws IOException { BibEntry entry2 = new BibEntry() .withField(StandardField.AUTHOR, - "Gustav Bostr\\\"{o}m" - + " and Jaana W\\\"{a}yrynen" - + " and Marine Bod\\'{e}n" - + " and Konstantin Beznosov" - + " and Philippe Kruchten") + "Gustav Bostr\\\"{o}m" + + " and Jaana W\\\"{a}yrynen" + + " and Marine Bod\\'{e}n" + + " and Konstantin Beznosov" + + " and Philippe Kruchten") .withField(StandardField.YEAR, "2006") .withField(StandardField.BOOKTITLE, "A book 2") .withField(StandardField.PUBLISHER, "ACM") @@ -726,11 +722,11 @@ void testGetCitationMarkerJoinFirst() throws IOException { // Last Author differs. BibEntry entry3 = new BibEntry() .withField(StandardField.AUTHOR, - "Gustav Bostr\\\"{o}m" - + " and Jaana W\\\"{a}yrynen" - + " and Marine Bod\\'{e}n" - + " and Konstantin Beznosov" - + " and Philippe NotKruchten") + "Gustav Bostr\\\"{o}m" + + " and Jaana W\\\"{a}yrynen" + + " and Marine Bod\\'{e}n" + + " and Konstantin Beznosov" + + " and Philippe NotKruchten") .withField(StandardField.YEAR, "2006") .withField(StandardField.BOOKTITLE, "A book 3") .withField(StandardField.PUBLISHER, "ACM") @@ -748,26 +744,26 @@ void testGetCitationMarkerJoinFirst() throws IOException { if (true) { List citationMarkerEntries = new ArrayList<>(); CitationMarkerEntry cm1 = - makeCitationMarkerEntry(entry1, database, "a", null, true); + makeCitationMarkerEntry(entry1, database, "a", null, true); citationMarkerEntries.add(cm1); CitationMarkerEntry cm2 = - makeCitationMarkerEntry(entry2, database, "b", null, true); + makeCitationMarkerEntry(entry2, database, "b", null, true); citationMarkerEntries.add(cm2); CitationMarkerEntry cm3 = - makeCitationMarkerEntry(entry3, database, "c", null, true); + makeCitationMarkerEntry(entry3, database, "c", null, true); citationMarkerEntries.add(cm3); assertEquals("[Boström, Wäyrynen, Bodén, Beznosov & Kruchten, 2006a,b" - + "; Boström, Wäyrynen, Bodén, Beznosov & NotKruchten, 2006c]", - style.createCitationMarker(citationMarkerEntries, - true, - NonUniqueCitationMarker.THROWS).toString()); + + "; Boström, Wäyrynen, Bodén, Beznosov & NotKruchten, 2006c]", + style.createCitationMarker(citationMarkerEntries, + true, + NonUniqueCitationMarker.THROWS).toString()); assertEquals("Boström, Wäyrynen, Bodén, Beznosov & Kruchten [2006a,b]" - + "; Boström, Wäyrynen, Bodén, Beznosov & NotKruchten [2006c]", - style.createCitationMarker(citationMarkerEntries, - false, - NonUniqueCitationMarker.THROWS).toString()); + + "; Boström, Wäyrynen, Bodén, Beznosov & NotKruchten [2006c]", + style.createCitationMarker(citationMarkerEntries, + false, + NonUniqueCitationMarker.THROWS).toString()); } // Without pageInfo, only the first is isFirstAppearanceOfSource. @@ -776,21 +772,20 @@ void testGetCitationMarkerJoinFirst() throws IOException { if (true) { List citationMarkerEntries = new ArrayList<>(); CitationMarkerEntry cm1 = - makeCitationMarkerEntry(entry1, database, "a", null, true); + makeCitationMarkerEntry(entry1, database, "a", null, true); citationMarkerEntries.add(cm1); CitationMarkerEntry cm2 = - makeCitationMarkerEntry(entry2, database, "b", null, false); + makeCitationMarkerEntry(entry2, database, "b", null, false); citationMarkerEntries.add(cm2); CitationMarkerEntry cm3 = - makeCitationMarkerEntry(entry3, database, "c", null, false); + makeCitationMarkerEntry(entry3, database, "c", null, false); citationMarkerEntries.add(cm3); assertEquals("[Boström, Wäyrynen, Bodén, Beznosov & Kruchten, 2006a,b" - + "; Boström et al., 2006c]", - style.createCitationMarker(citationMarkerEntries, - true, - NonUniqueCitationMarker.THROWS).toString()); - + + "; Boström et al., 2006c]", + style.createCitationMarker(citationMarkerEntries, + true, + NonUniqueCitationMarker.THROWS).toString()); } // Without pageInfo, only the second is isFirstAppearanceOfSource. // The second is not joined, because it is a first appearance, thus @@ -799,21 +794,21 @@ void testGetCitationMarkerJoinFirst() throws IOException { if (true) { List citationMarkerEntries = new ArrayList<>(); CitationMarkerEntry cm1 = - makeCitationMarkerEntry(entry1, database, "a", null, false); + makeCitationMarkerEntry(entry1, database, "a", null, false); citationMarkerEntries.add(cm1); CitationMarkerEntry cm2 = - makeCitationMarkerEntry(entry2, database, "b", null, true); + makeCitationMarkerEntry(entry2, database, "b", null, true); citationMarkerEntries.add(cm2); CitationMarkerEntry cm3 = - makeCitationMarkerEntry(entry3, database, "c", null, false); + makeCitationMarkerEntry(entry3, database, "c", null, false); citationMarkerEntries.add(cm3); assertEquals("[Boström et al., 2006a" - + "; Boström, Wäyrynen, Bodén, Beznosov & Kruchten, 2006b" - + "; Boström et al., 2006c]", - style.createCitationMarker(citationMarkerEntries, - true, - NonUniqueCitationMarker.THROWS).toString()); + + "; Boström, Wäyrynen, Bodén, Beznosov & Kruchten, 2006b" + + "; Boström et al., 2006c]", + style.createCitationMarker(citationMarkerEntries, + true, + NonUniqueCitationMarker.THROWS).toString()); } // Without pageInfo, neither is isFirstAppearanceOfSource. @@ -823,19 +818,19 @@ void testGetCitationMarkerJoinFirst() throws IOException { if (true) { List citationMarkerEntries = new ArrayList<>(); CitationMarkerEntry cm1 = - makeCitationMarkerEntry(entry1, database, "a", null, false); + makeCitationMarkerEntry(entry1, database, "a", null, false); citationMarkerEntries.add(cm1); CitationMarkerEntry cm2 = - makeCitationMarkerEntry(entry2, database, "b", null, false); + makeCitationMarkerEntry(entry2, database, "b", null, false); citationMarkerEntries.add(cm2); CitationMarkerEntry cm3 = - makeCitationMarkerEntry(entry3, database, "c", null, false); + makeCitationMarkerEntry(entry3, database, "c", null, false); citationMarkerEntries.add(cm3); assertEquals("[Boström et al., 2006a,b,c]", - style.createCitationMarker(citationMarkerEntries, - true, - NonUniqueCitationMarker.THROWS).toString()); + style.createCitationMarker(citationMarkerEntries, + true, + NonUniqueCitationMarker.THROWS).toString()); } // With pageInfo: different entries with identical non-null pageInfo: not joined. @@ -843,21 +838,21 @@ void testGetCitationMarkerJoinFirst() throws IOException { if (true) { List citationMarkerEntries = new ArrayList<>(); CitationMarkerEntry cm1 = - makeCitationMarkerEntry(entry1, database, "a", "p1", false); + makeCitationMarkerEntry(entry1, database, "a", "p1", false); citationMarkerEntries.add(cm1); CitationMarkerEntry cm2 = - makeCitationMarkerEntry(entry2, database, "b", "p1", false); + makeCitationMarkerEntry(entry2, database, "b", "p1", false); citationMarkerEntries.add(cm2); CitationMarkerEntry cm3 = - makeCitationMarkerEntry(entry3, database, "c", "p1", false); + makeCitationMarkerEntry(entry3, database, "c", "p1", false); citationMarkerEntries.add(cm3); assertEquals("[Boström et al., 2006a; p1" - + "; Boström et al., 2006b; p1" - + "; Boström et al., 2006c; p1]", - style.createCitationMarker(citationMarkerEntries, - true, - NonUniqueCitationMarker.THROWS).toString()); + + "; Boström et al., 2006b; p1" + + "; Boström et al., 2006c; p1]", + style.createCitationMarker(citationMarkerEntries, + true, + NonUniqueCitationMarker.THROWS).toString()); } // With pageInfo: same entries with identical non-null pageInfo: collapsed. @@ -866,43 +861,43 @@ void testGetCitationMarkerJoinFirst() throws IOException { if (true) { List citationMarkerEntries = new ArrayList<>(); CitationMarkerEntry cm1 = - makeCitationMarkerEntry(entry1, database, "a", "p1", false); + makeCitationMarkerEntry(entry1, database, "a", "p1", false); citationMarkerEntries.add(cm1); CitationMarkerEntry cm2 = - makeCitationMarkerEntry(entry1, database, "a", "p1", false); + makeCitationMarkerEntry(entry1, database, "a", "p1", false); citationMarkerEntries.add(cm2); CitationMarkerEntry cm3 = - makeCitationMarkerEntry(entry1, database, "a", "p1", false); + makeCitationMarkerEntry(entry1, database, "a", "p1", false); citationMarkerEntries.add(cm3); assertEquals("[Boström et al., 2006a; p1]", - style.createCitationMarker(citationMarkerEntries, - true, - NonUniqueCitationMarker.THROWS).toString()); + style.createCitationMarker(citationMarkerEntries, + true, + NonUniqueCitationMarker.THROWS).toString()); } // With pageInfo: same entries with different pageInfo: kept separate. // Empty ("") and missing pageInfos considered equal, thus collapsed. if (true) { List citationMarkerEntries = new ArrayList<>(); CitationMarkerEntry cm1 = - makeCitationMarkerEntry(entry1, database, "a", "p1", false); + makeCitationMarkerEntry(entry1, database, "a", "p1", false); citationMarkerEntries.add(cm1); CitationMarkerEntry cm2 = - makeCitationMarkerEntry(entry1, database, "a", "p2", false); + makeCitationMarkerEntry(entry1, database, "a", "p2", false); citationMarkerEntries.add(cm2); CitationMarkerEntry cm3 = - makeCitationMarkerEntry(entry1, database, "a", "", false); + makeCitationMarkerEntry(entry1, database, "a", "", false); citationMarkerEntries.add(cm3); CitationMarkerEntry cm4 = - makeCitationMarkerEntry(entry1, database, "a", null, false); + makeCitationMarkerEntry(entry1, database, "a", null, false); citationMarkerEntries.add(cm4); assertEquals("[Boström et al., 2006a; p1" - + "; Boström et al., 2006a; p2" - + "; Boström et al., 2006a]", - style.createCitationMarker(citationMarkerEntries, - true, - NonUniqueCitationMarker.THROWS).toString()); + + "; Boström et al., 2006a; p2" + + "; Boström et al., 2006a]", + style.createCitationMarker(citationMarkerEntries, + true, + NonUniqueCitationMarker.THROWS).toString()); } } } diff --git a/src/test/java/org/jabref/logic/openoffice/style/OOBibStyleTestHelper.java b/src/test/java/org/jabref/logic/openoffice/style/OOBibStyleTestHelper.java index ae5e83abd2f..4ab0c6ef5d3 100644 --- a/src/test/java/org/jabref/logic/openoffice/style/OOBibStyleTestHelper.java +++ b/src/test/java/org/jabref/logic/openoffice/style/OOBibStyleTestHelper.java @@ -1,6 +1,5 @@ package org.jabref.logic.openoffice.style; -import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -23,10 +22,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; class OOBibStyleTestHelper { - /* - * begin Helpers for testing style.getNumCitationMarker2 - */ - /* * Minimal implementation for CitationMarkerNumericEntry */ @@ -37,15 +32,15 @@ static class CitationMarkerNumericEntryImpl implements CitationMarkerNumericEntr */ public final static int UNRESOLVED_ENTRY_NUMBER = 0; - private String citationKey; - private Optional num; - private Optional pageInfo; + private final String citationKey; + private final Optional num; + private final Optional pageInfo; public CitationMarkerNumericEntryImpl(String citationKey, int num, Optional pageInfo) { this.citationKey = citationKey; this.num = (num == UNRESOLVED_ENTRY_NUMBER - ? Optional.empty() - : Optional.of(num)); + ? Optional.empty() + : Optional.of(num)); this.pageInfo = PageInfo.normalizePageInfo(pageInfo); } @@ -98,22 +93,21 @@ static String runGetNumCitationMarker2a(OOBibStyle style, List num, int minGroupingCount, boolean inList) { if (inList) { if (num.size() != 1) { - throw new IllegalArgumentException("Numeric label for the bibliography with " - + String.valueOf(num.size()) + " numbers?"); + throw new IllegalArgumentException("Numeric label for the bibliography with " + num.size() + " numbers?"); } int n = num.get(0); CitationMarkerNumericBibEntryImpl x = - new CitationMarkerNumericBibEntryImpl("key", - (n == 0) ? Optional.empty() : Optional.of(n)); + new CitationMarkerNumericBibEntryImpl("key", + (n == 0) ? Optional.empty() : Optional.of(n)); return style.getNumCitationMarkerForBibliography(x).toString(); } else { List input = - num.stream() - .map(n -> - new CitationMarkerNumericEntryImpl("key" + String.valueOf(n), - n, - Optional.empty())) - .collect(Collectors.toList()); + num.stream() + .map(n -> + new CitationMarkerNumericEntryImpl("key" + n, + n, + Optional.empty())) + .collect(Collectors.toList()); return style.getNumCitationMarker2(input, minGroupingCount).toString(); } } @@ -163,13 +157,14 @@ static CitationMarkerEntry makeCitationMarkerEntry(BibEntry entry, * Similar to old API. pageInfo is new, and unlimAuthors is * replaced with isFirstAppearanceOfSource */ - static String getCitationMarker2(OOBibStyle style, - List entries, - Map entryDBMap, - boolean inParenthesis, - String[] uniquefiers, - Boolean[] isFirstAppearanceOfSource, - String[] pageInfo) { + static String getCitationMarker2ab(OOBibStyle style, + List entries, + Map entryDBMap, + boolean inParenthesis, + String[] uniquefiers, + Boolean[] isFirstAppearanceOfSource, + String[] pageInfo, + NonUniqueCitationMarker nonunique) { if (uniquefiers == null) { uniquefiers = new String[entries.size()]; Arrays.fill(uniquefiers, null); @@ -186,151 +181,185 @@ static String getCitationMarker2(OOBibStyle style, for (int i = 0; i < entries.size(); i++) { BibEntry entry = entries.get(i); CitationMarkerEntry e = makeCitationMarkerEntry(entry, - entryDBMap.get(entry), - uniquefiers[i], - pageInfo[i], - isFirstAppearanceOfSource[i]); + entryDBMap.get(entry), + uniquefiers[i], + pageInfo[i], + isFirstAppearanceOfSource[i]); citationMarkerEntries.add(e); } return style.createCitationMarker(citationMarkerEntries, - inParenthesis, - NonUniqueCitationMarker.THROWS).toString(); + inParenthesis, + nonunique).toString(); + } + + static String getCitationMarker2(OOBibStyle style, + List entries, + Map entryDBMap, + boolean inParenthesis, + String[] uniquefiers, + Boolean[] isFirstAppearanceOfSource, + String[] pageInfo) { + return getCitationMarker2ab(style, + entries, + entryDBMap, + inParenthesis, + uniquefiers, + isFirstAppearanceOfSource, + pageInfo, + NonUniqueCitationMarker.THROWS); + } + + static String getCitationMarker2b(OOBibStyle style, + List entries, + Map entryDBMap, + boolean inParenthesis, + String[] uniquefiers, + Boolean[] isFirstAppearanceOfSource, + String[] pageInfo) { + return getCitationMarker2ab(style, + entries, + entryDBMap, + inParenthesis, + uniquefiers, + isFirstAppearanceOfSource, + pageInfo, + NonUniqueCitationMarker.FORGIVEN); } /* * end helper */ - static void testGetNumCitationMarkerExtra(OOBibStyle style) throws IOException { + static void testGetNumCitationMarkerExtra(OOBibStyle style) { // Identical numeric entries are joined. assertEquals("[1; 2]", runGetNumCitationMarker2b(style, 3, - numEntry("x1", 1, null), - numEntry("x2", 2, null), - numEntry("x1", 2, null), - numEntry("x2", 1, null))); + numEntry("x1", 1, null), + numEntry("x2", 2, null), + numEntry("x1", 2, null), + numEntry("x2", 1, null))); // ... unless minGroupingCount <= 0 assertEquals("[1; 1; 2; 2]", runGetNumCitationMarker2b(style, 0, - numEntry("x1", 1, null), - numEntry("x2", 2, null), - numEntry("x1", 2, null), - numEntry("x2", 1, null))); + numEntry("x1", 1, null), + numEntry("x2", 2, null), + numEntry("x1", 2, null), + numEntry("x2", 1, null))); // ... or have different pageInfos assertEquals("[1; p1a; 1; p1b; 2; p2; 3]", runGetNumCitationMarker2b(style, 1, - numEntry("x1", 1, "p1a"), - numEntry("x1", 1, "p1b"), - numEntry("x2", 2, "p2"), - numEntry("x2", 2, "p2"), - numEntry("x3", 3, null), - numEntry("x3", 3, null))); + numEntry("x1", 1, "p1a"), + numEntry("x1", 1, "p1b"), + numEntry("x2", 2, "p2"), + numEntry("x2", 2, "p2"), + numEntry("x3", 3, null), + numEntry("x3", 3, null))); // Consecutive numbers can become a range ... assertEquals("[1-3]", runGetNumCitationMarker2b(style, 1, - numEntry("x1", 1, null), - numEntry("x2", 2, null), - numEntry("x3", 3, null))); + numEntry("x1", 1, null), + numEntry("x2", 2, null), + numEntry("x3", 3, null))); // ... unless minGroupingCount is too high assertEquals("[1; 2; 3]", runGetNumCitationMarker2b(style, 4, - numEntry("x1", 1, null), - numEntry("x2", 2, null), - numEntry("x3", 3, null))); + numEntry("x1", 1, null), + numEntry("x2", 2, null), + numEntry("x3", 3, null))); // ... or if minGroupingCount <= 0 assertEquals("[1; 2; 3]", runGetNumCitationMarker2b(style, 0, - numEntry("x1", 1, null), - numEntry("x2", 2, null), - numEntry("x3", 3, null))); + numEntry("x1", 1, null), + numEntry("x2", 2, null), + numEntry("x3", 3, null))); // ... a pageInfo needs to be emitted assertEquals("[1; p1; 2-3]", runGetNumCitationMarker2b(style, 1, - numEntry("x1", 1, "p1"), - numEntry("x2", 2, null), - numEntry("x3", 3, null))); + numEntry("x1", 1, "p1"), + numEntry("x2", 2, null), + numEntry("x3", 3, null))); // null and "" pageInfos are taken as equal. // Due to trimming, " " is the same as well. assertEquals("[1]", runGetNumCitationMarker2b(style, 1, - numEntry("x1", 1, ""), - numEntry("x1", 1, null), - numEntry("x1", 1, " "))); + numEntry("x1", 1, ""), + numEntry("x1", 1, null), + numEntry("x1", 1, " "))); // pageInfos are trimmed assertEquals("[1; p1]", runGetNumCitationMarker2b(style, 1, - numEntry("x1", 1, "p1"), - numEntry("x1", 1, " p1"), - numEntry("x1", 1, "p1 "))); + numEntry("x1", 1, "p1"), + numEntry("x1", 1, " p1"), + numEntry("x1", 1, "p1 "))); // The citation numbers come out sorted assertEquals("[3-5; 7; 10-12]", runGetNumCitationMarker2b(style, 1, - numEntry("x12", 12, null), - numEntry("x7", 7, null), - numEntry("x3", 3, null), - numEntry("x4", 4, null), - numEntry("x11", 11, null), - numEntry("x10", 10, null), - numEntry("x5", 5, null))); + numEntry("x12", 12, null), + numEntry("x7", 7, null), + numEntry("x3", 3, null), + numEntry("x4", 4, null), + numEntry("x11", 11, null), + numEntry("x10", 10, null), + numEntry("x5", 5, null))); // pageInfos are sorted together with the numbers // (but they inhibit ranges where they are, even if they are identical, // but not empty-or-null) assertEquals("[3; p3; 4; p4; 5; p5; 7; p7; 10; px; 11; px; 12; px]", - runGetNumCitationMarker2b(style, 1, - numEntry("x12", 12, "px"), - numEntry("x7", 7, "p7"), - numEntry("x3", 3, "p3"), - numEntry("x4", 4, "p4"), - numEntry("x11", 11, "px"), - numEntry("x10", 10, "px"), - numEntry("x5", 5, "p5"))); + runGetNumCitationMarker2b(style, 1, + numEntry("x12", 12, "px"), + numEntry("x7", 7, "p7"), + numEntry("x3", 3, "p3"), + numEntry("x4", 4, "p4"), + numEntry("x11", 11, "px"), + numEntry("x10", 10, "px"), + numEntry("x5", 5, "p5"))); // pageInfo sorting (for the same number) assertEquals("[1; 1; a; 1; b]", - runGetNumCitationMarker2b(style, 1, - numEntry("x1", 1, ""), - numEntry("x1", 1, "b"), - numEntry("x1", 1, "a"))); + runGetNumCitationMarker2b(style, 1, + numEntry("x1", 1, ""), + numEntry("x1", 1, "b"), + numEntry("x1", 1, "a"))); // pageInfo sorting (for the same number) is not numeric. assertEquals("[1; p100; 1; p20; 1; p9]", - runGetNumCitationMarker2b(style, 1, - numEntry("x1", 1, "p20"), - numEntry("x1", 1, "p9"), - numEntry("x1", 1, "p100"))); + runGetNumCitationMarker2b(style, 1, + numEntry("x1", 1, "p20"), + numEntry("x1", 1, "p9"), + numEntry("x1", 1, "p100"))); assertEquals("[1-3]", - runGetNumCitationMarker2b(style, 1, - numEntry("x1", 1, null), - numEntry("x2", 2, null), - numEntry("x3", 3, null))); + runGetNumCitationMarker2b(style, 1, + numEntry("x1", 1, null), + numEntry("x2", 2, null), + numEntry("x3", 3, null))); assertEquals("[1; 2; 3]", - runGetNumCitationMarker2b(style, 5, - numEntry("x1", 1, null), - numEntry("x2", 2, null), - numEntry("x3", 3, null))); + runGetNumCitationMarker2b(style, 5, + numEntry("x1", 1, null), + numEntry("x2", 2, null), + numEntry("x3", 3, null))); assertEquals("[1; 2; 3]", - runGetNumCitationMarker2b(style, -1, - numEntry("x1", 1, null), - numEntry("x2", 2, null), - numEntry("x3", 3, null))); + runGetNumCitationMarker2b(style, -1, + numEntry("x1", 1, null), + numEntry("x2", 2, null), + numEntry("x3", 3, null))); assertEquals("[1; 3; 12]", - runGetNumCitationMarker2b(style, 1, - numEntry("x1", 1, null), - numEntry("x12", 12, null), - numEntry("x3", 3, null))); + runGetNumCitationMarker2b(style, 1, + numEntry("x1", 1, null), + numEntry("x12", 12, null), + numEntry("x3", 3, null))); assertEquals("[3-5; 7; 10-12]", - runGetNumCitationMarker2b(style, 1, - numEntry("x12", 12, ""), - numEntry("x7", 7, ""), - numEntry("x3", 3, ""), - numEntry("x4", 4, ""), - numEntry("x11", 11, ""), - numEntry("x10", 10, ""), - numEntry("x5", 5, ""))); + runGetNumCitationMarker2b(style, 1, + numEntry("x12", 12, ""), + numEntry("x7", 7, ""), + numEntry("x3", 3, ""), + numEntry("x4", 4, ""), + numEntry("x11", 11, ""), + numEntry("x10", 10, ""), + numEntry("x5", 5, ""))); } } diff --git a/src/test/java/org/jabref/logic/openoffice/style/StyleLoaderTest.java b/src/test/java/org/jabref/logic/openoffice/style/StyleLoaderTest.java index 9b5a58f4de5..50382895b56 100644 --- a/src/test/java/org/jabref/logic/openoffice/style/StyleLoaderTest.java +++ b/src/test/java/org/jabref/logic/openoffice/style/StyleLoaderTest.java @@ -40,23 +40,18 @@ public void setUp() { @Test public void throwNPEWithNullPreferences() { - assertThrows(NullPointerException.class, () -> loader = new StyleLoader(null, layoutPreferences, mock(Charset.class))); + assertThrows(NullPointerException.class, () -> loader = new StyleLoader(null, layoutPreferences)); } @Test public void throwNPEWithNullLayoutPreferences() { - assertThrows(NullPointerException.class, () -> loader = new StyleLoader(mock(OpenOfficePreferences.class), null, mock(Charset.class))); - } - - @Test - public void throwNPEWithNullCharset() { - assertThrows(NullPointerException.class, () -> loader = new StyleLoader(mock(OpenOfficePreferences.class), layoutPreferences, null)); + assertThrows(NullPointerException.class, () -> loader = new StyleLoader(mock(OpenOfficePreferences.class), null)); } @Test public void testGetStylesWithEmptyExternal() { preferences.setExternalStyles(Collections.emptyList()); - loader = new StyleLoader(preferences, layoutPreferences, encoding); + loader = new StyleLoader(preferences, layoutPreferences); assertEquals(2, loader.getStyles().size()); } @@ -64,7 +59,7 @@ public void testGetStylesWithEmptyExternal() { @Test public void testAddStyleLeadsToOneMoreStyle() throws URISyntaxException { preferences.setExternalStyles(Collections.emptyList()); - loader = new StyleLoader(preferences, layoutPreferences, encoding); + loader = new StyleLoader(preferences, layoutPreferences); String filename = Path.of(StyleLoader.class.getResource(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH).toURI()) .toFile().getPath(); @@ -75,7 +70,7 @@ public void testAddStyleLeadsToOneMoreStyle() throws URISyntaxException { @Test public void testAddInvalidStyleLeadsToNoMoreStyle() { preferences.setExternalStyles(Collections.emptyList()); - loader = new StyleLoader(preferences, layoutPreferences, encoding); + loader = new StyleLoader(preferences, layoutPreferences); int beforeAdding = loader.getStyles().size(); loader.addStyleIfValid("DefinitelyNotAValidFileNameOrWeAreExtremelyUnlucky"); assertEquals(beforeAdding, loader.getStyles().size()); @@ -84,9 +79,9 @@ public void testAddInvalidStyleLeadsToNoMoreStyle() { @Test public void testInitalizeWithOneExternalFile() throws URISyntaxException { String filename = Path.of(StyleLoader.class.getResource(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH).toURI()) - .toFile().getPath(); + .toFile().getPath(); when(preferences.getExternalStyles()).thenReturn(Collections.singletonList(filename)); - loader = new StyleLoader(preferences, layoutPreferences, encoding); + loader = new StyleLoader(preferences, layoutPreferences); assertEquals(NUMBER_OF_INTERNAL_STYLES + 1, loader.getStyles().size()); } @@ -94,17 +89,17 @@ public void testInitalizeWithOneExternalFile() throws URISyntaxException { public void testInitalizeWithIncorrectExternalFile() { preferences.setExternalStyles(Collections.singletonList("DefinitelyNotAValidFileNameOrWeAreExtremelyUnlucky")); - loader = new StyleLoader(preferences, layoutPreferences, encoding); + loader = new StyleLoader(preferences, layoutPreferences); assertEquals(NUMBER_OF_INTERNAL_STYLES, loader.getStyles().size()); } @Test public void testInitalizeWithOneExternalFileRemoveStyle() throws URISyntaxException { String filename = Path.of(StyleLoader.class.getResource(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH).toURI()) - .toFile().getPath(); + .toFile().getPath(); when(preferences.getExternalStyles()).thenReturn(Collections.singletonList(filename)); - loader = new StyleLoader(preferences, layoutPreferences, encoding); + loader = new StyleLoader(preferences, layoutPreferences); List toremove = new ArrayList<>(); int beforeRemoving = loader.getStyles().size(); for (OOBibStyle style : loader.getStyles()) { @@ -122,10 +117,10 @@ public void testInitalizeWithOneExternalFileRemoveStyle() throws URISyntaxExcept @Test public void testInitalizeWithOneExternalFileRemoveStyleUpdatesPreferences() throws URISyntaxException { String filename = Path.of(StyleLoader.class.getResource(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH).toURI()) - .toFile().getPath(); + .toFile().getPath(); when(preferences.getExternalStyles()).thenReturn(Collections.singletonList(filename)); - loader = new StyleLoader(preferences, layoutPreferences, encoding); + loader = new StyleLoader(preferences, layoutPreferences); List toremove = new ArrayList<>(); for (OOBibStyle style : loader.getStyles()) { if (!style.isInternalStyle()) { @@ -143,10 +138,10 @@ public void testInitalizeWithOneExternalFileRemoveStyleUpdatesPreferences() thro @Test public void testAddSameStyleTwiceLeadsToOneMoreStyle() throws URISyntaxException { preferences.setExternalStyles(Collections.emptyList()); - loader = new StyleLoader(preferences, layoutPreferences, encoding); + loader = new StyleLoader(preferences, layoutPreferences); int beforeAdding = loader.getStyles().size(); String filename = Path.of(StyleLoader.class.getResource(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH).toURI()) - .toFile().getPath(); + .toFile().getPath(); loader.addStyleIfValid(filename); loader.addStyleIfValid(filename); assertEquals(beforeAdding + 1, loader.getStyles().size()); @@ -154,7 +149,7 @@ public void testAddSameStyleTwiceLeadsToOneMoreStyle() throws URISyntaxException @Test public void testAddNullStyleThrowsNPE() { - loader = new StyleLoader(preferences, layoutPreferences, encoding); + loader = new StyleLoader(preferences, layoutPreferences); assertThrows(NullPointerException.class, () -> loader.addStyleIfValid(null)); } @@ -162,7 +157,7 @@ public void testAddNullStyleThrowsNPE() { public void testGetDefaultUsedStyleWhenEmpty() { when(preferences.getCurrentStyle()).thenReturn(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH); preferences.clearCurrentStyle(); - loader = new StyleLoader(preferences, layoutPreferences, encoding); + loader = new StyleLoader(preferences, layoutPreferences); OOBibStyle style = loader.getUsedStyle(); assertTrue(style.isValid()); assertEquals(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH, style.getPath()); @@ -172,7 +167,7 @@ public void testGetDefaultUsedStyleWhenEmpty() { @Test public void testGetStoredUsedStyle() { when(preferences.getCurrentStyle()).thenReturn(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH); - loader = new StyleLoader(preferences, layoutPreferences, encoding); + loader = new StyleLoader(preferences, layoutPreferences); OOBibStyle style = loader.getUsedStyle(); assertTrue(style.isValid()); assertEquals(StyleLoader.DEFAULT_NUMERICAL_STYLE_PATH, style.getPath()); @@ -182,7 +177,7 @@ public void testGetStoredUsedStyle() { @Test public void testGetDefaultUsedStyleWhenIncorrect() { when(preferences.getCurrentStyle()).thenReturn("ljlkjlkjnljnvdlsjniuhwelfhuewfhlkuewhfuwhelu"); - loader = new StyleLoader(preferences, layoutPreferences, encoding); + loader = new StyleLoader(preferences, layoutPreferences); OOBibStyle style = loader.getUsedStyle(); assertTrue(style.isValid()); assertEquals(StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH, style.getPath()); @@ -192,7 +187,7 @@ public void testGetDefaultUsedStyleWhenIncorrect() { public void testRemoveInternalStyleReturnsFalseAndDoNotRemove() { preferences.setExternalStyles(Collections.emptyList()); - loader = new StyleLoader(preferences, layoutPreferences, encoding); + loader = new StyleLoader(preferences, layoutPreferences); List toremove = new ArrayList<>(); for (OOBibStyle style : loader.getStyles()) { if (style.isInternalStyle()) { diff --git a/src/test/java/org/jabref/logic/remote/RemoteSetupTest.java b/src/test/java/org/jabref/logic/remote/RemoteSetupTest.java index 37598a854ec..cd3f7905c13 100644 --- a/src/test/java/org/jabref/logic/remote/RemoteSetupTest.java +++ b/src/test/java/org/jabref/logic/remote/RemoteSetupTest.java @@ -20,6 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -94,7 +95,7 @@ void testPortAlreadyInUse() throws IOException { assertFalse(server.isOpen()); server.openAndStart(messageHandler, port, preferencesService); assertFalse(server.isOpen()); - verify(messageHandler, never()).handleCommandLineArguments(any(), preferencesService); + verify(messageHandler, never()).handleCommandLineArguments(any(), eq(preferencesService)); } } } diff --git a/src/test/java/org/jabref/logic/texparser/LatexParserTest.java b/src/test/java/org/jabref/logic/texparser/LatexParserTest.java index 6cdfc20d9df..95355121317 100644 --- a/src/test/java/org/jabref/logic/texparser/LatexParserTest.java +++ b/src/test/java/org/jabref/logic/texparser/LatexParserTest.java @@ -1,7 +1,6 @@ package org.jabref.logic.texparser; import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Arrays; @@ -22,7 +21,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; public class LatexParserTest { private final static String DARWIN = "Darwin1888"; @@ -41,7 +39,6 @@ public class LatexParserTest { @BeforeEach private void setUp() { generalPreferences = mock(GeneralPreferences.class, Answers.RETURNS_DEEP_STUBS); - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.UTF_8); importFormatPreferences = mock(ImportFormatPreferences.class, Answers.RETURNS_DEEP_STUBS); database = new BibDatabase(); diff --git a/src/test/java/org/jabref/logic/texparser/TexBibEntriesResolverTest.java b/src/test/java/org/jabref/logic/texparser/TexBibEntriesResolverTest.java index 773851c147d..ca90e30330f 100644 --- a/src/test/java/org/jabref/logic/texparser/TexBibEntriesResolverTest.java +++ b/src/test/java/org/jabref/logic/texparser/TexBibEntriesResolverTest.java @@ -1,7 +1,6 @@ package org.jabref.logic.texparser; import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Arrays; @@ -22,7 +21,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; public class TexBibEntriesResolverTest { private final static String DARWIN = "Darwin1888"; @@ -42,7 +40,6 @@ public class TexBibEntriesResolverTest { @BeforeEach private void setUp() { generalPreferences = mock(GeneralPreferences.class, Answers.RETURNS_DEEP_STUBS); - when(generalPreferences.getDefaultEncoding()).thenReturn(StandardCharsets.UTF_8); importFormatPreferences = mock(ImportFormatPreferences.class, Answers.RETURNS_DEEP_STUBS); database = new BibDatabase(); diff --git a/src/test/java/org/jabref/logic/xmp/XmpUtilReaderTest.java b/src/test/java/org/jabref/logic/xmp/XmpUtilReaderTest.java index 8f012187d37..0573cf0c17c 100644 --- a/src/test/java/org/jabref/logic/xmp/XmpUtilReaderTest.java +++ b/src/test/java/org/jabref/logic/xmp/XmpUtilReaderTest.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Arrays; import java.util.Collections; @@ -10,11 +9,11 @@ import java.util.Optional; import org.jabref.logic.importer.ImportFormatPreferences; -import org.jabref.logic.importer.ParseException; import org.jabref.logic.importer.fileformat.BibtexImporter; import org.jabref.logic.importer.fileformat.BibtexParser; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.LinkedFile; +import org.jabref.model.schema.DublinCoreSchemaCustom; import org.jabref.model.util.DummyFileUpdateMonitor; import org.apache.xmpbox.XMPMetadata; @@ -53,16 +52,16 @@ void setUp() { * Tests reading of dublinCore metadata. */ @Test - void testReadArticleDublinCoreReadRawXmp() throws IOException, URISyntaxException, ParseException { - Path path = Path.of(XmpUtilShared.class.getResource("article_dublinCore.pdf").toURI()); + void testReadArticleDublinCoreReadRawXmp() throws IOException, URISyntaxException { + Path path = Path.of(XmpUtilShared.class.getResource("article_dublinCore_without_day.pdf").toURI()); List meta = XmpUtilReader.readRawXmp(path); - DublinCoreSchema dcSchema = meta.get(0).getDublinCoreSchema(); + DublinCoreSchema dcSchema = DublinCoreSchemaCustom.copyDublinCoreSchema(meta.get(0).getDublinCoreSchema()); DublinCoreExtractor dcExtractor = new DublinCoreExtractor(dcSchema, xmpPreferences, new BibEntry()); Optional entry = dcExtractor.extractBibtexEntry(); - Path bibFile = Path.of(XmpUtilShared.class.getResource("article_dublinCore.bib").toURI()); - List expected = testImporter.importDatabase(bibFile, StandardCharsets.UTF_8).getDatabase().getEntries(); + Path bibFile = Path.of(XmpUtilShared.class.getResource("article_dublinCore_without_day.bib").toURI()); + List expected = testImporter.importDatabase(bibFile).getDatabase().getEntries(); assertEquals(expected, Collections.singletonList(entry.get())); } @@ -75,7 +74,7 @@ void testReadArticleDublinCoreReadXmp() throws IOException, URISyntaxException { Path pathPdf = Path.of(XmpUtilShared.class.getResource("article_dublinCore.pdf").toURI()); List entries = XmpUtilReader.readXmp(pathPdf, xmpPreferences); Path bibFile = Path.of(XmpUtilShared.class.getResource("article_dublinCore.bib").toURI()); - List expected = testImporter.importDatabase(bibFile, StandardCharsets.UTF_8).getDatabase().getEntries(); + List expected = testImporter.importDatabase(bibFile).getDatabase().getEntries(); expected.forEach(bibEntry -> bibEntry.setFiles(Arrays.asList( new LinkedFile("", Path.of("paper.pdf"), "PDF"), @@ -85,6 +84,20 @@ void testReadArticleDublinCoreReadXmp() throws IOException, URISyntaxException { assertEquals(expected, entries); } + @Test + void testReadArticleDublinCoreReadXmpPartialDate() throws IOException, URISyntaxException { + Path pathPdf = Path.of(XmpUtilShared.class.getResource("article_dublinCore_partial_date.pdf").toURI()); + List entries = XmpUtilReader.readXmp(pathPdf, xmpPreferences); + Path bibFile = Path.of(XmpUtilShared.class.getResource("article_dublinCore_partial_date.bib").toURI()); + List expected = testImporter.importDatabase(bibFile).getDatabase().getEntries(); + + expected.forEach(bibEntry -> bibEntry.setFiles(Arrays.asList( + new LinkedFile("", pathPdf.toAbsolutePath(), "PDF")) + )); + + assertEquals(expected, entries); + } + /** * Tests an pdf file with an empty metadata section. */ @@ -103,7 +116,7 @@ void testReadPDMetadata() throws IOException, URISyntaxException { List entries = XmpUtilReader.readXmp(pathPdf, xmpPreferences); Path bibFile = Path.of(XmpUtilShared.class.getResource("PD_metadata.bib").toURI()); - List expected = testImporter.importDatabase(bibFile, StandardCharsets.UTF_8).getDatabase().getEntries(); + List expected = testImporter.importDatabase(bibFile).getDatabase().getEntries(); expected.forEach(bibEntry -> bibEntry.setFiles(Arrays.asList( new LinkedFile("", pathPdf.toAbsolutePath(), "PDF")) diff --git a/src/test/java/org/jabref/logic/xmp/XmpUtilWriterTest.java b/src/test/java/org/jabref/logic/xmp/XmpUtilWriterTest.java index 6013264bea4..537e0d08a42 100644 --- a/src/test/java/org/jabref/logic/xmp/XmpUtilWriterTest.java +++ b/src/test/java/org/jabref/logic/xmp/XmpUtilWriterTest.java @@ -8,8 +8,10 @@ import javax.xml.transform.TransformerException; import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.Date; import org.jabref.model.entry.Month; import org.jabref.model.entry.field.StandardField; +import org.jabref.model.entry.field.UnknownField; import org.jabref.model.entry.types.StandardEntryType; import org.apache.pdfbox.pdmodel.PDDocument; @@ -18,6 +20,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; +import static org.jabref.logic.xmp.DublinCoreExtractor.DC_COVERAGE; +import static org.jabref.logic.xmp.DublinCoreExtractor.DC_RIGHTS; +import static org.jabref.logic.xmp.DublinCoreExtractor.DC_SOURCE; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -68,6 +73,12 @@ private void initBibEntries() { vapnik2000.setField(StandardField.AUTHOR, "Vladimir N. Vapnik"); vapnik2000.setField(StandardField.DOI, "10.1007/978-1-4757-3264-1"); vapnik2000.setField(StandardField.OWNER, "Ich"); + vapnik2000.setField(StandardField.LANGUAGE, "English, Japanese"); + vapnik2000.setDate(new Date(2000, 5)); + + vapnik2000.setField(new UnknownField(DC_COVERAGE), "coverageField"); + vapnik2000.setField(new UnknownField((DC_SOURCE)), "JabRef"); + vapnik2000.setField(new UnknownField(DC_RIGHTS), "Right To X"); } /** diff --git a/src/test/java/org/jabref/model/entry/BibEntryTypesManagerTest.java b/src/test/java/org/jabref/model/entry/BibEntryTypesManagerTest.java index 5cd22cda058..0e20b77f3fd 100644 --- a/src/test/java/org/jabref/model/entry/BibEntryTypesManagerTest.java +++ b/src/test/java/org/jabref/model/entry/BibEntryTypesManagerTest.java @@ -172,7 +172,7 @@ void testsModifyingArticle(BibDatabaseMode mode) { Collections.emptySet()); entryTypesManager.addCustomOrModifiedType(overwrittenStandardType, mode); - assertEquals(Collections.singletonList(overwrittenStandardType), entryTypesManager.getAllTypes(mode).stream().filter(t->t.getType().getName().equals("article")).collect(Collectors.toList())); + assertEquals(Collections.singletonList(overwrittenStandardType), entryTypesManager.getAllTypes(mode).stream().filter(t -> t.getType().getName().equals("article")).collect(Collectors.toList())); } @ParameterizedTest diff --git a/src/test/java/org/jabref/model/openoffice/CitationEntryTest.java b/src/test/java/org/jabref/model/openoffice/CitationEntryTest.java index fd7ec48b9b3..8648d9b5df9 100644 --- a/src/test/java/org/jabref/model/openoffice/CitationEntryTest.java +++ b/src/test/java/org/jabref/model/openoffice/CitationEntryTest.java @@ -11,7 +11,7 @@ class CitationEntryTest { @Test - void testCitationEntryInitalPageInfo() { + void testCitationEntryInitialPageInfo() { CitationEntry citationEntry = new CitationEntry("RefMark", "Context", "Info"); assertTrue(citationEntry.getPageInfo().isPresent()); assertEquals("Info", citationEntry.getPageInfo().get()); @@ -20,7 +20,7 @@ void testCitationEntryInitalPageInfo() { } @Test - void testCitationEntryOptionalInitalPageInfo() { + void testCitationEntryOptionalInitialPageInfo() { CitationEntry citationEntry = new CitationEntry("RefMark", "Context", Optional.of("Info")); assertEquals(Optional.of("Info"), citationEntry.getPageInfo()); @@ -35,7 +35,7 @@ void testCitationEntryInitalPageInfoChanged() { } @Test - void testCitationEntryNoInitalPageInfo() { + void testCitationEntryNoInitialPageInfo() { CitationEntry citationEntry = new CitationEntry("RefMark", "Context"); assertEquals(Optional.empty(), citationEntry.getPageInfo()); } diff --git a/src/test/resources/org/jabref/logic/auxparser/papertwoargmacro.aux b/src/test/resources/org/jabref/logic/auxparser/papertwoargmacro.aux new file mode 100644 index 00000000000..347f3f78480 --- /dev/null +++ b/src/test/resources/org/jabref/logic/auxparser/papertwoargmacro.aux @@ -0,0 +1,8 @@ +\relax +\abx@aux@cite{0}{Darwin1888} +\abx@aux@cite{0}{Einstein1920} +\bibstyle{plain} +\bibdata{origin} +\bibcite{Darwin1888}{1} +\bibcite{Einstein1920}{2} +\@writefile{toc}{\contentsline {section}{\numberline {1}}{1}} diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/encoding-us-ascii-with-header.bib b/src/test/resources/org/jabref/logic/importer/fileformat/encoding-us-ascii-with-header.bib new file mode 100644 index 00000000000..4eb34fbc82b --- /dev/null +++ b/src/test/resources/org/jabref/logic/importer/fileformat/encoding-us-ascii-with-header.bib @@ -0,0 +1,5 @@ +% Encoding: US-ASCII + +@article{, + title = {testtitle}, +} diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/encoding-utf-8-with-header.bib b/src/test/resources/org/jabref/logic/importer/fileformat/encoding-utf-8-with-header.bib new file mode 100644 index 00000000000..ac8d4f84400 --- /dev/null +++ b/src/test/resources/org/jabref/logic/importer/fileformat/encoding-utf-8-with-header.bib @@ -0,0 +1,5 @@ +% Encoding: UTF-8 + +@article{, + title = {Ü ist ein Umlaut}, +} diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/encoding-utf-8-without-header.bib b/src/test/resources/org/jabref/logic/importer/fileformat/encoding-utf-8-without-header.bib new file mode 100644 index 00000000000..bf9f81c70c2 --- /dev/null +++ b/src/test/resources/org/jabref/logic/importer/fileformat/encoding-utf-8-without-header.bib @@ -0,0 +1,3 @@ +@article{, + title = {Ü ist ein Umlaut}, +} diff --git a/src/test/resources/org/jabref/logic/importer/fileformat/encoding-windows-1252-without-header.bib b/src/test/resources/org/jabref/logic/importer/fileformat/encoding-windows-1252-without-header.bib new file mode 100644 index 00000000000..c6269cc88e6 --- /dev/null +++ b/src/test/resources/org/jabref/logic/importer/fileformat/encoding-windows-1252-without-header.bib @@ -0,0 +1,7 @@ +% Encoding: windows-1252 + +@Article{, + abstract = {25 C}, +} + +@Comment{jabref-meta: databaseType:bibtex;} diff --git a/src/test/resources/org/jabref/logic/xmp/article_dublinCore.bib b/src/test/resources/org/jabref/logic/xmp/article_dublinCore.bib index 82c5604dd38..f959a333921 100644 --- a/src/test/resources/org/jabref/logic/xmp/article_dublinCore.bib +++ b/src/test/resources/org/jabref/logic/xmp/article_dublinCore.bib @@ -7,6 +7,7 @@ @Article{Olly2018 number = {1}, pages = {1-2}, month = mar, + day = {1}, issn = {978-123-123}, note = {That's a note}, abstract = {That's an abstract}, diff --git a/src/test/resources/org/jabref/logic/xmp/article_dublinCore_partial_date.bib b/src/test/resources/org/jabref/logic/xmp/article_dublinCore_partial_date.bib new file mode 100644 index 00000000000..39c4e5d137e --- /dev/null +++ b/src/test/resources/org/jabref/logic/xmp/article_dublinCore_partial_date.bib @@ -0,0 +1,8 @@ +@Article{, + coverage = {coverageField}, + language = {English,Japanese}, + month = jan, + rights = {Right To X}, + source = {JabRef}, + year = {2005}, +} diff --git a/src/test/resources/org/jabref/logic/xmp/article_dublinCore_partial_date.pdf b/src/test/resources/org/jabref/logic/xmp/article_dublinCore_partial_date.pdf new file mode 100644 index 00000000000..b9343488134 Binary files /dev/null and b/src/test/resources/org/jabref/logic/xmp/article_dublinCore_partial_date.pdf differ diff --git a/src/test/resources/org/jabref/logic/xmp/article_dublinCore_without_day.bib b/src/test/resources/org/jabref/logic/xmp/article_dublinCore_without_day.bib new file mode 100644 index 00000000000..82c5604dd38 --- /dev/null +++ b/src/test/resources/org/jabref/logic/xmp/article_dublinCore_without_day.bib @@ -0,0 +1,23 @@ +@Article{Olly2018, + author = {Olly and Johannes}, + title = {Stefan's palace}, + journal = {Test Journal}, + year = {2018}, + volume = {1}, + number = {1}, + pages = {1-2}, + month = mar, + issn = {978-123-123}, + note = {That's a note}, + abstract = {That's an abstract}, + comment = {That's a comment}, + doi = {10/3212.3123}, + file = {:paper.pdf:PDF}, + groups = {NO}, + howpublished = {Online}, + keywords = {Keyword1, Keyword2}, + owner = {Me}, + review = {Here are the reviews}, + timestamp = {2018-02-15}, + url = {https://www.olly2018.edu}, +} diff --git a/src/test/resources/org/jabref/logic/xmp/article_dublinCore_without_day.pdf b/src/test/resources/org/jabref/logic/xmp/article_dublinCore_without_day.pdf new file mode 100644 index 00000000000..ae2d982b0a3 Binary files /dev/null and b/src/test/resources/org/jabref/logic/xmp/article_dublinCore_without_day.pdf differ diff --git a/src/test/resources/tinylog-test.properties b/src/test/resources/tinylog-test.properties index af2f719ac2b..34b759ac485 100644 --- a/src/test/resources/tinylog-test.properties +++ b/src/test/resources/tinylog-test.properties @@ -1,2 +1,4 @@ level = info writer = console +# uncomment the following line to enable debug logging outputs +#level@org.jabref.model.entry.BibEntry = debug