From 9bdfd9a1c219b9c6870c74ddcae9023ae90eebdd Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sun, 27 Oct 2019 20:23:58 +0100 Subject: [PATCH 1/6] Add tests for month issue and strings (and some minor code improvements) - Add tests for `month = apr` and `month = "apr"` - Add tests for JabRef's string types - Remove Optional as method parameter in BibEntry.setField - Add builder to BibEntry - Mark "BIBTEX_STRING" as JabRef-internal field - Sort constants in InternalField.java - and add some comments --- .../jabref/logic/shared/DBMSProcessor.java | 5 +- .../jabref/logic/shared/DBMSSynchronizer.java | 5 +- .../java/org/jabref/model/entry/BibEntry.java | 43 +++++++-- .../model/entry/field/InternalField.java | 9 +- src/main/resources/csl-locales | 2 +- .../exporter/BibtexDatabaseWriterTest.java | 51 +++++++++- .../importer/fileformat/BibtexParserTest.java | 75 +++++++++++++++ .../jabref/model/entry/BibtexStringTest.java | 92 ++++++++++++++++++- .../resources/testbib/articleWithMonths.bib | 10 ++ 9 files changed, 270 insertions(+), 22 deletions(-) create mode 100644 src/test/resources/testbib/articleWithMonths.bib diff --git a/src/main/java/org/jabref/logic/shared/DBMSProcessor.java b/src/main/java/org/jabref/logic/shared/DBMSProcessor.java index e361ba20875..9192c915d21 100644 --- a/src/main/java/org/jabref/logic/shared/DBMSProcessor.java +++ b/src/main/java/org/jabref/logic/shared/DBMSProcessor.java @@ -473,7 +473,10 @@ public List getSharedEntries(List sharedIDs) { lastId = selectEntryResultSet.getInt("SHARED_ID"); } - bibEntry.setField(FieldFactory.parseField(selectEntryResultSet.getString("NAME")), Optional.ofNullable(selectEntryResultSet.getString("VALUE")), EntryEventSource.SHARED); + String value = selectEntryResultSet.getString("VALUE"); + if (value != null) { + bibEntry.setField(FieldFactory.parseField(selectEntryResultSet.getString("NAME")), value, EntryEventSource.SHARED); + } } } catch (SQLException e) { LOGGER.error("SQL Error", e); diff --git a/src/main/java/org/jabref/logic/shared/DBMSSynchronizer.java b/src/main/java/org/jabref/logic/shared/DBMSSynchronizer.java index 7a055dec41f..419e3775d6c 100644 --- a/src/main/java/org/jabref/logic/shared/DBMSSynchronizer.java +++ b/src/main/java/org/jabref/logic/shared/DBMSSynchronizer.java @@ -192,7 +192,10 @@ public void synchronizeLocalDatabase() { localEntry.getSharedBibEntryData() .setVersion(sharedEntry.get().getSharedBibEntryData().getVersion()); for (Field field : sharedEntry.get().getFields()) { - localEntry.setField(field, sharedEntry.get().getField(field), EntryEventSource.SHARED); + Optional sharedFieldValue = sharedEntry.get().getField(field); + if (sharedFieldValue.isPresent()) { + localEntry.setField(field, sharedFieldValue.get(), EntryEventSource.SHARED); + } } Set redundantLocalEntryFields = localEntry.getFields(); diff --git a/src/main/java/org/jabref/model/entry/BibEntry.java b/src/main/java/org/jabref/model/entry/BibEntry.java index de36489fc52..d3b83ec7460 100644 --- a/src/main/java/org/jabref/model/entry/BibEntry.java +++ b/src/main/java/org/jabref/model/entry/BibEntry.java @@ -63,6 +63,7 @@ public class BibEntry implements Cloneable { private ObservableMap fields = FXCollections.observableMap(new ConcurrentHashMap<>()); private String parsedSerialization = ""; private String commentsBeforeEntry = ""; + /** * Marks whether the complete serialization, which was read from file, should be used. * @@ -70,6 +71,36 @@ public class BibEntry implements Cloneable { */ private boolean changed; + /** + * A simple builder to enable quick creation of BibEntry instances. + * + * Builder pattern as described in Item 2 of the book "Effective Java". + */ + public static class Builder { + + private BibEntry bibEntry; + + public Builder(EntryType type) { + Objects.requireNonNull(type); + bibEntry = new BibEntry(type); + } + + public Builder citeKey(String citeKey) { + bibEntry.setCiteKey(citeKey); + return this; + } + + public Builder field(Field field, String value) { + bibEntry.setField(field, value); + return this; + } + + public BibEntry build() { + return bibEntry; + } + + } + /** * Constructs a new BibEntry. The internal ID is set to IdGenerator.next() */ @@ -266,8 +297,9 @@ public String getId() { } /** - * Sets this entry's ID, provided the database containing it - * doesn't veto the change. + * Sets this entry's identifier (ID). It is used internally to distinguish different BibTeX entries. It is not the BibTeX key. The BibTexKey is the {@link InternalField.KEY_FIELD}. + * + * The entry is also updated in the shared database - provided the database containing it doesn't veto the change. * * @param id The ID to be used */ @@ -523,13 +555,6 @@ public Optional setField(Field field, String value, EntryEventSourc return Optional.of(change); } - public Optional setField(Field field, Optional value, EntryEventSource eventSource) { - if (value.isPresent()) { - return setField(field, value.get(), eventSource); - } - return Optional.empty(); - } - /** * Set a field, and notify listeners about the change. * diff --git a/src/main/java/org/jabref/model/entry/field/InternalField.java b/src/main/java/org/jabref/model/entry/field/InternalField.java index b7025f8f8aa..b825069568d 100644 --- a/src/main/java/org/jabref/model/entry/field/InternalField.java +++ b/src/main/java/org/jabref/model/entry/field/InternalField.java @@ -10,16 +10,17 @@ * JabRef internal fields */ public enum InternalField implements Field { - INTERNAL_ALL_FIELD("all"), - INTERNAL_ALL_TEXT_FIELDS_FIELD("all-text-fields"), - MARKED_INTERNAL("__markedentry"), + MARKED_INTERNAL("__markedentry"), // used in old versions of JabRef. Currently used for conversion only OWNER("owner"), TIMESTAMP("timestamp", FieldProperty.DATE), GROUPS("groups"), KEY_FIELD("bibtexkey"), TYPE_HEADER("entrytype"), OBSOLETE_TYPE_HEADER("bibtextype"), - BIBTEX_STRING("__string"), + // all field names starting with "Jabref-internal-" are not appearing in .bib files + BIBTEX_STRING("JabRef-internal-bibtex-string"), // marker that the content is just a BibTeX string + INTERNAL_ALL_FIELD("JabRef-internal-all"), // virtual field to denote "all fields" + INTERNAL_ALL_TEXT_FIELDS_FIELD("JabRef-internal-all-text-fields"), // virtual field to denote "all text fields" INTERNAL_ID_FIELD("JabRef-internal-id"); private final String name; diff --git a/src/main/resources/csl-locales b/src/main/resources/csl-locales index 9785a6e3584..e89e6b08b5c 160000 --- a/src/main/resources/csl-locales +++ b/src/main/resources/csl-locales @@ -1 +1 @@ -Subproject commit 9785a6e3584e8c903df3d5a53f0e800dcabd282b +Subproject commit e89e6b08b5c621a414fc7114f2129efac5f8c7d5 diff --git a/src/test/java/org/jabref/logic/exporter/BibtexDatabaseWriterTest.java b/src/test/java/org/jabref/logic/exporter/BibtexDatabaseWriterTest.java index 876995c42ef..2892b3944d0 100644 --- a/src/test/java/org/jabref/logic/exporter/BibtexDatabaseWriterTest.java +++ b/src/test/java/org/jabref/logic/exporter/BibtexDatabaseWriterTest.java @@ -289,7 +289,56 @@ void writeEntryWithCustomizedTypeAlsoWritesTypeDeclaration() throws Exception { } @Test - void roundtrip() throws Exception { + void writeEntryWithConstantMonthApril() throws Exception { + BibEntry entry = new BibEntry.Builder(StandardEntryType.Misc) + .field(StandardField.MONTH, "#apr#") + .build(); + database.insertEntry(entry); + + databaseWriter.savePartOfDatabase(bibtexContext, Collections.singletonList(entry)); + + assertEquals(OS.NEWLINE + + "@Misc{," + OS.NEWLINE + + " month = apr," + OS.NEWLINE + + "}" + OS.NEWLINE + OS.NEWLINE + + "@Comment{jabref-meta: databaseType:bibtex;}" + OS.NEWLINE, stringWriter.toString()); + } + + @Test + void writeEntryWithMonthApril() throws Exception { + BibEntry entry = new BibEntry.Builder(StandardEntryType.Misc) + .field(StandardField.MONTH, "apr") + .build(); + database.insertEntry(entry); + + databaseWriter.savePartOfDatabase(bibtexContext, Collections.singletonList(entry)); + + assertEquals(OS.NEWLINE + + "@Misc{," + OS.NEWLINE + + " month = {apr}," + OS.NEWLINE + + "}" + OS.NEWLINE + OS.NEWLINE + + "@Comment{jabref-meta: databaseType:bibtex;}" + OS.NEWLINE, stringWriter.toString()); + } + + @Test + void roundtripWithArticleMonths() throws Exception { + Path testBibtexFile = Paths.get("src/test/resources/testbib/articleWithMonths.bib"); + Charset encoding = StandardCharsets.UTF_8; + ParserResult result = new BibtexParser(importFormatPreferences, fileMonitor).parse(Importer.getReader(testBibtexFile, encoding)); + + when(preferences.getEncoding()).thenReturn(encoding); + when(preferences.isSaveInOriginalOrder()).thenReturn(true); + BibDatabaseContext context = new BibDatabaseContext(result.getDatabase(), result.getMetaData(), + new Defaults(BibDatabaseMode.BIBTEX)); + + databaseWriter.savePartOfDatabase(context, result.getDatabase().getEntries()); + try (Scanner scanner = new Scanner(testBibtexFile, encoding.name())) { + assertEquals(scanner.useDelimiter("\\A").next(), stringWriter.toString()); + } + } + + @Test + void roundtripWithComplexBib() throws Exception { Path testBibtexFile = Paths.get("src/test/resources/testbib/complex.bib"); Charset encoding = StandardCharsets.UTF_8; ParserResult result = new BibtexParser(importFormatPreferences, fileMonitor).parse(Importer.getReader(testBibtexFile, encoding)); diff --git a/src/test/java/org/jabref/logic/importer/fileformat/BibtexParserTest.java b/src/test/java/org/jabref/logic/importer/fileformat/BibtexParserTest.java index 71b452cdd8b..db994b94d12 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/BibtexParserTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/BibtexParserTest.java @@ -26,6 +26,7 @@ import org.jabref.model.entry.BibEntryType; import org.jabref.model.entry.BibtexString; import org.jabref.model.entry.Date; +import org.jabref.model.entry.Month; import org.jabref.model.entry.field.BibField; import org.jabref.model.entry.field.FieldPriority; import org.jabref.model.entry.field.InternalField; @@ -1711,4 +1712,78 @@ void parseYear() throws Exception { assertEquals(new Date(2003), result.get().getPublicationDate().get()); } + + @Test + void parseEntryUsingStringConstantsForTwoAuthorsWithEtAsStringConstant() throws ParseException { + // source of the example: /~https://github.com/JabRef/help.jabref.org/blob/gh-pages/en/Strings.md + Collection parsed = parser + .parseEntries("@String { kopp = \"Kopp, Oliver\" }" + + "@String { kubovy = \"Kubovy, Jan\" }" + + "@String { et = \" and \" }" + + "@Misc{m1, author = kopp # et # kubovy }" ); + + BibEntry expectedEntry = new BibEntry.Builder(StandardEntryType.Misc) + .citeKey("m1") + .field(StandardField.AUTHOR, "#kopp##et##kubovy#") + .build(); + + assertEquals(List.of(expectedEntry), parsed); + } + + @Test + void parseStringConstantsForTwoAuthorsHasCorrectBibTeXEntry() throws ParseException { + // source of the example: /~https://github.com/JabRef/help.jabref.org/blob/gh-pages/en/Strings.md + Collection parsed = parser + .parseEntries("@String { kopp = \"Kopp, Oliver\" }" + + "@String { kubovy = \"Kubovy, Jan\" }" + + "@String { et = \" and \" }" + + "@Misc{m2, author = kopp # \" and \" # kubovy }" ); + + BibEntry expectedEntry = new BibEntry.Builder(StandardEntryType.Misc) + .citeKey("m2") + .field(StandardField.AUTHOR, "#kopp# and #kubovy#") + .build(); + + assertEquals(List.of(expectedEntry), parsed); + } + + @Test + void parseStringConstantsForTwoAuthors() throws ParseException { + // source of the example: /~https://github.com/JabRef/help.jabref.org/blob/gh-pages/en/Strings.md + Collection parsed = parser + .parseEntries("@String { kopp = \"Kopp, Oliver\" }" + + "@String { kubovy = \"Kubovy, Jan\" }" + + "@String { et = \" and \" }" + + "@Misc{m2, author = kopp # \" and \" # kubovy }" ); + + assertEquals("#kopp# and #kubovy#", parsed.iterator().next().getField(StandardField.AUTHOR).get()); + } + + @Test + void textAprilIsParsedAsMonthApril() throws ParseException { + Optional result = parser.parseSingleEntry("@Misc{m, month = \"apr\" }" ); + + assertEquals(Month.APRIL, result.get().getMonth().get()); + } + + @Test + void textAprilIsDisplayedAsConstant() throws ParseException { + Optional result = parser.parseSingleEntry("@Misc{m, month = \"apr\" }" ); + + assertEquals("apr", result.get().getField(StandardField.MONTH).get()); + } + + @Test + void bibTeXConstantAprilIsParsedAsMonthApril() throws ParseException { + Optional result = parser.parseSingleEntry("@Misc{m, month = apr }" ); + + assertEquals(Month.APRIL, result.get().getMonth().get()); + } + + @Test + void bibTeXConstantAprilIsDisplayedAsConstant() throws ParseException { + Optional result = parser.parseSingleEntry("@Misc{m, month = apr }" ); + + assertEquals("#apr#", result.get().getField(StandardField.MONTH).get()); + } } diff --git a/src/test/java/org/jabref/model/entry/BibtexStringTest.java b/src/test/java/org/jabref/model/entry/BibtexStringTest.java index 1341ac43b33..c6b251410f4 100644 --- a/src/test/java/org/jabref/model/entry/BibtexStringTest.java +++ b/src/test/java/org/jabref/model/entry/BibtexStringTest.java @@ -9,35 +9,117 @@ public class BibtexStringTest { @Test - public void test() { + public void initalizationWorksCorrectly() { // Instantiate BibtexString bs = new BibtexString("AAA", "An alternative action"); - bs.setId("ID"); - assertEquals("ID", bs.getId()); assertEquals("AAA", bs.getName()); assertEquals("An alternative action", bs.getContent()); assertEquals(BibtexString.Type.OTHER, bs.getType()); + } + + @Test + public void idIsUpdatedAtSetId() { + // Instantiate + BibtexString bs = new BibtexString("AAA", "An alternative action"); + bs.setId("ID"); + assertEquals("ID", bs.getId()); + } + + @Test + public void cloningDoesNotChangeContents() { + BibtexString bs = new BibtexString("AAA", "An alternative action"); + bs.setId("ID"); - // Clone BibtexString bs2 = (BibtexString) bs.clone(); + assertEquals(bs.getId(), bs2.getId()); assertEquals(bs.getName(), bs2.getName()); assertEquals(bs.getContent(), bs2.getContent()); assertEquals(bs.getType(), bs2.getType()); + } + + @Test + public void clonedBibtexStringEqualsOriginalString() { + BibtexString bibtexString = new BibtexString("AAA", "An alternative action"); + bibtexString.setId("ID"); + + BibtexString clone = (BibtexString) bibtexString.clone(); + + assertEquals(bibtexString, clone); + } - // Change cloned BibtexString + @Test + public void usingTheIdGeneratorDoesNotHitTheOriginalId() { + // Instantiate + BibtexString bs = new BibtexString("AAA", "An alternative action"); + bs.setId("ID"); + BibtexString bs2 = (BibtexString) bs.clone(); bs2.setId(IdGenerator.next()); assertNotEquals(bs.getId(), bs2.getId()); + } + + @Test + public void settingFieldsInACloneWorks() { + // Instantiate + BibtexString bs = new BibtexString("AAA", "An alternative action"); + bs.setId("ID"); + BibtexString bs2 = (BibtexString) bs.clone(); + + bs2.setId(IdGenerator.next()); bs2.setName("aOG"); assertEquals(BibtexString.Type.AUTHOR, bs2.getType()); + bs2.setContent("Oscar Gustafsson"); assertEquals("aOG", bs2.getName()); assertEquals("Oscar Gustafsson", bs2.getContent()); } + @Test + public void modifyingACloneDoesNotModifyTheOriginalEntry() { + // Instantiate + BibtexString original = new BibtexString("AAA", "An alternative action"); + original.setId("ID"); + + BibtexString clone = (BibtexString) original.clone(); + clone.setId(IdGenerator.next()); + clone.setName("aOG"); + clone.setContent("Oscar Gustafsson"); + + assertEquals("AAA", original.getName()); + assertEquals("An alternative action", original.getContent()); + } + @Test public void getContentNeverReturnsNull() { BibtexString bs = new BibtexString("SomeName", null); assertNotNull(bs.getContent()); } + + @Test + public void authorTypeCorrectlyDetermined() { + // Source of the example: https://help.jabref.org/en/Strings + BibtexString bibtexString = new BibtexString("aKopp", "KoppOliver"); + assertEquals(BibtexString.Type.AUTHOR, bibtexString.getType()); + } + + @Test + public void institutionTypeCorrectlyDetermined() { + // Source of the example: https://help.jabref.org/en/Strings + BibtexString bibtexString = new BibtexString("iMIT", "{Massachusetts Institute of Technology ({MIT})}"); + assertEquals(BibtexString.Type.INSTITUTION, bibtexString.getType()); + } + + @Test + public void otherTypeCorrectlyDeterminedForLowerCase() { + // Source of the example: https://help.jabref.org/en/Strings + BibtexString bibtexString = new BibtexString("anct", "Anecdote"); + assertEquals(BibtexString.Type.OTHER, bibtexString.getType()); + } + + @Test + public void otherTypeCorrectlyDeterminedForUpperCase() { + // Source of the example: https://help.jabref.org/en/Strings + BibtexString bibtexString = new BibtexString("lTOSCA", "Topology and Orchestration Specification for Cloud Applications"); + assertEquals(BibtexString.Type.OTHER, bibtexString.getType()); + } } diff --git a/src/test/resources/testbib/articleWithMonths.bib b/src/test/resources/testbib/articleWithMonths.bib new file mode 100644 index 00000000000..6898d754ade --- /dev/null +++ b/src/test/resources/testbib/articleWithMonths.bib @@ -0,0 +1,10 @@ +% Encoding: UTF-8 +@Article{constant, + month = apr +} + +@Article{text, + month = {apr} +} + +@Comment{jabref-meta: databaseType:bibtex;} From 40c2a868e37b266031c81fc9e2f191a8b5295699 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sun, 27 Oct 2019 22:58:27 +0100 Subject: [PATCH 2/6] Adress review comments - remove builder - move tests - replace scanner by Files --- .../java/org/jabref/model/entry/BibEntry.java | 36 +++---------------- .../logic/bibtex/BibEntryWriterTest.java | 30 ++++++++++++++++ .../exporter/BibtexDatabaseWriterTest.java | 32 ----------------- .../importer/fileformat/BibtexParserTest.java | 14 ++++---- 4 files changed, 41 insertions(+), 71 deletions(-) diff --git a/src/main/java/org/jabref/model/entry/BibEntry.java b/src/main/java/org/jabref/model/entry/BibEntry.java index d3b83ec7460..4212c48cc99 100644 --- a/src/main/java/org/jabref/model/entry/BibEntry.java +++ b/src/main/java/org/jabref/model/entry/BibEntry.java @@ -42,6 +42,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * Represents a BibTex / BibLaTeX entry. + * + * In case you search for a builder as described in Item 2 of the book "Effective Java", you won't find one. Please use the methods {@link #withCiteKey(String)} and {@link #withField(Field, String)}. + */ public class BibEntry implements Cloneable { public static final EntryType DEFAULT_TYPE = StandardEntryType.Misc; @@ -71,42 +76,11 @@ public class BibEntry implements Cloneable { */ private boolean changed; - /** - * A simple builder to enable quick creation of BibEntry instances. - * - * Builder pattern as described in Item 2 of the book "Effective Java". - */ - public static class Builder { - - private BibEntry bibEntry; - - public Builder(EntryType type) { - Objects.requireNonNull(type); - bibEntry = new BibEntry(type); - } - - public Builder citeKey(String citeKey) { - bibEntry.setCiteKey(citeKey); - return this; - } - - public Builder field(Field field, String value) { - bibEntry.setField(field, value); - return this; - } - - public BibEntry build() { - return bibEntry; - } - - } - /** * Constructs a new BibEntry. The internal ID is set to IdGenerator.next() */ public BibEntry() { this(IdGenerator.next(), DEFAULT_TYPE); - } /** diff --git a/src/test/java/org/jabref/logic/bibtex/BibEntryWriterTest.java b/src/test/java/org/jabref/logic/bibtex/BibEntryWriterTest.java index c8171a403c0..9e9dd427456 100644 --- a/src/test/java/org/jabref/logic/bibtex/BibEntryWriterTest.java +++ b/src/test/java/org/jabref/logic/bibtex/BibEntryWriterTest.java @@ -426,6 +426,36 @@ void monthFieldSpecialSyntax() throws IOException { assertEquals(bibtexEntry, actual); } + @Test + void constantMonthApril() throws Exception { + BibEntry entry = new BibEntry(StandardEntryType.Misc) + .withField(StandardField.MONTH, "#apr#"); + + StringWriter stringWriter = new StringWriter(); + writer.write(entry, stringWriter, BibDatabaseMode.BIBTEX); + + assertEquals(OS.NEWLINE + + "@Misc{," + OS.NEWLINE + + " month = apr," + OS.NEWLINE + + "}" + OS.NEWLINE + OS.NEWLINE + + "@Comment{jabref-meta: databaseType:bibtex;}" + OS.NEWLINE, stringWriter.toString()); + } + + @Test + void monthApril() throws Exception { + BibEntry entry = new BibEntry(StandardEntryType.Misc) + .withField(StandardField.MONTH, "apr"); + + StringWriter stringWriter = new StringWriter(); + writer.write(entry, stringWriter, BibDatabaseMode.BIBTEX); + + assertEquals(OS.NEWLINE + + "@Misc{," + OS.NEWLINE + + " month = {apr}," + OS.NEWLINE + + "}" + OS.NEWLINE + OS.NEWLINE + + "@Comment{jabref-meta: databaseType:bibtex;}" + OS.NEWLINE, stringWriter.toString()); + } + @Test void addFieldWithLongerLength() throws IOException { // @formatter:off diff --git a/src/test/java/org/jabref/logic/exporter/BibtexDatabaseWriterTest.java b/src/test/java/org/jabref/logic/exporter/BibtexDatabaseWriterTest.java index 2892b3944d0..0ec73d0ceac 100644 --- a/src/test/java/org/jabref/logic/exporter/BibtexDatabaseWriterTest.java +++ b/src/test/java/org/jabref/logic/exporter/BibtexDatabaseWriterTest.java @@ -288,38 +288,6 @@ void writeEntryWithCustomizedTypeAlsoWritesTypeDeclaration() throws Exception { stringWriter.toString()); } - @Test - void writeEntryWithConstantMonthApril() throws Exception { - BibEntry entry = new BibEntry.Builder(StandardEntryType.Misc) - .field(StandardField.MONTH, "#apr#") - .build(); - database.insertEntry(entry); - - databaseWriter.savePartOfDatabase(bibtexContext, Collections.singletonList(entry)); - - assertEquals(OS.NEWLINE + - "@Misc{," + OS.NEWLINE + - " month = apr," + OS.NEWLINE + - "}" + OS.NEWLINE + OS.NEWLINE + - "@Comment{jabref-meta: databaseType:bibtex;}" + OS.NEWLINE, stringWriter.toString()); - } - - @Test - void writeEntryWithMonthApril() throws Exception { - BibEntry entry = new BibEntry.Builder(StandardEntryType.Misc) - .field(StandardField.MONTH, "apr") - .build(); - database.insertEntry(entry); - - databaseWriter.savePartOfDatabase(bibtexContext, Collections.singletonList(entry)); - - assertEquals(OS.NEWLINE + - "@Misc{," + OS.NEWLINE + - " month = {apr}," + OS.NEWLINE + - "}" + OS.NEWLINE + OS.NEWLINE + - "@Comment{jabref-meta: databaseType:bibtex;}" + OS.NEWLINE, stringWriter.toString()); - } - @Test void roundtripWithArticleMonths() throws Exception { Path testBibtexFile = Paths.get("src/test/resources/testbib/articleWithMonths.bib"); diff --git a/src/test/java/org/jabref/logic/importer/fileformat/BibtexParserTest.java b/src/test/java/org/jabref/logic/importer/fileformat/BibtexParserTest.java index db994b94d12..1dcd5ba75c8 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/BibtexParserTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/BibtexParserTest.java @@ -1722,10 +1722,9 @@ void parseEntryUsingStringConstantsForTwoAuthorsWithEtAsStringConstant() throws "@String { et = \" and \" }" + "@Misc{m1, author = kopp # et # kubovy }" ); - BibEntry expectedEntry = new BibEntry.Builder(StandardEntryType.Misc) - .citeKey("m1") - .field(StandardField.AUTHOR, "#kopp##et##kubovy#") - .build(); + BibEntry expectedEntry = new BibEntry(StandardEntryType.Misc) + .withCiteKey("m1") + .withField(StandardField.AUTHOR, "#kopp##et##kubovy#"); assertEquals(List.of(expectedEntry), parsed); } @@ -1739,10 +1738,9 @@ void parseStringConstantsForTwoAuthorsHasCorrectBibTeXEntry() throws ParseExcept "@String { et = \" and \" }" + "@Misc{m2, author = kopp # \" and \" # kubovy }" ); - BibEntry expectedEntry = new BibEntry.Builder(StandardEntryType.Misc) - .citeKey("m2") - .field(StandardField.AUTHOR, "#kopp# and #kubovy#") - .build(); + BibEntry expectedEntry = new BibEntry(StandardEntryType.Misc) + .withCiteKey("m2") + .withField(StandardField.AUTHOR, "#kopp# and #kubovy#"); assertEquals(List.of(expectedEntry), parsed); } From 2a46d187464eded2d51f99ac304d95b6a19e1fc9 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sun, 27 Oct 2019 23:07:50 +0100 Subject: [PATCH 3/6] Use old values in InternalFields (and rearrange again) --- .../java/org/jabref/model/entry/field/InternalField.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/jabref/model/entry/field/InternalField.java b/src/main/java/org/jabref/model/entry/field/InternalField.java index b825069568d..2338da7fa1b 100644 --- a/src/main/java/org/jabref/model/entry/field/InternalField.java +++ b/src/main/java/org/jabref/model/entry/field/InternalField.java @@ -10,17 +10,17 @@ * JabRef internal fields */ public enum InternalField implements Field { - MARKED_INTERNAL("__markedentry"), // used in old versions of JabRef. Currently used for conversion only OWNER("owner"), TIMESTAMP("timestamp", FieldProperty.DATE), GROUPS("groups"), KEY_FIELD("bibtexkey"), TYPE_HEADER("entrytype"), OBSOLETE_TYPE_HEADER("bibtextype"), + MARKED_INTERNAL("__markedentry"), // used in old versions of JabRef. Currently used for conversion only // all field names starting with "Jabref-internal-" are not appearing in .bib files - BIBTEX_STRING("JabRef-internal-bibtex-string"), // marker that the content is just a BibTeX string - INTERNAL_ALL_FIELD("JabRef-internal-all"), // virtual field to denote "all fields" - INTERNAL_ALL_TEXT_FIELDS_FIELD("JabRef-internal-all-text-fields"), // virtual field to denote "all text fields" + BIBTEX_STRING("__string"), // marker that the content is just a BibTeX string + INTERNAL_ALL_FIELD("all"), // virtual field to denote "all fields". Used in the meta data serialiization for save actions. + INTERNAL_ALL_TEXT_FIELDS_FIELD("all-text-fields"), // virtual field to denote "all text fields". Used in the meta data serialiization for save actions. INTERNAL_ID_FIELD("JabRef-internal-id"); private final String name; From 48d76c67253d769d0f914b0f729e565c3f6968a5 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Mon, 28 Oct 2019 23:23:09 +0100 Subject: [PATCH 4/6] Fix modifiation of unmodifiable set --- .../jabref/logic/shared/DBMSSynchronizer.java | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/jabref/logic/shared/DBMSSynchronizer.java b/src/main/java/org/jabref/logic/shared/DBMSSynchronizer.java index 419e3775d6c..b16a94f72e8 100644 --- a/src/main/java/org/jabref/logic/shared/DBMSSynchronizer.java +++ b/src/main/java/org/jabref/logic/shared/DBMSSynchronizer.java @@ -30,7 +30,6 @@ import org.jabref.model.entry.event.EntryEvent; import org.jabref.model.entry.event.EntryEventSource; import org.jabref.model.entry.event.FieldChangedEvent; -import org.jabref.model.entry.field.Field; import org.jabref.model.metadata.MetaData; import org.jabref.model.metadata.event.MetaDataChangedEvent; import org.jabref.model.util.FileUpdateMonitor; @@ -191,20 +190,17 @@ public void synchronizeLocalDatabase() { localEntry.setType(sharedEntry.get().getType(), EntryEventSource.SHARED); localEntry.getSharedBibEntryData() .setVersion(sharedEntry.get().getSharedBibEntryData().getVersion()); - for (Field field : sharedEntry.get().getFields()) { - Optional sharedFieldValue = sharedEntry.get().getField(field); - if (sharedFieldValue.isPresent()) { - localEntry.setField(field, sharedFieldValue.get(), EntryEventSource.SHARED); - } - } - - Set redundantLocalEntryFields = localEntry.getFields(); - redundantLocalEntryFields.removeAll(sharedEntry.get().getFields()); - - // remove not existing fields - for (Field redundantField : redundantLocalEntryFields) { - localEntry.clearField(redundantField, EntryEventSource.SHARED); - } + // copy remote values to local entry + sharedEntry.get().getFieldMap().forEach( + (field, value) -> localEntry.setField(field, value, EntryEventSource.SHARED) + ); + + // locally remove not existing fields + localEntry.getFields().stream() + .filter(field -> !sharedEntry.get().hasField(field)) + .forEach( + field -> localEntry.clearField(field, EntryEventSource.SHARED) + ); } } } From 1632196506be8a98f96134352bef3f07a65f7497 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Mon, 28 Oct 2019 23:23:16 +0100 Subject: [PATCH 5/6] Format code --- .../jabref/logic/shared/DBMSSynchronizer.java | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/jabref/logic/shared/DBMSSynchronizer.java b/src/main/java/org/jabref/logic/shared/DBMSSynchronizer.java index b16a94f72e8..f93c3193342 100644 --- a/src/main/java/org/jabref/logic/shared/DBMSSynchronizer.java +++ b/src/main/java/org/jabref/logic/shared/DBMSSynchronizer.java @@ -40,8 +40,8 @@ import org.slf4j.LoggerFactory; /** - * Synchronizes the shared or local databases with their opposite side. - * Local changes are pushed by {@link EntryEvent} using Google's Guava EventBus. + * Synchronizes the shared or local databases with their opposite side. Local changes are pushed by {@link EntryEvent} + * using Google's Guava EventBus. */ public class DBMSSynchronizer implements DatabaseSynchronizer { @@ -134,11 +134,10 @@ public void listen(MetaDataChangedEvent event) { } /** - * Sets the table structure of shared database if needed and pulls all shared entries - * to the new local database. + * Sets the table structure of shared database if needed and pulls all shared entries to the new local database. * - * @throws DatabaseNotSupportedException if the version of shared database does not match - * the version of current shared database support ({@link DBMSProcessor}). + * @throws DatabaseNotSupportedException if the version of shared database does not match the version of current + * shared database support ({@link DBMSProcessor}). */ public void initializeDatabases() throws DatabaseNotSupportedException { try { @@ -162,8 +161,8 @@ public void initializeDatabases() throws DatabaseNotSupportedException { } /** - * Synchronizes the local database with shared one. - * Possible update types are removal, update or insert of a {@link BibEntry}. + * Synchronizes the local database with shared one. Possible update types are removal, update or insert of a {@link + * BibEntry}. */ @Override public void synchronizeLocalDatabase() { @@ -219,7 +218,7 @@ public void synchronizeLocalDatabase() { * Removes all local entries which are not present on shared database. * * @param localEntries List of {@link BibEntry} the entries should be removed from - * @param sharedIDs Set of all IDs which are present on shared database + * @param sharedIDs Set of all IDs which are present on shared database */ private void removeNotSharedEntries(List localEntries, Set sharedIDs) { for (int i = 0; i < localEntries.size(); i++) { @@ -324,8 +323,8 @@ public void pullChanges() { } /** - * Checks whether the current SQL connection is valid. - * In case that the connection is not valid a new {@link ConnectionLostEvent} is going to be sent. + * Checks whether the current SQL connection is valid. In case that the connection is not valid a new {@link + * ConnectionLostEvent} is going to be sent. * * @return true if the connection is valid, else false. */ @@ -336,7 +335,6 @@ public boolean checkCurrentConnection() { eventBus.post(new ConnectionLostEvent(bibDatabaseContext)); } return isValid; - } catch (SQLException e) { LOGGER.error("SQL Error:", e); return false; @@ -347,7 +345,8 @@ public boolean checkCurrentConnection() { * Checks whether the {@link EntryEventSource} of an {@link EntryEvent} is crucial for this class. * * @param event An {@link EntryEvent} - * @return true if the event is able to trigger operations in {@link DBMSSynchronizer}, else false + * @return true if the event is able to trigger operations in {@link DBMSSynchronizer}, else + * false */ public boolean isEventSourceAccepted(EntryEvent event) { EntryEventSource eventSource = event.getEntryEventSource(); From 6893dc502a6080f5dfc2e4da18bb75cd8437bbce Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Mon, 28 Oct 2019 23:28:54 +0100 Subject: [PATCH 6/6] Format code and fix test --- .../logic/bibtex/BibEntryWriterTest.java | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/test/java/org/jabref/logic/bibtex/BibEntryWriterTest.java b/src/test/java/org/jabref/logic/bibtex/BibEntryWriterTest.java index 9e9dd427456..b2e6183c8ed 100644 --- a/src/test/java/org/jabref/logic/bibtex/BibEntryWriterTest.java +++ b/src/test/java/org/jabref/logic/bibtex/BibEntryWriterTest.java @@ -108,30 +108,30 @@ void writeEntryWithFile() throws Exception { @Test void writeEntryWithOrField() throws Exception { - StringWriter stringWriter = new StringWriter(); - - BibEntry entry = new BibEntry(StandardEntryType.InBook); - //set an required OR field (author/editor) - entry.setField(StandardField.EDITOR, "Foo Bar"); - entry.setField(StandardField.JOURNAL, "International Journal of Something"); - //set an optional field - entry.setField(StandardField.NUMBER, "1"); - entry.setField(StandardField.NOTE, "some note"); - - writer.write(entry, stringWriter, BibDatabaseMode.BIBTEX); - - String actual = stringWriter.toString(); - - // @formatter:off - String expected = OS.NEWLINE + "@InBook{," + OS.NEWLINE + - " editor = {Foo Bar}," + OS.NEWLINE + - " note = {some note}," + OS.NEWLINE + - " number = {1}," + OS.NEWLINE + - " journal = {International Journal of Something}," + OS.NEWLINE + - "}" + OS.NEWLINE; - // @formatter:on - - assertEquals(expected, actual); + StringWriter stringWriter = new StringWriter(); + + BibEntry entry = new BibEntry(StandardEntryType.InBook); + //set an required OR field (author/editor) + entry.setField(StandardField.EDITOR, "Foo Bar"); + entry.setField(StandardField.JOURNAL, "International Journal of Something"); + //set an optional field + entry.setField(StandardField.NUMBER, "1"); + entry.setField(StandardField.NOTE, "some note"); + + writer.write(entry, stringWriter, BibDatabaseMode.BIBTEX); + + String actual = stringWriter.toString(); + + // @formatter:off + String expected = OS.NEWLINE + "@InBook{," + OS.NEWLINE + + " editor = {Foo Bar}," + OS.NEWLINE + + " note = {some note}," + OS.NEWLINE + + " number = {1}," + OS.NEWLINE + + " journal = {International Journal of Something}," + OS.NEWLINE + + "}" + OS.NEWLINE; + // @formatter:on + + assertEquals(expected, actual); } @Test @@ -435,10 +435,10 @@ void constantMonthApril() throws Exception { writer.write(entry, stringWriter, BibDatabaseMode.BIBTEX); assertEquals(OS.NEWLINE + - "@Misc{," + OS.NEWLINE + - " month = apr," + OS.NEWLINE + - "}" + OS.NEWLINE + OS.NEWLINE + - "@Comment{jabref-meta: databaseType:bibtex;}" + OS.NEWLINE, stringWriter.toString()); + "@Misc{," + OS.NEWLINE + + " month = apr," + OS.NEWLINE + + "}" + OS.NEWLINE, + stringWriter.toString()); } @Test @@ -450,10 +450,10 @@ void monthApril() throws Exception { writer.write(entry, stringWriter, BibDatabaseMode.BIBTEX); assertEquals(OS.NEWLINE + - "@Misc{," + OS.NEWLINE + - " month = {apr}," + OS.NEWLINE + - "}" + OS.NEWLINE + OS.NEWLINE + - "@Comment{jabref-meta: databaseType:bibtex;}" + OS.NEWLINE, stringWriter.toString()); + "@Misc{," + OS.NEWLINE + + " month = {apr}," + OS.NEWLINE + + "}" + OS.NEWLINE, + stringWriter.toString()); } @Test