From cfa43569e451b3c675b18742eb13008a3a40b5a3 Mon Sep 17 00:00:00 2001 From: conorfos Date: Wed, 5 Sep 2018 10:47:05 +0100 Subject: [PATCH 01/23] Recommendation retrieval from new Mr. DLib MrDLibImporter and MrDLibFetcher updated to support JSON and new Mr. DLib format. Tests updated and passing. --- .../logic/importer/fetcher/MrDLibFetcher.java | 15 +- .../importer/fileformat/MrDLibImporter.java | 238 ++++++++---------- .../jabref/logic/util/StandardFileType.java | 1 + .../fileformat/MrDLibImporterTest.java | 32 ++- 4 files changed, 125 insertions(+), 161 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java index 199d68dee32..b1104c192b8 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java @@ -29,7 +29,6 @@ */ public class MrDLibFetcher implements EntryBasedFetcher { private static final Logger LOGGER = LoggerFactory.getLogger(MrDLibFetcher.class); - private static final String NAME = "MDL_FETCHER"; private final String LANGUAGE; private final String VERSION; @@ -57,16 +56,17 @@ public List performSearch(BibEntry entry) throws FetcherException { parserResult = importer.importDatabase(response); } else { // For displaying An ErrorMessage + String error = importer.getResponseErrorMessage(response); BibEntry errorBibEntry = new BibEntry(); errorBibEntry.setField("html_representation", - Localization.lang("Error while fetching from %0", "Mr.DLib")); + Localization.lang(error)); BibDatabase errorBibDataBase = new BibDatabase(); errorBibDataBase.insertEntry(errorBibEntry); parserResult = new ParserResult(errorBibDataBase); } } catch (IOException e) { LOGGER.error(e.getMessage(), e); - throw new FetcherException("XML Parser IOException."); + throw new FetcherException("JSON Parser IOException."); } return parserResult.getDatabase().getEntries(); } else { @@ -104,11 +104,11 @@ private String makeServerRequest(String queryByTitle) throws FetcherException { */ private String constructQuery(String queryWithTitle) { // The encoding does not work for / so we convert them by our own - queryWithTitle = queryWithTitle.replaceAll("/", "convbckslsh"); + queryWithTitle = queryWithTitle.replaceAll("/", " "); URIBuilder builder = new URIBuilder(); - builder.setScheme("https"); - builder.setHost("api.mr-dlib.org"); - builder.setPath("/v1/documents/" + queryWithTitle + "/related_documents"); + builder.setScheme("http"); + builder.setHost("api-dev.darwingoliath.com"); + builder.setPath("/v2/related_items/" + queryWithTitle); builder.addParameter("partner_id", "jabref"); builder.addParameter("app_id", "jabref_desktop"); builder.addParameter("app_version", VERSION); @@ -116,6 +116,7 @@ private String constructQuery(String queryWithTitle) { URI uri = null; try { uri = builder.build(); + LOGGER.trace("Request: " + uri.toString()); return uri.toString(); } catch (URISyntaxException e) { LOGGER.error(e.getMessage(), e); diff --git a/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java index 491eff2c8d1..02c486925c6 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java @@ -4,18 +4,13 @@ package org.jabref.logic.importer.fileformat; import java.io.BufferedReader; -import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.InputStream; +import java.text.MessageFormat; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; -import java.util.Locale; import java.util.stream.Collectors; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - import org.jabref.logic.importer.Importer; import org.jabref.logic.importer.ParserResult; import org.jabref.logic.util.StandardFileType; @@ -23,11 +18,11 @@ import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.FieldName; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; /** * @@ -35,27 +30,21 @@ */ public class MrDLibImporter extends Importer { + private static final MessageFormat HTML_LIST_ITEM_TEMPLATE = new MessageFormat("{1}. {2} {3} {4}"); + private static final String DEFAULT_MRDLIB_ERROR_MESSAGE = "Error while fetching from Mr.DLib."; private static final Logger LOGGER = LoggerFactory.getLogger(MrDLibImporter.class); public ParserResult parserResult; + @SuppressWarnings("unused") @Override public boolean isRecognizedFormat(BufferedReader input) throws IOException { String recommendationsAsString = convertToString(input); - // check for valid format try { - SAXParserFactory factory = SAXParserFactory.newInstance(); - SAXParser saxParser = factory.newSAXParser(); - DefaultHandler handler = new DefaultHandler() { - // No Processing here. Just check for valid xml. - // Later here will be the check against the XML schema. - }; - - try (InputStream stream = new ByteArrayInputStream(recommendationsAsString.getBytes())) { - saxParser.parse(stream, handler); - } catch (Exception e) { + JSONObject jsonObject = new JSONObject(recommendationsAsString); + if (!jsonObject.has("recommendations")) { return false; } - } catch (ParserConfigurationException | SAXException e) { + } catch (JSONException ex) { return false; } return true; @@ -74,18 +63,18 @@ public String getName() { @Override public StandardFileType getFileType() { - return StandardFileType.XML; + return StandardFileType.JSON; } @Override public String getDescription() { - return "Takes valid xml documents. Parses from MrDLib API a BibEntry"; + return "Takes valid JSON documents from the Mr. DLib API and parses them into a BibEntry"; } /** - * The SaxParser needs this String. So I convert it here. - * @param Takes a BufferedReader with a reference to the XML document delivered by mdl server. - * @return Returns an String containing the XML file. + * Convert Buffered Reader response to string for JSON parsing. + * @param Takes a BufferedReader with a reference to the JSON document delivered by mdl server. + * @return Returns an String containing the JSON document. * @throws IOException */ private String convertToString(BufferedReader input) throws IOException { @@ -117,7 +106,7 @@ public RankedBibEntry(BibEntry entry, Integer rank) { /** * Parses the input from the server to a ParserResult - * @param input A BufferedReader with a reference to a string with the servers response + * @param input A BufferedReader with a reference to a string with the server's response * @throws IOException */ private void parse(BufferedReader input) throws IOException { @@ -126,133 +115,110 @@ private void parse(BufferedReader input) throws IOException { // The document to parse String recommendations = convertToString(input); // The sorted BibEntries gets stored here later - List bibEntries = new ArrayList<>(); - //Parsing the response with a SAX parser - try { - SAXParserFactory factory = SAXParserFactory.newInstance(); - SAXParser saxParser = factory.newSAXParser(); - MrDlibImporterHandler handler = new MrDlibImporterHandler(); - try (InputStream stream = new ByteArrayInputStream(recommendations.getBytes())) { - saxParser.parse(stream, handler); - } catch (SAXException e) { - LOGGER.error(e.getMessage(), e); - } - List rankedBibEntries = handler.getRankedBibEntries(); - rankedBibEntries.sort((RankedBibEntry rankedBibEntry1, - RankedBibEntry rankedBibEntry2) -> rankedBibEntry1.rank.compareTo(rankedBibEntry2.rank)); - bibEntries = rankedBibEntries.stream().map(e -> e.entry).collect(Collectors.toList()); - } catch (ParserConfigurationException | SAXException e) { - LOGGER.error(e.getMessage(), e); + List rankedBibEntries = new ArrayList<>(); + + // Get recommendations from response and populate bib entries + JSONObject recommendationsJson = new JSONObject(recommendations); + recommendationsJson = recommendationsJson.getJSONObject("recommendations"); + Iterator keys = recommendationsJson.keys(); + while (keys.hasNext()) { + String key = keys.next(); + JSONObject value = recommendationsJson.getJSONObject(key); + rankedBibEntries.add(populateBibEntry(value)); } + // Sort bib entries according to rank + rankedBibEntries.sort((RankedBibEntry rankedBibEntry1, + RankedBibEntry rankedBibEntry2) -> rankedBibEntry1.rank.compareTo(rankedBibEntry2.rank)); + List bibEntries = rankedBibEntries.stream().map(e -> e.entry).collect(Collectors.toList()); + for (BibEntry bibentry : bibEntries) { bibDatabase.insertEntry(bibentry); } - parserResult = new ParserResult(bibDatabase); } - public ParserResult getParserResult() { - return parserResult; - } - /** - * Handler that parses the response from Mr. DLib to BibEntries + * Parses the JSON recommendations into bib entries + * @param recommendation JSON object of a single recommendation returned by Mr. DLib + * @return A ranked bib entry created from the recommendation input */ - private class MrDlibImporterHandler extends DefaultHandler { - - // The list ob BibEntries with its associated rank - private final List rankedBibEntries = new ArrayList<>(); + private RankedBibEntry populateBibEntry(JSONObject recommendation) { + BibEntry current = new BibEntry(); + String authors = "", title = "", year = "", journal = "", url = ""; + Integer rank = 100; + + // parse each of the relevant fields into variables + if (recommendation.has("authors") && !recommendation.isNull("authors")) { + authors = getAuthorsString(recommendation); + } + if (recommendation.has("title") && !recommendation.isNull("title")) { + title = recommendation.getString("title"); + } + if (recommendation.has("date_published") && !recommendation.isNull("date_published")) { + year = recommendation.getString("date_published"); + } + if (recommendation.has("published_in") && !recommendation.isNull("published_in")) { + journal = recommendation.getString("published_in"); + } + if (recommendation.has("url") && !recommendation.isNull("url")) { + url = recommendation.getString("url") + "."; + } + if (recommendation.has("recommendation_id") && !recommendation.isNull("recommendation_id")) { + rank = recommendation.getInt("recommendation_id"); + } - private boolean authors; - private boolean published_in; - private boolean title; - private boolean year; - private boolean snippet; - private boolean rank; - private boolean type; - private String htmlSnippetSingle; - private int htmlSnippetSingleRank = -1; - private BibEntry currentEntry; + // Populate bib entry with relevant data + current.setField(FieldName.AUTHOR, authors); + current.setField(FieldName.TITLE, title); + current.setField(FieldName.YEAR, year); + current.setField(FieldName.JOURNAL, journal); - public List getRankedBibEntries() { - return rankedBibEntries; - } + // Create HTML representation of recommendation for display on the UI + Object[] args = {url, title, authors, journal, year}; + String htmlRepresentation = HTML_LIST_ITEM_TEMPLATE.format(args); + current.setField("html_representation", htmlRepresentation); - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) - throws SAXException { + return new RankedBibEntry(current, rank); + } - switch (qName.toLowerCase(Locale.ROOT)) { - case "related_article": - currentEntry = new BibEntry(); - htmlSnippetSingle = null; - htmlSnippetSingleRank = -1; - break; - case "authors": - authors = true; - break; - case "published_in": - published_in = true; - break; - case "title": - title = true; - break; - case "year": - year = true; - break; - case "type": - type = true; - break; - case "suggested_rank": - rank = true; - break; - default: - break; - } - if (qName.equalsIgnoreCase("snippet") - && attributes.getValue(0).equalsIgnoreCase("html_fully_formatted")) { - snippet = true; - } + /** + * Creates an authors string from a JSON recommendation + * @param recommendation JSON Object recommendation from Mr. DLib + * @return A string of all authors, separated by commas and finished with a full stop. + */ + private String getAuthorsString(JSONObject recommendation) { + String authorsString = ""; + JSONArray array = recommendation.getJSONArray("authors"); + for (int i = 0; i < array.length(); ++i) { + authorsString += array.getString(i) + ", "; } - - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - if (qName.equalsIgnoreCase("related_article")) { - rankedBibEntries.add(new RankedBibEntry(currentEntry, htmlSnippetSingleRank)); - currentEntry = new BibEntry(); - } + int stringLength = authorsString.length(); + if (stringLength > 2) { + authorsString = authorsString.substring(0, stringLength - 2) + "."; } + return authorsString; + } - @Override - public void characters(char ch[], int start, int length) throws SAXException { + public ParserResult getParserResult() { + return parserResult; + } - if (authors) { - currentEntry.setField(FieldName.AUTHOR, new String(ch, start, length)); - authors = false; - } - if (published_in) { - currentEntry.setField(FieldName.JOURNAL, new String(ch, start, length)); - published_in = false; - } - if (title) { - currentEntry.setField(FieldName.TITLE, new String(ch, start, length)); - title = false; - } - if (year) { - currentEntry.setField(FieldName.YEAR, new String(ch, start, length)); - year = false; - } - if (rank) { - htmlSnippetSingleRank = Integer.parseInt(new String(ch, start, length)); - rank = false; - } - if (snippet) { - currentEntry.setField("html_representation", new String(ch, start, length)); - snippet = false; + /** + * Gets the error message to be returned if there has been an error in returning recommendations. + * Returns default error message if there is no message from Mr. DLib. + * @param response The response from the MDL server as a string. + * @return String error message to be shown to the user. + */ + public String getResponseErrorMessage(String response) { + try { + JSONObject jsonObject = new JSONObject(response); + if (!jsonObject.has("message")) { + return jsonObject.getString("message"); } - + } catch (JSONException ex) { + return DEFAULT_MRDLIB_ERROR_MESSAGE; } - + return DEFAULT_MRDLIB_ERROR_MESSAGE; } } diff --git a/src/main/java/org/jabref/logic/util/StandardFileType.java b/src/main/java/org/jabref/logic/util/StandardFileType.java index 5eb21456754..db7766e9811 100644 --- a/src/main/java/org/jabref/logic/util/StandardFileType.java +++ b/src/main/java/org/jabref/logic/util/StandardFileType.java @@ -36,6 +36,7 @@ public enum StandardFileType implements FileType { RTF("rtf"), SXC("sxc"), XML("xml"), + JSON("json"), XMP("xmp"), ZIP("zip"); diff --git a/src/test/java/org/jabref/logic/importer/fileformat/MrDLibImporterTest.java b/src/test/java/org/jabref/logic/importer/fileformat/MrDLibImporterTest.java index 7c2c1e5d837..5dea3343ac7 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/MrDLibImporterTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/MrDLibImporterTest.java @@ -19,23 +19,19 @@ public class MrDLibImporterTest { private MrDLibImporter importer; - private BufferedReader inputMin; - private BufferedReader inputMax; + private BufferedReader input; + private String testInput; @BeforeEach public void setUp() { importer = new MrDLibImporter(); - - String testMin = ""; - String testMax = "https://api-dev.mr-dlib.org/v1/recommendations/204944/original_url?access_key=99ab2fc64f3228ab839e9e3525ac37f8&format=direct_url_forward02.02.033221.0http://sowiport.gesis.org/search/id/gesis-solis-00538797Fachhochschulverl.Gesundheit von Arbeitslosen fördern!: ein Handbuch für Wissenschaft und Praxis. . Fachhochschulverl.. 2009.]]>Gesundheit von Arbeitslosen fördern!: ein Handbuch für Wissenschaft und Praxis.. Fachhochschulverl.. 2009.]]>Gesundheit von Arbeitslosen fördern!: ein Handbuch für Wissenschaft und Praxis. . Fachhochschulverl.. 2009]]>2Gesundheit von Arbeitslosen fördern!: ein Handbuch für Wissenschaft und Praxis2009"; - testMax = testMax.replaceAll("&", ""); - inputMin = new BufferedReader(new StringReader(testMin)); - inputMax = new BufferedReader(new StringReader(testMax)); + testInput = "{ \"label\": { \"label-language\": \"en\", \"label-text\": \"Related Items\" }, \"recommendation-set-id\": \"1\", \"recommendations\": { \"74021358\": { \"abstract\": \"The theme of diploma is the preservation of the rural lands with the spatial development strategy on the case of the Hrastnik commune. The rural land with the potential production which is appropriate for the rural use is very important natural source. The natural source is very important for the quality of living and the spatial development. For this reason the assurance of the validity of the usage of the rural lands and to preserve the rural land is one of the basic ways of the strategy of the spatial development of Slovenia. The task is compose into two parts. The first part is theoretical. It informed us with the situations and achievements of the spatial development in Slovenia. In brief it shows the professional starting-point, which are for the use of the legally regime to preserve the rural lands and have been made by Dr. A. Stritar and they are still actual. In the review of the new and old rural land legislation it shows the adaptation of the rural lands through the periods until today. The second part treats the practical case of the preservation of the rural lands on the case of the Hrastnik commune. Based on the professional foundation for the classification of the rural lands presents the spatial analyses with reference to the rural lands and the category of the rural lands of the commune. At the end of the chapter it shows the part of Brnica. Here the commune of Hrastnik in the procedure of the preparation of new spatial-act wants to change the purpose of the best rural lands with the high production potential for the enlargement of the settlement and adaptation of the cemetery\", \"authors\": [ \"Sajovic, Marija\" ], \"date_published\": \"21-06-2006\", \"item_id_original\": \"12088644\", \"keywords\": [ \"visoko\\u0161olski program Geodezija - smer Prostorska informatika\" ], \"language_provided\": \"sl\", \"recommendation_id\": \"1\", \"title\": \"The protection of rural lands with the spatial development strategy on the case of Hrastnik commune\", \"url\": \"http://drugg.fgg.uni-lj.si/701/1/GEV_0199_Sajovic.pdf\" }, \"82005804\": { \"abstract\": \"The theme of my diploma thesis is the engagement of the volunteers in the solution to the accidents in the South-Moravia region. In my diploma thesis I am involved in the issue of the engagement of the volunteers in the solution to the accidents in the South-Moravia region. I assume that the utilization of the potential of the volunteers is one of the possibilities of the acquisition of the forces, which could be used for the recovery of the consequences, post-traumatic care to struck persons and other activities within the solution to the accidents, all parallelly with the actions of the professional teams of the integrated rescue system bodies. The needs of the population in case of the accidents are rather differentiated, and the engagement of the volunteers completes the appointed forces and means of the integrated rescue system bodies. At present time, the adequate legal framework, modifying the engagement of the volunteers in the solution to the accidents, does not exist in the Czech Republic. Non-governmental non-profit organizations are united in the South-Moravia region into the Panel of the South-Moravia Region, which establishes the platform and enables the South-Moravia Region more effective engagement of the non-governmental non-profit organizations. The volunteers, organized in the Panel of the South-Moravia Region, are engaged in the solution to the accidents and the trainings organized in the level of the region, municipalities with widened competence and the integrated rescue system bodies\", \"date_published\": null, \"item_id_original\": \"30145702\", \"language_provided\": null, \"recommendation_id\": \"2\", \"title\": \"Engagement of the volunteers in the solution to the accidents in the South-Moravia region\" }, \"82149599\": { \"abstract\": \"English Annotation (The work abstract) 5 key words: The Father, The Son, The Holy Spirit, The Holy Trinity, Saint John of the Cross \\\"The Only Father's Word\\\" The Relationship of the Father and the Son in documents of Saint John of the Cross The author presented the life of the saint in the first part of the work with the intention to put some key events of his life to the connection with the testimony of his texts. In the next part she analyzed those texts in the documents which are devoted to the relationship of the Father and the Son. Here we mainly talk about the twenty-second chapter of the second book, the Ascent of Mount Carmel, in which \\\" The Son is the only Father's word\\\". The father is active only in one way - begetting the Son; the begetting itself is Love, which is The Holy Spirit. The Son loves the Father and through this love he makes the Father love, he isn't passive. In the Romances, Saint John shows how the relationship of the Father and the Son in the Spirit is realized in the creation and incarnation. The poem the Source deepens our understanding of Son and Holy Spirit's proceeding from the Father and his acting in the Eucharist. In the third and the last part of the work, she made the synthesis of the knowledge gotten by the analysis of the given texts and she came to a conclusion that the..\", \"date_published\": null, \"item_id_original\": \"97690763\", \"language_provided\": null, \"recommendation_id\": \"3\", \"title\": \"\\\"The only Father's word\\\". The relationship of the Father and the Son in the documents of saint John of the Cross\", \"url\": \"http://www.nusl.cz/ntk/nusl-285711\" }, \"84863921\": { \"abstract\": \"This thesis provides an analytical presentation of the situation of the Greek Church of Cyprus, the Morea and Constantinople during the earlier part of the Frankish Era (1196-1303). It examines the establishment of the Latin Church in Constantinople, Cyprus and Achaea and it attempts to answer questions relating to the reactions of the Greek Church to the Latin conquests. It considers the similarities and differences in the establishment in Constantinople, the Morea and Cyprus, the diocesan structure, agreements regarding the fate of the Greek ecclesiastical properties, the payment of tithes and the agreements of 1220-1222. Moreover it analyses the relations of the Greek Church of Cyprus, the Greek Church of Constantinople and the Morea with the Latin Church. For instance it details the popes' involvement in the affairs of the Church in these three significant areas, the ecclesiastical differences between the Greek and the Latin Church, the behaviour of the Greek patriarchs, archbishops and bishops within the Greek Church, the reaction of the Greeks towards the establishment of the Latin Church, and significant events such as the martyrdom of the thirteen monks of Kantara and the promulgation of the Bulla Cypria. The third topic area pertains to the relationship of the Greek Church of the Morea, Constantinople and Cyprus with the secular authority. It discusses the attitude of the king of Cyprus, the rulers of the Morea and the emperor of Constantinople towards the problems between the Latin and Greeks, the relationship of the Latin nobility with the Greeks, and the involvement of the crown regarding the ecclesiastical property and possible explanations for the attitude of the Latin crown towards the Greeks\", \"authors\": [ \"Kaffa, Elena\" ], \"date_published\": null, \"item_id_original\": \"19397104\", \"keywords\": [ \"BX\", \"D111\" ], \"language_provided\": \"en\", \"recommendation_id\": \"4\", \"title\": \"Greek Church of Cyprus, the Morea and Constantinople during the Frankish Era (1196-1303)\" }, \"88950992\": { \"abstract\": \"1. The phylogeny map is the 4th-dimensional extension of a protoplast in which the generations repeated continuously. One generation in the phylogeny is the three-dimensional extension of the protoplast in certain period which is limited by a resting stage accompanying the reproductive phase. 2. It is considered that the ancestor of the seed plants was a hygrophytic multinuclear thallus having the structure like the cotyledonary ring including the hypocotyl in the plants of the present age. 3. In the second stage of the development in the phylogeny the thallus became uninuclear multicellular one, and the water storage cells differentiated in the body which gave the aerophytic habit for the plant. 4. Aerophytic habit gave the great change to the plant not only morphologically but also in the physiological natures. The epidermis having stomata differentiated. The mesophyll became to serve for the photosynthesis instead of the epidermis. The arrest of the escape of the metabolites from the surface of the body, the accumulation of the photosynthetic products, and the evaporation of water from the body surface lead the\\ndifferentiation of conductive tissues, the phloem and xylem. 5. The transfer of the nutrients and also the metabolites, especially such as the activator of the nuclear division, influenced to differentiate the secondary meristem. The growing point of the root and the primordium of the first node of the stem including the leaves and internode produced from the meristems. The embryo and bud formation are considered. 6. The appearance of the bud lead the formation of the complicated reproductive organ called the flower. The qualitative differences between the MiSI, and MaSI, and the migration of the SI were considered. 7. The ancestor of the Pteridophyte must be entirely different from that of the seed plants. It was a uninuclear multicellular plant having the growing point at the distal end of the body\", \"authors\": [ \"Yasui, Kono\" ], \"date_published\": null, \"item_id_original\": \"38763657\", \"language_provided\": null, \"recommendation_id\": \"5\", \"title\": \"A Phylogenetic Consideration on the Vascular Plants, Cotyledonary Node Including Hypocotyl Being Taken as the Ancestral Form : A Preliminary Note\" } }}"; + input = new BufferedReader(new StringReader(testInput)); } @Test public void testGetDescription() { - assertEquals("Takes valid xml documents. Parses from MrDLib API a BibEntry", importer.getDescription()); + assertEquals("Takes valid JSON documents from the Mr. DLib API and parses them into a BibEntry", importer.getDescription()); } @Test @@ -45,46 +41,46 @@ public void testGetName() { @Test public void testGetFileExtention() { - assertEquals(StandardFileType.XML, importer.getFileType()); + assertEquals(StandardFileType.JSON, importer.getFileType()); } @Test public void testImportDatabaseIsHtmlSetCorrectly() throws IOException { - ParserResult parserResult = importer.importDatabase(inputMax); + ParserResult parserResult = importer.importDatabase(input); List resultList = parserResult.getDatabase().getEntries(); assertEquals( - "Gesundheit von Arbeitslosen fördern!: ein Handbuch für Wissenschaft und Praxis.. Fachhochschulverl.. 2009.", + "The protection of rural lands with the spatial development strategy on the case of Hrastnik commune. Sajovic, Marija. 21-06-2006", resultList.get(0).getField("html_representation").get()); } @Test public void testImportDatabaseIsYearSetCorrectly() throws IOException { - ParserResult parserResult = importer.importDatabase(inputMax); + ParserResult parserResult = importer.importDatabase(input); List resultList = parserResult.getDatabase().getEntries(); - assertEquals("2009", + assertEquals("21-06-2006", resultList.get(0).getLatexFreeField(FieldName.YEAR).get()); } @Test public void testImportDatabaseIsTitleSetCorrectly() throws IOException { - ParserResult parserResult = importer.importDatabase(inputMax); + ParserResult parserResult = importer.importDatabase(input); List resultList = parserResult.getDatabase().getEntries(); - assertEquals("Gesundheit von Arbeitslosen fördern!: ein Handbuch für Wissenschaft und Praxis", + assertEquals("The protection of rural lands with the spatial development strategy on the case of Hrastnik commune", resultList.get(0).getLatexFreeField(FieldName.TITLE).get()); } @Test public void testImportDatabaseMin() throws IOException { - ParserResult parserResult = importer.importDatabase(inputMin); + ParserResult parserResult = importer.importDatabase(input); List resultList = parserResult.getDatabase().getEntries(); - assertSame(0, resultList.size()); + assertSame(5, resultList.size()); } } From 1320270d1960bae31cdee1d716ff394bacb05b68 Mon Sep 17 00:00:00 2001 From: conorfos Date: Mon, 17 Sep 2018 14:12:20 +0100 Subject: [PATCH 02/23] Create GDPR dialog and update GUI Created dialog to ask for consent to sed data to Mr. DLib Created preference setting to keep track of consent Updated the recommendations GUI to use JavaFX --- MicroRecsys.bib | 291 ++++++++++++++++++ .../jabref/gui/entryeditor/EntryEditor.css | 10 + .../entryeditor/EntryEditorPreferences.java | 10 +- .../gui/entryeditor/RelatedArticlesTab.java | 165 +++++++--- .../gui/preferences/EntryEditorPrefsTab.java | 10 +- .../logic/importer/fetcher/MrDLibFetcher.java | 4 +- .../importer/fileformat/MrDLibImporter.java | 13 +- .../jabref/preferences/JabRefPreferences.java | 3 + 8 files changed, 452 insertions(+), 54 deletions(-) create mode 100644 MicroRecsys.bib diff --git a/MicroRecsys.bib b/MicroRecsys.bib new file mode 100644 index 00000000000..93645845e27 --- /dev/null +++ b/MicroRecsys.bib @@ -0,0 +1,291 @@ +% Encoding: UTF-8 + +@STRING{dke = {Data \& Knowledge Engineering}} + +@STRING{joop = {Journal of Object-Oriented Programming}} + +@STRING{lnai = {Lecture Notes in Artificial Intelligence}} + +@STRING{lncs = {Lecture Notes in Computer Science}} + +@STRING{mibi = {Medizinische Informatik und Bioinformatik}} + +@STRING{tkde = {IEEE Transactions on Knowledge and Data Engineering}} + +@STRING{tods = {ACM Transactions on Database Systems}} + +@STRING{tois = {ACM Transactions on Information Systems}} + +@INPROCEEDINGS{DBLP:conf/ercimdl/BeelLNG13, + author = {J{\"{o}}ran Beel and Stefan Langer and Andreas N{\"{u}}rnberger and + Marcel Genzmehr}, + title = {The Impact of Demographics (Age and Gender) and Other User-Characteristics + on Evaluating Recommender Systems}, + booktitle = {Research and Advanced Technology for Digital Libraries - International + Conference on Theory and Practice of Digital Libraries, {TPDL} 2013, + Valletta, Malta, September 22-26, 2013. Proceedings}, + year = {2013}, + pages = {396--400}, + bibsource = {dblp computer science bibliography, https://dblp.org}, + biburl = {https://dblp.org/rec/bib/conf/ercimdl/BeelLNG13}, + crossref = {DBLP:conf/ercimdl/2013}, + doi = {10.1007/978-3-642-40501-3_45}, + timestamp = {Fri, 02 Jun 2017 20:47:58 +0200}, + url = {https://doi.org/10.1007/978-3-642-40501-3_45} +} + +@INPROCEEDINGS{DBLP:conf/recsys/EkstrandP17, + author = {Michael D. Ekstrand and Maria Soledad Pera}, + title = {The Demographics of Cool: Popularity and Recommender Performance + for Different Groups of Users}, + booktitle = {Proceedings of the Poster Track of the 11th {ACM} Conference on Recommender + Systems (RecSys 2017), Como, Italy, August 28, 2017.}, + year = {2017}, + bibsource = {dblp computer science bibliography, https://dblp.org}, + biburl = {https://dblp.org/rec/bib/conf/recsys/EkstrandP17}, + crossref = {DBLP:conf/recsys/2017p}, + timestamp = {Fri, 08 Sep 2017 10:53:00 +0200}, + url = {http://ceur-ws.org/Vol-1905/recsys2017_poster20.pdf} +} + +@Article{ahsan2005conceptual, + author = {Ahsan, Mujtaba and Ngo-Ye, Lin}, + title = {A Conceptual Model of Recommender System for Algorithm Selection}, + journal = {AMCIS 2005 Proceedings}, + year = {2005}, + pages = {122}, + file = {:C\:/Users/Conor/Desktop/PDFdoc.pdf:PDF}, +} + +@ARTICLE{beelproposal, + author = {Beel, Joeran}, + title = {A Macro/Micro Recommender System for Recommendation Algorithms [Proposal]}, + journal = {ResearchGate}, + year = {2017} +} + +@ARTICLE{beel2016towards, + author = {Beel, Joeran and Breitinger, Corinna and Langer, Stefan and Lommatzsch, + Andreas and Gipp, Bela}, + title = {Towards reproducibility in recommender-systems research}, + journal = {User modeling and user-adapted interaction}, + year = {2016}, + volume = {26}, + pages = {69--101}, + number = {1}, + publisher = {Springer} +} + +@INPROCEEDINGS{beel2013comparative, + author = {Beel, Joeran and Genzmehr, Marcel and Langer, Stefan and N{\"u}rnberger, + Andreas and Gipp, Bela}, + title = {A comparative analysis of offline and online evaluations and discussion + of research paper recommender system evaluation}, + booktitle = {Proceedings of the international workshop on reproducibility and + replication in recommender systems evaluation}, + year = {2013}, + pages = {7--14}, + organization = {ACM} +} + +@ARTICLE{beel2016paper, + author = {Beel, Joeran and Gipp, Bela and Langer, Stefan and Breitinger, Corinna}, + title = {paper recommender systems: a literature survey}, + journal = {International Journal on Digital Libraries}, + year = {2016}, + volume = {17}, + pages = {305--338}, + number = {4}, + publisher = {Springer} +} + +@INPROCEEDINGS{beel2011introducing, + author = {Beel, Joeran and Gipp, Bela and Langer, Stefan and Genzmehr, Marcel + and Wilde, Erik and N{\"u}rnberger, Andreas and Pitman, Jim}, + title = {Introducing Mr. DLib, a Machine-readable Digital Library}, + booktitle = {Proceedings of the 11th annual international ACM/IEEE joint conference + on Digital libraries}, + year = {2011}, + pages = {463--464}, + organization = {ACM} +} + +@ARTICLE{DBLP:journals/umuai/Burke02, + author = {Robin D. Burke}, + title = {Hybrid Recommender Systems: Survey and Experiments}, + journal = {User Model. User-Adapt. Interact.}, + year = {2002}, + volume = {12}, + pages = {331--370}, + number = {4}, + bibsource = {dblp computer science bibliography, https://dblp.org}, + biburl = {https://dblp.org/rec/bib/journals/umuai/Burke02}, + doi = {10.1023/A:1021240730564}, + timestamp = {Sat, 27 May 2017 14:24:37 +0200}, + url = {https://doi.org/10.1023/A:1021240730564} +} + +@ARTICLE{cunha2018cf4cf, + author = {Cunha, Tiago and Soares, Carlos and de Carvalho, Andr{\'e} CPLF}, + title = {CF4CF: Recommending Collaborative Filtering algorithms using Collaborative + Filtering}, + journal = {arXiv preprint arXiv:1803.02250}, + year = {2018} +} + +@ARTICLE{cunha2018metalearning, + author = {Cunha, Tiago and Soares, Carlos and de Carvalho, Andr{\'e} CPLF}, + title = {Metalearning and Recommender Systems: A literature review and empirical + study on the algorithm selection problem for Collaborative Filtering}, + journal = {Information Sciences}, + year = {2018}, + volume = {423}, + pages = {128--144}, + publisher = {Elsevier} +} + +@INPROCEEDINGS{cunha2016selecting, + author = {Cunha, Tiago and Soares, Carlos and de Carvalho, Andr{\'e} CPLF}, + title = {Selecting Collaborative Filtering algorithms using Metalearning}, + booktitle = {Joint European Conference on Machine Learning and Knowledge Discovery + in Databases}, + year = {2016}, + pages = {393--409}, + organization = {Springer} +} + +@INPROCEEDINGS{ekstrand2012recommenders, + author = {Ekstrand, Michael and Riedl, John}, + title = {When recommenders fail: predicting recommender failure for algorithm + selection and combination}, + booktitle = {Proceedings of the sixth ACM conference on Recommender systems}, + year = {2012}, + pages = {233--236}, + organization = {ACM} +} + +@ARTICLE{garciametalearning, + author = {Garc{\i}a-Saiz, Diego and Zorrilla, Marta}, + title = {Metalearning-based recommenders: towards automatic classification + algorithm selection} +} + +@ARTICLE{Gomez-Uribe:2015:NRS:2869770.2843948, + author = {Gomez-Uribe, Carlos A. and Hunt, Neil}, + title = {The Netflix Recommender System: Algorithms, Business Value, and Innovation}, + journal = {ACM Trans. Manage. Inf. Syst.}, + year = {2015}, + volume = {6}, + pages = {13:1--13:19}, + number = {4}, + month = {\#dec\#}, + acmid = {2843948}, + address = {New York, NY, USA}, + articleno = {13}, + doi = {10.1145/2843948}, + issn = {2158-656X}, + issue_date = {January 2016}, + keywords = {Recommender systems}, + numpages = {19}, + publisher = {ACM}, + url = {http://doi.acm.org/10.1145/2843948} +} + +@ARTICLE{DBLP:journals/tois/ImH07, + author = {Il Im and Alexander Hars}, + title = {Does a one-size recommendation system fit all? the effectiveness + of collaborative filtering based recommendation systems across different + domains and search modes}, + journal = {{ACM} Trans. Inf. Syst.}, + year = {2007}, + volume = {26}, + pages = {4}, + number = {1}, + bibsource = {dblp computer science bibliography, https://dblp.org}, + biburl = {https://dblp.org/rec/bib/journals/tois/ImH07}, + doi = {10.1145/1292591.1292595}, + timestamp = {Thu, 12 Jan 2017 13:39:58 +0100}, + url = {http://doi.acm.org/10.1145/1292591.1292595} +} + +@ARTICLE{koren2009bellkor, + author = {Koren, Yehuda}, + title = {The bellkor solution to the netflix grand prize}, + journal = {Netflix prize documentation}, + year = {2009}, + volume = {81}, + pages = {1--10} +} + +@ARTICLE{lemke2015metalearning, + author = {Lemke, Christiane and Budka, Marcin and Gabrys, Bogdan}, + title = {Metalearning: a survey of trends and technologies}, + journal = {Artificial intelligence review}, + year = {2015}, + volume = {44}, + pages = {117--130}, + number = {1}, + publisher = {Springer} +} + +@ARTICLE{rokach2010ensemble, + author = {Rokach, Lior}, + title = {Ensemble-based classifiers}, + journal = {Artificial Intelligence Review}, + year = {2010}, + volume = {33}, + pages = {1--39}, + number = {1-2}, + publisher = {Springer} +} + +@INPROCEEDINGS{romero2013meta, + author = {Romero, Crist{\'o}bal and Olmo, Juan Luis and Ventura, Sebasti{\'a}n}, + title = {A meta-learning approach for recommending a subset of white-box classification + algorithms for Moodle datasets}, + booktitle = {Educational Data Mining 2013}, + year = {2013} +} + +@ARTICLE{sill2009feature, + author = {Sill, Joseph and Tak{\'a}cs, G{\'a}bor and Mackey, Lester and Lin, + David}, + title = {Feature-weighted linear stacking}, + journal = {arXiv preprint arXiv:0911.0460}, + year = {2009} +} + +@ARTICLE{toscher2009bigchaos, + author = {T{\"o}scher, Andreas and Jahrer, Michael and Bell, Robert M}, + title = {The bigchaos solution to the netflix grand prize}, + journal = {Netflix prize documentation}, + year = {2009}, + pages = {1--52} +} + +@ARTICLE{wolpert1992stacked, + author = {Wolpert, David H}, + title = {Stacked generalization}, + journal = {Neural networks}, + year = {1992}, + volume = {5}, + pages = {241--259}, + number = {2}, + publisher = {Elsevier} +} + +@Comment{jabref-meta: databaseType:bibtex;} + +@Comment{jabref-meta: grouping: +0 AllEntriesGroup:; +1 StaticGroup:link spam\;0\;1\;\;\;\;; +1 StaticGroup:content spam\;0\;1\;\;\;\;; +1 StaticGroup:competiror click fraud\;0\;1\;\;\;\;; +1 KeywordGroup:Norman\;0\;owner\;Norman\;1\;0\;1\;\;\;\;; +1 StaticGroup:ourpublications\;0\;1\;\;\;\;; +1 StaticGroup:test\;0\;1\;\;\;\;; +} + +@Comment{jabref-meta: groupsversion: +3; +} diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.css b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.css index 47eefbdde49..73905764636 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.css +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.css @@ -79,3 +79,13 @@ .code-area .text { -fx-fill: -fx-text-background-color; } + +.gdpr-dialog { + -fx-font-size: 14pt; +} + +.accept-button { + -fx-background-color: -jr-selected; +} + + diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditorPreferences.java b/src/main/java/org/jabref/gui/entryeditor/EntryEditorPreferences.java index fd8e1d097b2..af90eff6596 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditorPreferences.java +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditorPreferences.java @@ -16,16 +16,18 @@ public class EntryEditorPreferences { private final BibtexKeyPatternPreferences bibtexKeyPatternPreferences; private final List customTabFieldNames; private final boolean shouldShowRecommendationsTab; + private final boolean isMrdlibAccepted; private boolean showSourceTabByDefault; private final KeyBindingRepository keyBindings; - private boolean avoidOverwritingCiteKey; + private final boolean avoidOverwritingCiteKey; - public EntryEditorPreferences(Map> entryEditorTabList, LatexFieldFormatterPreferences latexFieldFormatterPreferences, ImportFormatPreferences importFormatPreferences, List customTabFieldNames, boolean shouldShowRecommendationsTab, boolean showSourceTabByDefault, BibtexKeyPatternPreferences bibtexKeyPatternPreferences, KeyBindingRepository keyBindings, boolean avoidOverwritingCiteKey) { + public EntryEditorPreferences(Map> entryEditorTabList, LatexFieldFormatterPreferences latexFieldFormatterPreferences, ImportFormatPreferences importFormatPreferences, List customTabFieldNames, boolean shouldShowRecommendationsTab, boolean isMrdlibAccepted, boolean showSourceTabByDefault, BibtexKeyPatternPreferences bibtexKeyPatternPreferences, KeyBindingRepository keyBindings, boolean avoidOverwritingCiteKey) { this.entryEditorTabList = entryEditorTabList; this.latexFieldFormatterPreferences = latexFieldFormatterPreferences; this.importFormatPreferences = importFormatPreferences; this.customTabFieldNames = customTabFieldNames; this.shouldShowRecommendationsTab = shouldShowRecommendationsTab; + this.isMrdlibAccepted = isMrdlibAccepted; this.showSourceTabByDefault = showSourceTabByDefault; this.bibtexKeyPatternPreferences = bibtexKeyPatternPreferences; this.keyBindings = keyBindings; @@ -52,6 +54,10 @@ public boolean shouldShowRecommendationsTab() { return shouldShowRecommendationsTab; } + public boolean isMrdlibAccepted() { + return isMrdlibAccepted; + } + public boolean showSourceTabByDefault() { return showSourceTabByDefault; } diff --git a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java index 233d3207ed2..42fb904d05c 100644 --- a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java @@ -1,26 +1,40 @@ package org.jabref.gui.entryeditor; -import java.net.URL; +import java.io.IOException; import java.util.List; -import java.util.Optional; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.scene.control.Button; +import javafx.scene.control.Hyperlink; import javafx.scene.control.ProgressIndicator; import javafx.scene.control.Tooltip; +import javafx.scene.layout.HBox; import javafx.scene.layout.StackPane; -import javafx.scene.web.WebView; +import javafx.scene.layout.VBox; +import javafx.scene.text.Font; +import javafx.scene.text.FontPosture; +import javafx.scene.text.Text; import org.jabref.Globals; -import org.jabref.gui.icon.IconTheme; +import org.jabref.gui.desktop.JabRefDesktop; import org.jabref.gui.util.BackgroundTask; -import org.jabref.gui.util.OpenHyperlinksInExternalBrowser; import org.jabref.logic.importer.fetcher.MrDLibFetcher; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.FieldName; import org.jabref.preferences.JabRefPreferences; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * GUI for tab displaying article recommendations based on the currently selected BibEntry + */ public class RelatedArticlesTab extends EntryEditorTab { private final EntryEditorPreferences preferences; + private static final Logger LOGGER = LoggerFactory.getLogger(RelatedArticlesTab.class); public RelatedArticlesTab(EntryEditorPreferences preferences) { setText(Localization.lang("Related articles")); @@ -28,55 +42,117 @@ public RelatedArticlesTab(EntryEditorPreferences preferences) { this.preferences = preferences; } - private StackPane getPane(BibEntry entry) { + /** + * Gets a StackPane of related article information to be displayed in the Related Articles tab + * @param entry The currently selected BibEntry on the JabRef UI. + * @return A StackPane with related article information to be displayed in the Related Articles tab. + */ + private StackPane getRelatedArticlesPane(BibEntry entry) { StackPane root = new StackPane(); + root.setStyle("-fx-padding: 20 20 20 20"); ProgressIndicator progress = new ProgressIndicator(); progress.setMaxSize(100, 100); - WebView browser = new WebView(); - root.getChildren().addAll(browser, progress); MrDLibFetcher fetcher = new MrDLibFetcher(Globals.prefs.get(JabRefPreferences.LANGUAGE), - Globals.BUILD_INFO.getVersion().getFullVersion()); + Globals.BUILD_INFO.getVersion().getFullVersion()); BackgroundTask - .wrap(() -> fetcher.performSearch(entry)) - .onRunning(() -> progress.setVisible(true)) - .onSuccess(relatedArticles -> { - progress.setVisible(false); - browser.getEngine().loadContent(convertToHtml(relatedArticles)); - }) - .executeWith(Globals.TASK_EXECUTOR); + .wrap(() -> fetcher.performSearch(entry)) + .onRunning(() -> progress.setVisible(true)) + .onSuccess(relatedArticles -> { + progress.setVisible(false); + root.getChildren().add(getRelatedArticleInfo(relatedArticles)); + }) + .executeWith(Globals.TASK_EXECUTOR); - browser.getEngine().getLoadWorker().stateProperty().addListener(new OpenHyperlinksInExternalBrowser(browser)); + root.getChildren().add(progress); return root; } /** - * Takes a List of HTML snippets stored in the field "html_representation" of a list of bibentries - * - * @param list of bib entries having a field html_representation + * Creates a VBox of the related article information to be used in the StackPane displayed in the Related Articles tab + * @param list List of BibEntries of related articles + * @return VBox of related article descriptions to be displayed in the Related Articles tab */ - private String convertToHtml(List list) { - StringBuilder htmlContent = new StringBuilder(); - URL url = IconTheme.getIconUrl("mdlListIcon"); - htmlContent - .append(""); - htmlContent.append("
    "); - list.stream() - .map(bibEntry -> bibEntry.getField("html_representation")) - .filter(Optional::isPresent) - .map(o -> "
  • " + o.get() + "
  • ") - .forEach(html -> htmlContent.append(html)); - htmlContent.append("
"); - htmlContent.append("
"); - htmlContent.append(""); - return htmlContent.toString(); + private VBox getRelatedArticleInfo(List list) { + VBox vBox = new VBox(); + vBox.setSpacing(20.0); + + for (BibEntry entry : list) { + HBox hBox = new HBox(); + hBox.setSpacing(5.0); + + String title = entry.getTitle().orElse(""); + String journal = entry.getField(FieldName.JOURNAL).orElse(""); + String authors = entry.getField(FieldName.AUTHOR).orElse(""); + String year = entry.getField(FieldName.YEAR).orElse(""); + + Hyperlink titleLink = new Hyperlink(title); + Text journalText = new Text(journal); + journalText.setFont(Font.font(Font.getDefault().getFamily(), FontPosture.ITALIC, Font.getDefault().getSize())); + Text authorsText = new Text(authors); + Text yearText = new Text("(" + year + ")"); + titleLink.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + if (entry.getField(FieldName.URL).isPresent()) { + try { + JabRefDesktop.openBrowser(entry.getField(FieldName.URL).get()); + } catch (IOException e) { + LOGGER.error("Error opening the browser to: " + entry.getField(FieldName.URL).get(), e); + e.printStackTrace(); + } + } + } + }); + + hBox.getChildren().addAll(titleLink, journalText, authorsText, yearText); + vBox.getChildren().add(hBox); + } + return vBox; + } + + /** + * Returns a consent dialog used to ask permission to send data to Mr. DLib. + * @param entry Currently selected BibEntry. (required to allow reloading of pane if accepted) + * @return StackPane returned to be placed into Related Articles tab. + */ + private StackPane getPrivacyDialog(BibEntry entry) { + StackPane root = new StackPane(); + VBox vbox = new VBox(); + vbox.getStyleClass().add("gdpr-dialog"); + vbox.setSpacing(30.0); + + Button button = new Button("Accept"); + button.getStyleClass().add("accept-button"); + Text line1 = new Text("Data about the selected entry must be sent to the Mr. Dlib external service in order to provide recommendations."); + Text line2 = new Text("This setting may be changed in preferences at any time."); + Hyperlink mdlLink = new Hyperlink("Further information about Mr DLib."); + mdlLink.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + try { + JabRefDesktop.openBrowser("http://mr-dlib.org/information-for-users/information-about-mr-dlib-for-jabref-users/"); + } catch (IOException e) { + LOGGER.error("Error opening the browser to: " + entry.getField(FieldName.URL).get(), e); + } + } + }); + + button.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + JabRefPreferences prefs = JabRefPreferences.getInstance(); + prefs.putBoolean(JabRefPreferences.ACCEPT_RECOMMENDATIONS, true); + setContent(getRelatedArticlesPane(entry)); + } + }); + + root.setStyle("-fx-padding: 20 20 20 20"); + vbox.getChildren().addAll(line1, line2, mdlLink, button); + root.getChildren().addAll(vbox); + + return root; } @Override @@ -86,6 +162,11 @@ public boolean shouldShow(BibEntry entry) { @Override protected void bindToEntry(BibEntry entry) { - setContent(getPane(entry)); + // Ask for consent to send data to Mr. DLib on first time to tab + if (JabRefPreferences.getInstance().getBoolean(JabRefPreferences.ACCEPT_RECOMMENDATIONS)) { + setContent(getRelatedArticlesPane(entry)); + } else { + setContent(getPrivacyDialog(entry)); + } } } diff --git a/src/main/java/org/jabref/gui/preferences/EntryEditorPrefsTab.java b/src/main/java/org/jabref/gui/preferences/EntryEditorPrefsTab.java index 4530cb88157..ab874bf1287 100644 --- a/src/main/java/org/jabref/gui/preferences/EntryEditorPrefsTab.java +++ b/src/main/java/org/jabref/gui/preferences/EntryEditorPrefsTab.java @@ -27,6 +27,7 @@ class EntryEditorPrefsTab extends Pane implements PrefsTab { private final CheckBox emacsRebindCtrlF; private final CheckBox autoComplete; private final CheckBox recommendations; + private final CheckBox acceptRecommendations; private final CheckBox validation; private final RadioButton autoCompBoth; private final RadioButton autoCompFF; @@ -51,6 +52,7 @@ public EntryEditorPrefsTab(JabRefPreferences prefs) { emacsRebindCtrlF = new CheckBox(Localization.lang("Rebind C-f, too")); autoComplete = new CheckBox(Localization.lang("Enable word/name autocompletion")); recommendations = new CheckBox(Localization.lang("Show 'Related Articles' tab")); + acceptRecommendations = new CheckBox(Localization.lang("Accept recommendations from Mr. DLib")); validation = new CheckBox(Localization.lang("Show validation messages")); // allowed name formats @@ -84,8 +86,9 @@ public EntryEditorPrefsTab(JabRefPreferences prefs) { builder.add(emacsRebindCtrlA, 1, 5); builder.add(emacsRebindCtrlF, 1, 6); builder.add(recommendations, 1, 7); - builder.add(validation, 1, 8); - builder.add(new Label(""), 1, 9); + builder.add(acceptRecommendations, 1, 8); + builder.add(validation, 1, 9); + builder.add(new Label(""), 1, 10); Label autocompletionOptions = new Label(Localization.lang("Autocompletion options")); autocompletionOptions.getStyleClass().add("sectionHeader"); @@ -113,6 +116,7 @@ public EntryEditorPrefsTab(JabRefPreferences prefs) { builder.add(firstNameModeBoth, 1, 22); } + @Override public Node getBuilder() { return builder; } @@ -135,6 +139,7 @@ public void setValues() { emacsRebindCtrlA.setSelected(prefs.getBoolean(JabRefPreferences.EDITOR_EMACS_KEYBINDINGS_REBIND_CA)); emacsRebindCtrlF.setSelected(prefs.getBoolean(JabRefPreferences.EDITOR_EMACS_KEYBINDINGS_REBIND_CF)); recommendations.setSelected(prefs.getBoolean(JabRefPreferences.SHOW_RECOMMENDATIONS)); + acceptRecommendations.setSelected(prefs.getBoolean(JabRefPreferences.ACCEPT_RECOMMENDATIONS)); autoComplete.setSelected(autoCompletePreferences.shouldAutoComplete()); autoCompFields.setText(autoCompletePreferences.getCompleteNamesAsString()); @@ -171,6 +176,7 @@ public void storeSettings() { prefs.putBoolean(JabRefPreferences.AUTO_OPEN_FORM, autoOpenForm.isSelected()); prefs.putBoolean(JabRefPreferences.DEFAULT_SHOW_SOURCE, defSource.isSelected()); prefs.putBoolean(JabRefPreferences.SHOW_RECOMMENDATIONS, recommendations.isSelected()); + prefs.putBoolean(JabRefPreferences.ACCEPT_RECOMMENDATIONS, acceptRecommendations.isSelected()); prefs.putBoolean(JabRefPreferences.VALIDATE_IN_ENTRY_EDITOR, validation.isSelected()); boolean emacsModeChanged = prefs.getBoolean(JabRefPreferences.EDITOR_EMACS_KEYBINDINGS) != emacsMode.isSelected(); boolean emacsRebindCtrlAChanged = prefs.getBoolean(JabRefPreferences.EDITOR_EMACS_KEYBINDINGS_REBIND_CA) != emacsRebindCtrlA.isSelected(); diff --git a/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java index b1104c192b8..b21050bd052 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java @@ -25,7 +25,7 @@ import org.slf4j.LoggerFactory; /** - * This class is responible to get the recommendations from MDL + * This class is responsible for getting the recommendations from Mr. DLib */ public class MrDLibFetcher implements EntryBasedFetcher { private static final Logger LOGGER = LoggerFactory.getLogger(MrDLibFetcher.class); @@ -108,7 +108,7 @@ private String constructQuery(String queryWithTitle) { URIBuilder builder = new URIBuilder(); builder.setScheme("http"); builder.setHost("api-dev.darwingoliath.com"); - builder.setPath("/v2/related_items/" + queryWithTitle); + builder.setPath("/v2/items/" + queryWithTitle + "/related_items"); builder.addParameter("partner_id", "jabref"); builder.addParameter("app_id", "jabref_desktop"); builder.addParameter("app_version", VERSION); diff --git a/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java index 02c486925c6..d4f5dfe5ab8 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java @@ -25,8 +25,7 @@ import org.slf4j.LoggerFactory; /** - * - * + * Handles importing of recommended articles to be displayed in the Related Articles tab. */ public class MrDLibImporter extends Importer { @@ -35,6 +34,7 @@ public class MrDLibImporter extends Importer { private static final Logger LOGGER = LoggerFactory.getLogger(MrDLibImporter.class); public ParserResult parserResult; + @SuppressWarnings("unused") @Override public boolean isRecognizedFormat(BufferedReader input) throws IOException { @@ -155,14 +155,14 @@ private RankedBibEntry populateBibEntry(JSONObject recommendation) { if (recommendation.has("title") && !recommendation.isNull("title")) { title = recommendation.getString("title"); } - if (recommendation.has("date_published") && !recommendation.isNull("date_published")) { - year = recommendation.getString("date_published"); + if (recommendation.has("year_published") && !recommendation.isNull("year_published")) { + year = Integer.toString(recommendation.getInt("year_published")); } if (recommendation.has("published_in") && !recommendation.isNull("published_in")) { journal = recommendation.getString("published_in"); } if (recommendation.has("url") && !recommendation.isNull("url")) { - url = recommendation.getString("url") + "."; + url = recommendation.getString("url"); } if (recommendation.has("recommendation_id") && !recommendation.isNull("recommendation_id")) { rank = recommendation.getInt("recommendation_id"); @@ -173,6 +173,7 @@ private RankedBibEntry populateBibEntry(JSONObject recommendation) { current.setField(FieldName.TITLE, title); current.setField(FieldName.YEAR, year); current.setField(FieldName.JOURNAL, journal); + current.setField(FieldName.URL, url); // Create HTML representation of recommendation for display on the UI Object[] args = {url, title, authors, journal, year}; @@ -191,7 +192,7 @@ private String getAuthorsString(JSONObject recommendation) { String authorsString = ""; JSONArray array = recommendation.getJSONArray("authors"); for (int i = 0; i < array.length(); ++i) { - authorsString += array.getString(i) + ", "; + authorsString += array.getString(i) + "; "; } int stringLength = authorsString.length(); if (stringLength > 2) { diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index 1be4e2a6052..dff20f4785f 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -300,6 +300,7 @@ public class JabRefPreferences implements PreferencesService { public static final String NAME_FORMATER_KEY = "nameFormatterNames"; public static final String PUSH_TO_APPLICATION = "pushToApplication"; public static final String SHOW_RECOMMENDATIONS = "showRecommendations"; + public static final String ACCEPT_RECOMMENDATIONS = "acceptRecommendations"; public static final String VALIDATE_IN_ENTRY_EDITOR = "validateInEntryEditor"; // Dropped file handler public static final String DROPPEDFILEHANDLER_RENAME = "DroppedFileHandler_RenameFile"; @@ -575,6 +576,7 @@ private JabRefPreferences() { defaults.put(MERGE_ENTRIES_DIFF_MODE, 2); defaults.put(SHOW_RECOMMENDATIONS, Boolean.TRUE); + defaults.put(ACCEPT_RECOMMENDATIONS, Boolean.FALSE); defaults.put(VALIDATE_IN_ENTRY_EDITOR, Boolean.TRUE); defaults.put(EDITOR_EMACS_KEYBINDINGS, Boolean.FALSE); defaults.put(EDITOR_EMACS_KEYBINDINGS_REBIND_CA, Boolean.TRUE); @@ -905,6 +907,7 @@ public EntryEditorPreferences getEntryEditorPreferences() { getImportFormatPreferences(), getCustomTabFieldNames(), getBoolean(SHOW_RECOMMENDATIONS), + getBoolean(ACCEPT_RECOMMENDATIONS), getBoolean(DEFAULT_SHOW_SOURCE), getBibtexKeyPatternPreferences(), Globals.getKeyPrefs(), From 0416402c1cf0b4298f1113bd4a983c282bfeae8f Mon Sep 17 00:00:00 2001 From: conorfos Date: Tue, 18 Sep 2018 10:39:02 +0100 Subject: [PATCH 03/23] Privacy dialog text wrapping Changed privacy dialog text and allowed the text to wrap. --- .../gui/entryeditor/RelatedArticlesTab.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java index 42fb904d05c..95b83787acb 100644 --- a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java @@ -8,6 +8,7 @@ import javafx.scene.control.Button; import javafx.scene.control.Hyperlink; import javafx.scene.control.ProgressIndicator; +import javafx.scene.control.ScrollPane; import javafx.scene.control.Tooltip; import javafx.scene.layout.HBox; import javafx.scene.layout.StackPane; @@ -117,17 +118,19 @@ public void handle(ActionEvent event) { * @param entry Currently selected BibEntry. (required to allow reloading of pane if accepted) * @return StackPane returned to be placed into Related Articles tab. */ - private StackPane getPrivacyDialog(BibEntry entry) { - StackPane root = new StackPane(); + private ScrollPane getPrivacyDialog(BibEntry entry) { + ScrollPane root = new ScrollPane(); VBox vbox = new VBox(); vbox.getStyleClass().add("gdpr-dialog"); - vbox.setSpacing(30.0); + vbox.setSpacing(20.0); - Button button = new Button("Accept"); + Button button = new Button("I Agree"); button.getStyleClass().add("accept-button"); - Text line1 = new Text("Data about the selected entry must be sent to the Mr. Dlib external service in order to provide recommendations."); + Text line1 = new Text("Mr. DLib is an external service which provides article recommendations based on the currently selected entry. Data about the selected entry must be sent to Mr. DLib in order to provide these recommendations. Do you agree that this data may be sent?"); + + line1.setWrappingWidth(1300.0); Text line2 = new Text("This setting may be changed in preferences at any time."); - Hyperlink mdlLink = new Hyperlink("Further information about Mr DLib."); + Hyperlink mdlLink = new Hyperlink("Further information about Mr DLib. for JabRef users."); mdlLink.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { @@ -149,8 +152,8 @@ public void handle(ActionEvent event) { }); root.setStyle("-fx-padding: 20 20 20 20"); - vbox.getChildren().addAll(line1, line2, mdlLink, button); - root.getChildren().addAll(vbox); + vbox.getChildren().addAll(line1, mdlLink, line2, button); + root.setContent(vbox); return root; } From 86350c9c37ae48b4d30d4eadb234f944c2500d3a Mon Sep 17 00:00:00 2001 From: conorfos Date: Fri, 21 Sep 2018 15:07:20 +0100 Subject: [PATCH 04/23] Created dev switch based on JabRef version --- .../logic/importer/fetcher/MrDLibFetcher.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java index b21050bd052..6431417b770 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java @@ -10,12 +10,14 @@ import java.util.List; import java.util.Optional; +import org.jabref.Globals; import org.jabref.logic.importer.EntryBasedFetcher; import org.jabref.logic.importer.FetcherException; import org.jabref.logic.importer.ParserResult; import org.jabref.logic.importer.fileformat.MrDLibImporter; import org.jabref.logic.l10n.Localization; import org.jabref.logic.net.URLDownload; +import org.jabref.logic.util.Version; import org.jabref.model.database.BibDatabase; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.FieldName; @@ -107,7 +109,7 @@ private String constructQuery(String queryWithTitle) { queryWithTitle = queryWithTitle.replaceAll("/", " "); URIBuilder builder = new URIBuilder(); builder.setScheme("http"); - builder.setHost("api-dev.darwingoliath.com"); + builder.setHost(getMdlUrl()); builder.setPath("/v2/items/" + queryWithTitle + "/related_items"); builder.addParameter("partner_id", "jabref"); builder.addParameter("app_id", "jabref_desktop"); @@ -123,4 +125,13 @@ private String constructQuery(String queryWithTitle) { } return ""; } + + private String getMdlUrl() { + Version currentVersion = Globals.BUILD_INFO.getVersion(); + if (currentVersion.isDevelopmentVersion()) { + return "api-dev.darwingoliath.com"; + } else { + return "api.darwingoliath.com"; + } + } } From 25e5cb8a5cda34eddeef53cb519b96967ff2946d Mon Sep 17 00:00:00 2001 From: conorfos Date: Wed, 26 Sep 2018 14:30:16 +0100 Subject: [PATCH 05/23] Adjusted Hyperlink styling --- src/main/java/org/jabref/gui/Base.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/jabref/gui/Base.css b/src/main/java/org/jabref/gui/Base.css index 8eb1c449a3e..12ebeb5925c 100644 --- a/src/main/java/org/jabref/gui/Base.css +++ b/src/main/java/org/jabref/gui/Base.css @@ -247,6 +247,7 @@ -fx-underline: false; -fx-border-style: null; -fx-border-color: null; + -fx-text-fill: -jr-theme; } .hyperlink:visited { From 045c15d139e485a53339b255559fac525ac514ff Mon Sep 17 00:00:00 2001 From: conorfos Date: Wed, 26 Sep 2018 14:34:00 +0100 Subject: [PATCH 06/23] Removed .bib file included by mistake --- MicroRecsys.bib | 291 ------------------------------------------------ 1 file changed, 291 deletions(-) delete mode 100644 MicroRecsys.bib diff --git a/MicroRecsys.bib b/MicroRecsys.bib deleted file mode 100644 index 93645845e27..00000000000 --- a/MicroRecsys.bib +++ /dev/null @@ -1,291 +0,0 @@ -% Encoding: UTF-8 - -@STRING{dke = {Data \& Knowledge Engineering}} - -@STRING{joop = {Journal of Object-Oriented Programming}} - -@STRING{lnai = {Lecture Notes in Artificial Intelligence}} - -@STRING{lncs = {Lecture Notes in Computer Science}} - -@STRING{mibi = {Medizinische Informatik und Bioinformatik}} - -@STRING{tkde = {IEEE Transactions on Knowledge and Data Engineering}} - -@STRING{tods = {ACM Transactions on Database Systems}} - -@STRING{tois = {ACM Transactions on Information Systems}} - -@INPROCEEDINGS{DBLP:conf/ercimdl/BeelLNG13, - author = {J{\"{o}}ran Beel and Stefan Langer and Andreas N{\"{u}}rnberger and - Marcel Genzmehr}, - title = {The Impact of Demographics (Age and Gender) and Other User-Characteristics - on Evaluating Recommender Systems}, - booktitle = {Research and Advanced Technology for Digital Libraries - International - Conference on Theory and Practice of Digital Libraries, {TPDL} 2013, - Valletta, Malta, September 22-26, 2013. Proceedings}, - year = {2013}, - pages = {396--400}, - bibsource = {dblp computer science bibliography, https://dblp.org}, - biburl = {https://dblp.org/rec/bib/conf/ercimdl/BeelLNG13}, - crossref = {DBLP:conf/ercimdl/2013}, - doi = {10.1007/978-3-642-40501-3_45}, - timestamp = {Fri, 02 Jun 2017 20:47:58 +0200}, - url = {https://doi.org/10.1007/978-3-642-40501-3_45} -} - -@INPROCEEDINGS{DBLP:conf/recsys/EkstrandP17, - author = {Michael D. Ekstrand and Maria Soledad Pera}, - title = {The Demographics of Cool: Popularity and Recommender Performance - for Different Groups of Users}, - booktitle = {Proceedings of the Poster Track of the 11th {ACM} Conference on Recommender - Systems (RecSys 2017), Como, Italy, August 28, 2017.}, - year = {2017}, - bibsource = {dblp computer science bibliography, https://dblp.org}, - biburl = {https://dblp.org/rec/bib/conf/recsys/EkstrandP17}, - crossref = {DBLP:conf/recsys/2017p}, - timestamp = {Fri, 08 Sep 2017 10:53:00 +0200}, - url = {http://ceur-ws.org/Vol-1905/recsys2017_poster20.pdf} -} - -@Article{ahsan2005conceptual, - author = {Ahsan, Mujtaba and Ngo-Ye, Lin}, - title = {A Conceptual Model of Recommender System for Algorithm Selection}, - journal = {AMCIS 2005 Proceedings}, - year = {2005}, - pages = {122}, - file = {:C\:/Users/Conor/Desktop/PDFdoc.pdf:PDF}, -} - -@ARTICLE{beelproposal, - author = {Beel, Joeran}, - title = {A Macro/Micro Recommender System for Recommendation Algorithms [Proposal]}, - journal = {ResearchGate}, - year = {2017} -} - -@ARTICLE{beel2016towards, - author = {Beel, Joeran and Breitinger, Corinna and Langer, Stefan and Lommatzsch, - Andreas and Gipp, Bela}, - title = {Towards reproducibility in recommender-systems research}, - journal = {User modeling and user-adapted interaction}, - year = {2016}, - volume = {26}, - pages = {69--101}, - number = {1}, - publisher = {Springer} -} - -@INPROCEEDINGS{beel2013comparative, - author = {Beel, Joeran and Genzmehr, Marcel and Langer, Stefan and N{\"u}rnberger, - Andreas and Gipp, Bela}, - title = {A comparative analysis of offline and online evaluations and discussion - of research paper recommender system evaluation}, - booktitle = {Proceedings of the international workshop on reproducibility and - replication in recommender systems evaluation}, - year = {2013}, - pages = {7--14}, - organization = {ACM} -} - -@ARTICLE{beel2016paper, - author = {Beel, Joeran and Gipp, Bela and Langer, Stefan and Breitinger, Corinna}, - title = {paper recommender systems: a literature survey}, - journal = {International Journal on Digital Libraries}, - year = {2016}, - volume = {17}, - pages = {305--338}, - number = {4}, - publisher = {Springer} -} - -@INPROCEEDINGS{beel2011introducing, - author = {Beel, Joeran and Gipp, Bela and Langer, Stefan and Genzmehr, Marcel - and Wilde, Erik and N{\"u}rnberger, Andreas and Pitman, Jim}, - title = {Introducing Mr. DLib, a Machine-readable Digital Library}, - booktitle = {Proceedings of the 11th annual international ACM/IEEE joint conference - on Digital libraries}, - year = {2011}, - pages = {463--464}, - organization = {ACM} -} - -@ARTICLE{DBLP:journals/umuai/Burke02, - author = {Robin D. Burke}, - title = {Hybrid Recommender Systems: Survey and Experiments}, - journal = {User Model. User-Adapt. Interact.}, - year = {2002}, - volume = {12}, - pages = {331--370}, - number = {4}, - bibsource = {dblp computer science bibliography, https://dblp.org}, - biburl = {https://dblp.org/rec/bib/journals/umuai/Burke02}, - doi = {10.1023/A:1021240730564}, - timestamp = {Sat, 27 May 2017 14:24:37 +0200}, - url = {https://doi.org/10.1023/A:1021240730564} -} - -@ARTICLE{cunha2018cf4cf, - author = {Cunha, Tiago and Soares, Carlos and de Carvalho, Andr{\'e} CPLF}, - title = {CF4CF: Recommending Collaborative Filtering algorithms using Collaborative - Filtering}, - journal = {arXiv preprint arXiv:1803.02250}, - year = {2018} -} - -@ARTICLE{cunha2018metalearning, - author = {Cunha, Tiago and Soares, Carlos and de Carvalho, Andr{\'e} CPLF}, - title = {Metalearning and Recommender Systems: A literature review and empirical - study on the algorithm selection problem for Collaborative Filtering}, - journal = {Information Sciences}, - year = {2018}, - volume = {423}, - pages = {128--144}, - publisher = {Elsevier} -} - -@INPROCEEDINGS{cunha2016selecting, - author = {Cunha, Tiago and Soares, Carlos and de Carvalho, Andr{\'e} CPLF}, - title = {Selecting Collaborative Filtering algorithms using Metalearning}, - booktitle = {Joint European Conference on Machine Learning and Knowledge Discovery - in Databases}, - year = {2016}, - pages = {393--409}, - organization = {Springer} -} - -@INPROCEEDINGS{ekstrand2012recommenders, - author = {Ekstrand, Michael and Riedl, John}, - title = {When recommenders fail: predicting recommender failure for algorithm - selection and combination}, - booktitle = {Proceedings of the sixth ACM conference on Recommender systems}, - year = {2012}, - pages = {233--236}, - organization = {ACM} -} - -@ARTICLE{garciametalearning, - author = {Garc{\i}a-Saiz, Diego and Zorrilla, Marta}, - title = {Metalearning-based recommenders: towards automatic classification - algorithm selection} -} - -@ARTICLE{Gomez-Uribe:2015:NRS:2869770.2843948, - author = {Gomez-Uribe, Carlos A. and Hunt, Neil}, - title = {The Netflix Recommender System: Algorithms, Business Value, and Innovation}, - journal = {ACM Trans. Manage. Inf. Syst.}, - year = {2015}, - volume = {6}, - pages = {13:1--13:19}, - number = {4}, - month = {\#dec\#}, - acmid = {2843948}, - address = {New York, NY, USA}, - articleno = {13}, - doi = {10.1145/2843948}, - issn = {2158-656X}, - issue_date = {January 2016}, - keywords = {Recommender systems}, - numpages = {19}, - publisher = {ACM}, - url = {http://doi.acm.org/10.1145/2843948} -} - -@ARTICLE{DBLP:journals/tois/ImH07, - author = {Il Im and Alexander Hars}, - title = {Does a one-size recommendation system fit all? the effectiveness - of collaborative filtering based recommendation systems across different - domains and search modes}, - journal = {{ACM} Trans. Inf. Syst.}, - year = {2007}, - volume = {26}, - pages = {4}, - number = {1}, - bibsource = {dblp computer science bibliography, https://dblp.org}, - biburl = {https://dblp.org/rec/bib/journals/tois/ImH07}, - doi = {10.1145/1292591.1292595}, - timestamp = {Thu, 12 Jan 2017 13:39:58 +0100}, - url = {http://doi.acm.org/10.1145/1292591.1292595} -} - -@ARTICLE{koren2009bellkor, - author = {Koren, Yehuda}, - title = {The bellkor solution to the netflix grand prize}, - journal = {Netflix prize documentation}, - year = {2009}, - volume = {81}, - pages = {1--10} -} - -@ARTICLE{lemke2015metalearning, - author = {Lemke, Christiane and Budka, Marcin and Gabrys, Bogdan}, - title = {Metalearning: a survey of trends and technologies}, - journal = {Artificial intelligence review}, - year = {2015}, - volume = {44}, - pages = {117--130}, - number = {1}, - publisher = {Springer} -} - -@ARTICLE{rokach2010ensemble, - author = {Rokach, Lior}, - title = {Ensemble-based classifiers}, - journal = {Artificial Intelligence Review}, - year = {2010}, - volume = {33}, - pages = {1--39}, - number = {1-2}, - publisher = {Springer} -} - -@INPROCEEDINGS{romero2013meta, - author = {Romero, Crist{\'o}bal and Olmo, Juan Luis and Ventura, Sebasti{\'a}n}, - title = {A meta-learning approach for recommending a subset of white-box classification - algorithms for Moodle datasets}, - booktitle = {Educational Data Mining 2013}, - year = {2013} -} - -@ARTICLE{sill2009feature, - author = {Sill, Joseph and Tak{\'a}cs, G{\'a}bor and Mackey, Lester and Lin, - David}, - title = {Feature-weighted linear stacking}, - journal = {arXiv preprint arXiv:0911.0460}, - year = {2009} -} - -@ARTICLE{toscher2009bigchaos, - author = {T{\"o}scher, Andreas and Jahrer, Michael and Bell, Robert M}, - title = {The bigchaos solution to the netflix grand prize}, - journal = {Netflix prize documentation}, - year = {2009}, - pages = {1--52} -} - -@ARTICLE{wolpert1992stacked, - author = {Wolpert, David H}, - title = {Stacked generalization}, - journal = {Neural networks}, - year = {1992}, - volume = {5}, - pages = {241--259}, - number = {2}, - publisher = {Elsevier} -} - -@Comment{jabref-meta: databaseType:bibtex;} - -@Comment{jabref-meta: grouping: -0 AllEntriesGroup:; -1 StaticGroup:link spam\;0\;1\;\;\;\;; -1 StaticGroup:content spam\;0\;1\;\;\;\;; -1 StaticGroup:competiror click fraud\;0\;1\;\;\;\;; -1 KeywordGroup:Norman\;0\;owner\;Norman\;1\;0\;1\;\;\;\;; -1 StaticGroup:ourpublications\;0\;1\;\;\;\;; -1 StaticGroup:test\;0\;1\;\;\;\;; -} - -@Comment{jabref-meta: groupsversion: -3; -} From 69c63835ea2d21fb055887e183f47daac1aba2ef Mon Sep 17 00:00:00 2001 From: conorfos Date: Thu, 27 Sep 2018 08:32:36 +0100 Subject: [PATCH 07/23] Simplification of Dev switch Replaced if/else with in-line conditional --- .../logic/importer/fetcher/MrDLibFetcher.java | 6 +- .../preferences/JabRefPreferences.java.orig | 2029 +++++++++++++++++ 2 files changed, 2030 insertions(+), 5 deletions(-) create mode 100644 src/main/java/org/jabref/preferences/JabRefPreferences.java.orig diff --git a/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java index 6431417b770..d31d1eee0e6 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java @@ -128,10 +128,6 @@ private String constructQuery(String queryWithTitle) { private String getMdlUrl() { Version currentVersion = Globals.BUILD_INFO.getVersion(); - if (currentVersion.isDevelopmentVersion()) { - return "api-dev.darwingoliath.com"; - } else { - return "api.darwingoliath.com"; - } + return currentVersion.isDevelopmentVersion() ? "api-dev.darwingoliath.com" : "api.darwingoliath.com"; } } diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java.orig b/src/main/java/org/jabref/preferences/JabRefPreferences.java.orig new file mode 100644 index 00000000000..641003823bf --- /dev/null +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java.orig @@ -0,0 +1,2029 @@ +package org.jabref.preferences; + +import java.awt.Color; +import java.awt.Font; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +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; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.TreeMap; +import java.util.UUID; +import java.util.prefs.BackingStoreException; +import java.util.prefs.InvalidPreferencesFormatException; +import java.util.prefs.Preferences; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javafx.scene.control.TableColumn.SortType; + +import org.jabref.Globals; +import org.jabref.JabRefException; +import org.jabref.JabRefMain; +import org.jabref.gui.SidePaneType; +import org.jabref.gui.autocompleter.AutoCompleteFirstNameMode; +import org.jabref.gui.autocompleter.AutoCompletePreferences; +import org.jabref.gui.desktop.JabRefDesktop; +import org.jabref.gui.entryeditor.EntryEditorPreferences; +import org.jabref.gui.entryeditor.EntryEditorTabList; +import org.jabref.gui.groups.GroupViewMode; +import org.jabref.gui.keyboard.KeyBindingRepository; +import org.jabref.gui.maintable.ColumnPreferences; +import org.jabref.gui.maintable.MainTablePreferences; +import org.jabref.gui.preferences.ImportSettingsTab; +import org.jabref.logic.bibtex.FieldContentParserPreferences; +import org.jabref.logic.bibtex.LatexFieldFormatterPreferences; +import org.jabref.logic.bibtexkeypattern.BibtexKeyPatternPreferences; +import org.jabref.logic.citationstyle.CitationStyle; +import org.jabref.logic.cleanup.CleanupPreferences; +import org.jabref.logic.cleanup.CleanupPreset; +import org.jabref.logic.cleanup.Cleanups; +import org.jabref.logic.exporter.ExporterFactory; +import org.jabref.logic.exporter.SavePreferences; +import org.jabref.logic.exporter.TemplateExporter; +import org.jabref.logic.importer.ImportFormatPreferences; +import org.jabref.logic.importer.fetcher.DoiFetcher; +import org.jabref.logic.journals.JournalAbbreviationLoader; +import org.jabref.logic.journals.JournalAbbreviationPreferences; +import org.jabref.logic.l10n.Language; +import org.jabref.logic.l10n.Localization; +import org.jabref.logic.layout.LayoutFormatterPreferences; +import org.jabref.logic.layout.format.FileLinkPreferences; +import org.jabref.logic.layout.format.NameFormatterPreferences; +import org.jabref.logic.net.ProxyPreferences; +import org.jabref.logic.openoffice.OpenOfficePreferences; +import org.jabref.logic.openoffice.StyleLoader; +import org.jabref.logic.preferences.TimestampPreferences; +import org.jabref.logic.protectedterms.ProtectedTermsList; +import org.jabref.logic.protectedterms.ProtectedTermsLoader; +import org.jabref.logic.protectedterms.ProtectedTermsPreferences; +import org.jabref.logic.remote.RemotePreferences; +import org.jabref.logic.shared.prefs.SharedDatabasePreferences; +import org.jabref.logic.util.OS; +import org.jabref.logic.util.UpdateFieldPreferences; +import org.jabref.logic.util.Version; +import org.jabref.logic.util.io.AutoLinkPreferences; +import org.jabref.logic.util.io.FileHistory; +import org.jabref.logic.xmp.XmpPreferences; +import org.jabref.model.bibtexkeypattern.GlobalBibtexKeyPattern; +import org.jabref.model.cleanup.FieldFormatterCleanups; +import org.jabref.model.database.BibDatabaseMode; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.BibtexSingleField; +import org.jabref.model.entry.CustomEntryType; +import org.jabref.model.entry.FieldName; +import org.jabref.model.entry.InternalBibtexFields; +import org.jabref.model.entry.specialfields.SpecialField; +import org.jabref.model.metadata.FilePreferences; +import org.jabref.model.metadata.SaveOrderConfig; +import org.jabref.model.strings.StringUtil; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class JabRefPreferences implements PreferencesService { + + // Push to application preferences + public static final String EMACS_PATH = "emacsPath"; + public static final String EMACS_ADDITIONAL_PARAMETERS = "emacsParameters"; + + /* contents of the defaults HashMap that are defined in this class. + * There are more default parameters in this map which belong to separate preference classes. + */ + public static final String TEXSTUDIO_PATH = "TeXstudioPath"; + public static final String WIN_EDT_PATH = "winEdtPath"; + public static final String TEXMAKER_PATH = "texmakerPath"; + public static final String VIM_SERVER = "vimServer"; + public static final String VIM = "vim"; + public static final String LYXPIPE = "lyxpipe"; + public static final String EXTERNAL_FILE_TYPES = "externalFileTypes"; + public static final String FONT_FAMILY = "fontFamily"; + public static final String FX_FONT_RENDERING_TWEAK = "fxFontRenderingTweak"; + public static final String LANGUAGE = "language"; + public static final String NAMES_LAST_ONLY = "namesLastOnly"; + public static final String ABBR_AUTHOR_NAMES = "abbrAuthorNames"; + public static final String NAMES_NATBIB = "namesNatbib"; + public static final String NAMES_FIRST_LAST = "namesFf"; + public static final String BIBLATEX_DEFAULT_MODE = "biblatexMode"; + public static final String NAMES_AS_IS = "namesAsIs"; + public static final String ENTRY_EDITOR_HEIGHT = "entryEditorHeightFX"; + public static final String AUTO_RESIZE_MODE = "autoResizeMode"; + public static final String WINDOW_MAXIMISED = "windowMaximised"; + public static final String USE_DEFAULT_LOOK_AND_FEEL = "useDefaultLookAndFeel"; + public static final String PROXY_PORT = "proxyPort"; + public static final String PROXY_HOSTNAME = "proxyHostname"; + public static final String PROXY_USE = "useProxy"; + public static final String PROXY_USERNAME = "proxyUsername"; + public static final String PROXY_PASSWORD = "proxyPassword"; + public static final String PROXY_USE_AUTHENTICATION = "useProxyAuthentication"; + + public static final String REFORMAT_FILE_ON_SAVE_AND_EXPORT = "reformatFileOnSaveAndExport"; + public static final String EXPORT_IN_ORIGINAL_ORDER = "exportInOriginalOrder"; + public static final String EXPORT_IN_SPECIFIED_ORDER = "exportInSpecifiedOrder"; + public static final String EXPORT_PRIMARY_SORT_FIELD = "exportPriSort"; + public static final String EXPORT_PRIMARY_SORT_DESCENDING = "exportPriDescending"; + public static final String EXPORT_SECONDARY_SORT_FIELD = "exportSecSort"; + public static final String EXPORT_SECONDARY_SORT_DESCENDING = "exportSecDescending"; + public static final String EXPORT_TERTIARY_SORT_FIELD = "exportTerSort"; + public static final String EXPORT_TERTIARY_SORT_DESCENDING = "exportTerDescending"; + public static final String NEWLINE = "newline"; + public static final String COLUMN_WIDTHS = "columnWidths"; + public static final String COLUMN_NAMES = "columnNames"; + public static final String COLUMN_IN_SORT_ORDER = "columnInSortOrder"; + public static final String COlUMN_IN_SORT_ORDER_TYPE = "columnInSortOrderType"; + + public static final String SIDE_PANE_COMPONENT_PREFERRED_POSITIONS = "sidePaneComponentPreferredPositions"; + public static final String SIDE_PANE_COMPONENT_NAMES = "sidePaneComponentNames"; + public static final String XMP_PRIVACY_FILTERS = "xmpPrivacyFilters"; + public static final String USE_XMP_PRIVACY_FILTER = "useXmpPrivacyFilter"; + public static final String DEFAULT_AUTO_SORT = "defaultAutoSort"; + public static final String DEFAULT_SHOW_SOURCE = "defaultShowSource"; + // Window sizes + public static final String SIZE_Y = "mainWindowSizeY"; + public static final String SIZE_X = "mainWindowSizeX"; + public static final String POS_Y = "mainWindowPosY"; + public static final String POS_X = "mainWindowPosX"; + public static final String STRINGS_SIZE_Y = "stringsSizeY"; + public static final String STRINGS_SIZE_X = "stringsSizeX"; + public static final String STRINGS_POS_Y = "stringsPosY"; + public static final String STRINGS_POS_X = "stringsPosX"; + public static final String DUPLICATES_SIZE_Y = "duplicatesSizeY"; + public static final String DUPLICATES_SIZE_X = "duplicatesSizeX"; + public static final String DUPLICATES_POS_Y = "duplicatesPosY"; + public static final String DUPLICATES_POS_X = "duplicatesPosX"; + public static final String MERGEENTRIES_SIZE_Y = "mergeEntriesSizeY"; + public static final String MERGEENTRIES_SIZE_X = "mergeEntriesSizeX"; + public static final String MERGEENTRIES_POS_Y = "mergeEntriesPosY"; + public static final String MERGEENTRIES_POS_X = "mergeEntriesPosX"; + public static final String PREAMBLE_SIZE_Y = "preambleSizeY"; + public static final String PREAMBLE_SIZE_X = "preambleSizeX"; + public static final String PREAMBLE_POS_Y = "preamblePosY"; + public static final String PREAMBLE_POS_X = "preamblePosX"; + public static final String TERMS_SIZE_Y = "termsSizeY"; + public static final String TERMS_SIZE_X = "termsSizeX"; + public static final String TERMS_POS_Y = "termsPosY"; + public static final String TERMS_POS_X = "termsPosX"; + public static final String SEARCH_DIALOG_HEIGHT = "searchDialogHeight"; + public static final String SEARCH_DIALOG_WIDTH = "searchDialogWidth"; + public static final String IMPORT_INSPECTION_DIALOG_HEIGHT = "importInspectionDialogHeight"; + public static final String IMPORT_INSPECTION_DIALOG_WIDTH = "importInspectionDialogWidth"; + public static final String LAST_EDITED = "lastEdited"; + public static final String OPEN_LAST_EDITED = "openLastEdited"; + public static final String LAST_FOCUSED = "lastFocused"; + public static final String BACKUP = "backup"; + public static final String AUTO_OPEN_FORM = "autoOpenForm"; + public static final String IMPORT_WORKING_DIRECTORY = "importWorkingDirectory"; + public static final String EXPORT_WORKING_DIRECTORY = "exportWorkingDirectory"; + public static final String WORKING_DIRECTORY = "workingDirectory"; + public static final String EDITOR_EMACS_KEYBINDINGS = "editorEMACSkeyBindings"; + public static final String EDITOR_EMACS_KEYBINDINGS_REBIND_CA = "editorEMACSkeyBindingsRebindCA"; + public static final String EDITOR_EMACS_KEYBINDINGS_REBIND_CF = "editorEMACSkeyBindingsRebindCF"; + public static final String GROUPS_DEFAULT_FIELD = "groupsDefaultField"; + + public static final String KEYWORD_SEPARATOR = "groupKeywordSeparator"; + public static final String AUTO_ASSIGN_GROUP = "autoAssignGroup"; + public static final String LIST_OF_FILE_COLUMNS = "listOfFileColumns"; + public static final String EXTRA_FILE_COLUMNS = "extraFileColumns"; + public static final String ARXIV_COLUMN = "arxivColumn"; + public static final String FILE_COLUMN = "fileColumn"; + public static final String PREFER_URL_DOI = "preferUrlDoi"; + public static final String URL_COLUMN = "urlColumn"; + // Colors + public static final String FIELD_EDITOR_TEXT_COLOR = "fieldEditorTextColor"; + public static final String ACTIVE_FIELD_EDITOR_BACKGROUND_COLOR = "activeFieldEditorBackgroundColor"; + public static final String INVALID_FIELD_BACKGROUND_COLOR = "invalidFieldBackgroundColor"; + public static final String VALID_FIELD_BACKGROUND_COLOR = "validFieldBackgroundColor"; + public static final String ICON_ENABLED_COLOR = "iconEnabledColor"; + public static final String ICON_DISABLED_COLOR = "iconDisabledColor"; + public static final String FONT_SIZE = "fontSize"; + public static final String OVERRIDE_DEFAULT_FONT_SIZE = "overrideDefaultFontSize"; + public static final String MAIN_FONT_SIZE = "mainFontSize"; + public static final String FONT_STYLE = "fontStyle"; + public static final String RECENT_DATABASES = "recentDatabases"; + public static final String RENAME_ON_MOVE_FILE_TO_FILE_DIR = "renameOnMoveFileToFileDir"; + public static final String MEMORY_STICK_MODE = "memoryStickMode"; + public static final String DEFAULT_OWNER = "defaultOwner"; + public static final String DEFAULT_ENCODING = "defaultEncoding"; + public static final String TOOLBAR_VISIBLE = "toolbarVisible"; + // Timestamp preferences + public static final String USE_TIME_STAMP = "useTimeStamp"; + public static final String UPDATE_TIMESTAMP = "updateTimestamp"; + public static final String TIME_STAMP_FIELD = "timeStampField"; + public static final String TIME_STAMP_FORMAT = "timeStampFormat"; + public static final String OVERWRITE_TIME_STAMP = "overwriteTimeStamp"; + + public static final String WARN_ABOUT_DUPLICATES_IN_INSPECTION = "warnAboutDuplicatesInInspection"; + public static final String GENERATE_KEYS_AFTER_INSPECTION = "generateKeysAfterInspection"; + public static final String NON_WRAPPABLE_FIELDS = "nonWrappableFields"; + public static final String RESOLVE_STRINGS_ALL_FIELDS = "resolveStringsAllFields"; + public static final String DO_NOT_RESOLVE_STRINGS_FOR = "doNotResolveStringsFor"; + public static final String MERGE_ENTRIES_DIFF_MODE = "mergeEntriesDiffMode"; + public static final String CUSTOM_EXPORT_FORMAT = "customExportFormat"; + public static final String CUSTOM_IMPORT_FORMAT = "customImportFormat"; + public static final String KEY_PATTERN_REGEX = "KeyPatternRegex"; + public static final String KEY_PATTERN_REPLACEMENT = "KeyPatternReplacement"; + public static final String CONSOLE_COMMAND = "consoleCommand"; + public static final String USE_DEFAULT_CONSOLE_APPLICATION = "useDefaultConsoleApplication"; + public static final String ADOBE_ACROBAT_COMMAND = "adobeAcrobatCommand"; + public static final String SUMATRA_PDF_COMMAND = "sumatraCommand"; + public static final String USE_PDF_READER = "usePDFReader"; + // Currently, it is not possible to specify defaults for specific entry types + // When this should be made possible, the code to inspect is org.jabref.gui.preferences.BibtexKeyPatternPrefTab.storeSettings() -> LabelPattern keypatterns = getCiteKeyPattern(); etc + public static final String DEFAULT_BIBTEX_KEY_PATTERN = "defaultBibtexKeyPattern"; + public static final String GRAY_OUT_NON_HITS = "grayOutNonHits"; + public static final String CONFIRM_DELETE = "confirmDelete"; + public static final String WARN_BEFORE_OVERWRITING_KEY = "warnBeforeOverwritingKey"; + public static final String AVOID_OVERWRITING_KEY = "avoidOverwritingKey"; + public static final String OVERWRITE_OWNER = "overwriteOwner"; + public static final String USE_OWNER = "useOwner"; + public static final String AUTOLINK_EXACT_KEY_ONLY = "autolinkExactKeyOnly"; + public static final String SHOW_FILE_LINKS_UPGRADE_WARNING = "showFileLinksUpgradeWarning"; + public static final String SIDE_PANE_WIDTH = "sidePaneWidthFX"; + public static final String LAST_USED_EXPORT = "lastUsedExport"; + public static final String CITE_COMMAND = "citeCommand"; + public static final String GENERATE_KEYS_BEFORE_SAVING = "generateKeysBeforeSaving"; + public static final String EMAIL_SUBJECT = "emailSubject"; + public static final String OPEN_FOLDERS_OF_ATTACHED_FILES = "openFoldersOfAttachedFiles"; + public static final String KEY_GEN_ALWAYS_ADD_LETTER = "keyGenAlwaysAddLetter"; + public static final String KEY_GEN_FIRST_LETTER_A = "keyGenFirstLetterA"; + public static final String ENFORCE_LEGAL_BIBTEX_KEY = "enforceLegalBibtexKey"; + public static final String LOCAL_AUTO_SAVE = "localAutoSave"; + public static final String RUN_AUTOMATIC_FILE_SEARCH = "runAutomaticFileSearch"; + public static final String NUMERIC_FIELDS = "numericFields"; + public static final String AUTOLINK_REG_EXP_SEARCH_EXPRESSION_KEY = "regExpSearchExpression"; + public static final String AUTOLINK_USE_REG_EXP_SEARCH_KEY = "useRegExpSearch"; + public static final String BIB_LOC_AS_PRIMARY_DIR = "bibLocAsPrimaryDir"; + public static final String SELECTED_FETCHER_INDEX = "selectedFetcherIndex"; + public static final String WEB_SEARCH_VISIBLE = "webSearchVisible"; + public static final String GROUP_SIDEPANE_VISIBLE = "groupSidepaneVisible"; + public static final String ALLOW_FILE_AUTO_OPEN_BROWSE = "allowFileAutoOpenBrowse"; + public static final String CUSTOM_TAB_NAME = "customTabName_"; + public static final String CUSTOM_TAB_FIELDS = "customTabFields_"; + public static final String USE_UNIT_FORMATTER_ON_SEARCH = "useUnitFormatterOnSearch"; + public static final String USE_CASE_KEEPER_ON_SEARCH = "useCaseKeeperOnSearch"; + public static final String ASK_AUTO_NAMING_PDFS_AGAIN = "AskAutoNamingPDFsAgain"; + public static final String CLEANUP_DOI = "CleanUpDOI"; + public static final String CLEANUP_ISSN = "CleanUpISSN"; + public static final String CLEANUP_MOVE_PDF = "CleanUpMovePDF"; + public static final String CLEANUP_MAKE_PATHS_RELATIVE = "CleanUpMakePathsRelative"; + public static final String CLEANUP_RENAME_PDF = "CleanUpRenamePDF"; + public static final String CLEANUP_RENAME_PDF_ONLY_RELATIVE_PATHS = "CleanUpRenamePDFonlyRelativePaths"; + public static final String CLEANUP_UPGRADE_EXTERNAL_LINKS = "CleanUpUpgradeExternalLinks"; + public static final String CLEANUP_CONVERT_TO_BIBLATEX = "CleanUpConvertToBiblatex"; + public static final String CLEANUP_CONVERT_TO_BIBTEX = "CleanUpConvertToBibtex"; + public static final String CLEANUP_FIX_FILE_LINKS = "CleanUpFixFileLinks"; + public static final String CLEANUP_FORMATTERS = "CleanUpFormatters"; + public static final String IMPORT_DEFAULT_PDF_IMPORT_STYLE = "importDefaultPDFimportStyle"; + public static final String IMPORT_ALWAYSUSE = "importAlwaysUsePDFImportStyle"; + public static final String IMPORT_FILENAMEPATTERN = "importFileNamePattern"; + public static final String IMPORT_FILEDIRPATTERN = "importFileDirPattern"; + public static final String NAME_FORMATTER_VALUE = "nameFormatterFormats"; + public static final String NAME_FORMATER_KEY = "nameFormatterNames"; + public static final String PUSH_TO_APPLICATION = "pushToApplication"; + public static final String SHOW_RECOMMENDATIONS = "showRecommendations"; + public static final String ACCEPT_RECOMMENDATIONS = "acceptRecommendations"; + public static final String VALIDATE_IN_ENTRY_EDITOR = "validateInEntryEditor"; + // Dropped file handler + public static final String DROPPEDFILEHANDLER_RENAME = "DroppedFileHandler_RenameFile"; + public static final String DROPPEDFILEHANDLER_MOVE = "DroppedFileHandler_MoveFile"; + public static final String DROPPEDFILEHANDLER_COPY = "DroppedFileHandler_CopyFile"; + public static final String DROPPEDFILEHANDLER_LEAVE = "DroppedFileHandler_LeaveFileInDir"; + // Remote + public static final String USE_REMOTE_SERVER = "useRemoteServer"; + public static final String REMOTE_SERVER_PORT = "remoteServerPort"; + + /** + * The OpenOffice/LibreOffice connection preferences are: + * OO_PATH main directory for OO/LO installation, used to detect location on Win/OS X when using manual connect + * OO_EXECUTABLE_PATH path to soffice-file + * OO_JARS_PATH directory that contains juh.jar, jurt.jar, ridl.jar, unoil.jar + * OO_SYNC_WHEN_CITING true if the reference list is updated when adding a new citation + * OO_SHOW_PANEL true if the OO panel is shown on startup + * OO_USE_ALL_OPEN_DATABASES true if all databases should be used when citing + * OO_BIBLIOGRAPHY_STYLE_FILE path to the used style file + * OO_EXTERNAL_STYLE_FILES list with paths to external style files + * STYLES_*_* size and position of "Select style" dialog + */ + public static final String OO_EXECUTABLE_PATH = "ooExecutablePath"; + public static final String OO_PATH = "ooPath"; + public static final String OO_JARS_PATH = "ooJarsPath"; + public static final String OO_SHOW_PANEL = "showOOPanel"; + public static final String OO_SYNC_WHEN_CITING = "syncOOWhenCiting"; + public static final String OO_USE_ALL_OPEN_BASES = "useAllOpenBases"; + public static final String OO_BIBLIOGRAPHY_STYLE_FILE = "ooBibliographyStyleFile"; + public static final String OO_EXTERNAL_STYLE_FILES = "ooExternalStyleFiles"; + + public static final String STYLES_SIZE_Y = "stylesSizeY"; + public static final String STYLES_SIZE_X = "stylesSizeX"; + public static final String STYLES_POS_Y = "stylesPosY"; + public static final String STYLES_POS_X = "stylesPosX"; + // Special field preferences + public static final String SHOWCOLUMN_RELEVANCE = "showRelevanceColumn"; + public static final String SHOWCOLUMN_READ = "showReadColumn"; + public static final String SHOWCOLUMN_RANKING = "showRankingColumn"; + public static final String SHOWCOLUMN_QUALITY = "showQualityColumn"; + public static final String SHOWCOLUMN_PRIORITY = "showPriorityColumn"; + public static final String SHOWCOLUMN_PRINTED = "showPrintedColumn"; + public static final String SPECIALFIELDSENABLED = "specialFieldsEnabled"; + // The choice between AUTOSYNCSPECIALFIELDSTOKEYWORDS and SERIALIZESPECIALFIELDS is mutually exclusive + public static final String SERIALIZESPECIALFIELDS = "serializeSpecialFields"; + // The choice between AUTOSYNCSPECIALFIELDSTOKEYWORDS and SERIALIZESPECIALFIELDS is mutually exclusive + // At least in the settings, not in the implementation. But having both confused the users, therefore, having activated both options at the same time has been disabled + public static final String AUTOSYNCSPECIALFIELDSTOKEYWORDS = "autoSyncSpecialFieldsToKeywords"; + // Prefs node for BibtexKeyPatterns + public static final String BIBTEX_KEY_PATTERNS_NODE = "bibtexkeypatterns"; + // Prefs node for customized entry types + public static final String CUSTOMIZED_BIBTEX_TYPES = "customizedBibtexTypes"; + public static final String CUSTOMIZED_BIBLATEX_TYPES = "customizedBiblatexTypes"; + // Version + public static final String VERSION_IGNORED_UPDATE = "versionIgnoreUpdate"; + //KeyBindings - keys - public because needed for pref migration + public static final String BINDINGS = "bindings"; + + //AutcompleteFields - public because needed for pref migration + public static final String AUTOCOMPLETER_COMPLETE_FIELDS = "autoCompleteFields"; + + // Id Entry Generator Preferences + public static final String ID_ENTRY_GENERATOR = "idEntryGenerator"; + + // Preview + private static final String PREVIEW_STYLE = "previewStyle"; + private static final String CYCLE_PREVIEW_POS = "cyclePreviewPos"; + private static final String CYCLE_PREVIEW = "cyclePreview"; + private static final String PREVIEW_PANEL_HEIGHT = "previewPanelHeightFX"; + private static final String PREVIEW_ENABLED = "previewEnabled"; + + // Auto completion + private static final String AUTO_COMPLETE = "autoComplete"; + private static final String AUTOCOMPLETER_FIRSTNAME_MODE = "autoCompFirstNameMode"; + private static final String AUTOCOMPLETER_LAST_FIRST = "autoCompLF"; + private static final String AUTOCOMPLETER_FIRST_LAST = "autoCompFF"; + + private static final String BIND_NAMES = "bindNames"; + // User + private static final String USER_ID = "userId"; + private static final String EXTERNAL_JOURNAL_LISTS = "externalJournalLists"; + private static final String PERSONAL_JOURNAL_LIST = "personalJournalList"; + private static final String USE_IEEE_ABRV = "useIEEEAbrv"; + + // Telemetry collection + private static final String COLLECT_TELEMETRY = "collectTelemetry"; + private static final String ALREADY_ASKED_TO_COLLECT_TELEMETRY = "askedCollectTelemetry"; + private static final Logger LOGGER = LoggerFactory.getLogger(JabRefPreferences.class); + private static final Class PREFS_BASE_CLASS = JabRefMain.class; + private static final String DB_CONNECT_USERNAME = "dbConnectUsername"; + private static final String DB_CONNECT_DATABASE = "dbConnectDatabase"; + private static final String DB_CONNECT_HOSTNAME = "dbConnectHostname"; + private static final String DB_CONNECT_SERVER_TYPE = "dbConnectServerType"; + private static final String PROTECTED_TERMS_ENABLED_EXTERNAL = "protectedTermsEnabledExternal"; + private static final String PROTECTED_TERMS_DISABLED_EXTERNAL = "protectedTermsDisabledExternal"; + private static final String PROTECTED_TERMS_ENABLED_INTERNAL = "protectedTermsEnabledInternal"; + private static final String PROTECTED_TERMS_DISABLED_INTERNAL = "protectedTermsDisabledInternal"; + + //GroupViewMode + private static final String GROUP_INTERSECT_UNION_VIEW_MODE = "groupIntersectUnionViewModes"; + + // Dialog states + private static final String PREFS_EXPORT_PATH = "prefsExportPath"; + + // Helper string + private static final String USER_HOME = System.getProperty("user.home"); + // The only instance of this class: + private static JabRefPreferences singleton; + /** + * HashMap that contains all preferences which are set by default + */ + public final Map defaults = new HashMap<>(); + // Object containing custom export formats: + public final CustomExportList customExports; + /** + * Set with all custom {@link org.jabref.logic.importer.Importer}s + */ + public final CustomImportList customImports; + // The following field is used as a global variable during the export of a database. + // By setting this field to the path of the database's default file directory, formatters + // that should resolve external file paths can access this field. This is an ugly hack + // to solve the problem of formatters not having access to any context except for the + // string to be formatted and possible formatter arguments. + public List fileDirForDatabase; + private final Preferences prefs; + private GlobalBibtexKeyPattern keyPattern; + // Object containing info about customized entry editor tabs. + private Map> tabList; + + // The constructor is made private to enforce this as a singleton class: + private JabRefPreferences() { + try { + if (new File("jabref.xml").exists()) { + importPreferences("jabref.xml"); + } + } catch (JabRefException e) { + LOGGER.warn("Could not import preferences from jabref.xml: " + e.getMessage(), e); + } + + // load user preferences + prefs = Preferences.userNodeForPackage(PREFS_BASE_CLASS); + + // Since some of the preference settings themselves use localized strings, we cannot set the language after + // the initialization of the preferences in main + // Otherwise that language framework will be instantiated and more importantly, statically initialized preferences + // like the SearchDisplayMode will never be translated. + Localization.setLanguage(getLanguage()); + + SearchPreferences.putDefaults(defaults); + + defaults.put(TEXMAKER_PATH, JabRefDesktop.getNativeDesktop().detectProgramPath("texmaker", "Texmaker")); + defaults.put(WIN_EDT_PATH, JabRefDesktop.getNativeDesktop().detectProgramPath("WinEdt", "WinEdt Team\\WinEdt")); + defaults.put(TEXSTUDIO_PATH, JabRefDesktop.getNativeDesktop().detectProgramPath("texstudio", "TeXstudio")); + + defaults.put(BIBLATEX_DEFAULT_MODE, Boolean.FALSE); + + // Set DOI to be the default ID entry generator + defaults.put(ID_ENTRY_GENERATOR, DoiFetcher.NAME); + + if (OS.OS_X) { + defaults.put(FONT_FAMILY, "SansSerif"); + defaults.put(EMACS_PATH, "emacsclient"); + } else if (OS.WINDOWS) { + defaults.put(EMACS_PATH, "emacsclient.exe"); + } else { + // Linux + defaults.put(FONT_FAMILY, "SansSerif"); + defaults.put(EMACS_PATH, "emacsclient"); + } + + defaults.put(FX_FONT_RENDERING_TWEAK, OS.LINUX); //we turn this on per default on Linux + defaults.put(EMACS_ADDITIONAL_PARAMETERS, "-n -e"); + + defaults.put(PUSH_TO_APPLICATION, "TeXstudio"); + + defaults.put(RECENT_DATABASES, ""); + defaults.put(EXTERNAL_FILE_TYPES, ""); + defaults.put(KEY_PATTERN_REGEX, ""); + defaults.put(KEY_PATTERN_REPLACEMENT, ""); + + // Proxy + defaults.put(PROXY_USE, Boolean.FALSE); + defaults.put(PROXY_HOSTNAME, ""); + defaults.put(PROXY_PORT, "80"); + defaults.put(PROXY_USE_AUTHENTICATION, Boolean.FALSE); + defaults.put(PROXY_USERNAME, ""); + defaults.put(PROXY_PASSWORD, ""); + + defaults.put(USE_DEFAULT_LOOK_AND_FEEL, Boolean.TRUE); + defaults.put(LYXPIPE, USER_HOME + File.separator + ".lyx/lyxpipe"); + defaults.put(VIM, "vim"); + defaults.put(VIM_SERVER, "vim"); + defaults.put(POS_X, 0); + defaults.put(POS_Y, 0); + defaults.put(SIZE_X, 1024); + defaults.put(SIZE_Y, 768); + defaults.put(WINDOW_MAXIMISED, Boolean.TRUE); + defaults.put(AUTO_RESIZE_MODE, Boolean.TRUE); + defaults.put(ENTRY_EDITOR_HEIGHT, 0.65); + defaults.put(NAMES_AS_IS, Boolean.FALSE); // "Show names unchanged" + defaults.put(NAMES_FIRST_LAST, Boolean.FALSE); // "Show 'Firstname Lastname'" + defaults.put(NAMES_NATBIB, Boolean.TRUE); // "Natbib style" + defaults.put(ABBR_AUTHOR_NAMES, Boolean.TRUE); // "Abbreviate names" + defaults.put(NAMES_LAST_ONLY, Boolean.TRUE); // "Show last names only" + // system locale as default + defaults.put(LANGUAGE, Locale.getDefault().getLanguage()); + + defaults.put(REFORMAT_FILE_ON_SAVE_AND_EXPORT, Boolean.FALSE); + + // export order + defaults.put(EXPORT_IN_ORIGINAL_ORDER, Boolean.FALSE); + defaults.put(EXPORT_IN_SPECIFIED_ORDER, Boolean.FALSE); + + // export order: if EXPORT_IN_SPECIFIED_ORDER, then use following criteria + defaults.put(EXPORT_PRIMARY_SORT_FIELD, BibEntry.KEY_FIELD); + defaults.put(EXPORT_PRIMARY_SORT_DESCENDING, Boolean.FALSE); + defaults.put(EXPORT_SECONDARY_SORT_FIELD, FieldName.AUTHOR); + defaults.put(EXPORT_SECONDARY_SORT_DESCENDING, Boolean.FALSE); + defaults.put(EXPORT_TERTIARY_SORT_FIELD, FieldName.TITLE); + defaults.put(EXPORT_TERTIARY_SORT_DESCENDING, Boolean.TRUE); + + defaults.put(NEWLINE, System.lineSeparator()); + + defaults.put(SIDE_PANE_COMPONENT_NAMES, ""); + defaults.put(SIDE_PANE_COMPONENT_PREFERRED_POSITIONS, ""); + + defaults.put(COLUMN_NAMES, "entrytype;author/editor;title;year;journal/booktitle;bibtexkey"); + defaults.put(COLUMN_WIDTHS, "75;300;470;60;130;100"); + + defaults.put(XMP_PRIVACY_FILTERS, "pdf;timestamp;keywords;owner;note;review"); + defaults.put(USE_XMP_PRIVACY_FILTER, Boolean.FALSE); + defaults.put(WORKING_DIRECTORY, USER_HOME); + defaults.put(EXPORT_WORKING_DIRECTORY, USER_HOME); + // Remembers working directory of last import + defaults.put(IMPORT_WORKING_DIRECTORY, USER_HOME); + defaults.put(PREFS_EXPORT_PATH, USER_HOME); + defaults.put(AUTO_OPEN_FORM, Boolean.TRUE); + defaults.put(BACKUP, Boolean.TRUE); + defaults.put(OPEN_LAST_EDITED, Boolean.TRUE); + defaults.put(LAST_EDITED, ""); + defaults.put(LAST_FOCUSED, ""); + defaults.put(STRINGS_POS_X, 0); + defaults.put(STRINGS_POS_Y, 0); + defaults.put(STRINGS_SIZE_X, 600); + defaults.put(STRINGS_SIZE_Y, 400); + defaults.put(DUPLICATES_POS_X, 0); + defaults.put(DUPLICATES_POS_Y, 0); + defaults.put(DUPLICATES_SIZE_X, 800); + defaults.put(DUPLICATES_SIZE_Y, 600); + defaults.put(MERGEENTRIES_POS_X, 0); + defaults.put(MERGEENTRIES_POS_Y, 0); + defaults.put(MERGEENTRIES_SIZE_X, 800); + defaults.put(MERGEENTRIES_SIZE_Y, 600); + defaults.put(PREAMBLE_POS_X, 0); + defaults.put(PREAMBLE_POS_Y, 0); + defaults.put(PREAMBLE_SIZE_X, 600); + defaults.put(PREAMBLE_SIZE_Y, 400); + defaults.put(TERMS_POS_X, 0); + defaults.put(TERMS_POS_Y, 0); + defaults.put(TERMS_SIZE_X, 500); + defaults.put(TERMS_SIZE_Y, 500); + defaults.put(DEFAULT_SHOW_SOURCE, Boolean.FALSE); + + defaults.put(DEFAULT_AUTO_SORT, Boolean.FALSE); + + defaults.put(MERGE_ENTRIES_DIFF_MODE, 2); + + defaults.put(SHOW_RECOMMENDATIONS, Boolean.TRUE); + defaults.put(ACCEPT_RECOMMENDATIONS, Boolean.FALSE); + defaults.put(VALIDATE_IN_ENTRY_EDITOR, Boolean.TRUE); + defaults.put(EDITOR_EMACS_KEYBINDINGS, Boolean.FALSE); + defaults.put(EDITOR_EMACS_KEYBINDINGS_REBIND_CA, Boolean.TRUE); + defaults.put(EDITOR_EMACS_KEYBINDINGS_REBIND_CF, Boolean.TRUE); + defaults.put(AUTO_COMPLETE, Boolean.FALSE); + defaults.put(AUTOCOMPLETER_FIRSTNAME_MODE, AutoCompleteFirstNameMode.BOTH.name()); + defaults.put(AUTOCOMPLETER_FIRST_LAST, Boolean.FALSE); // "Autocomplete names in 'Firstname Lastname' format only" + defaults.put(AUTOCOMPLETER_LAST_FIRST, Boolean.FALSE); // "Autocomplete names in 'Lastname, Firstname' format only" + defaults.put(AUTOCOMPLETER_COMPLETE_FIELDS, "author;editor;title;journal;publisher;keywords;crossref;related;entryset"); + defaults.put(GROUPS_DEFAULT_FIELD, FieldName.KEYWORDS); + defaults.put(AUTO_ASSIGN_GROUP, Boolean.TRUE); + defaults.put(GROUP_INTERSECT_UNION_VIEW_MODE, GroupViewMode.INTERSECTION.name()); + defaults.put(KEYWORD_SEPARATOR, ", "); + defaults.put(TOOLBAR_VISIBLE, Boolean.TRUE); + defaults.put(DEFAULT_ENCODING, StandardCharsets.UTF_8.name()); + defaults.put(DEFAULT_OWNER, System.getProperty("user.name")); + defaults.put(MEMORY_STICK_MODE, Boolean.FALSE); + defaults.put(RENAME_ON_MOVE_FILE_TO_FILE_DIR, Boolean.TRUE); + + defaults.put(FONT_STYLE, Font.PLAIN); + defaults.put(FONT_SIZE, 12); + // Main table color settings: + defaults.put(VALID_FIELD_BACKGROUND_COLOR, "255:255:255"); + defaults.put(INVALID_FIELD_BACKGROUND_COLOR, "255:0:0"); + defaults.put(ACTIVE_FIELD_EDITOR_BACKGROUND_COLOR, "220:220:255"); + defaults.put(FIELD_EDITOR_TEXT_COLOR, "0:0:0"); + + // default icon colors + defaults.put(ICON_ENABLED_COLOR, "0:0:0"); + defaults.put(ICON_DISABLED_COLOR, "200:200:200"); + + defaults.put(URL_COLUMN, Boolean.TRUE); + defaults.put(PREFER_URL_DOI, Boolean.FALSE); + defaults.put(FILE_COLUMN, Boolean.TRUE); + defaults.put(ARXIV_COLUMN, Boolean.FALSE); + + defaults.put(EXTRA_FILE_COLUMNS, Boolean.FALSE); + defaults.put(LIST_OF_FILE_COLUMNS, ""); + + defaults.put(PROTECTED_TERMS_ENABLED_INTERNAL, convertListToString(ProtectedTermsLoader.getInternalLists())); + defaults.put(PROTECTED_TERMS_DISABLED_INTERNAL, ""); + defaults.put(PROTECTED_TERMS_ENABLED_EXTERNAL, ""); + defaults.put(PROTECTED_TERMS_DISABLED_EXTERNAL, ""); + + // OpenOffice/LibreOffice + if (OS.WINDOWS) { + defaults.put(OO_PATH, OpenOfficePreferences.DEFAULT_WINDOWS_PATH); + defaults.put(OO_EXECUTABLE_PATH, OpenOfficePreferences.DEFAULT_WIN_EXEC_PATH); + defaults.put(OO_JARS_PATH, OpenOfficePreferences.DEFAULT_WINDOWS_PATH); + } else if (OS.OS_X) { + defaults.put(OO_PATH, OpenOfficePreferences.DEFAULT_OSX_PATH); + defaults.put(OO_EXECUTABLE_PATH, OpenOfficePreferences.DEFAULT_OSX_EXEC_PATH); + defaults.put(OO_JARS_PATH, OpenOfficePreferences.DEFAULT_OSX_PATH); + } else { // Linux + defaults.put(OO_PATH, OpenOfficePreferences.DEFAULT_LINUX_PATH); + defaults.put(OO_EXECUTABLE_PATH, OpenOfficePreferences.DEFAULT_LINUX_EXEC_PATH); + defaults.put(OO_JARS_PATH, OpenOfficePreferences.DEFAULT_LINUX_PATH); + } + + defaults.put(OO_SYNC_WHEN_CITING, Boolean.FALSE); + defaults.put(OO_SHOW_PANEL, Boolean.FALSE); + defaults.put(OO_USE_ALL_OPEN_BASES, Boolean.TRUE); + defaults.put(OO_BIBLIOGRAPHY_STYLE_FILE, StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH); + defaults.put(OO_EXTERNAL_STYLE_FILES, ""); + defaults.put(STYLES_POS_X, 0); + defaults.put(STYLES_POS_Y, 0); + defaults.put(STYLES_SIZE_X, 600); + defaults.put(STYLES_SIZE_Y, 400); + + defaults.put(SPECIALFIELDSENABLED, Boolean.TRUE); + defaults.put(SHOWCOLUMN_PRIORITY, Boolean.FALSE); + defaults.put(SHOWCOLUMN_QUALITY, Boolean.FALSE); + defaults.put(SHOWCOLUMN_RANKING, Boolean.TRUE); + defaults.put(SHOWCOLUMN_RELEVANCE, Boolean.FALSE); + defaults.put(SHOWCOLUMN_PRINTED, Boolean.FALSE); + defaults.put(SHOWCOLUMN_READ, Boolean.FALSE); + defaults.put(AUTOSYNCSPECIALFIELDSTOKEYWORDS, Boolean.TRUE); + defaults.put(SERIALIZESPECIALFIELDS, Boolean.FALSE); + + defaults.put(USE_OWNER, Boolean.FALSE); + defaults.put(OVERWRITE_OWNER, Boolean.FALSE); + defaults.put(AVOID_OVERWRITING_KEY, Boolean.FALSE); + defaults.put(WARN_BEFORE_OVERWRITING_KEY, Boolean.TRUE); + defaults.put(CONFIRM_DELETE, Boolean.TRUE); + defaults.put(GRAY_OUT_NON_HITS, Boolean.TRUE); + defaults.put(DEFAULT_BIBTEX_KEY_PATTERN, "[auth][year]"); + defaults.put(DO_NOT_RESOLVE_STRINGS_FOR, FieldName.URL); + defaults.put(RESOLVE_STRINGS_ALL_FIELDS, Boolean.FALSE); + defaults.put(NON_WRAPPABLE_FIELDS, "pdf;ps;url;doi;file;isbn;issn"); + defaults.put(GENERATE_KEYS_AFTER_INSPECTION, Boolean.TRUE); + defaults.put(WARN_ABOUT_DUPLICATES_IN_INSPECTION, Boolean.TRUE); + defaults.put(USE_TIME_STAMP, Boolean.FALSE); + defaults.put(OVERWRITE_TIME_STAMP, Boolean.FALSE); + + // default time stamp follows ISO-8601. Reason: https://xkcd.com/1179/ + defaults.put(TIME_STAMP_FORMAT, "yyyy-MM-dd"); + + defaults.put(TIME_STAMP_FIELD, FieldName.TIMESTAMP); + defaults.put(UPDATE_TIMESTAMP, Boolean.FALSE); + + defaults.put(GENERATE_KEYS_BEFORE_SAVING, Boolean.FALSE); + + defaults.put(USE_REMOTE_SERVER, Boolean.TRUE); + defaults.put(REMOTE_SERVER_PORT, 6050); + + defaults.put(PERSONAL_JOURNAL_LIST, ""); + defaults.put(EXTERNAL_JOURNAL_LISTS, ""); + defaults.put(CITE_COMMAND, "\\cite"); // obsoleted by the app-specific ones (not any more?) + + defaults.put(LAST_USED_EXPORT, ""); + defaults.put(SIDE_PANE_WIDTH, 0.15); + + defaults.put(MAIN_FONT_SIZE, 9); + defaults.put(OVERRIDE_DEFAULT_FONT_SIZE, false); + + defaults.put(IMPORT_INSPECTION_DIALOG_WIDTH, 650); + defaults.put(IMPORT_INSPECTION_DIALOG_HEIGHT, 650); + defaults.put(SHOW_FILE_LINKS_UPGRADE_WARNING, Boolean.TRUE); + defaults.put(AUTOLINK_EXACT_KEY_ONLY, Boolean.FALSE); + defaults.put(NUMERIC_FIELDS, "mittnum;author"); + defaults.put(RUN_AUTOMATIC_FILE_SEARCH, Boolean.FALSE); + defaults.put(LOCAL_AUTO_SAVE, Boolean.FALSE); + defaults.put(ENFORCE_LEGAL_BIBTEX_KEY, Boolean.TRUE); + // Curly brackets ({}) are the default delimiters, not quotes (") as these cause trouble when they appear within the field value: + // Currently, JabRef does not escape them + defaults.put(KEY_GEN_FIRST_LETTER_A, Boolean.TRUE); + defaults.put(KEY_GEN_ALWAYS_ADD_LETTER, Boolean.FALSE); + defaults.put(EMAIL_SUBJECT, Localization.lang("References")); + defaults.put(OPEN_FOLDERS_OF_ATTACHED_FILES, Boolean.FALSE); + defaults.put(ALLOW_FILE_AUTO_OPEN_BROWSE, Boolean.TRUE); + defaults.put(WEB_SEARCH_VISIBLE, Boolean.TRUE); + defaults.put(GROUP_SIDEPANE_VISIBLE, Boolean.TRUE); + defaults.put(SELECTED_FETCHER_INDEX, 0); + defaults.put(BIB_LOC_AS_PRIMARY_DIR, Boolean.FALSE); + defaults.put(DB_CONNECT_SERVER_TYPE, "MySQL"); + defaults.put(DB_CONNECT_HOSTNAME, "localhost"); + defaults.put(DB_CONNECT_DATABASE, "jabref"); + defaults.put(DB_CONNECT_USERNAME, "root"); + defaults.put(COLLECT_TELEMETRY, Boolean.FALSE); + defaults.put(ALREADY_ASKED_TO_COLLECT_TELEMETRY, Boolean.FALSE); + + defaults.put(ASK_AUTO_NAMING_PDFS_AGAIN, Boolean.TRUE); + insertDefaultCleanupPreset(defaults); + + // defaults for DroppedFileHandler UI + defaults.put(DROPPEDFILEHANDLER_LEAVE, Boolean.FALSE); + defaults.put(DROPPEDFILEHANDLER_COPY, Boolean.TRUE); + defaults.put(DROPPEDFILEHANDLER_MOVE, Boolean.FALSE); + defaults.put(DROPPEDFILEHANDLER_RENAME, Boolean.FALSE); + + defaults.put(IMPORT_ALWAYSUSE, Boolean.FALSE); + defaults.put(IMPORT_DEFAULT_PDF_IMPORT_STYLE, ImportSettingsTab.DEFAULT_STYLE); + + // use BibTeX key appended with filename as default pattern + defaults.put(IMPORT_FILENAMEPATTERN, ImportSettingsTab.DEFAULT_FILENAMEPATTERNS[1]); + //Default empty String to be backwards compatible + defaults.put(IMPORT_FILEDIRPATTERN, ""); + + customExports = new CustomExportList(new ExportComparator()); + customImports = new CustomImportList(this); + + String defaultExpression = "**/.*[bibtexkey].*\\\\.[extension]"; + defaults.put(AUTOLINK_REG_EXP_SEARCH_EXPRESSION_KEY, defaultExpression); + defaults.put(AUTOLINK_USE_REG_EXP_SEARCH_KEY, Boolean.FALSE); + defaults.put(USE_IEEE_ABRV, Boolean.FALSE); + defaults.put(USE_CASE_KEEPER_ON_SEARCH, Boolean.TRUE); + defaults.put(USE_UNIT_FORMATTER_ON_SEARCH, Boolean.TRUE); + + defaults.put(USE_DEFAULT_CONSOLE_APPLICATION, Boolean.TRUE); + if (OS.WINDOWS) { + defaults.put(CONSOLE_COMMAND, "C:\\Program Files\\ConEmu\\ConEmu64.exe /single /dir \"%DIR\""); + defaults.put(ADOBE_ACROBAT_COMMAND, "C:\\Program Files (x86)\\Adobe\\Acrobat Reader DC\\Reader"); + defaults.put(SUMATRA_PDF_COMMAND, "C:\\Program Files\\SumatraPDF"); + defaults.put(USE_PDF_READER, ADOBE_ACROBAT_COMMAND); + } else { + defaults.put(CONSOLE_COMMAND, ""); + defaults.put(ADOBE_ACROBAT_COMMAND, ""); + defaults.put(SUMATRA_PDF_COMMAND, ""); + defaults.put(USE_PDF_READER, ""); + } + + //versioncheck defaults + defaults.put(VERSION_IGNORED_UPDATE, ""); + + // preview + defaults.put(CYCLE_PREVIEW, "Preview;" + CitationStyle.DEFAULT); + defaults.put(CYCLE_PREVIEW_POS, 0); + defaults.put(PREVIEW_PANEL_HEIGHT, 0.65); + defaults.put(PREVIEW_ENABLED, Boolean.TRUE); + defaults.put(PREVIEW_STYLE, + "" + + "\\bibtextype\\begin{bibtexkey} (\\bibtexkey)" + + "\\end{bibtexkey}
__NEWLINE__" + + "\\begin{author} \\format[Authors(LastFirst,Initials,Semicolon,Amp),HTMLChars]{\\author}
\\end{author}__NEWLINE__" + + "\\begin{editor} \\format[Authors(LastFirst,Initials,Semicolon,Amp),HTMLChars]{\\editor} " + + "(\\format[IfPlural(Eds.,Ed.)]{\\editor})
\\end{editor}__NEWLINE__" + + "\\begin{title} \\format[HTMLChars]{\\title} \\end{title}
__NEWLINE__" + + "\\begin{chapter} \\format[HTMLChars]{\\chapter}
\\end{chapter}__NEWLINE__" + + "\\begin{journal} \\format[HTMLChars]{\\journal}, \\end{journal}__NEWLINE__" + // Include the booktitle field for @inproceedings, @proceedings, etc. + + "\\begin{booktitle} \\format[HTMLChars]{\\booktitle}, \\end{booktitle}__NEWLINE__" + + "\\begin{school} \\format[HTMLChars]{\\school}, \\end{school}__NEWLINE__" + + "\\begin{institution} \\format[HTMLChars]{\\institution}, \\end{institution}__NEWLINE__" + + "\\begin{publisher} \\format[HTMLChars]{\\publisher}, \\end{publisher}__NEWLINE__" + + "\\begin{year}\\year\\end{year}\\begin{volume}, \\volume\\end{volume}" + + "\\begin{pages}, \\format[FormatPagesForHTML]{\\pages} \\end{pages}__NEWLINE__" + + "\\begin{abstract}

Abstract: \\format[HTMLChars]{\\abstract} \\end{abstract}__NEWLINE__" + + "\\begin{comment}

Comment: \\format[HTMLChars]{\\comment} \\end{comment}" + + "__NEWLINE__

"); + + setLanguageDependentDefaultValues(); + } + + public static JabRefPreferences getInstance() { + if (JabRefPreferences.singleton == null) { + JabRefPreferences.singleton = new JabRefPreferences(); + } + return JabRefPreferences.singleton; + } + + private static String convertListToString(List value) { + return value.stream().map(val -> StringUtil.quote(val, ";", '\\')).collect(Collectors.joining(";")); + } + + /** + * Looks up a color definition in preferences, and returns an array containing the RGB values. + * + * @param value The key for this setting. + * @return The RGB values corresponding to this color setting. + */ + private static int[] getRgb(String value) { + int[] values = new int[3]; + + if ((value != null) && !value.isEmpty()) { + String[] elements = value.split(":"); + values[0] = Integer.parseInt(elements[0]); + values[1] = Integer.parseInt(elements[1]); + values[2] = Integer.parseInt(elements[2]); + } else { + values[0] = 0; + values[1] = 0; + values[2] = 0; + } + return values; + } + + private static Preferences getPrefsNodeForCustomizedEntryTypes(BibDatabaseMode mode) { + if (mode == BibDatabaseMode.BIBLATEX) { + return Preferences.userNodeForPackage(PREFS_BASE_CLASS).node(CUSTOMIZED_BIBLATEX_TYPES); + } + if (mode == BibDatabaseMode.BIBTEX) { + return Preferences.userNodeForPackage(PREFS_BASE_CLASS).node(CUSTOMIZED_BIBTEX_TYPES); + } + + throw new IllegalArgumentException("Unknown BibDatabaseMode: " + mode); + } + + private static Optional getNextUnit(Reader data) throws IOException { + // character last read + // -1 if end of stream + // initialization necessary, because of Java compiler + int c = -1; + + // last character was escape symbol + boolean escape = false; + + // true if a ";" is found + boolean done = false; + + StringBuilder res = new StringBuilder(); + while (!done && ((c = data.read()) != -1)) { + if (c == '\\') { + if (escape) { + escape = false; + res.append('\\'); + } else { + escape = true; + } + } else { + if (c == ';') { + if (escape) { + res.append(';'); + } else { + done = true; + } + } else { + res.append((char) c); + } + escape = false; + } + } + if (res.length() > 0) { + return Optional.of(res.toString()); + } else if (c == -1) { + // end of stream + return Optional.empty(); + } else { + return Optional.of(""); + } + } + + private static void insertDefaultCleanupPreset(Map storage) { + EnumSet deactivatedJobs = EnumSet.of( + CleanupPreset.CleanupStep.CLEAN_UP_UPGRADE_EXTERNAL_LINKS, + CleanupPreset.CleanupStep.MOVE_PDF, + CleanupPreset.CleanupStep.RENAME_PDF_ONLY_RELATIVE_PATHS, + CleanupPreset.CleanupStep.CONVERT_TO_BIBLATEX, + CleanupPreset.CleanupStep.CONVERT_TO_BIBTEX); + + CleanupPreset preset = new CleanupPreset(EnumSet.complementOf(deactivatedJobs), Cleanups.DEFAULT_SAVE_ACTIONS); + + storage.put(CLEANUP_DOI, preset.isCleanUpDOI()); + storage.put(CLEANUP_ISSN, preset.isCleanUpISSN()); + storage.put(CLEANUP_MOVE_PDF, preset.isMovePDF()); + storage.put(CLEANUP_MAKE_PATHS_RELATIVE, preset.isMakePathsRelative()); + storage.put(CLEANUP_RENAME_PDF, preset.isRenamePDF()); + storage.put(CLEANUP_RENAME_PDF_ONLY_RELATIVE_PATHS, preset.isRenamePdfOnlyRelativePaths()); + storage.put(CLEANUP_UPGRADE_EXTERNAL_LINKS, preset.isCleanUpUpgradeExternalLinks()); + storage.put(CLEANUP_CONVERT_TO_BIBLATEX, preset.isConvertToBiblatex()); + storage.put(CLEANUP_CONVERT_TO_BIBTEX, preset.isConvertToBibtex()); + storage.put(CLEANUP_FIX_FILE_LINKS, preset.isFixFileLinks()); + storage.put(CLEANUP_FORMATTERS, convertListToString(preset.getFormatterCleanups().getAsStringList(OS.NEWLINE))); + } + + public EntryEditorPreferences getEntryEditorPreferences() { + return new EntryEditorPreferences(getEntryEditorTabList(), +<<<<<<< HEAD + getLatexFieldFormatterPreferences(), + getImportFormatPreferences(), + getCustomTabFieldNames(), + getBoolean(SHOW_RECOMMENDATIONS), + getBoolean(ACCEPT_RECOMMENDATIONS), + getBoolean(DEFAULT_SHOW_SOURCE), + getBibtexKeyPatternPreferences(), + Globals.getKeyPrefs(), + getBoolean(AVOID_OVERWRITING_KEY)); +======= + getLatexFieldFormatterPreferences(), + getImportFormatPreferences(), + getCustomTabFieldNames(), + getBoolean(SHOW_RECOMMENDATIONS), + getBoolean(DEFAULT_SHOW_SOURCE), + getBibtexKeyPatternPreferences(), + Globals.getKeyPrefs(), + getBoolean(AVOID_OVERWRITING_KEY)); +>>>>>>> master + } + + public Map getSidePanePreferredPositions() { + Map preferredPositions = new HashMap<>(); + + List componentNames = getStringList(SIDE_PANE_COMPONENT_NAMES); + List componentPositions = getStringList(SIDE_PANE_COMPONENT_PREFERRED_POSITIONS); + + for (int i = 0; i < componentNames.size(); ++i) { + String name = componentNames.get(i); + try { + SidePaneType type = Enum.valueOf(SidePaneType.class, name); + preferredPositions.put(type, Integer.parseInt(componentPositions.get(i))); + } catch (NumberFormatException e) { + LOGGER.debug("Invalid number format for side pane component '" + name + "'", e); + } catch (IllegalArgumentException e) { + LOGGER.debug("Following component is not a side pane: '" + name + "'", e); + } + } + + return preferredPositions; + } + + public String getUser() { + try { + return get(DEFAULT_OWNER) + '-' + InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException ex) { + LOGGER.debug("Hostname not found.", ex); + return get(DEFAULT_OWNER); + } + } + + /** + * Get a Map of default tab names to deafult tab fields. + * The fields are returned as a String with fields separated by ; + * They are combined into one string in order to feed into CustomizeGeneralFieldsDialogViewModel.resetFields() + * so that they do not have to be parsed in order to fit there + * + * @return A map of keys with tab names and values as a string containing + * fields for the given name separated by ; + */ + @Override + public Map getCustomTabsNamesAndFields() { + Map customTabsMap = new HashMap<>(); + + int defNumber = 0; + while (true) { + //Saved as CUSTOMTABNAME_def{number} and ; separated + String name = (String) defaults.get(CUSTOM_TAB_NAME + "_def" + defNumber); + String fields = (String) defaults.get(CUSTOM_TAB_FIELDS + "_def" + defNumber); + + if (StringUtil.isNullOrEmpty(name) || StringUtil.isNullOrEmpty(fields)) { + break; + } + customTabsMap.put(name, fields); + defNumber++; + } + return customTabsMap; + } + + @Override + public void setCustomTabsNameAndFields(String name, String fields, int defNumber) { + prefs.put(CUSTOM_TAB_NAME + defNumber, name); + prefs.put(CUSTOM_TAB_FIELDS + defNumber, fields); + } + + public List getCustomTabFieldNames() { + List customFields = new ArrayList<>(); + + int defNumber = 0; + while (true) { + // saved as CUSTOMTABNAME_def{number} and ; separated + String fields = (String) defaults.get(CUSTOM_TAB_FIELDS + "_def" + defNumber); + + if (StringUtil.isNullOrEmpty(fields)) { + break; + } + + customFields.addAll(Arrays.asList(fields.split(";"))); + defNumber++; + } + return customFields; + } + + public void setLanguageDependentDefaultValues() { + // Entry editor tab 0: + defaults.put(CUSTOM_TAB_NAME + "_def0", Localization.lang("General")); + String fieldNames = InternalBibtexFields.DEFAULT_GENERAL_FIELDS.stream().collect(Collectors.joining(";")); + defaults.put(CUSTOM_TAB_FIELDS + "_def0", fieldNames); + + // Entry editor tab 1: + defaults.put(CUSTOM_TAB_FIELDS + "_def1", FieldName.ABSTRACT); + defaults.put(CUSTOM_TAB_NAME + "_def1", Localization.lang("Abstract")); + + // Entry editor tab 2: Comments Field - used for research comments, etc. + defaults.put(CUSTOM_TAB_FIELDS + "_def2", FieldName.COMMENT); + defaults.put(CUSTOM_TAB_NAME + "_def2", Localization.lang("Comments")); + + defaults.put(EMAIL_SUBJECT, Localization.lang("References")); + } + + /** + * Check whether a key is set (differently from null). + * + * @param key The key to check. + * @return true if the key is set, false otherwise. + */ + public boolean hasKey(String key) { + return prefs.get(key, null) != null; + } + + public String get(String key) { + return prefs.get(key, (String) defaults.get(key)); + } + + public Optional getAsOptional(String key) { + return Optional.ofNullable(prefs.get(key, (String) defaults.get(key))); + } + + public String get(String key, String def) { + return prefs.get(key, def); + } + + public boolean getBoolean(String key) { + return prefs.getBoolean(key, getBooleanDefault(key)); + } + + public boolean getBoolean(String key, boolean def) { + return prefs.getBoolean(key, def); + } + + private boolean getBooleanDefault(String key) { + return (Boolean) defaults.get(key); + } + + public int getInt(String key) { + return prefs.getInt(key, getIntDefault(key)); + } + + public double getDouble(String key) { + return prefs.getDouble(key, getDoubleDefault(key)); + } + + public int getIntDefault(String key) { + return (Integer) defaults.get(key); + } + + private double getDoubleDefault(String key) { + return ((Number) defaults.get(key)).doubleValue(); + } + + public void put(String key, String value) { + prefs.put(key, value); + } + + public void putBoolean(String key, boolean value) { + prefs.putBoolean(key, value); + } + + public void putInt(String key, int value) { + prefs.putInt(key, value); + } + + public void putInt(String key, Number value) { + prefs.putInt(key, value.intValue()); + } + + public void putDouble(String key, double value) { + prefs.putDouble(key, value); + } + + public void remove(String key) { + prefs.remove(key); + } + + /** + * Puts a list of strings into the Preferences, by linking its elements with ';' into a single string. Escape + * characters make the process transparent even if strings contain ';'. + */ + public void putStringList(String key, List value) { + if (value == null) { + remove(key); + return; + } + + put(key, convertListToString(value)); + } + + /** + * Returns a List of Strings containing the chosen columns. + */ + public List getStringList(String key) { + String names = get(key); + if (names == null) { + return new ArrayList<>(); + } + + StringReader rd = new StringReader(names); + List res = new ArrayList<>(); + Optional rs; + try { + while ((rs = getNextUnit(rd)).isPresent()) { + res.add(rs.get()); + } + } catch (IOException ignored) { + // Ignored + } + return res; + } + + /** + * Looks up a color definition in preferences, and returns the Color object. + * + * @param key The key for this setting. + * @return The color corresponding to the setting. + */ + public Color getColor(String key) { + String value = get(key); + int[] rgb = getRgb(value); + return new Color(rgb[0], rgb[1], rgb[2]); + } + + public Color getDefaultColor(String key) { + String value = (String) defaults.get(key); + int[] rgb = getRgb(value); + return new Color(rgb[0], rgb[1], rgb[2]); + } + + /** + * Returns the default BibDatabase mode, which can be either BIBTEX or BIBLATEX. + * + * @return the default BibDatabaseMode + */ + public BibDatabaseMode getDefaultBibDatabaseMode() { + if (getBoolean(BIBLATEX_DEFAULT_MODE)) { + return BibDatabaseMode.BIBLATEX; + } else { + return BibDatabaseMode.BIBTEX; + } + } + + /** + * Set the default value for a key. This is useful for plugins that need to add default values for the prefs keys + * they use. + * + * @param key The preferences key. + * @param value The default value. + */ + public void putDefaultValue(String key, Object value) { + defaults.put(key, value); + } + + /** + * Stores a color in preferences. + * + * @param key The key for this setting. + * @param color The Color to store. + */ + public void putColor(String key, Color color) { + String rgb = String.valueOf(color.getRed()) + ':' + color.getGreen() + ':' + color.getBlue(); + put(key, rgb); + } + + /** + * Clear all preferences. + * + * @throws BackingStoreException + */ + public void clear() throws BackingStoreException { + clearAllCustomEntryTypes(); + clearKeyPatterns(); + prefs.clear(); + new SharedDatabasePreferences().clear(); + } + + public void clear(String key) { + prefs.remove(key); + } + + /** + * Calling this method will write all preferences into the preference store. + */ + public void flush() { + if (getBoolean(MEMORY_STICK_MODE)) { + try { + exportPreferences("jabref.xml"); + } catch (JabRefException e) { + LOGGER.warn("Could not export preferences for memory stick mode: " + e.getMessage(), e); + } + } + try { + prefs.flush(); + } catch (BackingStoreException ex) { + LOGGER.warn("Cannot communicate with backing store", ex); + } + } + + /** + * Fetches key patterns from preferences. + * The implementation doesn't cache the results + * + * @return LabelPattern containing all keys. Returned LabelPattern has no parent + */ + public GlobalBibtexKeyPattern getKeyPattern() { + keyPattern = GlobalBibtexKeyPattern.fromPattern(get(DEFAULT_BIBTEX_KEY_PATTERN)); + Preferences pre = Preferences.userNodeForPackage(PREFS_BASE_CLASS).node(BIBTEX_KEY_PATTERNS_NODE); + try { + String[] keys = pre.keys(); + if (keys.length > 0) { + for (String key : keys) { + keyPattern.addBibtexKeyPattern(key, pre.get(key, null)); + } + } + } catch (BackingStoreException ex) { + LOGGER.info("BackingStoreException in JabRefPreferences.getKeyPattern", ex); + } + return keyPattern; + } + + /** + * Adds the given key pattern to the preferences + * + * @param pattern the pattern to store + */ + public void putKeyPattern(GlobalBibtexKeyPattern pattern) { + keyPattern = pattern; + + // Store overridden definitions to Preferences. + Preferences pre = Preferences.userNodeForPackage(PREFS_BASE_CLASS).node(BIBTEX_KEY_PATTERNS_NODE); + try { + pre.clear(); // We remove all old entries. + } catch (BackingStoreException ex) { + LOGGER.info("BackingStoreException in JabRefPreferences.putKeyPattern", ex); + } + + Set allKeys = pattern.getAllKeys(); + for (String key : allKeys) { + if (!pattern.isDefaultValue(key)) { + // no default value + // the first entry in the array is the full pattern + // see org.jabref.logic.labelPattern.BibtexKeyGenerator.split(String) + pre.put(key, pattern.getValue(key).get(0)); + } + } + } + + private void clearKeyPatterns() throws BackingStoreException { + Preferences pre = Preferences.userNodeForPackage(PREFS_BASE_CLASS).node(BIBTEX_KEY_PATTERNS_NODE); + pre.clear(); + } + + public void storeCustomEntryTypes(List customEntryTypes, BibDatabaseMode bibDatabaseMode) { + Preferences prefsNode = getPrefsNodeForCustomizedEntryTypes(bibDatabaseMode); + + try { + // clear old custom types + clearCustomEntryTypes(bibDatabaseMode); + + // store current custom types + customEntryTypes.forEach(type -> prefsNode.put(type.getName(), type.getAsString())); + + prefsNode.flush(); + } catch (BackingStoreException e) { + LOGGER.info("Updating stored custom entry types failed.", e); + } + } + + public List loadCustomEntryTypes(BibDatabaseMode bibDatabaseMode) { + List storedEntryTypes = new ArrayList<>(); + Preferences prefsNode = getPrefsNodeForCustomizedEntryTypes(bibDatabaseMode); + try { + Arrays.stream(prefsNode.keys()) + .map(key -> prefsNode.get(key, null)) + .filter(Objects::nonNull) + .forEach(typeString -> CustomEntryType.parse(typeString).ifPresent(storedEntryTypes::add)); + } catch (BackingStoreException e) { + LOGGER.info("Parsing customized entry types failed.", e); + } + return storedEntryTypes; + } + + private void clearAllCustomEntryTypes() throws BackingStoreException { + for (BibDatabaseMode mode : BibDatabaseMode.values()) { + clearCustomEntryTypes(mode); + } + } + + private void clearCustomEntryTypes(BibDatabaseMode mode) throws BackingStoreException { + Preferences prefsNode = getPrefsNodeForCustomizedEntryTypes(mode); + prefsNode.clear(); + } + + public Map getPreferences() { + Map result = new HashMap<>(); + try { + for (String key : this.prefs.keys()) { + Object value = getObject(key); + result.put(key, value); + } + } catch (BackingStoreException e) { + LOGGER.info("could not retrieve preference keys", e); + } + return result; + } + + private Object getObject(String key) { + try { + return this.get(key); + } catch (ClassCastException e) { + try { + return this.getBoolean(key); + } catch (ClassCastException e2) { + try { + return this.getInt(key); + } catch (ClassCastException e3) { + return this.getDouble(key); + } + } + } + } + + /** + * Removes all entries keyed by prefix+number, where number is equal to or higher than the given number. + * + * @param number or higher. + */ + @Override + public void purgeSeries(String prefix, int number) { + int n = number; + while (get(prefix + n) != null) { + remove(prefix + n); + n++; + } + } + + @Override + public Map> getEntryEditorTabList() { + if (tabList == null) { + updateEntryEditorTabList(); + } + return tabList; + } + + @Override + public Boolean getEnforceLegalKeys() { + return getBoolean(ENFORCE_LEGAL_BIBTEX_KEY); + } + + @Override + public void updateEntryEditorTabList() { + tabList = EntryEditorTabList.create(this); + } + + /** + * Exports Preferences to an XML file. + * + * @param filename String File to export to + */ + public void exportPreferences(String filename) throws JabRefException { + exportPreferences(Paths.get(filename)); + } + + public void exportPreferences(Path file) throws JabRefException { + try (OutputStream os = Files.newOutputStream(file)) { + prefs.exportSubtree(os); + } catch (BackingStoreException | IOException ex) { + throw new JabRefException("Could not export preferences", Localization.lang("Could not export preferences"), + ex); + } + } + + /** + * Imports Preferences from an XML file. + * + * @param filename String File to import from + * @throws JabRefException thrown if importing the preferences failed due to an InvalidPreferencesFormatException + * or an IOException + */ + public void importPreferences(String filename) throws JabRefException { + importPreferences(Paths.get(filename)); + } + + public void importPreferences(Path file) throws JabRefException { + try (InputStream is = Files.newInputStream(file)) { + Preferences.importPreferences(is); + } catch (InvalidPreferencesFormatException | IOException ex) { + throw new JabRefException("Could not import preferences", Localization.lang("Could not import preferences"), + ex); + } + } + + /** + * ONLY FOR TESTING! + * + * Do not use in production code. Otherwise the singleton pattern is broken and preferences might get lost. + * + * @param owPrefs + */ + public void overwritePreferences(JabRefPreferences owPrefs) { + singleton = owPrefs; + } + + public String getWrappedUsername() { + return '[' + get(DEFAULT_OWNER) + ']'; + } + + public Charset getDefaultEncoding() { + return Charset.forName(get(DEFAULT_ENCODING)); + } + + public void setDefaultEncoding(Charset encoding) { + put(DEFAULT_ENCODING, encoding.name()); + } + + public FileHistory getFileHistory() { + return new FileHistory(getStringList(RECENT_DATABASES).stream().map(Paths::get).collect(Collectors.toList())); + } + + public void storeFileHistory(FileHistory history) { + if (!history.isEmpty()) { + putStringList(RECENT_DATABASES, history.getHistory().stream().map(Path::toAbsolutePath).map(Path::toString).collect(Collectors.toList())); + } + } + + @Override + public FilePreferences getFilePreferences() { + Map fieldDirectories = Stream.of(FieldName.FILE, FieldName.PDF, FieldName.PS) + .collect(Collectors.toMap(field -> field, field -> get(field + FilePreferences.DIR_SUFFIX, ""))); + return new FilePreferences( + getUser(), + fieldDirectories, + getBoolean(JabRefPreferences.BIB_LOC_AS_PRIMARY_DIR), + get(IMPORT_FILENAMEPATTERN), + get(IMPORT_FILEDIRPATTERN)); + } + + public UpdateFieldPreferences getUpdateFieldPreferences() { + return new UpdateFieldPreferences(getBoolean(USE_OWNER), getBoolean(OVERWRITE_OWNER), get(DEFAULT_OWNER), + getBoolean(USE_TIME_STAMP), getBoolean(OVERWRITE_TIME_STAMP), get(TIME_STAMP_FIELD), + get(TIME_STAMP_FORMAT)); + } + + public LatexFieldFormatterPreferences getLatexFieldFormatterPreferences() { + return new LatexFieldFormatterPreferences(getBoolean(RESOLVE_STRINGS_ALL_FIELDS), + getStringList(DO_NOT_RESOLVE_STRINGS_FOR), getFieldContentParserPreferences()); + } + + public FieldContentParserPreferences getFieldContentParserPreferences() { + return new FieldContentParserPreferences(getStringList(NON_WRAPPABLE_FIELDS)); + } + + public boolean isKeywordSyncEnabled() { + return getBoolean(JabRefPreferences.SPECIALFIELDSENABLED) + && getBoolean(JabRefPreferences.AUTOSYNCSPECIALFIELDSTOKEYWORDS); + } + + public ImportFormatPreferences getImportFormatPreferences() { + return new ImportFormatPreferences(customImports, getDefaultEncoding(), getKeywordDelimiter(), + getBibtexKeyPatternPreferences(), getFieldContentParserPreferences(), getXMPPreferences(), + isKeywordSyncEnabled()); + } + + public SavePreferences loadForExportFromPreferences() { + Boolean saveInOriginalOrder = this.getBoolean(JabRefPreferences.EXPORT_IN_ORIGINAL_ORDER); + SaveOrderConfig saveOrder = null; + if (!saveInOriginalOrder) { + if (this.getBoolean(JabRefPreferences.EXPORT_IN_SPECIFIED_ORDER)) { + saveOrder = this.loadExportSaveOrder(); + } else { + saveOrder = this.loadTableSaveOrder(); + } + } + return new SavePreferences( + saveInOriginalOrder, + saveOrder, + this.getDefaultEncoding(), + this.getBoolean(JabRefPreferences.BACKUP), + SavePreferences.DatabaseSaveType.ALL, + false, + this.getBoolean(JabRefPreferences.REFORMAT_FILE_ON_SAVE_AND_EXPORT), + this.getLatexFieldFormatterPreferences(), + this.getKeyPattern(), + getBoolean(JabRefPreferences.GENERATE_KEYS_BEFORE_SAVING), + getBibtexKeyPatternPreferences()); + } + + public SavePreferences loadForSaveFromPreferences() { + return new SavePreferences( + false, + null, + this.getDefaultEncoding(), + this.getBoolean(JabRefPreferences.BACKUP), + SavePreferences.DatabaseSaveType.ALL, + true, + this.getBoolean(JabRefPreferences.REFORMAT_FILE_ON_SAVE_AND_EXPORT), + this.getLatexFieldFormatterPreferences(), + this.getKeyPattern(), + getBoolean(JabRefPreferences.GENERATE_KEYS_BEFORE_SAVING), + getBibtexKeyPatternPreferences()); + } + + public ExporterFactory getExporterFactory(JournalAbbreviationLoader abbreviationLoader) { + Map customFormats = this.customExports.getCustomExportFormats(this, abbreviationLoader); + LayoutFormatterPreferences layoutPreferences = this.getLayoutFormatterPreferences(abbreviationLoader); + SavePreferences savePreferences = this.loadForExportFromPreferences(); + XmpPreferences xmpPreferences = this.getXMPPreferences(); + return ExporterFactory.create(customFormats, layoutPreferences, savePreferences, xmpPreferences); + } + + public BibtexKeyPatternPreferences getBibtexKeyPatternPreferences() { + return new BibtexKeyPatternPreferences( + get(KEY_PATTERN_REGEX), + get(KEY_PATTERN_REPLACEMENT), + getBoolean(KEY_GEN_ALWAYS_ADD_LETTER), + getBoolean(KEY_GEN_FIRST_LETTER_A), + getBoolean(ENFORCE_LEGAL_BIBTEX_KEY), + getKeyPattern(), + getKeywordDelimiter()); + } + + public TimestampPreferences getTimestampPreferences() { + return new TimestampPreferences(getBoolean(USE_TIME_STAMP), getBoolean(UPDATE_TIMESTAMP), get(TIME_STAMP_FIELD), get(TIME_STAMP_FORMAT), getBoolean(OVERWRITE_TIME_STAMP)); + } + + public LayoutFormatterPreferences getLayoutFormatterPreferences( + JournalAbbreviationLoader journalAbbreviationLoader) { + Objects.requireNonNull(journalAbbreviationLoader); + return new LayoutFormatterPreferences(getNameFormatterPreferences(), getJournalAbbreviationPreferences(), + getFileLinkPreferences(), journalAbbreviationLoader); + } + + public XmpPreferences getXMPPreferences() { + return new XmpPreferences(getBoolean(USE_XMP_PRIVACY_FILTER), getStringList(XMP_PRIVACY_FILTERS), + getKeywordDelimiter()); + } + + public OpenOfficePreferences getOpenOfficePreferences() { + return new OpenOfficePreferences( + this.get(JabRefPreferences.OO_JARS_PATH), + this.get(JabRefPreferences.OO_EXECUTABLE_PATH), + this.get(JabRefPreferences.OO_PATH), + this.getBoolean(JabRefPreferences.OO_USE_ALL_OPEN_BASES), + this.getBoolean(JabRefPreferences.OO_SYNC_WHEN_CITING), + this.getBoolean(JabRefPreferences.OO_SHOW_PANEL), + this.getStringList(JabRefPreferences.OO_EXTERNAL_STYLE_FILES), + this.get(JabRefPreferences.OO_BIBLIOGRAPHY_STYLE_FILE)); + } + + public void setOpenOfficePreferences(OpenOfficePreferences openOfficePreferences) { + this.put(JabRefPreferences.OO_JARS_PATH, openOfficePreferences.getJarsPath()); + this.put(JabRefPreferences.OO_EXECUTABLE_PATH, openOfficePreferences.getExecutablePath()); + this.put(JabRefPreferences.OO_PATH, openOfficePreferences.getInstallationPath()); + this.putBoolean(JabRefPreferences.OO_USE_ALL_OPEN_BASES, openOfficePreferences.getUseAllDatabases()); + this.putBoolean(JabRefPreferences.OO_SYNC_WHEN_CITING, openOfficePreferences.getSyncWhenCiting()); + this.putBoolean(JabRefPreferences.OO_SHOW_PANEL, openOfficePreferences.getShowPanel()); + this.putStringList(JabRefPreferences.OO_EXTERNAL_STYLE_FILES, openOfficePreferences.getExternalStyles()); + this.put(JabRefPreferences.OO_BIBLIOGRAPHY_STYLE_FILE, openOfficePreferences.getCurrentStyle()); + } + + private NameFormatterPreferences getNameFormatterPreferences() { + return new NameFormatterPreferences(getStringList(NAME_FORMATER_KEY), getStringList(NAME_FORMATTER_VALUE)); + } + + public FileLinkPreferences getFileLinkPreferences() { + return new FileLinkPreferences( + Collections.singletonList(get(FieldName.FILE + FilePreferences.DIR_SUFFIX)), + fileDirForDatabase); + } + + public JabRefPreferences storeVersionPreferences(VersionPreferences versionPreferences) { + put(VERSION_IGNORED_UPDATE, versionPreferences.getIgnoredVersion().toString()); + return this; + } + + public VersionPreferences getVersionPreferences() { + Version ignoredVersion = Version.parse(get(VERSION_IGNORED_UPDATE)); + return new VersionPreferences(ignoredVersion); + } + + public JabRefPreferences storePreviewPreferences(PreviewPreferences previewPreferences) { + putInt(CYCLE_PREVIEW_POS, previewPreferences.getPreviewCyclePosition()); + putStringList(CYCLE_PREVIEW, previewPreferences.getPreviewCycle()); + putDouble(PREVIEW_PANEL_HEIGHT, previewPreferences.getPreviewPanelDividerPosition().doubleValue()); + put(PREVIEW_STYLE, previewPreferences.getPreviewStyle()); + putBoolean(PREVIEW_ENABLED, previewPreferences.isPreviewPanelEnabled()); + return this; + } + + public PreviewPreferences getPreviewPreferences() { + int cyclePos = getInt(CYCLE_PREVIEW_POS); + List cycle = getStringList(CYCLE_PREVIEW); + double panelHeight = getDouble(PREVIEW_PANEL_HEIGHT); + String style = get(PREVIEW_STYLE); + String styleDefault = (String) defaults.get(PREVIEW_STYLE); + boolean enabled = getBoolean(PREVIEW_ENABLED); + return new PreviewPreferences(cycle, cyclePos, panelHeight, enabled, style, styleDefault); + } + + public void storeProxyPreferences(ProxyPreferences proxyPreferences) { + putBoolean(PROXY_USE, proxyPreferences.isUseProxy()); + put(PROXY_HOSTNAME, proxyPreferences.getHostname()); + put(PROXY_PORT, proxyPreferences.getPort()); + putBoolean(PROXY_USE_AUTHENTICATION, proxyPreferences.isUseAuthentication()); + put(PROXY_USERNAME, proxyPreferences.getUsername()); + put(PROXY_PASSWORD, proxyPreferences.getPassword()); + } + + public ProxyPreferences getProxyPreferences() { + Boolean useProxy = getBoolean(PROXY_USE); + String hostname = get(PROXY_HOSTNAME); + String port = get(PROXY_PORT); + Boolean useAuthentication = getBoolean(PROXY_USE_AUTHENTICATION); + String username = get(PROXY_USERNAME); + String password = get(PROXY_PASSWORD); + return new ProxyPreferences(useProxy, hostname, port, useAuthentication, username, password); + } + + public ProtectedTermsPreferences getProtectedTermsPreferences() { + return new ProtectedTermsPreferences(getStringList(PROTECTED_TERMS_ENABLED_INTERNAL), + getStringList(PROTECTED_TERMS_ENABLED_EXTERNAL), getStringList(PROTECTED_TERMS_DISABLED_INTERNAL), + getStringList(PROTECTED_TERMS_DISABLED_EXTERNAL)); + } + + public void setProtectedTermsPreferences(ProtectedTermsLoader loader) { + List enabledExternalList = new ArrayList<>(); + List disabledExternalList = new ArrayList<>(); + List enabledInternalList = new ArrayList<>(); + List disabledInternalList = new ArrayList<>(); + + for (ProtectedTermsList list : loader.getProtectedTermsLists()) { + if (list.isInternalList()) { + if (list.isEnabled()) { + enabledInternalList.add(list.getLocation()); + } else { + disabledInternalList.add(list.getLocation()); + } + } else { + if (list.isEnabled()) { + enabledExternalList.add(list.getLocation()); + } else { + disabledExternalList.add(list.getLocation()); + } + } + } + + putStringList(PROTECTED_TERMS_ENABLED_EXTERNAL, enabledExternalList); + putStringList(PROTECTED_TERMS_DISABLED_EXTERNAL, disabledExternalList); + putStringList(PROTECTED_TERMS_ENABLED_INTERNAL, enabledInternalList); + putStringList(PROTECTED_TERMS_DISABLED_INTERNAL, disabledInternalList); + + } + + @Override + public JournalAbbreviationPreferences getJournalAbbreviationPreferences() { + return new JournalAbbreviationPreferences(getStringList(EXTERNAL_JOURNAL_LISTS), get(PERSONAL_JOURNAL_LIST), + getBoolean(USE_IEEE_ABRV), getDefaultEncoding()); + } + + public CleanupPreferences getCleanupPreferences(JournalAbbreviationLoader journalAbbreviationLoader) { + return new CleanupPreferences( + getLayoutFormatterPreferences(journalAbbreviationLoader), + getFilePreferences()); + } + + public CleanupPreset getCleanupPreset() { + Set activeJobs = EnumSet.noneOf(CleanupPreset.CleanupStep.class); + + if (this.getBoolean(JabRefPreferences.CLEANUP_DOI)) { + activeJobs.add(CleanupPreset.CleanupStep.CLEAN_UP_DOI); + } + if (this.getBoolean(JabRefPreferences.CLEANUP_ISSN)) { + activeJobs.add(CleanupPreset.CleanupStep.CLEAN_UP_ISSN); + } + if (this.getBoolean(JabRefPreferences.CLEANUP_MOVE_PDF)) { + activeJobs.add(CleanupPreset.CleanupStep.MOVE_PDF); + } + if (this.getBoolean(JabRefPreferences.CLEANUP_MAKE_PATHS_RELATIVE)) { + activeJobs.add(CleanupPreset.CleanupStep.MAKE_PATHS_RELATIVE); + } + if (this.getBoolean(JabRefPreferences.CLEANUP_RENAME_PDF)) { + activeJobs.add(CleanupPreset.CleanupStep.RENAME_PDF); + } + if (this.getBoolean(JabRefPreferences.CLEANUP_RENAME_PDF_ONLY_RELATIVE_PATHS)) { + activeJobs.add(CleanupPreset.CleanupStep.RENAME_PDF_ONLY_RELATIVE_PATHS); + } + if (this.getBoolean(JabRefPreferences.CLEANUP_UPGRADE_EXTERNAL_LINKS)) { + activeJobs.add(CleanupPreset.CleanupStep.CLEAN_UP_UPGRADE_EXTERNAL_LINKS); + } + if (this.getBoolean(JabRefPreferences.CLEANUP_CONVERT_TO_BIBLATEX)) { + activeJobs.add(CleanupPreset.CleanupStep.CONVERT_TO_BIBLATEX); + } + if (this.getBoolean(JabRefPreferences.CLEANUP_CONVERT_TO_BIBTEX)) { + activeJobs.add(CleanupPreset.CleanupStep.CONVERT_TO_BIBTEX); + } + if (this.getBoolean(JabRefPreferences.CLEANUP_FIX_FILE_LINKS)) { + activeJobs.add(CleanupPreset.CleanupStep.FIX_FILE_LINKS); + } + + FieldFormatterCleanups formatterCleanups = Cleanups.parse( + this.getStringList(JabRefPreferences.CLEANUP_FORMATTERS)); + + return new CleanupPreset(activeJobs, formatterCleanups); + } + + public void setCleanupPreset(CleanupPreset cleanupPreset) { + this.putBoolean(JabRefPreferences.CLEANUP_DOI, cleanupPreset.isActive(CleanupPreset.CleanupStep.CLEAN_UP_DOI)); + this.putBoolean(JabRefPreferences.CLEANUP_ISSN, cleanupPreset.isActive(CleanupPreset.CleanupStep.CLEAN_UP_ISSN)); + this.putBoolean(JabRefPreferences.CLEANUP_MOVE_PDF, cleanupPreset.isActive(CleanupPreset.CleanupStep.MOVE_PDF)); + this.putBoolean(JabRefPreferences.CLEANUP_MAKE_PATHS_RELATIVE, cleanupPreset.isActive(CleanupPreset.CleanupStep.MAKE_PATHS_RELATIVE)); + this.putBoolean(JabRefPreferences.CLEANUP_RENAME_PDF, cleanupPreset.isActive(CleanupPreset.CleanupStep.RENAME_PDF)); + this.putBoolean(JabRefPreferences.CLEANUP_RENAME_PDF_ONLY_RELATIVE_PATHS, + cleanupPreset.isActive(CleanupPreset.CleanupStep.RENAME_PDF_ONLY_RELATIVE_PATHS)); + this.putBoolean(JabRefPreferences.CLEANUP_UPGRADE_EXTERNAL_LINKS, + cleanupPreset.isActive(CleanupPreset.CleanupStep.CLEAN_UP_UPGRADE_EXTERNAL_LINKS)); + this.putBoolean(JabRefPreferences.CLEANUP_CONVERT_TO_BIBLATEX, cleanupPreset.isActive(CleanupPreset.CleanupStep.CONVERT_TO_BIBLATEX)); + this.putBoolean(JabRefPreferences.CLEANUP_CONVERT_TO_BIBTEX, cleanupPreset.isActive(CleanupPreset.CleanupStep.CONVERT_TO_BIBTEX)); + this.putBoolean(JabRefPreferences.CLEANUP_FIX_FILE_LINKS, cleanupPreset.isActive(CleanupPreset.CleanupStep.FIX_FILE_LINKS)); + this.putStringList(JabRefPreferences.CLEANUP_FORMATTERS, cleanupPreset.getFormatterCleanups().getAsStringList(OS.NEWLINE)); + } + + public RemotePreferences getRemotePreferences() { + return new RemotePreferences(getInt(REMOTE_SERVER_PORT), getBoolean(USE_REMOTE_SERVER)); + } + + public void setRemotePreferences(RemotePreferences remotePreferences) { + putInt(REMOTE_SERVER_PORT, remotePreferences.getPort()); + putBoolean(USE_REMOTE_SERVER, remotePreferences.useRemoteServer()); + } + + public void storeExportSaveOrder(SaveOrderConfig config) { + putBoolean(EXPORT_PRIMARY_SORT_DESCENDING, config.getSortCriteria().get(0).descending); + putBoolean(EXPORT_SECONDARY_SORT_DESCENDING, config.getSortCriteria().get(1).descending); + putBoolean(EXPORT_TERTIARY_SORT_DESCENDING, config.getSortCriteria().get(2).descending); + + put(EXPORT_PRIMARY_SORT_FIELD, config.getSortCriteria().get(0).field); + put(EXPORT_SECONDARY_SORT_FIELD, config.getSortCriteria().get(1).field); + put(EXPORT_TERTIARY_SORT_FIELD, config.getSortCriteria().get(2).field); + } + + private SaveOrderConfig loadTableSaveOrder() { + SaveOrderConfig config = new SaveOrderConfig(); + List columns = getStringList(COLUMN_IN_SORT_ORDER); + List sortTypes = getStringList(COlUMN_IN_SORT_ORDER_TYPE).stream().map(SortType::valueOf).map(type -> type == SortType.DESCENDING).collect(Collectors.toList()); + + for (int i = 0; i < columns.size(); i++) { + config.getSortCriteria().add(new SaveOrderConfig.SortCriterion(columns.get(i), sortTypes.get(i))); + } + + return config; + } + + public SaveOrderConfig loadExportSaveOrder() { + return new SaveOrderConfig(true, + new SaveOrderConfig.SortCriterion(get(EXPORT_PRIMARY_SORT_FIELD), getBoolean(EXPORT_PRIMARY_SORT_DESCENDING)), + new SaveOrderConfig.SortCriterion(get(EXPORT_SECONDARY_SORT_FIELD), getBoolean(EXPORT_SECONDARY_SORT_DESCENDING)), + new SaveOrderConfig.SortCriterion(get(EXPORT_TERTIARY_SORT_FIELD), getBoolean(EXPORT_TERTIARY_SORT_DESCENDING)) + ); + } + + public Character getKeywordDelimiter() { + return get(KEYWORD_SEPARATOR).charAt(0); + } + + public String getOrCreateUserId() { + Optional userId = getAsOptional(USER_ID); + if (userId.isPresent()) { + return userId.get(); + } else { + String newUserId = UUID.randomUUID().toString(); + put(USER_ID, newUserId); + return newUserId; + } + } + + public Boolean shouldCollectTelemetry() { + return getBoolean(COLLECT_TELEMETRY); + } + + public void setShouldCollectTelemetry(boolean value) { + putBoolean(COLLECT_TELEMETRY, value); + } + + public Boolean shouldAskToCollectTelemetry() { + return getBoolean(ALREADY_ASKED_TO_COLLECT_TELEMETRY); + } + + public void askedToCollectTelemetry() { + putBoolean(ALREADY_ASKED_TO_COLLECT_TELEMETRY, true); + } + + @Override + public void storeKeyBindingRepository(KeyBindingRepository keyBindingRepository) { + putStringList(JabRefPreferences.BIND_NAMES, keyBindingRepository.getBindNames()); + putStringList(JabRefPreferences.BINDINGS, keyBindingRepository.getBindings()); + } + + @Override + public KeyBindingRepository getKeyBindingRepository() { + return new KeyBindingRepository(getStringList(BIND_NAMES), getStringList(BINDINGS)); + } + + @Override + public void storeJournalAbbreviationPreferences(JournalAbbreviationPreferences abbreviationsPreferences) { + putStringList(JabRefPreferences.EXTERNAL_JOURNAL_LISTS, abbreviationsPreferences.getExternalJournalLists()); + putBoolean(JabRefPreferences.USE_IEEE_ABRV, abbreviationsPreferences.useIEEEAbbreviations()); + } + + public AutoLinkPreferences getAutoLinkPreferences() { + return new AutoLinkPreferences( + getBoolean(JabRefPreferences.AUTOLINK_USE_REG_EXP_SEARCH_KEY), + get(JabRefPreferences.AUTOLINK_REG_EXP_SEARCH_EXPRESSION_KEY), + getBoolean(JabRefPreferences.AUTOLINK_EXACT_KEY_ONLY), + getKeywordDelimiter()); + } + + public AutoCompletePreferences getAutoCompletePreferences() { + return new AutoCompletePreferences( + getBoolean(AUTO_COMPLETE), + AutoCompleteFirstNameMode.parse(get(AUTOCOMPLETER_FIRSTNAME_MODE)), + getBoolean(AUTOCOMPLETER_LAST_FIRST), + getBoolean(AUTOCOMPLETER_FIRST_LAST), + getStringList(AUTOCOMPLETER_COMPLETE_FIELDS), + getJournalAbbreviationPreferences()); + } + + public void storeAutoCompletePreferences(AutoCompletePreferences autoCompletePreferences) { + putBoolean(AUTO_COMPLETE, autoCompletePreferences.shouldAutoComplete()); + put(AUTOCOMPLETER_FIRSTNAME_MODE, autoCompletePreferences.getFirstNameMode().name()); + putBoolean(AUTOCOMPLETER_LAST_FIRST, autoCompletePreferences.getOnlyCompleteLastFirst()); + putBoolean(AUTOCOMPLETER_FIRST_LAST, autoCompletePreferences.getOnlyCompleteFirstLast()); + putStringList(AUTOCOMPLETER_COMPLETE_FIELDS, autoCompletePreferences.getCompleteFields()); + } + + public void storeSidePanePreferredPositions(Map preferredPositions) { + // Split the map into a pair of parallel String lists suitable for storage + List names = preferredPositions.keySet().stream() + .map(Enum::toString) + .collect(Collectors.toList()); + + List positions = preferredPositions.values().stream() + .map(integer -> Integer.toString(integer)) + .collect(Collectors.toList()); + + putStringList(SIDE_PANE_COMPONENT_NAMES, names); + putStringList(SIDE_PANE_COMPONENT_PREFERRED_POSITIONS, positions); + } + + private List createExtraFileColumns() { + if (getBoolean(EXTRA_FILE_COLUMNS)) { + return getStringList(LIST_OF_FILE_COLUMNS); + } else { + return Collections.emptyList(); + } + } + + private List createSpecialFieldColumns() { + if (getBoolean(SPECIALFIELDSENABLED)) { + List fieldsToShow = new ArrayList<>(); + if (getBoolean(SHOWCOLUMN_RANKING)) { + fieldsToShow.add(SpecialField.RANKING); + } + if (getBoolean(SHOWCOLUMN_RELEVANCE)) { + fieldsToShow.add(SpecialField.RELEVANCE); + } + if (getBoolean(SHOWCOLUMN_QUALITY)) { + fieldsToShow.add(SpecialField.QUALITY); + } + + if (getBoolean(SHOWCOLUMN_PRIORITY)) { + fieldsToShow.add(SpecialField.PRIORITY); + } + + if (getBoolean(SHOWCOLUMN_PRINTED)) { + fieldsToShow.add(SpecialField.PRINTED); + } + + if (getBoolean(SHOWCOLUMN_READ)) { + fieldsToShow.add(SpecialField.READ_STATUS); + } + return fieldsToShow; + } else { + return Collections.emptyList(); + } + } + + private Map createColumnWidths() { + List columns = getStringList(COLUMN_NAMES); + List widths = getStringList(COLUMN_WIDTHS) + .stream() + .map(string -> { + try { + return Double.parseDouble(string); + } catch (NumberFormatException e) { + LOGGER.error("Exception while parsing column widths. Choosing default.", e); + return BibtexSingleField.DEFAULT_FIELD_LENGTH; + } + }) + .collect(Collectors.toList()); + + Map map = new TreeMap<>(); + for (int i = 0; i < columns.size(); i++) { + map.put(columns.get(i), widths.get(i)); + } + return map; + } + + public ColumnPreferences getColumnPreferences() { + return new ColumnPreferences( + getBoolean(FILE_COLUMN), + getBoolean(URL_COLUMN), + getBoolean(PREFER_URL_DOI), + getBoolean(ARXIV_COLUMN), + getStringList(COLUMN_NAMES), + createSpecialFieldColumns(), + createExtraFileColumns(), + createColumnWidths(), + getMainTableColumnSortTypes()); + } + + public MainTablePreferences getMainTablePreferences() { + return new MainTablePreferences( + getColumnPreferences(), + getBoolean(AUTO_RESIZE_MODE)); + } + + @Override + public Path getWorkingDir() { + return Paths.get(get(WORKING_DIRECTORY)); + } + + @Override + public void setWorkingDir(Path dir) { + put(WORKING_DIRECTORY, dir.toString()); + + } + + public GroupViewMode getGroupViewMode() { + return GroupViewMode.valueOf(get(GROUP_INTERSECT_UNION_VIEW_MODE)); + } + + public void setGroupViewMode(GroupViewMode mode) { + put(GROUP_INTERSECT_UNION_VIEW_MODE, mode.name()); + } + + public void setPreviewStyle(String previewStyle) { + put(PREVIEW_STYLE, previewStyle); + } + + public String getPreviewStyle() { + return get(PREVIEW_STYLE); + } + + public Optional getFontSize() { + if (getBoolean(OVERRIDE_DEFAULT_FONT_SIZE)) { + return Optional.of(getInt(MAIN_FONT_SIZE)); + } else { + return Optional.empty(); + } + } + + public String setLastPreferencesExportPath() { + return get(PREFS_EXPORT_PATH); + } + + public void setLastPreferencesExportPath(Path exportFile) { + put(PREFS_EXPORT_PATH, exportFile.toString()); + } + + public Language getLanguage() { + String languageId = get(LANGUAGE); + return Stream.of(Language.values()) + .filter(language -> language.getId().equalsIgnoreCase(languageId)) + .findFirst() + .orElse(Language.English); + } + + public void setLanguage(Language language) { + Language oldLanguage = getLanguage(); + put(LANGUAGE, language.getId()); + if (language != oldLanguage) { + // Update any defaults that might be language dependent: + setLanguageDependentDefaultValues(); + } + } + + public void setIdBasedFetcherForEntryGenerator(String fetcherName) { + put(ID_ENTRY_GENERATOR, fetcherName); + } + + public String getIdBasedFetcherForEntryGenerator() { + return get(ID_ENTRY_GENERATOR); + } + + public void setMainTableColumnSortType(Map sortOrder) { + putStringList(COLUMN_IN_SORT_ORDER, new ArrayList<>(sortOrder.keySet())); + List sortTypes = sortOrder.values().stream().map(SortType::name).collect(Collectors.toList()); + putStringList(COlUMN_IN_SORT_ORDER_TYPE, sortTypes); + } + + public Map getMainTableColumnSortTypes() { + List columns = getStringList(COLUMN_IN_SORT_ORDER); + List sortTypes = getStringList(COlUMN_IN_SORT_ORDER_TYPE).stream().map(SortType::valueOf).collect(Collectors.toList()); + Map map = new LinkedHashMap<>(); + for (int i = 0; i < columns.size(); i++) { + map.put(columns.get(i), sortTypes.get(i)); + } + return map; + } + +} From 35185963211f3d8232604b335b29bca494a28e95 Mon Sep 17 00:00:00 2001 From: conorfos Date: Thu, 27 Sep 2018 09:16:04 +0100 Subject: [PATCH 08/23] Removed unnecessary setting of html_representation Recommendation html_representation field no longer set as it is not used --- .../jabref/logic/importer/fileformat/MrDLibImporter.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java index d4f5dfe5ab8..0d7454c4054 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java @@ -5,7 +5,6 @@ import java.io.BufferedReader; import java.io.IOException; -import java.text.MessageFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -29,7 +28,6 @@ */ public class MrDLibImporter extends Importer { - private static final MessageFormat HTML_LIST_ITEM_TEMPLATE = new MessageFormat("{1}. {2} {3} {4}"); private static final String DEFAULT_MRDLIB_ERROR_MESSAGE = "Error while fetching from Mr.DLib."; private static final Logger LOGGER = LoggerFactory.getLogger(MrDLibImporter.class); public ParserResult parserResult; @@ -175,11 +173,6 @@ private RankedBibEntry populateBibEntry(JSONObject recommendation) { current.setField(FieldName.JOURNAL, journal); current.setField(FieldName.URL, url); - // Create HTML representation of recommendation for display on the UI - Object[] args = {url, title, authors, journal, year}; - String htmlRepresentation = HTML_LIST_ITEM_TEMPLATE.format(args); - current.setField("html_representation", htmlRepresentation); - return new RankedBibEntry(current, rank); } From 4215e13de7baf9f74d8a823cda2ad850e080a3f1 Mon Sep 17 00:00:00 2001 From: conorfos Date: Thu, 27 Sep 2018 09:24:59 +0100 Subject: [PATCH 09/23] Removed .orig file mistakenly added --- .../preferences/JabRefPreferences.java.orig | 2029 ----------------- 1 file changed, 2029 deletions(-) delete mode 100644 src/main/java/org/jabref/preferences/JabRefPreferences.java.orig diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java.orig b/src/main/java/org/jabref/preferences/JabRefPreferences.java.orig deleted file mode 100644 index 641003823bf..00000000000 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java.orig +++ /dev/null @@ -1,2029 +0,0 @@ -package org.jabref.preferences; - -import java.awt.Color; -import java.awt.Font; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Reader; -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; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.TreeMap; -import java.util.UUID; -import java.util.prefs.BackingStoreException; -import java.util.prefs.InvalidPreferencesFormatException; -import java.util.prefs.Preferences; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import javafx.scene.control.TableColumn.SortType; - -import org.jabref.Globals; -import org.jabref.JabRefException; -import org.jabref.JabRefMain; -import org.jabref.gui.SidePaneType; -import org.jabref.gui.autocompleter.AutoCompleteFirstNameMode; -import org.jabref.gui.autocompleter.AutoCompletePreferences; -import org.jabref.gui.desktop.JabRefDesktop; -import org.jabref.gui.entryeditor.EntryEditorPreferences; -import org.jabref.gui.entryeditor.EntryEditorTabList; -import org.jabref.gui.groups.GroupViewMode; -import org.jabref.gui.keyboard.KeyBindingRepository; -import org.jabref.gui.maintable.ColumnPreferences; -import org.jabref.gui.maintable.MainTablePreferences; -import org.jabref.gui.preferences.ImportSettingsTab; -import org.jabref.logic.bibtex.FieldContentParserPreferences; -import org.jabref.logic.bibtex.LatexFieldFormatterPreferences; -import org.jabref.logic.bibtexkeypattern.BibtexKeyPatternPreferences; -import org.jabref.logic.citationstyle.CitationStyle; -import org.jabref.logic.cleanup.CleanupPreferences; -import org.jabref.logic.cleanup.CleanupPreset; -import org.jabref.logic.cleanup.Cleanups; -import org.jabref.logic.exporter.ExporterFactory; -import org.jabref.logic.exporter.SavePreferences; -import org.jabref.logic.exporter.TemplateExporter; -import org.jabref.logic.importer.ImportFormatPreferences; -import org.jabref.logic.importer.fetcher.DoiFetcher; -import org.jabref.logic.journals.JournalAbbreviationLoader; -import org.jabref.logic.journals.JournalAbbreviationPreferences; -import org.jabref.logic.l10n.Language; -import org.jabref.logic.l10n.Localization; -import org.jabref.logic.layout.LayoutFormatterPreferences; -import org.jabref.logic.layout.format.FileLinkPreferences; -import org.jabref.logic.layout.format.NameFormatterPreferences; -import org.jabref.logic.net.ProxyPreferences; -import org.jabref.logic.openoffice.OpenOfficePreferences; -import org.jabref.logic.openoffice.StyleLoader; -import org.jabref.logic.preferences.TimestampPreferences; -import org.jabref.logic.protectedterms.ProtectedTermsList; -import org.jabref.logic.protectedterms.ProtectedTermsLoader; -import org.jabref.logic.protectedterms.ProtectedTermsPreferences; -import org.jabref.logic.remote.RemotePreferences; -import org.jabref.logic.shared.prefs.SharedDatabasePreferences; -import org.jabref.logic.util.OS; -import org.jabref.logic.util.UpdateFieldPreferences; -import org.jabref.logic.util.Version; -import org.jabref.logic.util.io.AutoLinkPreferences; -import org.jabref.logic.util.io.FileHistory; -import org.jabref.logic.xmp.XmpPreferences; -import org.jabref.model.bibtexkeypattern.GlobalBibtexKeyPattern; -import org.jabref.model.cleanup.FieldFormatterCleanups; -import org.jabref.model.database.BibDatabaseMode; -import org.jabref.model.entry.BibEntry; -import org.jabref.model.entry.BibtexSingleField; -import org.jabref.model.entry.CustomEntryType; -import org.jabref.model.entry.FieldName; -import org.jabref.model.entry.InternalBibtexFields; -import org.jabref.model.entry.specialfields.SpecialField; -import org.jabref.model.metadata.FilePreferences; -import org.jabref.model.metadata.SaveOrderConfig; -import org.jabref.model.strings.StringUtil; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class JabRefPreferences implements PreferencesService { - - // Push to application preferences - public static final String EMACS_PATH = "emacsPath"; - public static final String EMACS_ADDITIONAL_PARAMETERS = "emacsParameters"; - - /* contents of the defaults HashMap that are defined in this class. - * There are more default parameters in this map which belong to separate preference classes. - */ - public static final String TEXSTUDIO_PATH = "TeXstudioPath"; - public static final String WIN_EDT_PATH = "winEdtPath"; - public static final String TEXMAKER_PATH = "texmakerPath"; - public static final String VIM_SERVER = "vimServer"; - public static final String VIM = "vim"; - public static final String LYXPIPE = "lyxpipe"; - public static final String EXTERNAL_FILE_TYPES = "externalFileTypes"; - public static final String FONT_FAMILY = "fontFamily"; - public static final String FX_FONT_RENDERING_TWEAK = "fxFontRenderingTweak"; - public static final String LANGUAGE = "language"; - public static final String NAMES_LAST_ONLY = "namesLastOnly"; - public static final String ABBR_AUTHOR_NAMES = "abbrAuthorNames"; - public static final String NAMES_NATBIB = "namesNatbib"; - public static final String NAMES_FIRST_LAST = "namesFf"; - public static final String BIBLATEX_DEFAULT_MODE = "biblatexMode"; - public static final String NAMES_AS_IS = "namesAsIs"; - public static final String ENTRY_EDITOR_HEIGHT = "entryEditorHeightFX"; - public static final String AUTO_RESIZE_MODE = "autoResizeMode"; - public static final String WINDOW_MAXIMISED = "windowMaximised"; - public static final String USE_DEFAULT_LOOK_AND_FEEL = "useDefaultLookAndFeel"; - public static final String PROXY_PORT = "proxyPort"; - public static final String PROXY_HOSTNAME = "proxyHostname"; - public static final String PROXY_USE = "useProxy"; - public static final String PROXY_USERNAME = "proxyUsername"; - public static final String PROXY_PASSWORD = "proxyPassword"; - public static final String PROXY_USE_AUTHENTICATION = "useProxyAuthentication"; - - public static final String REFORMAT_FILE_ON_SAVE_AND_EXPORT = "reformatFileOnSaveAndExport"; - public static final String EXPORT_IN_ORIGINAL_ORDER = "exportInOriginalOrder"; - public static final String EXPORT_IN_SPECIFIED_ORDER = "exportInSpecifiedOrder"; - public static final String EXPORT_PRIMARY_SORT_FIELD = "exportPriSort"; - public static final String EXPORT_PRIMARY_SORT_DESCENDING = "exportPriDescending"; - public static final String EXPORT_SECONDARY_SORT_FIELD = "exportSecSort"; - public static final String EXPORT_SECONDARY_SORT_DESCENDING = "exportSecDescending"; - public static final String EXPORT_TERTIARY_SORT_FIELD = "exportTerSort"; - public static final String EXPORT_TERTIARY_SORT_DESCENDING = "exportTerDescending"; - public static final String NEWLINE = "newline"; - public static final String COLUMN_WIDTHS = "columnWidths"; - public static final String COLUMN_NAMES = "columnNames"; - public static final String COLUMN_IN_SORT_ORDER = "columnInSortOrder"; - public static final String COlUMN_IN_SORT_ORDER_TYPE = "columnInSortOrderType"; - - public static final String SIDE_PANE_COMPONENT_PREFERRED_POSITIONS = "sidePaneComponentPreferredPositions"; - public static final String SIDE_PANE_COMPONENT_NAMES = "sidePaneComponentNames"; - public static final String XMP_PRIVACY_FILTERS = "xmpPrivacyFilters"; - public static final String USE_XMP_PRIVACY_FILTER = "useXmpPrivacyFilter"; - public static final String DEFAULT_AUTO_SORT = "defaultAutoSort"; - public static final String DEFAULT_SHOW_SOURCE = "defaultShowSource"; - // Window sizes - public static final String SIZE_Y = "mainWindowSizeY"; - public static final String SIZE_X = "mainWindowSizeX"; - public static final String POS_Y = "mainWindowPosY"; - public static final String POS_X = "mainWindowPosX"; - public static final String STRINGS_SIZE_Y = "stringsSizeY"; - public static final String STRINGS_SIZE_X = "stringsSizeX"; - public static final String STRINGS_POS_Y = "stringsPosY"; - public static final String STRINGS_POS_X = "stringsPosX"; - public static final String DUPLICATES_SIZE_Y = "duplicatesSizeY"; - public static final String DUPLICATES_SIZE_X = "duplicatesSizeX"; - public static final String DUPLICATES_POS_Y = "duplicatesPosY"; - public static final String DUPLICATES_POS_X = "duplicatesPosX"; - public static final String MERGEENTRIES_SIZE_Y = "mergeEntriesSizeY"; - public static final String MERGEENTRIES_SIZE_X = "mergeEntriesSizeX"; - public static final String MERGEENTRIES_POS_Y = "mergeEntriesPosY"; - public static final String MERGEENTRIES_POS_X = "mergeEntriesPosX"; - public static final String PREAMBLE_SIZE_Y = "preambleSizeY"; - public static final String PREAMBLE_SIZE_X = "preambleSizeX"; - public static final String PREAMBLE_POS_Y = "preamblePosY"; - public static final String PREAMBLE_POS_X = "preamblePosX"; - public static final String TERMS_SIZE_Y = "termsSizeY"; - public static final String TERMS_SIZE_X = "termsSizeX"; - public static final String TERMS_POS_Y = "termsPosY"; - public static final String TERMS_POS_X = "termsPosX"; - public static final String SEARCH_DIALOG_HEIGHT = "searchDialogHeight"; - public static final String SEARCH_DIALOG_WIDTH = "searchDialogWidth"; - public static final String IMPORT_INSPECTION_DIALOG_HEIGHT = "importInspectionDialogHeight"; - public static final String IMPORT_INSPECTION_DIALOG_WIDTH = "importInspectionDialogWidth"; - public static final String LAST_EDITED = "lastEdited"; - public static final String OPEN_LAST_EDITED = "openLastEdited"; - public static final String LAST_FOCUSED = "lastFocused"; - public static final String BACKUP = "backup"; - public static final String AUTO_OPEN_FORM = "autoOpenForm"; - public static final String IMPORT_WORKING_DIRECTORY = "importWorkingDirectory"; - public static final String EXPORT_WORKING_DIRECTORY = "exportWorkingDirectory"; - public static final String WORKING_DIRECTORY = "workingDirectory"; - public static final String EDITOR_EMACS_KEYBINDINGS = "editorEMACSkeyBindings"; - public static final String EDITOR_EMACS_KEYBINDINGS_REBIND_CA = "editorEMACSkeyBindingsRebindCA"; - public static final String EDITOR_EMACS_KEYBINDINGS_REBIND_CF = "editorEMACSkeyBindingsRebindCF"; - public static final String GROUPS_DEFAULT_FIELD = "groupsDefaultField"; - - public static final String KEYWORD_SEPARATOR = "groupKeywordSeparator"; - public static final String AUTO_ASSIGN_GROUP = "autoAssignGroup"; - public static final String LIST_OF_FILE_COLUMNS = "listOfFileColumns"; - public static final String EXTRA_FILE_COLUMNS = "extraFileColumns"; - public static final String ARXIV_COLUMN = "arxivColumn"; - public static final String FILE_COLUMN = "fileColumn"; - public static final String PREFER_URL_DOI = "preferUrlDoi"; - public static final String URL_COLUMN = "urlColumn"; - // Colors - public static final String FIELD_EDITOR_TEXT_COLOR = "fieldEditorTextColor"; - public static final String ACTIVE_FIELD_EDITOR_BACKGROUND_COLOR = "activeFieldEditorBackgroundColor"; - public static final String INVALID_FIELD_BACKGROUND_COLOR = "invalidFieldBackgroundColor"; - public static final String VALID_FIELD_BACKGROUND_COLOR = "validFieldBackgroundColor"; - public static final String ICON_ENABLED_COLOR = "iconEnabledColor"; - public static final String ICON_DISABLED_COLOR = "iconDisabledColor"; - public static final String FONT_SIZE = "fontSize"; - public static final String OVERRIDE_DEFAULT_FONT_SIZE = "overrideDefaultFontSize"; - public static final String MAIN_FONT_SIZE = "mainFontSize"; - public static final String FONT_STYLE = "fontStyle"; - public static final String RECENT_DATABASES = "recentDatabases"; - public static final String RENAME_ON_MOVE_FILE_TO_FILE_DIR = "renameOnMoveFileToFileDir"; - public static final String MEMORY_STICK_MODE = "memoryStickMode"; - public static final String DEFAULT_OWNER = "defaultOwner"; - public static final String DEFAULT_ENCODING = "defaultEncoding"; - public static final String TOOLBAR_VISIBLE = "toolbarVisible"; - // Timestamp preferences - public static final String USE_TIME_STAMP = "useTimeStamp"; - public static final String UPDATE_TIMESTAMP = "updateTimestamp"; - public static final String TIME_STAMP_FIELD = "timeStampField"; - public static final String TIME_STAMP_FORMAT = "timeStampFormat"; - public static final String OVERWRITE_TIME_STAMP = "overwriteTimeStamp"; - - public static final String WARN_ABOUT_DUPLICATES_IN_INSPECTION = "warnAboutDuplicatesInInspection"; - public static final String GENERATE_KEYS_AFTER_INSPECTION = "generateKeysAfterInspection"; - public static final String NON_WRAPPABLE_FIELDS = "nonWrappableFields"; - public static final String RESOLVE_STRINGS_ALL_FIELDS = "resolveStringsAllFields"; - public static final String DO_NOT_RESOLVE_STRINGS_FOR = "doNotResolveStringsFor"; - public static final String MERGE_ENTRIES_DIFF_MODE = "mergeEntriesDiffMode"; - public static final String CUSTOM_EXPORT_FORMAT = "customExportFormat"; - public static final String CUSTOM_IMPORT_FORMAT = "customImportFormat"; - public static final String KEY_PATTERN_REGEX = "KeyPatternRegex"; - public static final String KEY_PATTERN_REPLACEMENT = "KeyPatternReplacement"; - public static final String CONSOLE_COMMAND = "consoleCommand"; - public static final String USE_DEFAULT_CONSOLE_APPLICATION = "useDefaultConsoleApplication"; - public static final String ADOBE_ACROBAT_COMMAND = "adobeAcrobatCommand"; - public static final String SUMATRA_PDF_COMMAND = "sumatraCommand"; - public static final String USE_PDF_READER = "usePDFReader"; - // Currently, it is not possible to specify defaults for specific entry types - // When this should be made possible, the code to inspect is org.jabref.gui.preferences.BibtexKeyPatternPrefTab.storeSettings() -> LabelPattern keypatterns = getCiteKeyPattern(); etc - public static final String DEFAULT_BIBTEX_KEY_PATTERN = "defaultBibtexKeyPattern"; - public static final String GRAY_OUT_NON_HITS = "grayOutNonHits"; - public static final String CONFIRM_DELETE = "confirmDelete"; - public static final String WARN_BEFORE_OVERWRITING_KEY = "warnBeforeOverwritingKey"; - public static final String AVOID_OVERWRITING_KEY = "avoidOverwritingKey"; - public static final String OVERWRITE_OWNER = "overwriteOwner"; - public static final String USE_OWNER = "useOwner"; - public static final String AUTOLINK_EXACT_KEY_ONLY = "autolinkExactKeyOnly"; - public static final String SHOW_FILE_LINKS_UPGRADE_WARNING = "showFileLinksUpgradeWarning"; - public static final String SIDE_PANE_WIDTH = "sidePaneWidthFX"; - public static final String LAST_USED_EXPORT = "lastUsedExport"; - public static final String CITE_COMMAND = "citeCommand"; - public static final String GENERATE_KEYS_BEFORE_SAVING = "generateKeysBeforeSaving"; - public static final String EMAIL_SUBJECT = "emailSubject"; - public static final String OPEN_FOLDERS_OF_ATTACHED_FILES = "openFoldersOfAttachedFiles"; - public static final String KEY_GEN_ALWAYS_ADD_LETTER = "keyGenAlwaysAddLetter"; - public static final String KEY_GEN_FIRST_LETTER_A = "keyGenFirstLetterA"; - public static final String ENFORCE_LEGAL_BIBTEX_KEY = "enforceLegalBibtexKey"; - public static final String LOCAL_AUTO_SAVE = "localAutoSave"; - public static final String RUN_AUTOMATIC_FILE_SEARCH = "runAutomaticFileSearch"; - public static final String NUMERIC_FIELDS = "numericFields"; - public static final String AUTOLINK_REG_EXP_SEARCH_EXPRESSION_KEY = "regExpSearchExpression"; - public static final String AUTOLINK_USE_REG_EXP_SEARCH_KEY = "useRegExpSearch"; - public static final String BIB_LOC_AS_PRIMARY_DIR = "bibLocAsPrimaryDir"; - public static final String SELECTED_FETCHER_INDEX = "selectedFetcherIndex"; - public static final String WEB_SEARCH_VISIBLE = "webSearchVisible"; - public static final String GROUP_SIDEPANE_VISIBLE = "groupSidepaneVisible"; - public static final String ALLOW_FILE_AUTO_OPEN_BROWSE = "allowFileAutoOpenBrowse"; - public static final String CUSTOM_TAB_NAME = "customTabName_"; - public static final String CUSTOM_TAB_FIELDS = "customTabFields_"; - public static final String USE_UNIT_FORMATTER_ON_SEARCH = "useUnitFormatterOnSearch"; - public static final String USE_CASE_KEEPER_ON_SEARCH = "useCaseKeeperOnSearch"; - public static final String ASK_AUTO_NAMING_PDFS_AGAIN = "AskAutoNamingPDFsAgain"; - public static final String CLEANUP_DOI = "CleanUpDOI"; - public static final String CLEANUP_ISSN = "CleanUpISSN"; - public static final String CLEANUP_MOVE_PDF = "CleanUpMovePDF"; - public static final String CLEANUP_MAKE_PATHS_RELATIVE = "CleanUpMakePathsRelative"; - public static final String CLEANUP_RENAME_PDF = "CleanUpRenamePDF"; - public static final String CLEANUP_RENAME_PDF_ONLY_RELATIVE_PATHS = "CleanUpRenamePDFonlyRelativePaths"; - public static final String CLEANUP_UPGRADE_EXTERNAL_LINKS = "CleanUpUpgradeExternalLinks"; - public static final String CLEANUP_CONVERT_TO_BIBLATEX = "CleanUpConvertToBiblatex"; - public static final String CLEANUP_CONVERT_TO_BIBTEX = "CleanUpConvertToBibtex"; - public static final String CLEANUP_FIX_FILE_LINKS = "CleanUpFixFileLinks"; - public static final String CLEANUP_FORMATTERS = "CleanUpFormatters"; - public static final String IMPORT_DEFAULT_PDF_IMPORT_STYLE = "importDefaultPDFimportStyle"; - public static final String IMPORT_ALWAYSUSE = "importAlwaysUsePDFImportStyle"; - public static final String IMPORT_FILENAMEPATTERN = "importFileNamePattern"; - public static final String IMPORT_FILEDIRPATTERN = "importFileDirPattern"; - public static final String NAME_FORMATTER_VALUE = "nameFormatterFormats"; - public static final String NAME_FORMATER_KEY = "nameFormatterNames"; - public static final String PUSH_TO_APPLICATION = "pushToApplication"; - public static final String SHOW_RECOMMENDATIONS = "showRecommendations"; - public static final String ACCEPT_RECOMMENDATIONS = "acceptRecommendations"; - public static final String VALIDATE_IN_ENTRY_EDITOR = "validateInEntryEditor"; - // Dropped file handler - public static final String DROPPEDFILEHANDLER_RENAME = "DroppedFileHandler_RenameFile"; - public static final String DROPPEDFILEHANDLER_MOVE = "DroppedFileHandler_MoveFile"; - public static final String DROPPEDFILEHANDLER_COPY = "DroppedFileHandler_CopyFile"; - public static final String DROPPEDFILEHANDLER_LEAVE = "DroppedFileHandler_LeaveFileInDir"; - // Remote - public static final String USE_REMOTE_SERVER = "useRemoteServer"; - public static final String REMOTE_SERVER_PORT = "remoteServerPort"; - - /** - * The OpenOffice/LibreOffice connection preferences are: - * OO_PATH main directory for OO/LO installation, used to detect location on Win/OS X when using manual connect - * OO_EXECUTABLE_PATH path to soffice-file - * OO_JARS_PATH directory that contains juh.jar, jurt.jar, ridl.jar, unoil.jar - * OO_SYNC_WHEN_CITING true if the reference list is updated when adding a new citation - * OO_SHOW_PANEL true if the OO panel is shown on startup - * OO_USE_ALL_OPEN_DATABASES true if all databases should be used when citing - * OO_BIBLIOGRAPHY_STYLE_FILE path to the used style file - * OO_EXTERNAL_STYLE_FILES list with paths to external style files - * STYLES_*_* size and position of "Select style" dialog - */ - public static final String OO_EXECUTABLE_PATH = "ooExecutablePath"; - public static final String OO_PATH = "ooPath"; - public static final String OO_JARS_PATH = "ooJarsPath"; - public static final String OO_SHOW_PANEL = "showOOPanel"; - public static final String OO_SYNC_WHEN_CITING = "syncOOWhenCiting"; - public static final String OO_USE_ALL_OPEN_BASES = "useAllOpenBases"; - public static final String OO_BIBLIOGRAPHY_STYLE_FILE = "ooBibliographyStyleFile"; - public static final String OO_EXTERNAL_STYLE_FILES = "ooExternalStyleFiles"; - - public static final String STYLES_SIZE_Y = "stylesSizeY"; - public static final String STYLES_SIZE_X = "stylesSizeX"; - public static final String STYLES_POS_Y = "stylesPosY"; - public static final String STYLES_POS_X = "stylesPosX"; - // Special field preferences - public static final String SHOWCOLUMN_RELEVANCE = "showRelevanceColumn"; - public static final String SHOWCOLUMN_READ = "showReadColumn"; - public static final String SHOWCOLUMN_RANKING = "showRankingColumn"; - public static final String SHOWCOLUMN_QUALITY = "showQualityColumn"; - public static final String SHOWCOLUMN_PRIORITY = "showPriorityColumn"; - public static final String SHOWCOLUMN_PRINTED = "showPrintedColumn"; - public static final String SPECIALFIELDSENABLED = "specialFieldsEnabled"; - // The choice between AUTOSYNCSPECIALFIELDSTOKEYWORDS and SERIALIZESPECIALFIELDS is mutually exclusive - public static final String SERIALIZESPECIALFIELDS = "serializeSpecialFields"; - // The choice between AUTOSYNCSPECIALFIELDSTOKEYWORDS and SERIALIZESPECIALFIELDS is mutually exclusive - // At least in the settings, not in the implementation. But having both confused the users, therefore, having activated both options at the same time has been disabled - public static final String AUTOSYNCSPECIALFIELDSTOKEYWORDS = "autoSyncSpecialFieldsToKeywords"; - // Prefs node for BibtexKeyPatterns - public static final String BIBTEX_KEY_PATTERNS_NODE = "bibtexkeypatterns"; - // Prefs node for customized entry types - public static final String CUSTOMIZED_BIBTEX_TYPES = "customizedBibtexTypes"; - public static final String CUSTOMIZED_BIBLATEX_TYPES = "customizedBiblatexTypes"; - // Version - public static final String VERSION_IGNORED_UPDATE = "versionIgnoreUpdate"; - //KeyBindings - keys - public because needed for pref migration - public static final String BINDINGS = "bindings"; - - //AutcompleteFields - public because needed for pref migration - public static final String AUTOCOMPLETER_COMPLETE_FIELDS = "autoCompleteFields"; - - // Id Entry Generator Preferences - public static final String ID_ENTRY_GENERATOR = "idEntryGenerator"; - - // Preview - private static final String PREVIEW_STYLE = "previewStyle"; - private static final String CYCLE_PREVIEW_POS = "cyclePreviewPos"; - private static final String CYCLE_PREVIEW = "cyclePreview"; - private static final String PREVIEW_PANEL_HEIGHT = "previewPanelHeightFX"; - private static final String PREVIEW_ENABLED = "previewEnabled"; - - // Auto completion - private static final String AUTO_COMPLETE = "autoComplete"; - private static final String AUTOCOMPLETER_FIRSTNAME_MODE = "autoCompFirstNameMode"; - private static final String AUTOCOMPLETER_LAST_FIRST = "autoCompLF"; - private static final String AUTOCOMPLETER_FIRST_LAST = "autoCompFF"; - - private static final String BIND_NAMES = "bindNames"; - // User - private static final String USER_ID = "userId"; - private static final String EXTERNAL_JOURNAL_LISTS = "externalJournalLists"; - private static final String PERSONAL_JOURNAL_LIST = "personalJournalList"; - private static final String USE_IEEE_ABRV = "useIEEEAbrv"; - - // Telemetry collection - private static final String COLLECT_TELEMETRY = "collectTelemetry"; - private static final String ALREADY_ASKED_TO_COLLECT_TELEMETRY = "askedCollectTelemetry"; - private static final Logger LOGGER = LoggerFactory.getLogger(JabRefPreferences.class); - private static final Class PREFS_BASE_CLASS = JabRefMain.class; - private static final String DB_CONNECT_USERNAME = "dbConnectUsername"; - private static final String DB_CONNECT_DATABASE = "dbConnectDatabase"; - private static final String DB_CONNECT_HOSTNAME = "dbConnectHostname"; - private static final String DB_CONNECT_SERVER_TYPE = "dbConnectServerType"; - private static final String PROTECTED_TERMS_ENABLED_EXTERNAL = "protectedTermsEnabledExternal"; - private static final String PROTECTED_TERMS_DISABLED_EXTERNAL = "protectedTermsDisabledExternal"; - private static final String PROTECTED_TERMS_ENABLED_INTERNAL = "protectedTermsEnabledInternal"; - private static final String PROTECTED_TERMS_DISABLED_INTERNAL = "protectedTermsDisabledInternal"; - - //GroupViewMode - private static final String GROUP_INTERSECT_UNION_VIEW_MODE = "groupIntersectUnionViewModes"; - - // Dialog states - private static final String PREFS_EXPORT_PATH = "prefsExportPath"; - - // Helper string - private static final String USER_HOME = System.getProperty("user.home"); - // The only instance of this class: - private static JabRefPreferences singleton; - /** - * HashMap that contains all preferences which are set by default - */ - public final Map defaults = new HashMap<>(); - // Object containing custom export formats: - public final CustomExportList customExports; - /** - * Set with all custom {@link org.jabref.logic.importer.Importer}s - */ - public final CustomImportList customImports; - // The following field is used as a global variable during the export of a database. - // By setting this field to the path of the database's default file directory, formatters - // that should resolve external file paths can access this field. This is an ugly hack - // to solve the problem of formatters not having access to any context except for the - // string to be formatted and possible formatter arguments. - public List fileDirForDatabase; - private final Preferences prefs; - private GlobalBibtexKeyPattern keyPattern; - // Object containing info about customized entry editor tabs. - private Map> tabList; - - // The constructor is made private to enforce this as a singleton class: - private JabRefPreferences() { - try { - if (new File("jabref.xml").exists()) { - importPreferences("jabref.xml"); - } - } catch (JabRefException e) { - LOGGER.warn("Could not import preferences from jabref.xml: " + e.getMessage(), e); - } - - // load user preferences - prefs = Preferences.userNodeForPackage(PREFS_BASE_CLASS); - - // Since some of the preference settings themselves use localized strings, we cannot set the language after - // the initialization of the preferences in main - // Otherwise that language framework will be instantiated and more importantly, statically initialized preferences - // like the SearchDisplayMode will never be translated. - Localization.setLanguage(getLanguage()); - - SearchPreferences.putDefaults(defaults); - - defaults.put(TEXMAKER_PATH, JabRefDesktop.getNativeDesktop().detectProgramPath("texmaker", "Texmaker")); - defaults.put(WIN_EDT_PATH, JabRefDesktop.getNativeDesktop().detectProgramPath("WinEdt", "WinEdt Team\\WinEdt")); - defaults.put(TEXSTUDIO_PATH, JabRefDesktop.getNativeDesktop().detectProgramPath("texstudio", "TeXstudio")); - - defaults.put(BIBLATEX_DEFAULT_MODE, Boolean.FALSE); - - // Set DOI to be the default ID entry generator - defaults.put(ID_ENTRY_GENERATOR, DoiFetcher.NAME); - - if (OS.OS_X) { - defaults.put(FONT_FAMILY, "SansSerif"); - defaults.put(EMACS_PATH, "emacsclient"); - } else if (OS.WINDOWS) { - defaults.put(EMACS_PATH, "emacsclient.exe"); - } else { - // Linux - defaults.put(FONT_FAMILY, "SansSerif"); - defaults.put(EMACS_PATH, "emacsclient"); - } - - defaults.put(FX_FONT_RENDERING_TWEAK, OS.LINUX); //we turn this on per default on Linux - defaults.put(EMACS_ADDITIONAL_PARAMETERS, "-n -e"); - - defaults.put(PUSH_TO_APPLICATION, "TeXstudio"); - - defaults.put(RECENT_DATABASES, ""); - defaults.put(EXTERNAL_FILE_TYPES, ""); - defaults.put(KEY_PATTERN_REGEX, ""); - defaults.put(KEY_PATTERN_REPLACEMENT, ""); - - // Proxy - defaults.put(PROXY_USE, Boolean.FALSE); - defaults.put(PROXY_HOSTNAME, ""); - defaults.put(PROXY_PORT, "80"); - defaults.put(PROXY_USE_AUTHENTICATION, Boolean.FALSE); - defaults.put(PROXY_USERNAME, ""); - defaults.put(PROXY_PASSWORD, ""); - - defaults.put(USE_DEFAULT_LOOK_AND_FEEL, Boolean.TRUE); - defaults.put(LYXPIPE, USER_HOME + File.separator + ".lyx/lyxpipe"); - defaults.put(VIM, "vim"); - defaults.put(VIM_SERVER, "vim"); - defaults.put(POS_X, 0); - defaults.put(POS_Y, 0); - defaults.put(SIZE_X, 1024); - defaults.put(SIZE_Y, 768); - defaults.put(WINDOW_MAXIMISED, Boolean.TRUE); - defaults.put(AUTO_RESIZE_MODE, Boolean.TRUE); - defaults.put(ENTRY_EDITOR_HEIGHT, 0.65); - defaults.put(NAMES_AS_IS, Boolean.FALSE); // "Show names unchanged" - defaults.put(NAMES_FIRST_LAST, Boolean.FALSE); // "Show 'Firstname Lastname'" - defaults.put(NAMES_NATBIB, Boolean.TRUE); // "Natbib style" - defaults.put(ABBR_AUTHOR_NAMES, Boolean.TRUE); // "Abbreviate names" - defaults.put(NAMES_LAST_ONLY, Boolean.TRUE); // "Show last names only" - // system locale as default - defaults.put(LANGUAGE, Locale.getDefault().getLanguage()); - - defaults.put(REFORMAT_FILE_ON_SAVE_AND_EXPORT, Boolean.FALSE); - - // export order - defaults.put(EXPORT_IN_ORIGINAL_ORDER, Boolean.FALSE); - defaults.put(EXPORT_IN_SPECIFIED_ORDER, Boolean.FALSE); - - // export order: if EXPORT_IN_SPECIFIED_ORDER, then use following criteria - defaults.put(EXPORT_PRIMARY_SORT_FIELD, BibEntry.KEY_FIELD); - defaults.put(EXPORT_PRIMARY_SORT_DESCENDING, Boolean.FALSE); - defaults.put(EXPORT_SECONDARY_SORT_FIELD, FieldName.AUTHOR); - defaults.put(EXPORT_SECONDARY_SORT_DESCENDING, Boolean.FALSE); - defaults.put(EXPORT_TERTIARY_SORT_FIELD, FieldName.TITLE); - defaults.put(EXPORT_TERTIARY_SORT_DESCENDING, Boolean.TRUE); - - defaults.put(NEWLINE, System.lineSeparator()); - - defaults.put(SIDE_PANE_COMPONENT_NAMES, ""); - defaults.put(SIDE_PANE_COMPONENT_PREFERRED_POSITIONS, ""); - - defaults.put(COLUMN_NAMES, "entrytype;author/editor;title;year;journal/booktitle;bibtexkey"); - defaults.put(COLUMN_WIDTHS, "75;300;470;60;130;100"); - - defaults.put(XMP_PRIVACY_FILTERS, "pdf;timestamp;keywords;owner;note;review"); - defaults.put(USE_XMP_PRIVACY_FILTER, Boolean.FALSE); - defaults.put(WORKING_DIRECTORY, USER_HOME); - defaults.put(EXPORT_WORKING_DIRECTORY, USER_HOME); - // Remembers working directory of last import - defaults.put(IMPORT_WORKING_DIRECTORY, USER_HOME); - defaults.put(PREFS_EXPORT_PATH, USER_HOME); - defaults.put(AUTO_OPEN_FORM, Boolean.TRUE); - defaults.put(BACKUP, Boolean.TRUE); - defaults.put(OPEN_LAST_EDITED, Boolean.TRUE); - defaults.put(LAST_EDITED, ""); - defaults.put(LAST_FOCUSED, ""); - defaults.put(STRINGS_POS_X, 0); - defaults.put(STRINGS_POS_Y, 0); - defaults.put(STRINGS_SIZE_X, 600); - defaults.put(STRINGS_SIZE_Y, 400); - defaults.put(DUPLICATES_POS_X, 0); - defaults.put(DUPLICATES_POS_Y, 0); - defaults.put(DUPLICATES_SIZE_X, 800); - defaults.put(DUPLICATES_SIZE_Y, 600); - defaults.put(MERGEENTRIES_POS_X, 0); - defaults.put(MERGEENTRIES_POS_Y, 0); - defaults.put(MERGEENTRIES_SIZE_X, 800); - defaults.put(MERGEENTRIES_SIZE_Y, 600); - defaults.put(PREAMBLE_POS_X, 0); - defaults.put(PREAMBLE_POS_Y, 0); - defaults.put(PREAMBLE_SIZE_X, 600); - defaults.put(PREAMBLE_SIZE_Y, 400); - defaults.put(TERMS_POS_X, 0); - defaults.put(TERMS_POS_Y, 0); - defaults.put(TERMS_SIZE_X, 500); - defaults.put(TERMS_SIZE_Y, 500); - defaults.put(DEFAULT_SHOW_SOURCE, Boolean.FALSE); - - defaults.put(DEFAULT_AUTO_SORT, Boolean.FALSE); - - defaults.put(MERGE_ENTRIES_DIFF_MODE, 2); - - defaults.put(SHOW_RECOMMENDATIONS, Boolean.TRUE); - defaults.put(ACCEPT_RECOMMENDATIONS, Boolean.FALSE); - defaults.put(VALIDATE_IN_ENTRY_EDITOR, Boolean.TRUE); - defaults.put(EDITOR_EMACS_KEYBINDINGS, Boolean.FALSE); - defaults.put(EDITOR_EMACS_KEYBINDINGS_REBIND_CA, Boolean.TRUE); - defaults.put(EDITOR_EMACS_KEYBINDINGS_REBIND_CF, Boolean.TRUE); - defaults.put(AUTO_COMPLETE, Boolean.FALSE); - defaults.put(AUTOCOMPLETER_FIRSTNAME_MODE, AutoCompleteFirstNameMode.BOTH.name()); - defaults.put(AUTOCOMPLETER_FIRST_LAST, Boolean.FALSE); // "Autocomplete names in 'Firstname Lastname' format only" - defaults.put(AUTOCOMPLETER_LAST_FIRST, Boolean.FALSE); // "Autocomplete names in 'Lastname, Firstname' format only" - defaults.put(AUTOCOMPLETER_COMPLETE_FIELDS, "author;editor;title;journal;publisher;keywords;crossref;related;entryset"); - defaults.put(GROUPS_DEFAULT_FIELD, FieldName.KEYWORDS); - defaults.put(AUTO_ASSIGN_GROUP, Boolean.TRUE); - defaults.put(GROUP_INTERSECT_UNION_VIEW_MODE, GroupViewMode.INTERSECTION.name()); - defaults.put(KEYWORD_SEPARATOR, ", "); - defaults.put(TOOLBAR_VISIBLE, Boolean.TRUE); - defaults.put(DEFAULT_ENCODING, StandardCharsets.UTF_8.name()); - defaults.put(DEFAULT_OWNER, System.getProperty("user.name")); - defaults.put(MEMORY_STICK_MODE, Boolean.FALSE); - defaults.put(RENAME_ON_MOVE_FILE_TO_FILE_DIR, Boolean.TRUE); - - defaults.put(FONT_STYLE, Font.PLAIN); - defaults.put(FONT_SIZE, 12); - // Main table color settings: - defaults.put(VALID_FIELD_BACKGROUND_COLOR, "255:255:255"); - defaults.put(INVALID_FIELD_BACKGROUND_COLOR, "255:0:0"); - defaults.put(ACTIVE_FIELD_EDITOR_BACKGROUND_COLOR, "220:220:255"); - defaults.put(FIELD_EDITOR_TEXT_COLOR, "0:0:0"); - - // default icon colors - defaults.put(ICON_ENABLED_COLOR, "0:0:0"); - defaults.put(ICON_DISABLED_COLOR, "200:200:200"); - - defaults.put(URL_COLUMN, Boolean.TRUE); - defaults.put(PREFER_URL_DOI, Boolean.FALSE); - defaults.put(FILE_COLUMN, Boolean.TRUE); - defaults.put(ARXIV_COLUMN, Boolean.FALSE); - - defaults.put(EXTRA_FILE_COLUMNS, Boolean.FALSE); - defaults.put(LIST_OF_FILE_COLUMNS, ""); - - defaults.put(PROTECTED_TERMS_ENABLED_INTERNAL, convertListToString(ProtectedTermsLoader.getInternalLists())); - defaults.put(PROTECTED_TERMS_DISABLED_INTERNAL, ""); - defaults.put(PROTECTED_TERMS_ENABLED_EXTERNAL, ""); - defaults.put(PROTECTED_TERMS_DISABLED_EXTERNAL, ""); - - // OpenOffice/LibreOffice - if (OS.WINDOWS) { - defaults.put(OO_PATH, OpenOfficePreferences.DEFAULT_WINDOWS_PATH); - defaults.put(OO_EXECUTABLE_PATH, OpenOfficePreferences.DEFAULT_WIN_EXEC_PATH); - defaults.put(OO_JARS_PATH, OpenOfficePreferences.DEFAULT_WINDOWS_PATH); - } else if (OS.OS_X) { - defaults.put(OO_PATH, OpenOfficePreferences.DEFAULT_OSX_PATH); - defaults.put(OO_EXECUTABLE_PATH, OpenOfficePreferences.DEFAULT_OSX_EXEC_PATH); - defaults.put(OO_JARS_PATH, OpenOfficePreferences.DEFAULT_OSX_PATH); - } else { // Linux - defaults.put(OO_PATH, OpenOfficePreferences.DEFAULT_LINUX_PATH); - defaults.put(OO_EXECUTABLE_PATH, OpenOfficePreferences.DEFAULT_LINUX_EXEC_PATH); - defaults.put(OO_JARS_PATH, OpenOfficePreferences.DEFAULT_LINUX_PATH); - } - - defaults.put(OO_SYNC_WHEN_CITING, Boolean.FALSE); - defaults.put(OO_SHOW_PANEL, Boolean.FALSE); - defaults.put(OO_USE_ALL_OPEN_BASES, Boolean.TRUE); - defaults.put(OO_BIBLIOGRAPHY_STYLE_FILE, StyleLoader.DEFAULT_AUTHORYEAR_STYLE_PATH); - defaults.put(OO_EXTERNAL_STYLE_FILES, ""); - defaults.put(STYLES_POS_X, 0); - defaults.put(STYLES_POS_Y, 0); - defaults.put(STYLES_SIZE_X, 600); - defaults.put(STYLES_SIZE_Y, 400); - - defaults.put(SPECIALFIELDSENABLED, Boolean.TRUE); - defaults.put(SHOWCOLUMN_PRIORITY, Boolean.FALSE); - defaults.put(SHOWCOLUMN_QUALITY, Boolean.FALSE); - defaults.put(SHOWCOLUMN_RANKING, Boolean.TRUE); - defaults.put(SHOWCOLUMN_RELEVANCE, Boolean.FALSE); - defaults.put(SHOWCOLUMN_PRINTED, Boolean.FALSE); - defaults.put(SHOWCOLUMN_READ, Boolean.FALSE); - defaults.put(AUTOSYNCSPECIALFIELDSTOKEYWORDS, Boolean.TRUE); - defaults.put(SERIALIZESPECIALFIELDS, Boolean.FALSE); - - defaults.put(USE_OWNER, Boolean.FALSE); - defaults.put(OVERWRITE_OWNER, Boolean.FALSE); - defaults.put(AVOID_OVERWRITING_KEY, Boolean.FALSE); - defaults.put(WARN_BEFORE_OVERWRITING_KEY, Boolean.TRUE); - defaults.put(CONFIRM_DELETE, Boolean.TRUE); - defaults.put(GRAY_OUT_NON_HITS, Boolean.TRUE); - defaults.put(DEFAULT_BIBTEX_KEY_PATTERN, "[auth][year]"); - defaults.put(DO_NOT_RESOLVE_STRINGS_FOR, FieldName.URL); - defaults.put(RESOLVE_STRINGS_ALL_FIELDS, Boolean.FALSE); - defaults.put(NON_WRAPPABLE_FIELDS, "pdf;ps;url;doi;file;isbn;issn"); - defaults.put(GENERATE_KEYS_AFTER_INSPECTION, Boolean.TRUE); - defaults.put(WARN_ABOUT_DUPLICATES_IN_INSPECTION, Boolean.TRUE); - defaults.put(USE_TIME_STAMP, Boolean.FALSE); - defaults.put(OVERWRITE_TIME_STAMP, Boolean.FALSE); - - // default time stamp follows ISO-8601. Reason: https://xkcd.com/1179/ - defaults.put(TIME_STAMP_FORMAT, "yyyy-MM-dd"); - - defaults.put(TIME_STAMP_FIELD, FieldName.TIMESTAMP); - defaults.put(UPDATE_TIMESTAMP, Boolean.FALSE); - - defaults.put(GENERATE_KEYS_BEFORE_SAVING, Boolean.FALSE); - - defaults.put(USE_REMOTE_SERVER, Boolean.TRUE); - defaults.put(REMOTE_SERVER_PORT, 6050); - - defaults.put(PERSONAL_JOURNAL_LIST, ""); - defaults.put(EXTERNAL_JOURNAL_LISTS, ""); - defaults.put(CITE_COMMAND, "\\cite"); // obsoleted by the app-specific ones (not any more?) - - defaults.put(LAST_USED_EXPORT, ""); - defaults.put(SIDE_PANE_WIDTH, 0.15); - - defaults.put(MAIN_FONT_SIZE, 9); - defaults.put(OVERRIDE_DEFAULT_FONT_SIZE, false); - - defaults.put(IMPORT_INSPECTION_DIALOG_WIDTH, 650); - defaults.put(IMPORT_INSPECTION_DIALOG_HEIGHT, 650); - defaults.put(SHOW_FILE_LINKS_UPGRADE_WARNING, Boolean.TRUE); - defaults.put(AUTOLINK_EXACT_KEY_ONLY, Boolean.FALSE); - defaults.put(NUMERIC_FIELDS, "mittnum;author"); - defaults.put(RUN_AUTOMATIC_FILE_SEARCH, Boolean.FALSE); - defaults.put(LOCAL_AUTO_SAVE, Boolean.FALSE); - defaults.put(ENFORCE_LEGAL_BIBTEX_KEY, Boolean.TRUE); - // Curly brackets ({}) are the default delimiters, not quotes (") as these cause trouble when they appear within the field value: - // Currently, JabRef does not escape them - defaults.put(KEY_GEN_FIRST_LETTER_A, Boolean.TRUE); - defaults.put(KEY_GEN_ALWAYS_ADD_LETTER, Boolean.FALSE); - defaults.put(EMAIL_SUBJECT, Localization.lang("References")); - defaults.put(OPEN_FOLDERS_OF_ATTACHED_FILES, Boolean.FALSE); - defaults.put(ALLOW_FILE_AUTO_OPEN_BROWSE, Boolean.TRUE); - defaults.put(WEB_SEARCH_VISIBLE, Boolean.TRUE); - defaults.put(GROUP_SIDEPANE_VISIBLE, Boolean.TRUE); - defaults.put(SELECTED_FETCHER_INDEX, 0); - defaults.put(BIB_LOC_AS_PRIMARY_DIR, Boolean.FALSE); - defaults.put(DB_CONNECT_SERVER_TYPE, "MySQL"); - defaults.put(DB_CONNECT_HOSTNAME, "localhost"); - defaults.put(DB_CONNECT_DATABASE, "jabref"); - defaults.put(DB_CONNECT_USERNAME, "root"); - defaults.put(COLLECT_TELEMETRY, Boolean.FALSE); - defaults.put(ALREADY_ASKED_TO_COLLECT_TELEMETRY, Boolean.FALSE); - - defaults.put(ASK_AUTO_NAMING_PDFS_AGAIN, Boolean.TRUE); - insertDefaultCleanupPreset(defaults); - - // defaults for DroppedFileHandler UI - defaults.put(DROPPEDFILEHANDLER_LEAVE, Boolean.FALSE); - defaults.put(DROPPEDFILEHANDLER_COPY, Boolean.TRUE); - defaults.put(DROPPEDFILEHANDLER_MOVE, Boolean.FALSE); - defaults.put(DROPPEDFILEHANDLER_RENAME, Boolean.FALSE); - - defaults.put(IMPORT_ALWAYSUSE, Boolean.FALSE); - defaults.put(IMPORT_DEFAULT_PDF_IMPORT_STYLE, ImportSettingsTab.DEFAULT_STYLE); - - // use BibTeX key appended with filename as default pattern - defaults.put(IMPORT_FILENAMEPATTERN, ImportSettingsTab.DEFAULT_FILENAMEPATTERNS[1]); - //Default empty String to be backwards compatible - defaults.put(IMPORT_FILEDIRPATTERN, ""); - - customExports = new CustomExportList(new ExportComparator()); - customImports = new CustomImportList(this); - - String defaultExpression = "**/.*[bibtexkey].*\\\\.[extension]"; - defaults.put(AUTOLINK_REG_EXP_SEARCH_EXPRESSION_KEY, defaultExpression); - defaults.put(AUTOLINK_USE_REG_EXP_SEARCH_KEY, Boolean.FALSE); - defaults.put(USE_IEEE_ABRV, Boolean.FALSE); - defaults.put(USE_CASE_KEEPER_ON_SEARCH, Boolean.TRUE); - defaults.put(USE_UNIT_FORMATTER_ON_SEARCH, Boolean.TRUE); - - defaults.put(USE_DEFAULT_CONSOLE_APPLICATION, Boolean.TRUE); - if (OS.WINDOWS) { - defaults.put(CONSOLE_COMMAND, "C:\\Program Files\\ConEmu\\ConEmu64.exe /single /dir \"%DIR\""); - defaults.put(ADOBE_ACROBAT_COMMAND, "C:\\Program Files (x86)\\Adobe\\Acrobat Reader DC\\Reader"); - defaults.put(SUMATRA_PDF_COMMAND, "C:\\Program Files\\SumatraPDF"); - defaults.put(USE_PDF_READER, ADOBE_ACROBAT_COMMAND); - } else { - defaults.put(CONSOLE_COMMAND, ""); - defaults.put(ADOBE_ACROBAT_COMMAND, ""); - defaults.put(SUMATRA_PDF_COMMAND, ""); - defaults.put(USE_PDF_READER, ""); - } - - //versioncheck defaults - defaults.put(VERSION_IGNORED_UPDATE, ""); - - // preview - defaults.put(CYCLE_PREVIEW, "Preview;" + CitationStyle.DEFAULT); - defaults.put(CYCLE_PREVIEW_POS, 0); - defaults.put(PREVIEW_PANEL_HEIGHT, 0.65); - defaults.put(PREVIEW_ENABLED, Boolean.TRUE); - defaults.put(PREVIEW_STYLE, - "" - + "\\bibtextype\\begin{bibtexkey} (\\bibtexkey)" - + "\\end{bibtexkey}
__NEWLINE__" - + "\\begin{author} \\format[Authors(LastFirst,Initials,Semicolon,Amp),HTMLChars]{\\author}
\\end{author}__NEWLINE__" - + "\\begin{editor} \\format[Authors(LastFirst,Initials,Semicolon,Amp),HTMLChars]{\\editor} " - + "(\\format[IfPlural(Eds.,Ed.)]{\\editor})
\\end{editor}__NEWLINE__" - + "\\begin{title} \\format[HTMLChars]{\\title} \\end{title}
__NEWLINE__" - + "\\begin{chapter} \\format[HTMLChars]{\\chapter}
\\end{chapter}__NEWLINE__" - + "\\begin{journal} \\format[HTMLChars]{\\journal}, \\end{journal}__NEWLINE__" - // Include the booktitle field for @inproceedings, @proceedings, etc. - + "\\begin{booktitle} \\format[HTMLChars]{\\booktitle}, \\end{booktitle}__NEWLINE__" - + "\\begin{school} \\format[HTMLChars]{\\school}, \\end{school}__NEWLINE__" - + "\\begin{institution} \\format[HTMLChars]{\\institution}, \\end{institution}__NEWLINE__" - + "\\begin{publisher} \\format[HTMLChars]{\\publisher}, \\end{publisher}__NEWLINE__" - + "\\begin{year}\\year\\end{year}\\begin{volume}, \\volume\\end{volume}" - + "\\begin{pages}, \\format[FormatPagesForHTML]{\\pages} \\end{pages}__NEWLINE__" - + "\\begin{abstract}

Abstract: \\format[HTMLChars]{\\abstract} \\end{abstract}__NEWLINE__" - + "\\begin{comment}

Comment: \\format[HTMLChars]{\\comment} \\end{comment}" - + "__NEWLINE__

"); - - setLanguageDependentDefaultValues(); - } - - public static JabRefPreferences getInstance() { - if (JabRefPreferences.singleton == null) { - JabRefPreferences.singleton = new JabRefPreferences(); - } - return JabRefPreferences.singleton; - } - - private static String convertListToString(List value) { - return value.stream().map(val -> StringUtil.quote(val, ";", '\\')).collect(Collectors.joining(";")); - } - - /** - * Looks up a color definition in preferences, and returns an array containing the RGB values. - * - * @param value The key for this setting. - * @return The RGB values corresponding to this color setting. - */ - private static int[] getRgb(String value) { - int[] values = new int[3]; - - if ((value != null) && !value.isEmpty()) { - String[] elements = value.split(":"); - values[0] = Integer.parseInt(elements[0]); - values[1] = Integer.parseInt(elements[1]); - values[2] = Integer.parseInt(elements[2]); - } else { - values[0] = 0; - values[1] = 0; - values[2] = 0; - } - return values; - } - - private static Preferences getPrefsNodeForCustomizedEntryTypes(BibDatabaseMode mode) { - if (mode == BibDatabaseMode.BIBLATEX) { - return Preferences.userNodeForPackage(PREFS_BASE_CLASS).node(CUSTOMIZED_BIBLATEX_TYPES); - } - if (mode == BibDatabaseMode.BIBTEX) { - return Preferences.userNodeForPackage(PREFS_BASE_CLASS).node(CUSTOMIZED_BIBTEX_TYPES); - } - - throw new IllegalArgumentException("Unknown BibDatabaseMode: " + mode); - } - - private static Optional getNextUnit(Reader data) throws IOException { - // character last read - // -1 if end of stream - // initialization necessary, because of Java compiler - int c = -1; - - // last character was escape symbol - boolean escape = false; - - // true if a ";" is found - boolean done = false; - - StringBuilder res = new StringBuilder(); - while (!done && ((c = data.read()) != -1)) { - if (c == '\\') { - if (escape) { - escape = false; - res.append('\\'); - } else { - escape = true; - } - } else { - if (c == ';') { - if (escape) { - res.append(';'); - } else { - done = true; - } - } else { - res.append((char) c); - } - escape = false; - } - } - if (res.length() > 0) { - return Optional.of(res.toString()); - } else if (c == -1) { - // end of stream - return Optional.empty(); - } else { - return Optional.of(""); - } - } - - private static void insertDefaultCleanupPreset(Map storage) { - EnumSet deactivatedJobs = EnumSet.of( - CleanupPreset.CleanupStep.CLEAN_UP_UPGRADE_EXTERNAL_LINKS, - CleanupPreset.CleanupStep.MOVE_PDF, - CleanupPreset.CleanupStep.RENAME_PDF_ONLY_RELATIVE_PATHS, - CleanupPreset.CleanupStep.CONVERT_TO_BIBLATEX, - CleanupPreset.CleanupStep.CONVERT_TO_BIBTEX); - - CleanupPreset preset = new CleanupPreset(EnumSet.complementOf(deactivatedJobs), Cleanups.DEFAULT_SAVE_ACTIONS); - - storage.put(CLEANUP_DOI, preset.isCleanUpDOI()); - storage.put(CLEANUP_ISSN, preset.isCleanUpISSN()); - storage.put(CLEANUP_MOVE_PDF, preset.isMovePDF()); - storage.put(CLEANUP_MAKE_PATHS_RELATIVE, preset.isMakePathsRelative()); - storage.put(CLEANUP_RENAME_PDF, preset.isRenamePDF()); - storage.put(CLEANUP_RENAME_PDF_ONLY_RELATIVE_PATHS, preset.isRenamePdfOnlyRelativePaths()); - storage.put(CLEANUP_UPGRADE_EXTERNAL_LINKS, preset.isCleanUpUpgradeExternalLinks()); - storage.put(CLEANUP_CONVERT_TO_BIBLATEX, preset.isConvertToBiblatex()); - storage.put(CLEANUP_CONVERT_TO_BIBTEX, preset.isConvertToBibtex()); - storage.put(CLEANUP_FIX_FILE_LINKS, preset.isFixFileLinks()); - storage.put(CLEANUP_FORMATTERS, convertListToString(preset.getFormatterCleanups().getAsStringList(OS.NEWLINE))); - } - - public EntryEditorPreferences getEntryEditorPreferences() { - return new EntryEditorPreferences(getEntryEditorTabList(), -<<<<<<< HEAD - getLatexFieldFormatterPreferences(), - getImportFormatPreferences(), - getCustomTabFieldNames(), - getBoolean(SHOW_RECOMMENDATIONS), - getBoolean(ACCEPT_RECOMMENDATIONS), - getBoolean(DEFAULT_SHOW_SOURCE), - getBibtexKeyPatternPreferences(), - Globals.getKeyPrefs(), - getBoolean(AVOID_OVERWRITING_KEY)); -======= - getLatexFieldFormatterPreferences(), - getImportFormatPreferences(), - getCustomTabFieldNames(), - getBoolean(SHOW_RECOMMENDATIONS), - getBoolean(DEFAULT_SHOW_SOURCE), - getBibtexKeyPatternPreferences(), - Globals.getKeyPrefs(), - getBoolean(AVOID_OVERWRITING_KEY)); ->>>>>>> master - } - - public Map getSidePanePreferredPositions() { - Map preferredPositions = new HashMap<>(); - - List componentNames = getStringList(SIDE_PANE_COMPONENT_NAMES); - List componentPositions = getStringList(SIDE_PANE_COMPONENT_PREFERRED_POSITIONS); - - for (int i = 0; i < componentNames.size(); ++i) { - String name = componentNames.get(i); - try { - SidePaneType type = Enum.valueOf(SidePaneType.class, name); - preferredPositions.put(type, Integer.parseInt(componentPositions.get(i))); - } catch (NumberFormatException e) { - LOGGER.debug("Invalid number format for side pane component '" + name + "'", e); - } catch (IllegalArgumentException e) { - LOGGER.debug("Following component is not a side pane: '" + name + "'", e); - } - } - - return preferredPositions; - } - - public String getUser() { - try { - return get(DEFAULT_OWNER) + '-' + InetAddress.getLocalHost().getHostName(); - } catch (UnknownHostException ex) { - LOGGER.debug("Hostname not found.", ex); - return get(DEFAULT_OWNER); - } - } - - /** - * Get a Map of default tab names to deafult tab fields. - * The fields are returned as a String with fields separated by ; - * They are combined into one string in order to feed into CustomizeGeneralFieldsDialogViewModel.resetFields() - * so that they do not have to be parsed in order to fit there - * - * @return A map of keys with tab names and values as a string containing - * fields for the given name separated by ; - */ - @Override - public Map getCustomTabsNamesAndFields() { - Map customTabsMap = new HashMap<>(); - - int defNumber = 0; - while (true) { - //Saved as CUSTOMTABNAME_def{number} and ; separated - String name = (String) defaults.get(CUSTOM_TAB_NAME + "_def" + defNumber); - String fields = (String) defaults.get(CUSTOM_TAB_FIELDS + "_def" + defNumber); - - if (StringUtil.isNullOrEmpty(name) || StringUtil.isNullOrEmpty(fields)) { - break; - } - customTabsMap.put(name, fields); - defNumber++; - } - return customTabsMap; - } - - @Override - public void setCustomTabsNameAndFields(String name, String fields, int defNumber) { - prefs.put(CUSTOM_TAB_NAME + defNumber, name); - prefs.put(CUSTOM_TAB_FIELDS + defNumber, fields); - } - - public List getCustomTabFieldNames() { - List customFields = new ArrayList<>(); - - int defNumber = 0; - while (true) { - // saved as CUSTOMTABNAME_def{number} and ; separated - String fields = (String) defaults.get(CUSTOM_TAB_FIELDS + "_def" + defNumber); - - if (StringUtil.isNullOrEmpty(fields)) { - break; - } - - customFields.addAll(Arrays.asList(fields.split(";"))); - defNumber++; - } - return customFields; - } - - public void setLanguageDependentDefaultValues() { - // Entry editor tab 0: - defaults.put(CUSTOM_TAB_NAME + "_def0", Localization.lang("General")); - String fieldNames = InternalBibtexFields.DEFAULT_GENERAL_FIELDS.stream().collect(Collectors.joining(";")); - defaults.put(CUSTOM_TAB_FIELDS + "_def0", fieldNames); - - // Entry editor tab 1: - defaults.put(CUSTOM_TAB_FIELDS + "_def1", FieldName.ABSTRACT); - defaults.put(CUSTOM_TAB_NAME + "_def1", Localization.lang("Abstract")); - - // Entry editor tab 2: Comments Field - used for research comments, etc. - defaults.put(CUSTOM_TAB_FIELDS + "_def2", FieldName.COMMENT); - defaults.put(CUSTOM_TAB_NAME + "_def2", Localization.lang("Comments")); - - defaults.put(EMAIL_SUBJECT, Localization.lang("References")); - } - - /** - * Check whether a key is set (differently from null). - * - * @param key The key to check. - * @return true if the key is set, false otherwise. - */ - public boolean hasKey(String key) { - return prefs.get(key, null) != null; - } - - public String get(String key) { - return prefs.get(key, (String) defaults.get(key)); - } - - public Optional getAsOptional(String key) { - return Optional.ofNullable(prefs.get(key, (String) defaults.get(key))); - } - - public String get(String key, String def) { - return prefs.get(key, def); - } - - public boolean getBoolean(String key) { - return prefs.getBoolean(key, getBooleanDefault(key)); - } - - public boolean getBoolean(String key, boolean def) { - return prefs.getBoolean(key, def); - } - - private boolean getBooleanDefault(String key) { - return (Boolean) defaults.get(key); - } - - public int getInt(String key) { - return prefs.getInt(key, getIntDefault(key)); - } - - public double getDouble(String key) { - return prefs.getDouble(key, getDoubleDefault(key)); - } - - public int getIntDefault(String key) { - return (Integer) defaults.get(key); - } - - private double getDoubleDefault(String key) { - return ((Number) defaults.get(key)).doubleValue(); - } - - public void put(String key, String value) { - prefs.put(key, value); - } - - public void putBoolean(String key, boolean value) { - prefs.putBoolean(key, value); - } - - public void putInt(String key, int value) { - prefs.putInt(key, value); - } - - public void putInt(String key, Number value) { - prefs.putInt(key, value.intValue()); - } - - public void putDouble(String key, double value) { - prefs.putDouble(key, value); - } - - public void remove(String key) { - prefs.remove(key); - } - - /** - * Puts a list of strings into the Preferences, by linking its elements with ';' into a single string. Escape - * characters make the process transparent even if strings contain ';'. - */ - public void putStringList(String key, List value) { - if (value == null) { - remove(key); - return; - } - - put(key, convertListToString(value)); - } - - /** - * Returns a List of Strings containing the chosen columns. - */ - public List getStringList(String key) { - String names = get(key); - if (names == null) { - return new ArrayList<>(); - } - - StringReader rd = new StringReader(names); - List res = new ArrayList<>(); - Optional rs; - try { - while ((rs = getNextUnit(rd)).isPresent()) { - res.add(rs.get()); - } - } catch (IOException ignored) { - // Ignored - } - return res; - } - - /** - * Looks up a color definition in preferences, and returns the Color object. - * - * @param key The key for this setting. - * @return The color corresponding to the setting. - */ - public Color getColor(String key) { - String value = get(key); - int[] rgb = getRgb(value); - return new Color(rgb[0], rgb[1], rgb[2]); - } - - public Color getDefaultColor(String key) { - String value = (String) defaults.get(key); - int[] rgb = getRgb(value); - return new Color(rgb[0], rgb[1], rgb[2]); - } - - /** - * Returns the default BibDatabase mode, which can be either BIBTEX or BIBLATEX. - * - * @return the default BibDatabaseMode - */ - public BibDatabaseMode getDefaultBibDatabaseMode() { - if (getBoolean(BIBLATEX_DEFAULT_MODE)) { - return BibDatabaseMode.BIBLATEX; - } else { - return BibDatabaseMode.BIBTEX; - } - } - - /** - * Set the default value for a key. This is useful for plugins that need to add default values for the prefs keys - * they use. - * - * @param key The preferences key. - * @param value The default value. - */ - public void putDefaultValue(String key, Object value) { - defaults.put(key, value); - } - - /** - * Stores a color in preferences. - * - * @param key The key for this setting. - * @param color The Color to store. - */ - public void putColor(String key, Color color) { - String rgb = String.valueOf(color.getRed()) + ':' + color.getGreen() + ':' + color.getBlue(); - put(key, rgb); - } - - /** - * Clear all preferences. - * - * @throws BackingStoreException - */ - public void clear() throws BackingStoreException { - clearAllCustomEntryTypes(); - clearKeyPatterns(); - prefs.clear(); - new SharedDatabasePreferences().clear(); - } - - public void clear(String key) { - prefs.remove(key); - } - - /** - * Calling this method will write all preferences into the preference store. - */ - public void flush() { - if (getBoolean(MEMORY_STICK_MODE)) { - try { - exportPreferences("jabref.xml"); - } catch (JabRefException e) { - LOGGER.warn("Could not export preferences for memory stick mode: " + e.getMessage(), e); - } - } - try { - prefs.flush(); - } catch (BackingStoreException ex) { - LOGGER.warn("Cannot communicate with backing store", ex); - } - } - - /** - * Fetches key patterns from preferences. - * The implementation doesn't cache the results - * - * @return LabelPattern containing all keys. Returned LabelPattern has no parent - */ - public GlobalBibtexKeyPattern getKeyPattern() { - keyPattern = GlobalBibtexKeyPattern.fromPattern(get(DEFAULT_BIBTEX_KEY_PATTERN)); - Preferences pre = Preferences.userNodeForPackage(PREFS_BASE_CLASS).node(BIBTEX_KEY_PATTERNS_NODE); - try { - String[] keys = pre.keys(); - if (keys.length > 0) { - for (String key : keys) { - keyPattern.addBibtexKeyPattern(key, pre.get(key, null)); - } - } - } catch (BackingStoreException ex) { - LOGGER.info("BackingStoreException in JabRefPreferences.getKeyPattern", ex); - } - return keyPattern; - } - - /** - * Adds the given key pattern to the preferences - * - * @param pattern the pattern to store - */ - public void putKeyPattern(GlobalBibtexKeyPattern pattern) { - keyPattern = pattern; - - // Store overridden definitions to Preferences. - Preferences pre = Preferences.userNodeForPackage(PREFS_BASE_CLASS).node(BIBTEX_KEY_PATTERNS_NODE); - try { - pre.clear(); // We remove all old entries. - } catch (BackingStoreException ex) { - LOGGER.info("BackingStoreException in JabRefPreferences.putKeyPattern", ex); - } - - Set allKeys = pattern.getAllKeys(); - for (String key : allKeys) { - if (!pattern.isDefaultValue(key)) { - // no default value - // the first entry in the array is the full pattern - // see org.jabref.logic.labelPattern.BibtexKeyGenerator.split(String) - pre.put(key, pattern.getValue(key).get(0)); - } - } - } - - private void clearKeyPatterns() throws BackingStoreException { - Preferences pre = Preferences.userNodeForPackage(PREFS_BASE_CLASS).node(BIBTEX_KEY_PATTERNS_NODE); - pre.clear(); - } - - public void storeCustomEntryTypes(List customEntryTypes, BibDatabaseMode bibDatabaseMode) { - Preferences prefsNode = getPrefsNodeForCustomizedEntryTypes(bibDatabaseMode); - - try { - // clear old custom types - clearCustomEntryTypes(bibDatabaseMode); - - // store current custom types - customEntryTypes.forEach(type -> prefsNode.put(type.getName(), type.getAsString())); - - prefsNode.flush(); - } catch (BackingStoreException e) { - LOGGER.info("Updating stored custom entry types failed.", e); - } - } - - public List loadCustomEntryTypes(BibDatabaseMode bibDatabaseMode) { - List storedEntryTypes = new ArrayList<>(); - Preferences prefsNode = getPrefsNodeForCustomizedEntryTypes(bibDatabaseMode); - try { - Arrays.stream(prefsNode.keys()) - .map(key -> prefsNode.get(key, null)) - .filter(Objects::nonNull) - .forEach(typeString -> CustomEntryType.parse(typeString).ifPresent(storedEntryTypes::add)); - } catch (BackingStoreException e) { - LOGGER.info("Parsing customized entry types failed.", e); - } - return storedEntryTypes; - } - - private void clearAllCustomEntryTypes() throws BackingStoreException { - for (BibDatabaseMode mode : BibDatabaseMode.values()) { - clearCustomEntryTypes(mode); - } - } - - private void clearCustomEntryTypes(BibDatabaseMode mode) throws BackingStoreException { - Preferences prefsNode = getPrefsNodeForCustomizedEntryTypes(mode); - prefsNode.clear(); - } - - public Map getPreferences() { - Map result = new HashMap<>(); - try { - for (String key : this.prefs.keys()) { - Object value = getObject(key); - result.put(key, value); - } - } catch (BackingStoreException e) { - LOGGER.info("could not retrieve preference keys", e); - } - return result; - } - - private Object getObject(String key) { - try { - return this.get(key); - } catch (ClassCastException e) { - try { - return this.getBoolean(key); - } catch (ClassCastException e2) { - try { - return this.getInt(key); - } catch (ClassCastException e3) { - return this.getDouble(key); - } - } - } - } - - /** - * Removes all entries keyed by prefix+number, where number is equal to or higher than the given number. - * - * @param number or higher. - */ - @Override - public void purgeSeries(String prefix, int number) { - int n = number; - while (get(prefix + n) != null) { - remove(prefix + n); - n++; - } - } - - @Override - public Map> getEntryEditorTabList() { - if (tabList == null) { - updateEntryEditorTabList(); - } - return tabList; - } - - @Override - public Boolean getEnforceLegalKeys() { - return getBoolean(ENFORCE_LEGAL_BIBTEX_KEY); - } - - @Override - public void updateEntryEditorTabList() { - tabList = EntryEditorTabList.create(this); - } - - /** - * Exports Preferences to an XML file. - * - * @param filename String File to export to - */ - public void exportPreferences(String filename) throws JabRefException { - exportPreferences(Paths.get(filename)); - } - - public void exportPreferences(Path file) throws JabRefException { - try (OutputStream os = Files.newOutputStream(file)) { - prefs.exportSubtree(os); - } catch (BackingStoreException | IOException ex) { - throw new JabRefException("Could not export preferences", Localization.lang("Could not export preferences"), - ex); - } - } - - /** - * Imports Preferences from an XML file. - * - * @param filename String File to import from - * @throws JabRefException thrown if importing the preferences failed due to an InvalidPreferencesFormatException - * or an IOException - */ - public void importPreferences(String filename) throws JabRefException { - importPreferences(Paths.get(filename)); - } - - public void importPreferences(Path file) throws JabRefException { - try (InputStream is = Files.newInputStream(file)) { - Preferences.importPreferences(is); - } catch (InvalidPreferencesFormatException | IOException ex) { - throw new JabRefException("Could not import preferences", Localization.lang("Could not import preferences"), - ex); - } - } - - /** - * ONLY FOR TESTING! - * - * Do not use in production code. Otherwise the singleton pattern is broken and preferences might get lost. - * - * @param owPrefs - */ - public void overwritePreferences(JabRefPreferences owPrefs) { - singleton = owPrefs; - } - - public String getWrappedUsername() { - return '[' + get(DEFAULT_OWNER) + ']'; - } - - public Charset getDefaultEncoding() { - return Charset.forName(get(DEFAULT_ENCODING)); - } - - public void setDefaultEncoding(Charset encoding) { - put(DEFAULT_ENCODING, encoding.name()); - } - - public FileHistory getFileHistory() { - return new FileHistory(getStringList(RECENT_DATABASES).stream().map(Paths::get).collect(Collectors.toList())); - } - - public void storeFileHistory(FileHistory history) { - if (!history.isEmpty()) { - putStringList(RECENT_DATABASES, history.getHistory().stream().map(Path::toAbsolutePath).map(Path::toString).collect(Collectors.toList())); - } - } - - @Override - public FilePreferences getFilePreferences() { - Map fieldDirectories = Stream.of(FieldName.FILE, FieldName.PDF, FieldName.PS) - .collect(Collectors.toMap(field -> field, field -> get(field + FilePreferences.DIR_SUFFIX, ""))); - return new FilePreferences( - getUser(), - fieldDirectories, - getBoolean(JabRefPreferences.BIB_LOC_AS_PRIMARY_DIR), - get(IMPORT_FILENAMEPATTERN), - get(IMPORT_FILEDIRPATTERN)); - } - - public UpdateFieldPreferences getUpdateFieldPreferences() { - return new UpdateFieldPreferences(getBoolean(USE_OWNER), getBoolean(OVERWRITE_OWNER), get(DEFAULT_OWNER), - getBoolean(USE_TIME_STAMP), getBoolean(OVERWRITE_TIME_STAMP), get(TIME_STAMP_FIELD), - get(TIME_STAMP_FORMAT)); - } - - public LatexFieldFormatterPreferences getLatexFieldFormatterPreferences() { - return new LatexFieldFormatterPreferences(getBoolean(RESOLVE_STRINGS_ALL_FIELDS), - getStringList(DO_NOT_RESOLVE_STRINGS_FOR), getFieldContentParserPreferences()); - } - - public FieldContentParserPreferences getFieldContentParserPreferences() { - return new FieldContentParserPreferences(getStringList(NON_WRAPPABLE_FIELDS)); - } - - public boolean isKeywordSyncEnabled() { - return getBoolean(JabRefPreferences.SPECIALFIELDSENABLED) - && getBoolean(JabRefPreferences.AUTOSYNCSPECIALFIELDSTOKEYWORDS); - } - - public ImportFormatPreferences getImportFormatPreferences() { - return new ImportFormatPreferences(customImports, getDefaultEncoding(), getKeywordDelimiter(), - getBibtexKeyPatternPreferences(), getFieldContentParserPreferences(), getXMPPreferences(), - isKeywordSyncEnabled()); - } - - public SavePreferences loadForExportFromPreferences() { - Boolean saveInOriginalOrder = this.getBoolean(JabRefPreferences.EXPORT_IN_ORIGINAL_ORDER); - SaveOrderConfig saveOrder = null; - if (!saveInOriginalOrder) { - if (this.getBoolean(JabRefPreferences.EXPORT_IN_SPECIFIED_ORDER)) { - saveOrder = this.loadExportSaveOrder(); - } else { - saveOrder = this.loadTableSaveOrder(); - } - } - return new SavePreferences( - saveInOriginalOrder, - saveOrder, - this.getDefaultEncoding(), - this.getBoolean(JabRefPreferences.BACKUP), - SavePreferences.DatabaseSaveType.ALL, - false, - this.getBoolean(JabRefPreferences.REFORMAT_FILE_ON_SAVE_AND_EXPORT), - this.getLatexFieldFormatterPreferences(), - this.getKeyPattern(), - getBoolean(JabRefPreferences.GENERATE_KEYS_BEFORE_SAVING), - getBibtexKeyPatternPreferences()); - } - - public SavePreferences loadForSaveFromPreferences() { - return new SavePreferences( - false, - null, - this.getDefaultEncoding(), - this.getBoolean(JabRefPreferences.BACKUP), - SavePreferences.DatabaseSaveType.ALL, - true, - this.getBoolean(JabRefPreferences.REFORMAT_FILE_ON_SAVE_AND_EXPORT), - this.getLatexFieldFormatterPreferences(), - this.getKeyPattern(), - getBoolean(JabRefPreferences.GENERATE_KEYS_BEFORE_SAVING), - getBibtexKeyPatternPreferences()); - } - - public ExporterFactory getExporterFactory(JournalAbbreviationLoader abbreviationLoader) { - Map customFormats = this.customExports.getCustomExportFormats(this, abbreviationLoader); - LayoutFormatterPreferences layoutPreferences = this.getLayoutFormatterPreferences(abbreviationLoader); - SavePreferences savePreferences = this.loadForExportFromPreferences(); - XmpPreferences xmpPreferences = this.getXMPPreferences(); - return ExporterFactory.create(customFormats, layoutPreferences, savePreferences, xmpPreferences); - } - - public BibtexKeyPatternPreferences getBibtexKeyPatternPreferences() { - return new BibtexKeyPatternPreferences( - get(KEY_PATTERN_REGEX), - get(KEY_PATTERN_REPLACEMENT), - getBoolean(KEY_GEN_ALWAYS_ADD_LETTER), - getBoolean(KEY_GEN_FIRST_LETTER_A), - getBoolean(ENFORCE_LEGAL_BIBTEX_KEY), - getKeyPattern(), - getKeywordDelimiter()); - } - - public TimestampPreferences getTimestampPreferences() { - return new TimestampPreferences(getBoolean(USE_TIME_STAMP), getBoolean(UPDATE_TIMESTAMP), get(TIME_STAMP_FIELD), get(TIME_STAMP_FORMAT), getBoolean(OVERWRITE_TIME_STAMP)); - } - - public LayoutFormatterPreferences getLayoutFormatterPreferences( - JournalAbbreviationLoader journalAbbreviationLoader) { - Objects.requireNonNull(journalAbbreviationLoader); - return new LayoutFormatterPreferences(getNameFormatterPreferences(), getJournalAbbreviationPreferences(), - getFileLinkPreferences(), journalAbbreviationLoader); - } - - public XmpPreferences getXMPPreferences() { - return new XmpPreferences(getBoolean(USE_XMP_PRIVACY_FILTER), getStringList(XMP_PRIVACY_FILTERS), - getKeywordDelimiter()); - } - - public OpenOfficePreferences getOpenOfficePreferences() { - return new OpenOfficePreferences( - this.get(JabRefPreferences.OO_JARS_PATH), - this.get(JabRefPreferences.OO_EXECUTABLE_PATH), - this.get(JabRefPreferences.OO_PATH), - this.getBoolean(JabRefPreferences.OO_USE_ALL_OPEN_BASES), - this.getBoolean(JabRefPreferences.OO_SYNC_WHEN_CITING), - this.getBoolean(JabRefPreferences.OO_SHOW_PANEL), - this.getStringList(JabRefPreferences.OO_EXTERNAL_STYLE_FILES), - this.get(JabRefPreferences.OO_BIBLIOGRAPHY_STYLE_FILE)); - } - - public void setOpenOfficePreferences(OpenOfficePreferences openOfficePreferences) { - this.put(JabRefPreferences.OO_JARS_PATH, openOfficePreferences.getJarsPath()); - this.put(JabRefPreferences.OO_EXECUTABLE_PATH, openOfficePreferences.getExecutablePath()); - this.put(JabRefPreferences.OO_PATH, openOfficePreferences.getInstallationPath()); - this.putBoolean(JabRefPreferences.OO_USE_ALL_OPEN_BASES, openOfficePreferences.getUseAllDatabases()); - this.putBoolean(JabRefPreferences.OO_SYNC_WHEN_CITING, openOfficePreferences.getSyncWhenCiting()); - this.putBoolean(JabRefPreferences.OO_SHOW_PANEL, openOfficePreferences.getShowPanel()); - this.putStringList(JabRefPreferences.OO_EXTERNAL_STYLE_FILES, openOfficePreferences.getExternalStyles()); - this.put(JabRefPreferences.OO_BIBLIOGRAPHY_STYLE_FILE, openOfficePreferences.getCurrentStyle()); - } - - private NameFormatterPreferences getNameFormatterPreferences() { - return new NameFormatterPreferences(getStringList(NAME_FORMATER_KEY), getStringList(NAME_FORMATTER_VALUE)); - } - - public FileLinkPreferences getFileLinkPreferences() { - return new FileLinkPreferences( - Collections.singletonList(get(FieldName.FILE + FilePreferences.DIR_SUFFIX)), - fileDirForDatabase); - } - - public JabRefPreferences storeVersionPreferences(VersionPreferences versionPreferences) { - put(VERSION_IGNORED_UPDATE, versionPreferences.getIgnoredVersion().toString()); - return this; - } - - public VersionPreferences getVersionPreferences() { - Version ignoredVersion = Version.parse(get(VERSION_IGNORED_UPDATE)); - return new VersionPreferences(ignoredVersion); - } - - public JabRefPreferences storePreviewPreferences(PreviewPreferences previewPreferences) { - putInt(CYCLE_PREVIEW_POS, previewPreferences.getPreviewCyclePosition()); - putStringList(CYCLE_PREVIEW, previewPreferences.getPreviewCycle()); - putDouble(PREVIEW_PANEL_HEIGHT, previewPreferences.getPreviewPanelDividerPosition().doubleValue()); - put(PREVIEW_STYLE, previewPreferences.getPreviewStyle()); - putBoolean(PREVIEW_ENABLED, previewPreferences.isPreviewPanelEnabled()); - return this; - } - - public PreviewPreferences getPreviewPreferences() { - int cyclePos = getInt(CYCLE_PREVIEW_POS); - List cycle = getStringList(CYCLE_PREVIEW); - double panelHeight = getDouble(PREVIEW_PANEL_HEIGHT); - String style = get(PREVIEW_STYLE); - String styleDefault = (String) defaults.get(PREVIEW_STYLE); - boolean enabled = getBoolean(PREVIEW_ENABLED); - return new PreviewPreferences(cycle, cyclePos, panelHeight, enabled, style, styleDefault); - } - - public void storeProxyPreferences(ProxyPreferences proxyPreferences) { - putBoolean(PROXY_USE, proxyPreferences.isUseProxy()); - put(PROXY_HOSTNAME, proxyPreferences.getHostname()); - put(PROXY_PORT, proxyPreferences.getPort()); - putBoolean(PROXY_USE_AUTHENTICATION, proxyPreferences.isUseAuthentication()); - put(PROXY_USERNAME, proxyPreferences.getUsername()); - put(PROXY_PASSWORD, proxyPreferences.getPassword()); - } - - public ProxyPreferences getProxyPreferences() { - Boolean useProxy = getBoolean(PROXY_USE); - String hostname = get(PROXY_HOSTNAME); - String port = get(PROXY_PORT); - Boolean useAuthentication = getBoolean(PROXY_USE_AUTHENTICATION); - String username = get(PROXY_USERNAME); - String password = get(PROXY_PASSWORD); - return new ProxyPreferences(useProxy, hostname, port, useAuthentication, username, password); - } - - public ProtectedTermsPreferences getProtectedTermsPreferences() { - return new ProtectedTermsPreferences(getStringList(PROTECTED_TERMS_ENABLED_INTERNAL), - getStringList(PROTECTED_TERMS_ENABLED_EXTERNAL), getStringList(PROTECTED_TERMS_DISABLED_INTERNAL), - getStringList(PROTECTED_TERMS_DISABLED_EXTERNAL)); - } - - public void setProtectedTermsPreferences(ProtectedTermsLoader loader) { - List enabledExternalList = new ArrayList<>(); - List disabledExternalList = new ArrayList<>(); - List enabledInternalList = new ArrayList<>(); - List disabledInternalList = new ArrayList<>(); - - for (ProtectedTermsList list : loader.getProtectedTermsLists()) { - if (list.isInternalList()) { - if (list.isEnabled()) { - enabledInternalList.add(list.getLocation()); - } else { - disabledInternalList.add(list.getLocation()); - } - } else { - if (list.isEnabled()) { - enabledExternalList.add(list.getLocation()); - } else { - disabledExternalList.add(list.getLocation()); - } - } - } - - putStringList(PROTECTED_TERMS_ENABLED_EXTERNAL, enabledExternalList); - putStringList(PROTECTED_TERMS_DISABLED_EXTERNAL, disabledExternalList); - putStringList(PROTECTED_TERMS_ENABLED_INTERNAL, enabledInternalList); - putStringList(PROTECTED_TERMS_DISABLED_INTERNAL, disabledInternalList); - - } - - @Override - public JournalAbbreviationPreferences getJournalAbbreviationPreferences() { - return new JournalAbbreviationPreferences(getStringList(EXTERNAL_JOURNAL_LISTS), get(PERSONAL_JOURNAL_LIST), - getBoolean(USE_IEEE_ABRV), getDefaultEncoding()); - } - - public CleanupPreferences getCleanupPreferences(JournalAbbreviationLoader journalAbbreviationLoader) { - return new CleanupPreferences( - getLayoutFormatterPreferences(journalAbbreviationLoader), - getFilePreferences()); - } - - public CleanupPreset getCleanupPreset() { - Set activeJobs = EnumSet.noneOf(CleanupPreset.CleanupStep.class); - - if (this.getBoolean(JabRefPreferences.CLEANUP_DOI)) { - activeJobs.add(CleanupPreset.CleanupStep.CLEAN_UP_DOI); - } - if (this.getBoolean(JabRefPreferences.CLEANUP_ISSN)) { - activeJobs.add(CleanupPreset.CleanupStep.CLEAN_UP_ISSN); - } - if (this.getBoolean(JabRefPreferences.CLEANUP_MOVE_PDF)) { - activeJobs.add(CleanupPreset.CleanupStep.MOVE_PDF); - } - if (this.getBoolean(JabRefPreferences.CLEANUP_MAKE_PATHS_RELATIVE)) { - activeJobs.add(CleanupPreset.CleanupStep.MAKE_PATHS_RELATIVE); - } - if (this.getBoolean(JabRefPreferences.CLEANUP_RENAME_PDF)) { - activeJobs.add(CleanupPreset.CleanupStep.RENAME_PDF); - } - if (this.getBoolean(JabRefPreferences.CLEANUP_RENAME_PDF_ONLY_RELATIVE_PATHS)) { - activeJobs.add(CleanupPreset.CleanupStep.RENAME_PDF_ONLY_RELATIVE_PATHS); - } - if (this.getBoolean(JabRefPreferences.CLEANUP_UPGRADE_EXTERNAL_LINKS)) { - activeJobs.add(CleanupPreset.CleanupStep.CLEAN_UP_UPGRADE_EXTERNAL_LINKS); - } - if (this.getBoolean(JabRefPreferences.CLEANUP_CONVERT_TO_BIBLATEX)) { - activeJobs.add(CleanupPreset.CleanupStep.CONVERT_TO_BIBLATEX); - } - if (this.getBoolean(JabRefPreferences.CLEANUP_CONVERT_TO_BIBTEX)) { - activeJobs.add(CleanupPreset.CleanupStep.CONVERT_TO_BIBTEX); - } - if (this.getBoolean(JabRefPreferences.CLEANUP_FIX_FILE_LINKS)) { - activeJobs.add(CleanupPreset.CleanupStep.FIX_FILE_LINKS); - } - - FieldFormatterCleanups formatterCleanups = Cleanups.parse( - this.getStringList(JabRefPreferences.CLEANUP_FORMATTERS)); - - return new CleanupPreset(activeJobs, formatterCleanups); - } - - public void setCleanupPreset(CleanupPreset cleanupPreset) { - this.putBoolean(JabRefPreferences.CLEANUP_DOI, cleanupPreset.isActive(CleanupPreset.CleanupStep.CLEAN_UP_DOI)); - this.putBoolean(JabRefPreferences.CLEANUP_ISSN, cleanupPreset.isActive(CleanupPreset.CleanupStep.CLEAN_UP_ISSN)); - this.putBoolean(JabRefPreferences.CLEANUP_MOVE_PDF, cleanupPreset.isActive(CleanupPreset.CleanupStep.MOVE_PDF)); - this.putBoolean(JabRefPreferences.CLEANUP_MAKE_PATHS_RELATIVE, cleanupPreset.isActive(CleanupPreset.CleanupStep.MAKE_PATHS_RELATIVE)); - this.putBoolean(JabRefPreferences.CLEANUP_RENAME_PDF, cleanupPreset.isActive(CleanupPreset.CleanupStep.RENAME_PDF)); - this.putBoolean(JabRefPreferences.CLEANUP_RENAME_PDF_ONLY_RELATIVE_PATHS, - cleanupPreset.isActive(CleanupPreset.CleanupStep.RENAME_PDF_ONLY_RELATIVE_PATHS)); - this.putBoolean(JabRefPreferences.CLEANUP_UPGRADE_EXTERNAL_LINKS, - cleanupPreset.isActive(CleanupPreset.CleanupStep.CLEAN_UP_UPGRADE_EXTERNAL_LINKS)); - this.putBoolean(JabRefPreferences.CLEANUP_CONVERT_TO_BIBLATEX, cleanupPreset.isActive(CleanupPreset.CleanupStep.CONVERT_TO_BIBLATEX)); - this.putBoolean(JabRefPreferences.CLEANUP_CONVERT_TO_BIBTEX, cleanupPreset.isActive(CleanupPreset.CleanupStep.CONVERT_TO_BIBTEX)); - this.putBoolean(JabRefPreferences.CLEANUP_FIX_FILE_LINKS, cleanupPreset.isActive(CleanupPreset.CleanupStep.FIX_FILE_LINKS)); - this.putStringList(JabRefPreferences.CLEANUP_FORMATTERS, cleanupPreset.getFormatterCleanups().getAsStringList(OS.NEWLINE)); - } - - public RemotePreferences getRemotePreferences() { - return new RemotePreferences(getInt(REMOTE_SERVER_PORT), getBoolean(USE_REMOTE_SERVER)); - } - - public void setRemotePreferences(RemotePreferences remotePreferences) { - putInt(REMOTE_SERVER_PORT, remotePreferences.getPort()); - putBoolean(USE_REMOTE_SERVER, remotePreferences.useRemoteServer()); - } - - public void storeExportSaveOrder(SaveOrderConfig config) { - putBoolean(EXPORT_PRIMARY_SORT_DESCENDING, config.getSortCriteria().get(0).descending); - putBoolean(EXPORT_SECONDARY_SORT_DESCENDING, config.getSortCriteria().get(1).descending); - putBoolean(EXPORT_TERTIARY_SORT_DESCENDING, config.getSortCriteria().get(2).descending); - - put(EXPORT_PRIMARY_SORT_FIELD, config.getSortCriteria().get(0).field); - put(EXPORT_SECONDARY_SORT_FIELD, config.getSortCriteria().get(1).field); - put(EXPORT_TERTIARY_SORT_FIELD, config.getSortCriteria().get(2).field); - } - - private SaveOrderConfig loadTableSaveOrder() { - SaveOrderConfig config = new SaveOrderConfig(); - List columns = getStringList(COLUMN_IN_SORT_ORDER); - List sortTypes = getStringList(COlUMN_IN_SORT_ORDER_TYPE).stream().map(SortType::valueOf).map(type -> type == SortType.DESCENDING).collect(Collectors.toList()); - - for (int i = 0; i < columns.size(); i++) { - config.getSortCriteria().add(new SaveOrderConfig.SortCriterion(columns.get(i), sortTypes.get(i))); - } - - return config; - } - - public SaveOrderConfig loadExportSaveOrder() { - return new SaveOrderConfig(true, - new SaveOrderConfig.SortCriterion(get(EXPORT_PRIMARY_SORT_FIELD), getBoolean(EXPORT_PRIMARY_SORT_DESCENDING)), - new SaveOrderConfig.SortCriterion(get(EXPORT_SECONDARY_SORT_FIELD), getBoolean(EXPORT_SECONDARY_SORT_DESCENDING)), - new SaveOrderConfig.SortCriterion(get(EXPORT_TERTIARY_SORT_FIELD), getBoolean(EXPORT_TERTIARY_SORT_DESCENDING)) - ); - } - - public Character getKeywordDelimiter() { - return get(KEYWORD_SEPARATOR).charAt(0); - } - - public String getOrCreateUserId() { - Optional userId = getAsOptional(USER_ID); - if (userId.isPresent()) { - return userId.get(); - } else { - String newUserId = UUID.randomUUID().toString(); - put(USER_ID, newUserId); - return newUserId; - } - } - - public Boolean shouldCollectTelemetry() { - return getBoolean(COLLECT_TELEMETRY); - } - - public void setShouldCollectTelemetry(boolean value) { - putBoolean(COLLECT_TELEMETRY, value); - } - - public Boolean shouldAskToCollectTelemetry() { - return getBoolean(ALREADY_ASKED_TO_COLLECT_TELEMETRY); - } - - public void askedToCollectTelemetry() { - putBoolean(ALREADY_ASKED_TO_COLLECT_TELEMETRY, true); - } - - @Override - public void storeKeyBindingRepository(KeyBindingRepository keyBindingRepository) { - putStringList(JabRefPreferences.BIND_NAMES, keyBindingRepository.getBindNames()); - putStringList(JabRefPreferences.BINDINGS, keyBindingRepository.getBindings()); - } - - @Override - public KeyBindingRepository getKeyBindingRepository() { - return new KeyBindingRepository(getStringList(BIND_NAMES), getStringList(BINDINGS)); - } - - @Override - public void storeJournalAbbreviationPreferences(JournalAbbreviationPreferences abbreviationsPreferences) { - putStringList(JabRefPreferences.EXTERNAL_JOURNAL_LISTS, abbreviationsPreferences.getExternalJournalLists()); - putBoolean(JabRefPreferences.USE_IEEE_ABRV, abbreviationsPreferences.useIEEEAbbreviations()); - } - - public AutoLinkPreferences getAutoLinkPreferences() { - return new AutoLinkPreferences( - getBoolean(JabRefPreferences.AUTOLINK_USE_REG_EXP_SEARCH_KEY), - get(JabRefPreferences.AUTOLINK_REG_EXP_SEARCH_EXPRESSION_KEY), - getBoolean(JabRefPreferences.AUTOLINK_EXACT_KEY_ONLY), - getKeywordDelimiter()); - } - - public AutoCompletePreferences getAutoCompletePreferences() { - return new AutoCompletePreferences( - getBoolean(AUTO_COMPLETE), - AutoCompleteFirstNameMode.parse(get(AUTOCOMPLETER_FIRSTNAME_MODE)), - getBoolean(AUTOCOMPLETER_LAST_FIRST), - getBoolean(AUTOCOMPLETER_FIRST_LAST), - getStringList(AUTOCOMPLETER_COMPLETE_FIELDS), - getJournalAbbreviationPreferences()); - } - - public void storeAutoCompletePreferences(AutoCompletePreferences autoCompletePreferences) { - putBoolean(AUTO_COMPLETE, autoCompletePreferences.shouldAutoComplete()); - put(AUTOCOMPLETER_FIRSTNAME_MODE, autoCompletePreferences.getFirstNameMode().name()); - putBoolean(AUTOCOMPLETER_LAST_FIRST, autoCompletePreferences.getOnlyCompleteLastFirst()); - putBoolean(AUTOCOMPLETER_FIRST_LAST, autoCompletePreferences.getOnlyCompleteFirstLast()); - putStringList(AUTOCOMPLETER_COMPLETE_FIELDS, autoCompletePreferences.getCompleteFields()); - } - - public void storeSidePanePreferredPositions(Map preferredPositions) { - // Split the map into a pair of parallel String lists suitable for storage - List names = preferredPositions.keySet().stream() - .map(Enum::toString) - .collect(Collectors.toList()); - - List positions = preferredPositions.values().stream() - .map(integer -> Integer.toString(integer)) - .collect(Collectors.toList()); - - putStringList(SIDE_PANE_COMPONENT_NAMES, names); - putStringList(SIDE_PANE_COMPONENT_PREFERRED_POSITIONS, positions); - } - - private List createExtraFileColumns() { - if (getBoolean(EXTRA_FILE_COLUMNS)) { - return getStringList(LIST_OF_FILE_COLUMNS); - } else { - return Collections.emptyList(); - } - } - - private List createSpecialFieldColumns() { - if (getBoolean(SPECIALFIELDSENABLED)) { - List fieldsToShow = new ArrayList<>(); - if (getBoolean(SHOWCOLUMN_RANKING)) { - fieldsToShow.add(SpecialField.RANKING); - } - if (getBoolean(SHOWCOLUMN_RELEVANCE)) { - fieldsToShow.add(SpecialField.RELEVANCE); - } - if (getBoolean(SHOWCOLUMN_QUALITY)) { - fieldsToShow.add(SpecialField.QUALITY); - } - - if (getBoolean(SHOWCOLUMN_PRIORITY)) { - fieldsToShow.add(SpecialField.PRIORITY); - } - - if (getBoolean(SHOWCOLUMN_PRINTED)) { - fieldsToShow.add(SpecialField.PRINTED); - } - - if (getBoolean(SHOWCOLUMN_READ)) { - fieldsToShow.add(SpecialField.READ_STATUS); - } - return fieldsToShow; - } else { - return Collections.emptyList(); - } - } - - private Map createColumnWidths() { - List columns = getStringList(COLUMN_NAMES); - List widths = getStringList(COLUMN_WIDTHS) - .stream() - .map(string -> { - try { - return Double.parseDouble(string); - } catch (NumberFormatException e) { - LOGGER.error("Exception while parsing column widths. Choosing default.", e); - return BibtexSingleField.DEFAULT_FIELD_LENGTH; - } - }) - .collect(Collectors.toList()); - - Map map = new TreeMap<>(); - for (int i = 0; i < columns.size(); i++) { - map.put(columns.get(i), widths.get(i)); - } - return map; - } - - public ColumnPreferences getColumnPreferences() { - return new ColumnPreferences( - getBoolean(FILE_COLUMN), - getBoolean(URL_COLUMN), - getBoolean(PREFER_URL_DOI), - getBoolean(ARXIV_COLUMN), - getStringList(COLUMN_NAMES), - createSpecialFieldColumns(), - createExtraFileColumns(), - createColumnWidths(), - getMainTableColumnSortTypes()); - } - - public MainTablePreferences getMainTablePreferences() { - return new MainTablePreferences( - getColumnPreferences(), - getBoolean(AUTO_RESIZE_MODE)); - } - - @Override - public Path getWorkingDir() { - return Paths.get(get(WORKING_DIRECTORY)); - } - - @Override - public void setWorkingDir(Path dir) { - put(WORKING_DIRECTORY, dir.toString()); - - } - - public GroupViewMode getGroupViewMode() { - return GroupViewMode.valueOf(get(GROUP_INTERSECT_UNION_VIEW_MODE)); - } - - public void setGroupViewMode(GroupViewMode mode) { - put(GROUP_INTERSECT_UNION_VIEW_MODE, mode.name()); - } - - public void setPreviewStyle(String previewStyle) { - put(PREVIEW_STYLE, previewStyle); - } - - public String getPreviewStyle() { - return get(PREVIEW_STYLE); - } - - public Optional getFontSize() { - if (getBoolean(OVERRIDE_DEFAULT_FONT_SIZE)) { - return Optional.of(getInt(MAIN_FONT_SIZE)); - } else { - return Optional.empty(); - } - } - - public String setLastPreferencesExportPath() { - return get(PREFS_EXPORT_PATH); - } - - public void setLastPreferencesExportPath(Path exportFile) { - put(PREFS_EXPORT_PATH, exportFile.toString()); - } - - public Language getLanguage() { - String languageId = get(LANGUAGE); - return Stream.of(Language.values()) - .filter(language -> language.getId().equalsIgnoreCase(languageId)) - .findFirst() - .orElse(Language.English); - } - - public void setLanguage(Language language) { - Language oldLanguage = getLanguage(); - put(LANGUAGE, language.getId()); - if (language != oldLanguage) { - // Update any defaults that might be language dependent: - setLanguageDependentDefaultValues(); - } - } - - public void setIdBasedFetcherForEntryGenerator(String fetcherName) { - put(ID_ENTRY_GENERATOR, fetcherName); - } - - public String getIdBasedFetcherForEntryGenerator() { - return get(ID_ENTRY_GENERATOR); - } - - public void setMainTableColumnSortType(Map sortOrder) { - putStringList(COLUMN_IN_SORT_ORDER, new ArrayList<>(sortOrder.keySet())); - List sortTypes = sortOrder.values().stream().map(SortType::name).collect(Collectors.toList()); - putStringList(COlUMN_IN_SORT_ORDER_TYPE, sortTypes); - } - - public Map getMainTableColumnSortTypes() { - List columns = getStringList(COLUMN_IN_SORT_ORDER); - List sortTypes = getStringList(COlUMN_IN_SORT_ORDER_TYPE).stream().map(SortType::valueOf).collect(Collectors.toList()); - Map map = new LinkedHashMap<>(); - for (int i = 0; i < columns.size(); i++) { - map.put(columns.get(i), sortTypes.get(i)); - } - return map; - } - -} From 55ca6964b4a40177a36808645e47529c014eb777 Mon Sep 17 00:00:00 2001 From: conorfos Date: Thu, 27 Sep 2018 11:54:02 +0100 Subject: [PATCH 10/23] Fixed Codacy issues and removed abstracts from tests Removed html representation test Removed abstracts from tests --- .../gui/entryeditor/RelatedArticlesTab.java | 2 +- .../importer/fileformat/MrDLibImporter.java | 31 ++++++------------- .../fileformat/MrDLibImporterTest.java | 16 ++-------- 3 files changed, 13 insertions(+), 36 deletions(-) diff --git a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java index 95b83787acb..b802b3ddd0b 100644 --- a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java @@ -34,8 +34,8 @@ */ public class RelatedArticlesTab extends EntryEditorTab { - private final EntryEditorPreferences preferences; private static final Logger LOGGER = LoggerFactory.getLogger(RelatedArticlesTab.class); + private final EntryEditorPreferences preferences; public RelatedArticlesTab(EntryEditorPreferences preferences) { setText(Localization.lang("Related articles")); diff --git a/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java index 0d7454c4054..4a5bd332730 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java @@ -32,7 +32,6 @@ public class MrDLibImporter extends Importer { private static final Logger LOGGER = LoggerFactory.getLogger(MrDLibImporter.class); public ParserResult parserResult; - @SuppressWarnings("unused") @Override public boolean isRecognizedFormat(BufferedReader input) throws IOException { @@ -143,28 +142,14 @@ private void parse(BufferedReader input) throws IOException { */ private RankedBibEntry populateBibEntry(JSONObject recommendation) { BibEntry current = new BibEntry(); - String authors = "", title = "", year = "", journal = "", url = ""; - Integer rank = 100; // parse each of the relevant fields into variables - if (recommendation.has("authors") && !recommendation.isNull("authors")) { - authors = getAuthorsString(recommendation); - } - if (recommendation.has("title") && !recommendation.isNull("title")) { - title = recommendation.getString("title"); - } - if (recommendation.has("year_published") && !recommendation.isNull("year_published")) { - year = Integer.toString(recommendation.getInt("year_published")); - } - if (recommendation.has("published_in") && !recommendation.isNull("published_in")) { - journal = recommendation.getString("published_in"); - } - if (recommendation.has("url") && !recommendation.isNull("url")) { - url = recommendation.getString("url"); - } - if (recommendation.has("recommendation_id") && !recommendation.isNull("recommendation_id")) { - rank = recommendation.getInt("recommendation_id"); - } + String authors = isRecommendationFieldPresent(recommendation, "authors") ? getAuthorsString(recommendation) : ""; + String title = isRecommendationFieldPresent(recommendation, "title") ? recommendation.getString("title") : ""; + String year = isRecommendationFieldPresent(recommendation, "year_published") ? Integer.toString(recommendation.getInt("year_published")) : ""; + String journal = isRecommendationFieldPresent(recommendation, "published_in") ? recommendation.getString("published_in") : ""; + String url = isRecommendationFieldPresent(recommendation, "url") ? recommendation.getString("url") : ""; + Integer rank = isRecommendationFieldPresent(recommendation, "url") ? recommendation.getInt("recommendation_id") : 100; // Populate bib entry with relevant data current.setField(FieldName.AUTHOR, authors); @@ -176,6 +161,10 @@ private RankedBibEntry populateBibEntry(JSONObject recommendation) { return new RankedBibEntry(current, rank); } + private Boolean isRecommendationFieldPresent(JSONObject recommendation, String field) { + return recommendation.has(field) && !recommendation.isNull(field); + } + /** * Creates an authors string from a JSON recommendation * @param recommendation JSON Object recommendation from Mr. DLib diff --git a/src/test/java/org/jabref/logic/importer/fileformat/MrDLibImporterTest.java b/src/test/java/org/jabref/logic/importer/fileformat/MrDLibImporterTest.java index 5dea3343ac7..5af07b4dfa3 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/MrDLibImporterTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/MrDLibImporterTest.java @@ -20,12 +20,11 @@ public class MrDLibImporterTest { private MrDLibImporter importer; private BufferedReader input; - private String testInput; @BeforeEach public void setUp() { importer = new MrDLibImporter(); - testInput = "{ \"label\": { \"label-language\": \"en\", \"label-text\": \"Related Items\" }, \"recommendation-set-id\": \"1\", \"recommendations\": { \"74021358\": { \"abstract\": \"The theme of diploma is the preservation of the rural lands with the spatial development strategy on the case of the Hrastnik commune. The rural land with the potential production which is appropriate for the rural use is very important natural source. The natural source is very important for the quality of living and the spatial development. For this reason the assurance of the validity of the usage of the rural lands and to preserve the rural land is one of the basic ways of the strategy of the spatial development of Slovenia. The task is compose into two parts. The first part is theoretical. It informed us with the situations and achievements of the spatial development in Slovenia. In brief it shows the professional starting-point, which are for the use of the legally regime to preserve the rural lands and have been made by Dr. A. Stritar and they are still actual. In the review of the new and old rural land legislation it shows the adaptation of the rural lands through the periods until today. The second part treats the practical case of the preservation of the rural lands on the case of the Hrastnik commune. Based on the professional foundation for the classification of the rural lands presents the spatial analyses with reference to the rural lands and the category of the rural lands of the commune. At the end of the chapter it shows the part of Brnica. Here the commune of Hrastnik in the procedure of the preparation of new spatial-act wants to change the purpose of the best rural lands with the high production potential for the enlargement of the settlement and adaptation of the cemetery\", \"authors\": [ \"Sajovic, Marija\" ], \"date_published\": \"21-06-2006\", \"item_id_original\": \"12088644\", \"keywords\": [ \"visoko\\u0161olski program Geodezija - smer Prostorska informatika\" ], \"language_provided\": \"sl\", \"recommendation_id\": \"1\", \"title\": \"The protection of rural lands with the spatial development strategy on the case of Hrastnik commune\", \"url\": \"http://drugg.fgg.uni-lj.si/701/1/GEV_0199_Sajovic.pdf\" }, \"82005804\": { \"abstract\": \"The theme of my diploma thesis is the engagement of the volunteers in the solution to the accidents in the South-Moravia region. In my diploma thesis I am involved in the issue of the engagement of the volunteers in the solution to the accidents in the South-Moravia region. I assume that the utilization of the potential of the volunteers is one of the possibilities of the acquisition of the forces, which could be used for the recovery of the consequences, post-traumatic care to struck persons and other activities within the solution to the accidents, all parallelly with the actions of the professional teams of the integrated rescue system bodies. The needs of the population in case of the accidents are rather differentiated, and the engagement of the volunteers completes the appointed forces and means of the integrated rescue system bodies. At present time, the adequate legal framework, modifying the engagement of the volunteers in the solution to the accidents, does not exist in the Czech Republic. Non-governmental non-profit organizations are united in the South-Moravia region into the Panel of the South-Moravia Region, which establishes the platform and enables the South-Moravia Region more effective engagement of the non-governmental non-profit organizations. The volunteers, organized in the Panel of the South-Moravia Region, are engaged in the solution to the accidents and the trainings organized in the level of the region, municipalities with widened competence and the integrated rescue system bodies\", \"date_published\": null, \"item_id_original\": \"30145702\", \"language_provided\": null, \"recommendation_id\": \"2\", \"title\": \"Engagement of the volunteers in the solution to the accidents in the South-Moravia region\" }, \"82149599\": { \"abstract\": \"English Annotation (The work abstract) 5 key words: The Father, The Son, The Holy Spirit, The Holy Trinity, Saint John of the Cross \\\"The Only Father's Word\\\" The Relationship of the Father and the Son in documents of Saint John of the Cross The author presented the life of the saint in the first part of the work with the intention to put some key events of his life to the connection with the testimony of his texts. In the next part she analyzed those texts in the documents which are devoted to the relationship of the Father and the Son. Here we mainly talk about the twenty-second chapter of the second book, the Ascent of Mount Carmel, in which \\\" The Son is the only Father's word\\\". The father is active only in one way - begetting the Son; the begetting itself is Love, which is The Holy Spirit. The Son loves the Father and through this love he makes the Father love, he isn't passive. In the Romances, Saint John shows how the relationship of the Father and the Son in the Spirit is realized in the creation and incarnation. The poem the Source deepens our understanding of Son and Holy Spirit's proceeding from the Father and his acting in the Eucharist. In the third and the last part of the work, she made the synthesis of the knowledge gotten by the analysis of the given texts and she came to a conclusion that the..\", \"date_published\": null, \"item_id_original\": \"97690763\", \"language_provided\": null, \"recommendation_id\": \"3\", \"title\": \"\\\"The only Father's word\\\". The relationship of the Father and the Son in the documents of saint John of the Cross\", \"url\": \"http://www.nusl.cz/ntk/nusl-285711\" }, \"84863921\": { \"abstract\": \"This thesis provides an analytical presentation of the situation of the Greek Church of Cyprus, the Morea and Constantinople during the earlier part of the Frankish Era (1196-1303). It examines the establishment of the Latin Church in Constantinople, Cyprus and Achaea and it attempts to answer questions relating to the reactions of the Greek Church to the Latin conquests. It considers the similarities and differences in the establishment in Constantinople, the Morea and Cyprus, the diocesan structure, agreements regarding the fate of the Greek ecclesiastical properties, the payment of tithes and the agreements of 1220-1222. Moreover it analyses the relations of the Greek Church of Cyprus, the Greek Church of Constantinople and the Morea with the Latin Church. For instance it details the popes' involvement in the affairs of the Church in these three significant areas, the ecclesiastical differences between the Greek and the Latin Church, the behaviour of the Greek patriarchs, archbishops and bishops within the Greek Church, the reaction of the Greeks towards the establishment of the Latin Church, and significant events such as the martyrdom of the thirteen monks of Kantara and the promulgation of the Bulla Cypria. The third topic area pertains to the relationship of the Greek Church of the Morea, Constantinople and Cyprus with the secular authority. It discusses the attitude of the king of Cyprus, the rulers of the Morea and the emperor of Constantinople towards the problems between the Latin and Greeks, the relationship of the Latin nobility with the Greeks, and the involvement of the crown regarding the ecclesiastical property and possible explanations for the attitude of the Latin crown towards the Greeks\", \"authors\": [ \"Kaffa, Elena\" ], \"date_published\": null, \"item_id_original\": \"19397104\", \"keywords\": [ \"BX\", \"D111\" ], \"language_provided\": \"en\", \"recommendation_id\": \"4\", \"title\": \"Greek Church of Cyprus, the Morea and Constantinople during the Frankish Era (1196-1303)\" }, \"88950992\": { \"abstract\": \"1. The phylogeny map is the 4th-dimensional extension of a protoplast in which the generations repeated continuously. One generation in the phylogeny is the three-dimensional extension of the protoplast in certain period which is limited by a resting stage accompanying the reproductive phase. 2. It is considered that the ancestor of the seed plants was a hygrophytic multinuclear thallus having the structure like the cotyledonary ring including the hypocotyl in the plants of the present age. 3. In the second stage of the development in the phylogeny the thallus became uninuclear multicellular one, and the water storage cells differentiated in the body which gave the aerophytic habit for the plant. 4. Aerophytic habit gave the great change to the plant not only morphologically but also in the physiological natures. The epidermis having stomata differentiated. The mesophyll became to serve for the photosynthesis instead of the epidermis. The arrest of the escape of the metabolites from the surface of the body, the accumulation of the photosynthetic products, and the evaporation of water from the body surface lead the\\ndifferentiation of conductive tissues, the phloem and xylem. 5. The transfer of the nutrients and also the metabolites, especially such as the activator of the nuclear division, influenced to differentiate the secondary meristem. The growing point of the root and the primordium of the first node of the stem including the leaves and internode produced from the meristems. The embryo and bud formation are considered. 6. The appearance of the bud lead the formation of the complicated reproductive organ called the flower. The qualitative differences between the MiSI, and MaSI, and the migration of the SI were considered. 7. The ancestor of the Pteridophyte must be entirely different from that of the seed plants. It was a uninuclear multicellular plant having the growing point at the distal end of the body\", \"authors\": [ \"Yasui, Kono\" ], \"date_published\": null, \"item_id_original\": \"38763657\", \"language_provided\": null, \"recommendation_id\": \"5\", \"title\": \"A Phylogenetic Consideration on the Vascular Plants, Cotyledonary Node Including Hypocotyl Being Taken as the Ancestral Form : A Preliminary Note\" } }}"; + String testInput = "{ \"label\": { \"label-language\": \"en\", \"label-text\": \"Related Items\" }, \"recommendation-set-id\": \"1\", \"recommendations\": { \"74021358\": { \"abstract\": \"abstract\", \"authors\": [ \"Sajovic, Marija\" ], \"year_published\": \"2006\", \"item_id_original\": \"12088644\", \"keywords\": [ \"visoko\\u0161olski program Geodezija - smer Prostorska informatika\" ], \"language_provided\": \"sl\", \"recommendation_id\": \"1\", \"title\": \"The protection of rural lands with the spatial development strategy on the case of Hrastnik commune\", \"url\": \"http://drugg.fgg.uni-lj.si/701/1/GEV_0199_Sajovic.pdf\" }, \"82005804\": { \"abstract\": \"abstract\", \"year_published\": null, \"item_id_original\": \"30145702\", \"language_provided\": null, \"recommendation_id\": \"2\", \"title\": \"Engagement of the volunteers in the solution to the accidents in the South-Moravia region\" }, \"82149599\": { \"abstract\": \"abstract\", \"year_published\": null, \"item_id_original\": \"97690763\", \"language_provided\": null, \"recommendation_id\": \"3\", \"title\": \"\\\"The only Father's word\\\". The relationship of the Father and the Son in the documents of saint John of the Cross\", \"url\": \"http://www.nusl.cz/ntk/nusl-285711\" }, \"84863921\": { \"abstract\": \"abstract\", \"authors\": [ \"Kaffa, Elena\" ], \"year_published\": null, \"item_id_original\": \"19397104\", \"keywords\": [ \"BX\", \"D111\" ], \"language_provided\": \"en\", \"recommendation_id\": \"4\", \"title\": \"Greek Church of Cyprus, the Morea and Constantinople during the Frankish Era (1196-1303)\" }, \"88950992\": { \"abstract\": \"abstract\", \"authors\": [ \"Yasui, Kono\" ], \"year_published\": null, \"item_id_original\": \"38763657\", \"language_provided\": null, \"recommendation_id\": \"5\", \"title\": \"A Phylogenetic Consideration on the Vascular Plants, Cotyledonary Node Including Hypocotyl Being Taken as the Ancestral Form : A Preliminary Note\" } }}"; input = new BufferedReader(new StringReader(testInput)); } @@ -44,24 +43,13 @@ public void testGetFileExtention() { assertEquals(StandardFileType.JSON, importer.getFileType()); } - @Test - public void testImportDatabaseIsHtmlSetCorrectly() throws IOException { - ParserResult parserResult = importer.importDatabase(input); - - List resultList = parserResult.getDatabase().getEntries(); - - assertEquals( - "The protection of rural lands with the spatial development strategy on the case of Hrastnik commune. Sajovic, Marija. 21-06-2006", - resultList.get(0).getField("html_representation").get()); - } - @Test public void testImportDatabaseIsYearSetCorrectly() throws IOException { ParserResult parserResult = importer.importDatabase(input); List resultList = parserResult.getDatabase().getEntries(); - assertEquals("21-06-2006", + assertEquals("2006", resultList.get(0).getLatexFreeField(FieldName.YEAR).get()); } From 4ccbea6537504524999f9ce13da7bdc3cab3da15 Mon Sep 17 00:00:00 2001 From: conorfos Date: Thu, 11 Oct 2018 15:30:15 +0100 Subject: [PATCH 11/23] Moved root styling to css file --- src/main/java/org/jabref/gui/entryeditor/EntryEditor.css | 4 ++++ .../java/org/jabref/gui/entryeditor/RelatedArticlesTab.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.css b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.css index 73905764636..f489871f65f 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.css +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.css @@ -88,4 +88,8 @@ -fx-background-color: -jr-selected; } +.related-articles-tab { + -fx-padding: 20 20 20 20; +} + diff --git a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java index b802b3ddd0b..fa961267db1 100644 --- a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java @@ -50,7 +50,7 @@ public RelatedArticlesTab(EntryEditorPreferences preferences) { */ private StackPane getRelatedArticlesPane(BibEntry entry) { StackPane root = new StackPane(); - root.setStyle("-fx-padding: 20 20 20 20"); + root.getStyleClass().add("related-articles-tab"); ProgressIndicator progress = new ProgressIndicator(); progress.setMaxSize(100, 100); From 440db51806fcd04925cdea097273b52640a5bbff Mon Sep 17 00:00:00 2001 From: conorfos Date: Fri, 12 Oct 2018 09:59:59 +0100 Subject: [PATCH 12/23] Removed Print Stack Trace call --- .../gui/entryeditor/RelatedArticlesTab.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java index fa961267db1..3256bb6beef 100644 --- a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java @@ -1,15 +1,17 @@ package org.jabref.gui.entryeditor; import java.io.IOException; +import java.nio.file.Path; +import java.util.Collection; import java.util.List; +import java.util.Optional; +import java.util.function.Consumer; +import javafx.concurrent.Task; import javafx.event.ActionEvent; import javafx.event.EventHandler; -import javafx.scene.control.Button; -import javafx.scene.control.Hyperlink; -import javafx.scene.control.ProgressIndicator; -import javafx.scene.control.ScrollPane; -import javafx.scene.control.Tooltip; +import javafx.print.PrinterJob; +import javafx.scene.control.*; import javafx.scene.layout.HBox; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; @@ -18,13 +20,17 @@ import javafx.scene.text.Text; import org.jabref.Globals; +import org.jabref.gui.Dialog; import org.jabref.gui.desktop.JabRefDesktop; import org.jabref.gui.util.BackgroundTask; +import org.jabref.gui.util.DirectoryDialogConfiguration; +import org.jabref.gui.util.FileDialogConfiguration; import org.jabref.logic.importer.fetcher.MrDLibFetcher; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.FieldName; import org.jabref.preferences.JabRefPreferences; +import org.jabref.gui.DialogService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -101,7 +107,6 @@ public void handle(ActionEvent event) { JabRefDesktop.openBrowser(entry.getField(FieldName.URL).get()); } catch (IOException e) { LOGGER.error("Error opening the browser to: " + entry.getField(FieldName.URL).get(), e); - e.printStackTrace(); } } } From 40af08cb140cb82abef3f81936034d7f8491e2a2 Mon Sep 17 00:00:00 2001 From: conorfos Date: Fri, 12 Oct 2018 11:21:14 +0100 Subject: [PATCH 13/23] Replaced UI strings with Localization.lang strings --- .../org/jabref/gui/entryeditor/RelatedArticlesTab.java | 8 ++++---- .../org/jabref/logic/importer/fetcher/MrDLibFetcher.java | 7 +++---- .../jabref/logic/importer/fileformat/MrDLibImporter.java | 3 ++- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java index 3256bb6beef..a21856dad49 100644 --- a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java @@ -129,13 +129,13 @@ private ScrollPane getPrivacyDialog(BibEntry entry) { vbox.getStyleClass().add("gdpr-dialog"); vbox.setSpacing(20.0); - Button button = new Button("I Agree"); + Button button = new Button(Localization.lang("I Agree")); button.getStyleClass().add("accept-button"); - Text line1 = new Text("Mr. DLib is an external service which provides article recommendations based on the currently selected entry. Data about the selected entry must be sent to Mr. DLib in order to provide these recommendations. Do you agree that this data may be sent?"); + Text line1 = new Text(Localization.lang("Mr. DLib is an external service which provides article recommendations based on the currently selected entry. Data about the selected entry must be sent to Mr. DLib in order to provide these recommendations. Do you agree that this data may be sent?")); line1.setWrappingWidth(1300.0); - Text line2 = new Text("This setting may be changed in preferences at any time."); - Hyperlink mdlLink = new Hyperlink("Further information about Mr DLib. for JabRef users."); + Text line2 = new Text(Localization.lang("This setting may be changed in preferences at any time.")); + Hyperlink mdlLink = new Hyperlink(Localization.lang("Further information about Mr DLib. for JabRef users.")); mdlLink.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { diff --git a/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java index d31d1eee0e6..bcfe0060b8e 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java @@ -60,8 +60,7 @@ public List performSearch(BibEntry entry) throws FetcherException { // For displaying An ErrorMessage String error = importer.getResponseErrorMessage(response); BibEntry errorBibEntry = new BibEntry(); - errorBibEntry.setField("html_representation", - Localization.lang(error)); + errorBibEntry.setField("html_representation", error); BibDatabase errorBibDataBase = new BibDatabase(); errorBibDataBase.insertEntry(errorBibEntry); parserResult = new ParserResult(errorBibDataBase); @@ -80,7 +79,7 @@ public List performSearch(BibEntry entry) throws FetcherException { /** * Contact the server with the title of the selected item * - * @param query: The query holds the title of the selected entry. Used to make a query to the MDL Server + * @param queryByTitle: The query holds the title of the selected entry. Used to make a query to the MDL Server * @return Returns the server response. This is an XML document as a String. */ private String makeServerRequest(String queryByTitle) throws FetcherException { @@ -101,7 +100,7 @@ private String makeServerRequest(String queryByTitle) throws FetcherException { /** * Constructs the query based on title of the bibentry. Adds statistical stuff to the url. * - * @param query: the title of the bib entry. + * @param queryWithTitle: the title of the bib entry. * @return the string used to make the query at mdl server */ private String constructQuery(String queryWithTitle) { diff --git a/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java index 4a5bd332730..92f9cf32bde 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java @@ -12,6 +12,7 @@ import org.jabref.logic.importer.Importer; import org.jabref.logic.importer.ParserResult; +import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.StandardFileType; import org.jabref.model.database.BibDatabase; import org.jabref.model.entry.BibEntry; @@ -28,7 +29,7 @@ */ public class MrDLibImporter extends Importer { - private static final String DEFAULT_MRDLIB_ERROR_MESSAGE = "Error while fetching from Mr.DLib."; + private static final String DEFAULT_MRDLIB_ERROR_MESSAGE = Localization.lang("Error while fetching from Mr.DLib."); private static final Logger LOGGER = LoggerFactory.getLogger(MrDLibImporter.class); public ParserResult parserResult; From 4d5df3d55c46e11cb5be356cedf89c40efbc952b Mon Sep 17 00:00:00 2001 From: conorfos Date: Fri, 12 Oct 2018 13:48:24 +0100 Subject: [PATCH 14/23] everted to EntryEditorPreferences --- .../java/org/jabref/gui/entryeditor/RelatedArticlesTab.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java index a21856dad49..1080afa879b 100644 --- a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java @@ -125,6 +125,7 @@ public void handle(ActionEvent event) { */ private ScrollPane getPrivacyDialog(BibEntry entry) { ScrollPane root = new ScrollPane(); + root.getStyleClass().add("related-articles-tab"); VBox vbox = new VBox(); vbox.getStyleClass().add("gdpr-dialog"); vbox.setSpacing(20.0); @@ -156,7 +157,6 @@ public void handle(ActionEvent event) { } }); - root.setStyle("-fx-padding: 20 20 20 20"); vbox.getChildren().addAll(line1, mdlLink, line2, button); root.setContent(vbox); @@ -171,7 +171,7 @@ public boolean shouldShow(BibEntry entry) { @Override protected void bindToEntry(BibEntry entry) { // Ask for consent to send data to Mr. DLib on first time to tab - if (JabRefPreferences.getInstance().getBoolean(JabRefPreferences.ACCEPT_RECOMMENDATIONS)) { + if (preferences.isMrdlibAccepted()) { setContent(getRelatedArticlesPane(entry)); } else { setContent(getPrivacyDialog(entry)); From 761ed98e5d891482fc3915bbbdcb4e06841cfae5 Mon Sep 17 00:00:00 2001 From: conorfos Date: Mon, 15 Oct 2018 09:57:06 +0100 Subject: [PATCH 15/23] Removed reference to Globals in MrDLibFetcher --- .../org/jabref/gui/entryeditor/RelatedArticlesTab.java | 2 +- .../org/jabref/logic/importer/fetcher/MrDLibFetcher.java | 9 ++++----- .../jabref/logic/importer/fileformat/MrDLibImporter.java | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java index 1080afa879b..4f84a7d0437 100644 --- a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java @@ -61,7 +61,7 @@ private StackPane getRelatedArticlesPane(BibEntry entry) { progress.setMaxSize(100, 100); MrDLibFetcher fetcher = new MrDLibFetcher(Globals.prefs.get(JabRefPreferences.LANGUAGE), - Globals.BUILD_INFO.getVersion().getFullVersion()); + Globals.BUILD_INFO.getVersion()); BackgroundTask .wrap(() -> fetcher.performSearch(entry)) .onRunning(() -> progress.setVisible(true)) diff --git a/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java index bcfe0060b8e..76fba7a855f 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java @@ -33,10 +33,10 @@ public class MrDLibFetcher implements EntryBasedFetcher { private static final Logger LOGGER = LoggerFactory.getLogger(MrDLibFetcher.class); private static final String NAME = "MDL_FETCHER"; private final String LANGUAGE; - private final String VERSION; + private final Version VERSION; - public MrDLibFetcher(String language, String version) { + public MrDLibFetcher(String language, Version version) { LANGUAGE = language; VERSION = version; } @@ -112,7 +112,7 @@ private String constructQuery(String queryWithTitle) { builder.setPath("/v2/items/" + queryWithTitle + "/related_items"); builder.addParameter("partner_id", "jabref"); builder.addParameter("app_id", "jabref_desktop"); - builder.addParameter("app_version", VERSION); + builder.addParameter("app_version", VERSION.getFullVersion()); builder.addParameter("app_lang", LANGUAGE); URI uri = null; try { @@ -126,7 +126,6 @@ private String constructQuery(String queryWithTitle) { } private String getMdlUrl() { - Version currentVersion = Globals.BUILD_INFO.getVersion(); - return currentVersion.isDevelopmentVersion() ? "api-dev.darwingoliath.com" : "api.darwingoliath.com"; + return VERSION.isDevelopmentVersion() ? "api-dev.darwingoliath.com" : "api.darwingoliath.com"; } } diff --git a/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java index 92f9cf32bde..e7e4c86f6a6 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java @@ -71,7 +71,7 @@ public String getDescription() { /** * Convert Buffered Reader response to string for JSON parsing. - * @param Takes a BufferedReader with a reference to the JSON document delivered by mdl server. + * @param input Takes a BufferedReader with a reference to the JSON document delivered by mdl server. * @return Returns an String containing the JSON document. * @throws IOException */ From b4dabe04e49b6950ba96a802238e02bf50e20e48 Mon Sep 17 00:00:00 2001 From: conorfos Date: Mon, 15 Oct 2018 10:30:54 +0100 Subject: [PATCH 16/23] Fixed awkward syntax with JSONObject --- .../org/jabref/logic/importer/fileformat/MrDLibImporter.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java b/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java index e7e4c86f6a6..6320b8d7483 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/MrDLibImporter.java @@ -116,8 +116,7 @@ private void parse(BufferedReader input) throws IOException { List rankedBibEntries = new ArrayList<>(); // Get recommendations from response and populate bib entries - JSONObject recommendationsJson = new JSONObject(recommendations); - recommendationsJson = recommendationsJson.getJSONObject("recommendations"); + JSONObject recommendationsJson = new JSONObject(recommendations).getJSONObject("recommendations"); Iterator keys = recommendationsJson.keys(); while (keys.hasNext()) { String key = keys.next(); From bfe5abf234bd4d51eb0236d6545f9fb751245b66 Mon Sep 17 00:00:00 2001 From: conorfos Date: Mon, 15 Oct 2018 11:32:42 +0100 Subject: [PATCH 17/23] Implemented Dialogs One to notify the user to restart JabRef after changing preferences Two to show IOExceptions to the user --- .../java/org/jabref/gui/entryeditor/EntryEditor.java | 2 +- .../org/jabref/gui/entryeditor/RelatedArticlesTab.java | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java index b71d2b3e727..5dcfd8434cf 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java @@ -249,7 +249,7 @@ private List createTabs() { // Special tabs tabs.add(new MathSciNetTab()); tabs.add(new FileAnnotationTab(panel.getAnnotationCache())); - tabs.add(new RelatedArticlesTab(preferences)); + tabs.add(new RelatedArticlesTab(preferences, dialogService)); // Source tab sourceTab = new SourceTab(databaseContext, undoManager, preferences.getLatexFieldFormatterPreferences(), preferences.getImportFormatPreferences(), fileMonitor); diff --git a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java index 4f84a7d0437..c79112134aa 100644 --- a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java @@ -2,6 +2,7 @@ import java.io.IOException; import java.nio.file.Path; +import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Optional; @@ -42,11 +43,13 @@ public class RelatedArticlesTab extends EntryEditorTab { private static final Logger LOGGER = LoggerFactory.getLogger(RelatedArticlesTab.class); private final EntryEditorPreferences preferences; + private final DialogService dialogService; - public RelatedArticlesTab(EntryEditorPreferences preferences) { + public RelatedArticlesTab(EntryEditorPreferences preferences, DialogService dialogService) { setText(Localization.lang("Related articles")); setTooltip(new Tooltip(Localization.lang("Related articles"))); this.preferences = preferences; + this.dialogService = dialogService; } /** @@ -107,6 +110,7 @@ public void handle(ActionEvent event) { JabRefDesktop.openBrowser(entry.getField(FieldName.URL).get()); } catch (IOException e) { LOGGER.error("Error opening the browser to: " + entry.getField(FieldName.URL).get(), e); + dialogService.showErrorDialogAndWait(e); } } } @@ -143,7 +147,8 @@ public void handle(ActionEvent event) { try { JabRefDesktop.openBrowser("http://mr-dlib.org/information-for-users/information-about-mr-dlib-for-jabref-users/"); } catch (IOException e) { - LOGGER.error("Error opening the browser to: " + entry.getField(FieldName.URL).get(), e); + LOGGER.error("Error opening the browser to Mr. DLib information page.", e); + dialogService.showErrorDialogAndWait(e); } } }); @@ -153,6 +158,7 @@ public void handle(ActionEvent event) { public void handle(ActionEvent event) { JabRefPreferences prefs = JabRefPreferences.getInstance(); prefs.putBoolean(JabRefPreferences.ACCEPT_RECOMMENDATIONS, true); + dialogService.showWarningDialogAndWait(Localization.lang("Restart"), Localization.lang("Please restart JabRef for preferences to take effect.")); setContent(getRelatedArticlesPane(entry)); } }); From fb2fc7906715cf2c724bd7c0f4734fd7361921d4 Mon Sep 17 00:00:00 2001 From: conorfos Date: Wed, 17 Oct 2018 10:35:40 +0100 Subject: [PATCH 18/23] Reverting unintended change --- .../java/org/jabref/gui/entryeditor/EntryEditorPreferences.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditorPreferences.java b/src/main/java/org/jabref/gui/entryeditor/EntryEditorPreferences.java index af90eff6596..ed059ab9f7f 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditorPreferences.java +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditorPreferences.java @@ -19,7 +19,7 @@ public class EntryEditorPreferences { private final boolean isMrdlibAccepted; private boolean showSourceTabByDefault; private final KeyBindingRepository keyBindings; - private final boolean avoidOverwritingCiteKey; + private boolean avoidOverwritingCiteKey; public EntryEditorPreferences(Map> entryEditorTabList, LatexFieldFormatterPreferences latexFieldFormatterPreferences, ImportFormatPreferences importFormatPreferences, List customTabFieldNames, boolean shouldShowRecommendationsTab, boolean isMrdlibAccepted, boolean showSourceTabByDefault, BibtexKeyPatternPreferences bibtexKeyPatternPreferences, KeyBindingRepository keyBindings, boolean avoidOverwritingCiteKey) { this.entryEditorTabList = entryEditorTabList; From fd825628d54d70db86b1a2b71776383440086a59 Mon Sep 17 00:00:00 2001 From: conorfos Date: Wed, 17 Oct 2018 10:54:38 +0100 Subject: [PATCH 19/23] Set Accept button as default button --- src/main/java/org/jabref/gui/entryeditor/EntryEditor.css | 4 ---- .../java/org/jabref/gui/entryeditor/RelatedArticlesTab.java | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.css b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.css index f489871f65f..313583ed222 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.css +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.css @@ -84,10 +84,6 @@ -fx-font-size: 14pt; } -.accept-button { - -fx-background-color: -jr-selected; -} - .related-articles-tab { -fx-padding: 20 20 20 20; } diff --git a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java index c79112134aa..175ece95b72 100644 --- a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java @@ -135,7 +135,7 @@ private ScrollPane getPrivacyDialog(BibEntry entry) { vbox.setSpacing(20.0); Button button = new Button(Localization.lang("I Agree")); - button.getStyleClass().add("accept-button"); + button.setDefaultButton(true); Text line1 = new Text(Localization.lang("Mr. DLib is an external service which provides article recommendations based on the currently selected entry. Data about the selected entry must be sent to Mr. DLib in order to provide these recommendations. Do you agree that this data may be sent?")); line1.setWrappingWidth(1300.0); From 9c769b1f774900e78058a0202ecdb86c68a91922 Mon Sep 17 00:00:00 2001 From: conorfos Date: Thu, 18 Oct 2018 10:36:11 +0100 Subject: [PATCH 20/23] Updated CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61130cb9435..803f26c4aee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - We add auto url formatting when user paste link to URL field in entry editor. [#254](https://github.com/koppor/jabref/issues/254) - We added a minimal height for the entry editor so that it can no longer be hidden by accident. [#4279](https://github.com/JabRef/jabref/issues/4279) - We added a new keyboard shortcut so that the entry editor could be closed by Ctrl + E. [#4222] (https://github.com/JabRef/jabref/issues/4222) +- We updated updated the Related Articles tab to accept JSON from the new version of the Mr. DLib service From 493d5e6dcfe09bc07b0163912f3697277045b8dc Mon Sep 17 00:00:00 2001 From: conorfos Date: Thu, 25 Oct 2018 17:06:05 +0100 Subject: [PATCH 21/23] Fix for broken MrDLibFetcherTest --- .../org/jabref/logic/importer/fetcher/MrDLibFetcherTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/jabref/logic/importer/fetcher/MrDLibFetcherTest.java b/src/test/java/org/jabref/logic/importer/fetcher/MrDLibFetcherTest.java index c35684edf48..357e50393fd 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/MrDLibFetcherTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/MrDLibFetcherTest.java @@ -3,6 +3,7 @@ import java.util.List; import org.jabref.logic.importer.FetcherException; +import org.jabref.logic.util.Version; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.FieldName; import org.jabref.testutils.category.FetcherTest; @@ -20,7 +21,7 @@ public class MrDLibFetcherTest { @BeforeEach public void setUp() { - fetcher = new MrDLibFetcher("", ""); + fetcher = new MrDLibFetcher("", Version.parse("")); } @Test From 571618ca64bc6d1a5d753ec0637a0b64b2222c1a Mon Sep 17 00:00:00 2001 From: Patrick Scheibe Date: Fri, 26 Oct 2018 08:06:57 +0200 Subject: [PATCH 22/23] Fix unused imports, refactor event listener to lambda, call static method through classname --- .../gui/entryeditor/RelatedArticlesTab.java | 67 +++++++------------ .../logic/importer/fetcher/MrDLibFetcher.java | 14 ++-- 2 files changed, 29 insertions(+), 52 deletions(-) diff --git a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java index 175ece95b72..dbbe9ff096a 100644 --- a/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/RelatedArticlesTab.java @@ -1,18 +1,13 @@ package org.jabref.gui.entryeditor; import java.io.IOException; -import java.nio.file.Path; -import java.util.Arrays; -import java.util.Collection; import java.util.List; -import java.util.Optional; -import java.util.function.Consumer; - -import javafx.concurrent.Task; -import javafx.event.ActionEvent; -import javafx.event.EventHandler; -import javafx.print.PrinterJob; -import javafx.scene.control.*; + +import javafx.scene.control.Button; +import javafx.scene.control.Hyperlink; +import javafx.scene.control.ProgressIndicator; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.Tooltip; import javafx.scene.layout.HBox; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; @@ -21,17 +16,14 @@ import javafx.scene.text.Text; import org.jabref.Globals; -import org.jabref.gui.Dialog; +import org.jabref.gui.DialogService; import org.jabref.gui.desktop.JabRefDesktop; import org.jabref.gui.util.BackgroundTask; -import org.jabref.gui.util.DirectoryDialogConfiguration; -import org.jabref.gui.util.FileDialogConfiguration; import org.jabref.logic.importer.fetcher.MrDLibFetcher; import org.jabref.logic.l10n.Localization; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.FieldName; import org.jabref.preferences.JabRefPreferences; -import org.jabref.gui.DialogService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -102,16 +94,13 @@ private VBox getRelatedArticleInfo(List list) { journalText.setFont(Font.font(Font.getDefault().getFamily(), FontPosture.ITALIC, Font.getDefault().getSize())); Text authorsText = new Text(authors); Text yearText = new Text("(" + year + ")"); - titleLink.setOnAction(new EventHandler() { - @Override - public void handle(ActionEvent event) { - if (entry.getField(FieldName.URL).isPresent()) { - try { - JabRefDesktop.openBrowser(entry.getField(FieldName.URL).get()); - } catch (IOException e) { - LOGGER.error("Error opening the browser to: " + entry.getField(FieldName.URL).get(), e); - dialogService.showErrorDialogAndWait(e); - } + titleLink.setOnAction(event -> { + if (entry.getField(FieldName.URL).isPresent()) { + try { + JabRefDesktop.openBrowser(entry.getField(FieldName.URL).get()); + } catch (IOException e) { + LOGGER.error("Error opening the browser to: " + entry.getField(FieldName.URL).get(), e); + dialogService.showErrorDialogAndWait(e); } } }); @@ -141,26 +130,20 @@ private ScrollPane getPrivacyDialog(BibEntry entry) { line1.setWrappingWidth(1300.0); Text line2 = new Text(Localization.lang("This setting may be changed in preferences at any time.")); Hyperlink mdlLink = new Hyperlink(Localization.lang("Further information about Mr DLib. for JabRef users.")); - mdlLink.setOnAction(new EventHandler() { - @Override - public void handle(ActionEvent event) { - try { - JabRefDesktop.openBrowser("http://mr-dlib.org/information-for-users/information-about-mr-dlib-for-jabref-users/"); - } catch (IOException e) { - LOGGER.error("Error opening the browser to Mr. DLib information page.", e); - dialogService.showErrorDialogAndWait(e); - } + mdlLink.setOnAction(event -> { + try { + JabRefDesktop.openBrowser("http://mr-dlib.org/information-for-users/information-about-mr-dlib-for-jabref-users/"); + } catch (IOException e) { + LOGGER.error("Error opening the browser to Mr. DLib information page.", e); + dialogService.showErrorDialogAndWait(e); } }); - button.setOnAction(new EventHandler() { - @Override - public void handle(ActionEvent event) { - JabRefPreferences prefs = JabRefPreferences.getInstance(); - prefs.putBoolean(JabRefPreferences.ACCEPT_RECOMMENDATIONS, true); - dialogService.showWarningDialogAndWait(Localization.lang("Restart"), Localization.lang("Please restart JabRef for preferences to take effect.")); - setContent(getRelatedArticlesPane(entry)); - } + button.setOnAction(event -> { + JabRefPreferences prefs = JabRefPreferences.getInstance(); + prefs.putBoolean(JabRefPreferences.ACCEPT_RECOMMENDATIONS, true); + dialogService.showWarningDialogAndWait(Localization.lang("Restart"), Localization.lang("Please restart JabRef for preferences to take effect.")); + setContent(getRelatedArticlesPane(entry)); }); vbox.getChildren().addAll(line1, mdlLink, line2, button); diff --git a/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java b/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java index 76fba7a855f..2ae7db36e35 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/MrDLibFetcher.java @@ -1,6 +1,3 @@ -/** - * - */ package org.jabref.logic.importer.fetcher; import java.io.IOException; @@ -10,12 +7,10 @@ import java.util.List; import java.util.Optional; -import org.jabref.Globals; import org.jabref.logic.importer.EntryBasedFetcher; import org.jabref.logic.importer.FetcherException; import org.jabref.logic.importer.ParserResult; import org.jabref.logic.importer.fileformat.MrDLibImporter; -import org.jabref.logic.l10n.Localization; import org.jabref.logic.net.URLDownload; import org.jabref.logic.util.Version; import org.jabref.model.database.BibDatabase; @@ -52,7 +47,7 @@ public List performSearch(BibEntry entry) throws FetcherException { if (title.isPresent()) { String response = makeServerRequest(title.get()); MrDLibImporter importer = new MrDLibImporter(); - ParserResult parserResult = new ParserResult(); + ParserResult parserResult; try { if (importer.isRecognizedFormat(response)) { parserResult = importer.importDatabase(response); @@ -85,7 +80,7 @@ public List performSearch(BibEntry entry) throws FetcherException { private String makeServerRequest(String queryByTitle) throws FetcherException { try { URLDownload urlDownload = new URLDownload(constructQuery(queryByTitle)); - urlDownload.bypassSSLVerification(); + URLDownload.bypassSSLVerification(); String response = urlDownload.asString(); //Conversion of < and > @@ -98,7 +93,7 @@ private String makeServerRequest(String queryByTitle) throws FetcherException { } /** - * Constructs the query based on title of the bibentry. Adds statistical stuff to the url. + * Constructs the query based on title of the BibEntry. Adds statistical stuff to the url. * * @param queryWithTitle: the title of the bib entry. * @return the string used to make the query at mdl server @@ -114,9 +109,8 @@ private String constructQuery(String queryWithTitle) { builder.addParameter("app_id", "jabref_desktop"); builder.addParameter("app_version", VERSION.getFullVersion()); builder.addParameter("app_lang", LANGUAGE); - URI uri = null; try { - uri = builder.build(); + URI uri = builder.build(); LOGGER.trace("Request: " + uri.toString()); return uri.toString(); } catch (URISyntaxException e) { From ecf9eb5477fffc9b12e57c5945f8b1ac107bfe19 Mon Sep 17 00:00:00 2001 From: Patrick Scheibe Date: Fri, 26 Oct 2018 08:40:11 +0200 Subject: [PATCH 23/23] Fix localization strings --- src/main/resources/l10n/JabRef_en.properties | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 529922c4b94..aa3101e4371 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -31,9 +31,9 @@ Accept=Accept Accept\ change=Accept change -Action=Action +Accept\ recommendations\ from\ Mr.\ DLib=Accept recommendations from Mr. DLib -What\ is\ Mr.\ DLib?=What is Mr. DLib? +Action=Action Add=Add @@ -379,6 +379,8 @@ Error\ occurred\ when\ parsing\ entry=Error occurred when parsing entry Error\ opening\ file=Error opening file +Error\ while\ fetching\ from\ Mr.DLib.=Error while fetching from Mr.DLib. + Error\ while\ writing=Error while writing '%0'\ exists.\ Overwrite\ file?='%0' exists. Overwrite file? @@ -466,6 +468,8 @@ found\ in\ AUX\ file=found in AUX file Full\ name=Full name +Further\ information\ about\ Mr\ DLib.\ for\ JabRef\ users.=Further information about Mr DLib. for JabRef users. + General=General General\ Fields=General Fields @@ -560,6 +564,8 @@ Independent\ group\:\ When\ selected,\ view\ only\ this\ group's\ entries=Indepe Work\ options=Work options +I\ Agree=I Agree + Insert=Insert Insert\ rows=Insert rows @@ -656,6 +662,9 @@ Move\ up=Move up Moved\ group\ "%0".=Moved group "%0". +Mr.\ DLib\ is\ an\ external\ service\ which\ provides\ article\ recommendations\ based\ on\ the\ currently\ selected\ entry.\ Data\ about\ the\ selected\ entry\ must\ be\ sent\ to\ Mr.\ DLib\ in\ order\ to\ provide\ these\ recommendations.\ Do\ you\ agree\ that\ this\ data\ may\ be\ sent?=Mr. DLib is an external service which provides article recommendations based on the currently selected entry. Data about the selected entry must be sent to Mr. DLib in order to provide these recommendations. Do you agree that this data may be sent? + + Name=Name Name\ formatter=Name formatter @@ -786,6 +795,8 @@ Please\ enter\ the\ string's\ label=Please enter the string's label Please\ select\ an\ importer.=Please select an importer. +Please\ restart\ JabRef\ for\ preferences\ to\ take\ effect.=Please restart JabRef for preferences to take effect. + Possible\ duplicate\ entries=Possible duplicate entries Possible\ duplicate\ of\ existing\ entry.\ Click\ to\ resolve.=Possible duplicate of existing entry. Click to resolve. @@ -897,6 +908,9 @@ Resolve\ strings\ for\ all\ fields\ except=Resolve strings for all fields except Resolve\ strings\ for\ standard\ BibTeX\ fields\ only=Resolve strings for standard BibTeX fields only resolved=resolved + +Restart=Restart + Review=Review Review\ changes=Review changes Review\ Field\ Migration=Review Field Migration @@ -1063,6 +1077,8 @@ This\ operation\ requires\ all\ selected\ entries\ to\ have\ BibTeX\ keys\ defin This\ operation\ requires\ one\ or\ more\ entries\ to\ be\ selected.=This operation requires one or more entries to be selected. +This\ setting\ may\ be\ changed\ in\ preferences\ at\ any\ time.=This setting may be changed in preferences at any time. + Toggle\ entry\ preview=Toggle entry preview Toggle\ groups\ interface=Toggle groups interface