Skip to content

Commit 14e9790

Browse files
authoredMar 29, 2020
Fix package of PreviewLayout (#5702)
... and also improve (bst) VM (and introduce BstPreviewLayout) * Move PreviewLayout to org.jabref.logic.preview * Modernize code of (bst) VM * Add IEEEtran.bst * Introduce BstPreviewLayout * Fix Bst.g to allow "_" as identifier * Fix quotes and other output of IEEEtran.bst * Use public final instead of getters
1 parent e461523 commit 14e9790

27 files changed

+314
-95
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Use `public final` instead of getters to offer access to immutable variables
2+
3+
## Context and Problem Statement
4+
5+
When making immutable data accessible in a java class, should it be using getters or by non-modifiable fields?
6+
7+
## Considered Options
8+
9+
* Offer public static field
10+
* Offer getters
11+
12+
## Decision Outcome
13+
14+
Chosen option: "Offer public static field", because getters used to be a convention which was even more manifested due to libraries depending on the existence on getters/setters. In the case of immutable variables, adding public getters is just useless since one is not hiding anything.
15+
16+
### Positive Consequences
17+
18+
* Shorter code
19+
20+
### Negative Consequences
21+
22+
* new comers could get confused, because getters/setters are still teached

‎src/main/java/org/jabref/gui/DragAndDropDataFormats.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import javafx.scene.input.DataFormat;
66

7-
import org.jabref.logic.citationstyle.PreviewLayout;
7+
import org.jabref.logic.preview.PreviewLayout;
88

99
/**
1010
* Contains all the different {@link DataFormat}s that may occur in JabRef.

‎src/main/java/org/jabref/gui/maintable/RightClickMenu.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import org.jabref.gui.specialfields.SpecialFieldMenuItemFactory;
2424
import org.jabref.logic.citationstyle.CitationStyleOutputFormat;
2525
import org.jabref.logic.citationstyle.CitationStylePreviewLayout;
26-
import org.jabref.logic.citationstyle.PreviewLayout;
26+
import org.jabref.logic.preview.PreviewLayout;
2727
import org.jabref.model.entry.field.SpecialField;
2828
import org.jabref.preferences.JabRefPreferences;
2929
import org.jabref.preferences.PreferencesService;

‎src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
import org.jabref.gui.util.BaseDialog;
1919
import org.jabref.gui.util.ValueTableCellFactory;
2020
import org.jabref.gui.util.ViewModelTableRowFactory;
21-
import org.jabref.logic.citationstyle.TextBasedPreviewLayout;
2221
import org.jabref.logic.l10n.Localization;
22+
import org.jabref.logic.layout.TextBasedPreviewLayout;
2323
import org.jabref.logic.openoffice.OOBibStyle;
2424
import org.jabref.logic.openoffice.StyleLoader;
2525
import org.jabref.logic.util.TestEntry;

‎src/main/java/org/jabref/gui/preferences/PreviewTabView.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
import org.jabref.gui.preview.PreviewViewer;
3030
import org.jabref.gui.util.IconValidationDecorator;
3131
import org.jabref.gui.util.ViewModelListCellFactory;
32-
import org.jabref.logic.citationstyle.PreviewLayout;
3332
import org.jabref.logic.l10n.Localization;
33+
import org.jabref.logic.preview.PreviewLayout;
3434
import org.jabref.logic.util.TestEntry;
3535
import org.jabref.model.database.BibDatabaseContext;
3636
import org.jabref.preferences.JabRefPreferences;

‎src/main/java/org/jabref/gui/preferences/PreviewTabViewModel.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@
3434
import org.jabref.gui.util.TaskExecutor;
3535
import org.jabref.logic.citationstyle.CitationStyle;
3636
import org.jabref.logic.citationstyle.CitationStylePreviewLayout;
37-
import org.jabref.logic.citationstyle.PreviewLayout;
38-
import org.jabref.logic.citationstyle.TextBasedPreviewLayout;
3937
import org.jabref.logic.l10n.Localization;
38+
import org.jabref.logic.layout.TextBasedPreviewLayout;
39+
import org.jabref.logic.preview.PreviewLayout;
4040
import org.jabref.preferences.JabRefPreferences;
4141
import org.jabref.preferences.PreviewPreferences;
4242

‎src/main/java/org/jabref/gui/preview/CopyCitationAction.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@
1818
import org.jabref.logic.citationstyle.CitationStyleGenerator;
1919
import org.jabref.logic.citationstyle.CitationStyleOutputFormat;
2020
import org.jabref.logic.citationstyle.CitationStylePreviewLayout;
21-
import org.jabref.logic.citationstyle.PreviewLayout;
2221
import org.jabref.logic.l10n.Localization;
2322
import org.jabref.logic.layout.Layout;
2423
import org.jabref.logic.layout.LayoutFormatterPreferences;
2524
import org.jabref.logic.layout.LayoutHelper;
25+
import org.jabref.logic.preview.PreviewLayout;
2626
import org.jabref.logic.util.OS;
2727
import org.jabref.model.entry.BibEntry;
2828
import org.jabref.preferences.PreviewPreferences;

‎src/main/java/org/jabref/gui/preview/PreviewPanel.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
import org.jabref.gui.icon.IconTheme;
2424
import org.jabref.gui.keyboard.KeyBinding;
2525
import org.jabref.gui.keyboard.KeyBindingRepository;
26-
import org.jabref.logic.citationstyle.PreviewLayout;
2726
import org.jabref.logic.l10n.Localization;
27+
import org.jabref.logic.preview.PreviewLayout;
2828
import org.jabref.model.database.BibDatabaseContext;
2929
import org.jabref.model.entry.BibEntry;
3030
import org.jabref.preferences.JabRefPreferences;

‎src/main/java/org/jabref/gui/preview/PreviewViewer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
import org.jabref.gui.util.BackgroundTask;
2424
import org.jabref.gui.util.TaskExecutor;
2525
import org.jabref.gui.util.ThemeLoader;
26-
import org.jabref.logic.citationstyle.PreviewLayout;
2726
import org.jabref.logic.exporter.ExporterFactory;
2827
import org.jabref.logic.l10n.Localization;
28+
import org.jabref.logic.preview.PreviewLayout;
2929
import org.jabref.logic.search.SearchQuery;
3030
import org.jabref.model.database.BibDatabaseContext;
3131
import org.jabref.model.entry.BibEntry;

‎src/main/java/org/jabref/gui/util/CustomLocalDragboard.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import org.jabref.gui.DragAndDropDataFormats;
99
import org.jabref.gui.StateManager;
10-
import org.jabref.logic.citationstyle.PreviewLayout;
10+
import org.jabref.logic.preview.PreviewLayout;
1111
import org.jabref.model.entry.BibEntry;
1212

1313
/**

‎src/main/java/org/jabref/logic/bibtex/BibEntryWriter.java

+1-5
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,7 @@ public void writeWithoutPrependedNewlines(BibEntry entry, Writer out, BibDatabas
8787
}
8888

8989
/**
90-
* Write fields in the order of requiredFields, optionalFields and other fields, but does not sort the fields.
91-
*
92-
* @param entry
93-
* @param out
94-
* @throws IOException
90+
* Writes fields in the order of requiredFields, optionalFields and other fields, but does not sort the fields.
9591
*/
9692
private void writeRequiredFieldsFirstRemainingFieldsSecond(BibEntry entry, Writer out,
9793
BibDatabaseMode bibDatabaseMode) throws IOException {

‎src/main/java/org/jabref/logic/bibtex/FieldContentFormatter.java

-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ public FieldContentFormatter(FieldContentFormatterPreferences preferences) {
4343
*/
4444
public String format(String fieldContent, Field field) {
4545
if (multiLineFields.contains(field)) {
46-
// Unify line breaks
4746
return StringUtil.unifyLineBreaks(fieldContent, OS.NEWLINE);
4847
}
4948

‎src/main/java/org/jabref/logic/bibtex/FieldContentFormatterPreferences.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ public class FieldContentFormatterPreferences {
99

1010
private final List<Field> nonWrappableFields;
1111

12+
/**
13+
* Constructor defining that there are not any non-wrappable fields
14+
*/
1215
public FieldContentFormatterPreferences() {
13-
// This constructor is only to allow an empty constructor in SavePreferences
1416
this.nonWrappableFields = Collections.emptyList();
1517
}
1618

‎src/main/java/org/jabref/logic/bibtex/FieldWriter.java

+35-21
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,22 @@
66
import org.jabref.model.entry.field.StandardField;
77
import org.jabref.model.strings.StringUtil;
88

9+
import org.slf4j.Logger;
10+
import org.slf4j.LoggerFactory;
11+
912
/**
10-
* Obeys following settings:
11-
* * JabRefPreferences.RESOLVE_STRINGS_ALL_FIELDS
12-
* * JabRefPreferences.DO_NOT_RESOLVE_STRINGS_FOR
13-
* * JabRefPreferences.WRITEFIELD_WRAPFIELD
13+
* Converts JabRef's internal BibTeX representation of a BibTeX field to BibTeX text representation
1414
*/
1515
public class FieldWriter {
1616

17+
private static final Logger LOGGER = LoggerFactory.getLogger(FieldWriter.class);
18+
1719
private static final char FIELD_START = '{';
1820
private static final char FIELD_END = '}';
21+
1922
private final boolean neverFailOnHashes;
2023
private final FieldWriterPreferences preferences;
2124
private final FieldContentFormatter formatter;
22-
private StringBuilder stringBuilder;
2325

2426
public FieldWriter(FieldWriterPreferences preferences) {
2527
this(true, preferences);
@@ -58,12 +60,15 @@ private static void checkBraces(String text) throws InvalidFieldValueException {
5860

5961
// Then we throw an exception if the error criteria are met.
6062
if (!(right == 0) && (left == 0)) {
63+
LOGGER.error("Unescaped '}' character without opening bracket ends string prematurely. Field value: {}", text );
6164
throw new InvalidFieldValueException("Unescaped '}' character without opening bracket ends string prematurely. Field value: " + text);
6265
}
6366
if (!(right == 0) && (right < left)) {
67+
LOGGER.error("Unescaped '}' character without opening bracket ends string prematurely. Field value: {}", text);
6468
throw new InvalidFieldValueException("Unescaped '}' character without opening bracket ends string prematurely. Field value: " + text);
6569
}
6670
if (left != right) {
71+
LOGGER.error("Braces don't match. Field value: {}", text);
6772
throw new InvalidFieldValueException("Braces don't match. Field value: " + text);
6873
}
6974
}
@@ -95,9 +100,10 @@ public String write(Field field, String content) throws InvalidFieldValueExcepti
95100
* For instance, <code>#jan# - #feb#</code> gets <code>jan #{ - } # feb</code> (see @link{org.jabref.logic.bibtex.LatexFieldFormatterTests#makeHashEnclosedWordsRealStringsInMonthField()})
96101
*/
97102
private String formatAndResolveStrings(String content, Field field) throws InvalidFieldValueException {
98-
stringBuilder = new StringBuilder();
99103
checkBraces(content);
100104

105+
StringBuilder stringBuilder = new StringBuilder();
106+
101107
// Here we assume that the user encloses any bibtex strings in #, e.g.:
102108
// #jan# - #feb#
103109
// ...which will be written to the file like this:
@@ -126,6 +132,9 @@ private String formatAndResolveStrings(String content, Field field) throws Inval
126132
if (neverFailOnHashes) {
127133
pos1 = content.length(); // just write out the rest of the text, and throw no exception
128134
} else {
135+
LOGGER.error("The # character is not allowed in BibTeX strings unless escaped as in '\\#'. "
136+
+ "In JabRef, use pairs of # characters to indicate a string. "
137+
+ "Note that the entry causing the problem has been selected. Field value: {}", content);
129138
throw new InvalidFieldValueException(
130139
"The # character is not allowed in BibTeX strings unless escaped as in '\\#'.\n"
131140
+ "In JabRef, use pairs of # characters to indicate a string.\n"
@@ -135,13 +144,13 @@ private String formatAndResolveStrings(String content, Field field) throws Inval
135144
}
136145

137146
if (pos1 > pivot) {
138-
writeText(content, pivot, pos1);
147+
writeText(stringBuilder, content, pivot, pos1);
139148
}
140149
if ((pos1 < content.length()) && ((pos2 - 1) > pos1)) {
141150
// We check that the string label is not empty. That means
142151
// an occurrence of ## will simply be ignored. Should it instead
143152
// cause an error message?
144-
writeStringLabel(content, pos1 + 1, pos2, pos1 == pivot,
153+
writeStringLabel(stringBuilder, content, pos1 + 1, pos2, pos1 == pivot,
145154
(pos2 + 1) == content.length());
146155
}
147156

@@ -168,28 +177,33 @@ private boolean shouldResolveStrings(Field field) {
168177
private String formatWithoutResolvingStrings(String content, Field field) throws InvalidFieldValueException {
169178
checkBraces(content);
170179

171-
stringBuilder = new StringBuilder(String.valueOf(FIELD_START));
172-
180+
StringBuilder stringBuilder = new StringBuilder(String.valueOf(FIELD_START));
173181
stringBuilder.append(formatter.format(content, field));
174-
175182
stringBuilder.append(FIELD_END);
176-
177183
return stringBuilder.toString();
178184
}
179185

180-
private void writeText(String text, int startPos, int endPos) {
186+
/**
187+
* @param stringBuilder the StringBuilder to append the text to
188+
* @param text the text to append
189+
*/
190+
private void writeText(StringBuilder stringBuilder, String text, int startPos, int endPos) {
181191
stringBuilder.append(FIELD_START);
182192
stringBuilder.append(text, startPos, endPos);
183193
stringBuilder.append(FIELD_END);
184194
}
185195

186-
private void writeStringLabel(String text, int startPos, int endPos, boolean first, boolean last) {
187-
putIn((first ? "" : " # ") + text.substring(startPos, endPos)
188-
+ (last ? "" : " # "));
189-
}
190-
191-
private void putIn(String s) {
192-
stringBuilder.append(StringUtil.wrap(s, preferences.getLineLength(), OS.NEWLINE));
196+
/**
197+
* @param stringBuilder the StringBuilder to append the text to
198+
* @param text the text use as basis to get the text to append
199+
* @param startPos the position in text where the text to add starts
200+
* @param endPos the position in text where the text to add ends
201+
* @param isFirst true if the label to write is the first one to write
202+
* @param isLast true if the label to write is the last one to write
203+
*/
204+
private void writeStringLabel(StringBuilder stringBuilder, String text, int startPos, int endPos, boolean isFirst, boolean isLast) {
205+
String line = (isFirst ? "" : " # ") + text.substring(startPos, endPos) + (isLast ? "" : " # ");
206+
String wrappedLine = StringUtil.wrap(line, preferences.getLineLength(), OS.NEWLINE);
207+
stringBuilder.append(wrappedLine);
193208
}
194-
195209
}

‎src/main/java/org/jabref/logic/bibtex/FieldWriterPreferences.java

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ public FieldWriterPreferences(boolean resolveStringsAllFields, List<Field> doNot
1919
this.fieldContentFormatterPreferences = fieldContentFormatterPreferences;
2020
}
2121

22+
/**
23+
* Creates an instance with default values (not obeying any user preferences). This constructor should be used with
24+
* caution. The other constructor has to be preferred.
25+
*/
2226
public FieldWriterPreferences() {
2327
// This constructor is only to allow an empty constructor in SavePreferences
2428
this(true, Collections.emptyList(), new FieldContentFormatterPreferences());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package org.jabref.logic.bst;
2+
3+
import java.nio.file.Files;
4+
import java.nio.file.Path;
5+
import java.util.List;
6+
7+
import org.jabref.logic.cleanup.ConvertToBibtexCleanup;
8+
import org.jabref.logic.formatter.bibtexfields.RemoveNewlinesFormatter;
9+
import org.jabref.logic.l10n.Localization;
10+
import org.jabref.logic.layout.format.LatexToUnicodeFormatter;
11+
import org.jabref.logic.layout.format.RemoveLatexCommandsFormatter;
12+
import org.jabref.logic.layout.format.RemoveTilde;
13+
import org.jabref.logic.preview.PreviewLayout;
14+
import org.jabref.model.database.BibDatabase;
15+
import org.jabref.model.entry.BibEntry;
16+
17+
import org.slf4j.Logger;
18+
import org.slf4j.LoggerFactory;
19+
20+
public class BstPreviewLayout implements PreviewLayout {
21+
22+
private static final Logger LOGGER = LoggerFactory.getLogger(BstPreviewLayout.class);
23+
24+
private final String name;
25+
26+
private VM vm;
27+
private String error;
28+
29+
public BstPreviewLayout(Path path) {
30+
name = path.getFileName().toString();
31+
if (!Files.exists(path)) {
32+
LOGGER.error("File {} not found", path.toAbsolutePath());
33+
error = Localization.lang("Error opening file '%0'.", path.toString());
34+
return;
35+
}
36+
try {
37+
vm = new VM(path.toFile());
38+
} catch (Exception e) {
39+
LOGGER.error("Could not read {}.", path.toAbsolutePath(), e);
40+
error = Localization.lang("Error opening file '%0'.", path.toString());
41+
}
42+
}
43+
44+
@Override
45+
public String generatePreview(BibEntry originalEntry, BibDatabase database) {
46+
if (error != null) {
47+
return error;
48+
}
49+
// ensure that the entry is of BibTeX format (and do not modify the original entry)
50+
BibEntry entry = (BibEntry) originalEntry.clone();
51+
new ConvertToBibtexCleanup().cleanup(entry);
52+
String result = vm.run(List.of(entry));
53+
// Remove all comments
54+
result = result.replaceAll("%.*", "");
55+
// Remove all LaTeX comments
56+
// The RemoveLatexCommandsFormatter keeps the words inside latex environments. Therefore, we remove them manually
57+
result = result.replace("\\begin{thebibliography}{1}", "");
58+
result = result.replace("\\end{thebibliography}", "");
59+
// The RemoveLatexCommandsFormatter keeps the word inside the latex command, but we want to remove that completely
60+
result = result.replaceAll("\\\\bibitem[{].*[}]", "");
61+
// We want to replace \newblock by a space instead of completely removing it
62+
result = result.replace("\\newblock", " ");
63+
// remove all latex commands statements - assumption: command in a separate line
64+
result = result.replaceAll("(?m)^\\\\.*$", "");
65+
// remove some IEEEtran.bst output (resulting from a multiline \providecommand)
66+
result = result.replace("#2}}", "");
67+
// Have quotes right - and more
68+
result = new LatexToUnicodeFormatter().format(result);
69+
result = result.replace("``", "\"");
70+
result = result.replace("''", "\"");
71+
// Final cleanup
72+
result = new RemoveNewlinesFormatter().format(result);
73+
result = new RemoveLatexCommandsFormatter().format(result);
74+
result = new RemoveTilde().format(result);
75+
result = result.trim().replaceAll(" +", " ");
76+
return result;
77+
}
78+
79+
@Override
80+
public String getName() {
81+
return name;
82+
}
83+
}

‎src/main/java/org/jabref/logic/bst/VM.java

+51-28
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@
1414
import java.util.regex.Matcher;
1515
import java.util.regex.Pattern;
1616

17+
import org.jabref.logic.bibtex.FieldWriter;
18+
import org.jabref.logic.bibtex.FieldWriterPreferences;
19+
import org.jabref.logic.bibtex.InvalidFieldValueException;
1720
import org.jabref.model.database.BibDatabase;
1821
import org.jabref.model.entry.AuthorList;
1922
import org.jabref.model.entry.BibEntry;
23+
import org.jabref.model.entry.Month;
2024
import org.jabref.model.entry.field.Field;
2125
import org.jabref.model.entry.field.FieldFactory;
2226
import org.jabref.model.entry.field.StandardField;
@@ -136,7 +140,7 @@ private VM(CommonTree tree) {
136140
stack.push(((Integer) o1).compareTo((Integer) o2) > 0 ? VM.TRUE : VM.FALSE);
137141
});
138142

139-
/* Analogous. */
143+
/* Analogous to >. */
140144
buildInFunctions.put("<", context -> {
141145
if (stack.size() < 2) {
142146
throw new VMException("Not enough operands on stack for operation <");
@@ -270,7 +274,7 @@ private VM(CommonTree tree) {
270274
if (context == null) {
271275
throw new VMException("Call.type$ can only be called from within a context (ITERATE or REVERSE).");
272276
}
273-
VM.this.execute(context.getBibtexEntry().getType().getName(), context);
277+
VM.this.execute(context.entry.getType().getName(), context);
274278
});
275279

276280
buildInFunctions.put("change.case$", new ChangeCaseFunction(this));
@@ -303,7 +307,7 @@ private VM(CommonTree tree) {
303307
if (context == null) {
304308
throw new VMException("Must have an entry to cite$");
305309
}
306-
stack.push(context.getBibtexEntry().getCiteKeyOptional().orElse(null));
310+
stack.push(context.entry.getCiteKeyOptional().orElse(null));
307311
});
308312

309313
/*
@@ -581,7 +585,7 @@ private VM(CommonTree tree) {
581585
throw new VMException("type$ need a context.");
582586
}
583587

584-
stack.push(context.getBibtexEntry().getType().getName());
588+
stack.push(context.entry.getType().getName());
585589
});
586590

587591
/*
@@ -843,11 +847,14 @@ public String run(Collection<BibEntry> bibtex) {
843847
}
844848

845849
/**
846-
* @param bibtex list of entries to convert
850+
* Transforms the given list of BibEntries to a rendered list of references using the underlying bst file
851+
*
852+
* @param bibEntries list of entries to convert
847853
* @param bibDatabase (may be null) the bibDatabase used for resolving strings / crossref
854+
* @return list of references in plain text form
848855
*/
849-
public String run(Collection<BibEntry> bibtex, BibDatabase bibDatabase) {
850-
Objects.requireNonNull(bibtex);
856+
public String run(Collection<BibEntry> bibEntries, BibDatabase bibDatabase) {
857+
Objects.requireNonNull(bibEntries);
851858

852859
// Reset
853860
bbl = new StringBuilder();
@@ -864,8 +871,8 @@ public String run(Collection<BibEntry> bibtex, BibDatabase bibDatabase) {
864871
stack = new Stack<>();
865872

866873
// Create entries
867-
entries = new ArrayList<>(bibtex.size());
868-
for (BibEntry entry : bibtex) {
874+
entries = new ArrayList<>(bibEntries.size());
875+
for (BibEntry entry : bibEntries) {
869876
entries.add(new BstEntry(entry));
870877
}
871878

@@ -921,17 +928,40 @@ public String run(Collection<BibEntry> bibtex, BibDatabase bibDatabase) {
921928
* @param bibDatabase
922929
*/
923930
private void read(BibDatabase bibDatabase) {
931+
FieldWriter fieldWriter = new FieldWriter(new FieldWriterPreferences());
924932
for (BstEntry e : entries) {
925-
for (Map.Entry<String, String> mEntry : e.getFields().entrySet()) {
933+
for (Map.Entry<String, String> mEntry : e.fields.entrySet()) {
926934
Field field = FieldFactory.parseField(mEntry.getKey());
927-
String fieldValue = e.getBibtexEntry().getResolvedFieldOrAlias(field, bibDatabase).orElse(null);
935+
String fieldValue = e.entry.getResolvedFieldOrAlias(field, bibDatabase)
936+
.map(content -> {
937+
try {
938+
String result = fieldWriter.write(field, content);
939+
if (result.startsWith("{")) {
940+
// Strip enclosing {} from the output
941+
return result.substring(1, result.length() - 1);
942+
}
943+
if (field == StandardField.MONTH) {
944+
// We don't have the internal BibTeX strings at hand.
945+
// We nevertheless want to have the full month name.
946+
// Thus, we lookup the full month name here.
947+
return Month.parse(result)
948+
.map(month -> month.getFullName())
949+
.orElse(result);
950+
}
951+
return result;
952+
} catch (InvalidFieldValueException invalidFieldValueException) {
953+
// in case there is something wrong with the content, just return the content itself
954+
return content;
955+
}
956+
})
957+
.orElse(null);
928958
mEntry.setValue(fieldValue);
929959
}
930960
}
931961

932962
for (BstEntry e : entries) {
933-
if (!e.getFields().containsKey(StandardField.CROSSREF.getName())) {
934-
e.getFields().put(StandardField.CROSSREF.getName(), null);
963+
if (!e.fields.containsKey(StandardField.CROSSREF.getName())) {
964+
e.fields.put(StandardField.CROSSREF.getName(), null);
935965
}
936966
}
937967
}
@@ -978,7 +1008,7 @@ private void entry(Tree child) {
9781008
String name = t.getChild(i).getText();
9791009

9801010
for (BstEntry entry : entries) {
981-
entry.getFields().put(name, null);
1011+
entry.fields.put(name, null);
9821012
}
9831013
}
9841014

@@ -1103,8 +1133,8 @@ private void execute(String name, BstEntry context) {
11031133

11041134
if (context != null) {
11051135

1106-
if (context.getFields().containsKey(name)) {
1107-
stack.push(context.getFields().get(name));
1136+
if (context.fields.containsKey(name)) {
1137+
stack.push(context.fields.get(name));
11081138
return;
11091139
}
11101140
if (context.localStrings.containsKey(name)) {
@@ -1171,25 +1201,18 @@ private void strings(Tree child) {
11711201

11721202
public static class BstEntry {
11731203

1174-
private final BibEntry entry;
1204+
public final BibEntry entry;
11751205

1176-
private final Map<String, String> localStrings = new HashMap<>();
1206+
public final Map<String, String> localStrings = new HashMap<>();
11771207

1178-
private final Map<String, String> fields = new HashMap<>();
1208+
// keys filled by org.jabref.logic.bst.VM.entry based on the contents of the bst file
1209+
public final Map<String, String> fields = new HashMap<>();
11791210

1180-
private final Map<String, Integer> localIntegers = new HashMap<>();
1211+
public final Map<String, Integer> localIntegers = new HashMap<>();
11811212

11821213
public BstEntry(BibEntry e) {
11831214
this.entry = e;
11841215
}
1185-
1186-
public Map<String, String> getFields() {
1187-
return fields;
1188-
}
1189-
1190-
public BibEntry getBibtexEntry() {
1191-
return entry;
1192-
}
11931216
}
11941217

11951218
private void push(Integer integer) {

‎src/main/java/org/jabref/logic/citationstyle/CitationStyleCache.java

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.Objects;
44

5+
import org.jabref.logic.preview.PreviewLayout;
56
import org.jabref.model.database.BibDatabaseContext;
67
import org.jabref.model.database.event.EntriesRemovedEvent;
78
import org.jabref.model.entry.BibEntry;

‎src/main/java/org/jabref/logic/citationstyle/CitationStylePreviewLayout.java

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.jabref.logic.citationstyle;
22

3+
import org.jabref.logic.preview.PreviewLayout;
34
import org.jabref.model.database.BibDatabase;
45
import org.jabref.model.entry.BibEntry;
56

‎src/main/java/org/jabref/logic/citationstyle/TextBasedPreviewLayout.java ‎src/main/java/org/jabref/logic/layout/TextBasedPreviewLayout.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
package org.jabref.logic.citationstyle;
1+
package org.jabref.logic.layout;
22

33
import java.io.IOException;
44
import java.io.StringReader;
55

66
import org.jabref.logic.l10n.Localization;
7-
import org.jabref.logic.layout.Layout;
8-
import org.jabref.logic.layout.LayoutFormatterPreferences;
9-
import org.jabref.logic.layout.LayoutHelper;
7+
import org.jabref.logic.preview.PreviewLayout;
108
import org.jabref.model.database.BibDatabase;
119
import org.jabref.model.entry.BibEntry;
1210

1311
import org.slf4j.Logger;
1412
import org.slf4j.LoggerFactory;
1513

14+
/**
15+
* Implements the preview based JabRef's <a href="https://docs.jabref.org/import-export/export/customexports">Custom export fitlters</a>.
16+
*/
1617
public class TextBasedPreviewLayout implements PreviewLayout {
1718
private static final Logger LOGGER = LoggerFactory.getLogger(TextBasedPreviewLayout.class);
1819

‎src/main/java/org/jabref/logic/layout/format/RemoveWhitespace.java

-3
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,11 @@
44

55
/**
66
* Remove non printable character formatter.
7-
*
8-
* Based on the RemoveBrackets.java class (Revision 1.2) by mortenalver
97
*/
108
public class RemoveWhitespace implements LayoutFormatter {
119

1210
@Override
1311
public String format(String fieldEntry) {
14-
1512
if (fieldEntry == null) {
1613
return null;
1714
}

‎src/main/java/org/jabref/logic/citationstyle/PreviewLayout.java ‎src/main/java/org/jabref/logic/preview/PreviewLayout.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
package org.jabref.logic.citationstyle;
1+
package org.jabref.logic.preview;
22

33
import org.jabref.model.database.BibDatabase;
44
import org.jabref.model.entry.BibEntry;
55

6+
/**
7+
* Used for displaying a rendered entry in the UI. Due to historical reasons, "rendering" is called "layout".
8+
*/
69
public interface PreviewLayout {
710

811
String generatePreview(BibEntry entry, BibDatabase database);

‎src/main/java/org/jabref/model/strings/StringUtil.java

+19-12
Original file line numberDiff line numberDiff line change
@@ -193,20 +193,19 @@ public static String getCorrectFileName(String orgName, String defaultExtension)
193193
}
194194

195195
/**
196-
* Formats field contents for output. Must be "symmetric" with the parse method above,
197-
* so stored and reloaded fields are not mangled.
196+
* Formats field contents for output. Must be "symmetric" with the parse method above, so stored and reloaded fields
197+
* are not mangled.
198198
*
199-
* @param in
200-
* @param wrapAmount
201-
* @param newline
202-
* @return the wrapped String.
199+
* @param in the string to wrap
200+
* @param wrapAmount the number of characters belonging to a line of text
201+
* @param newline the newline character(s)
202+
* @return the wrapped string
203203
*/
204204
public static String wrap(String in, int wrapAmount, String newline) {
205-
206205
String[] lines = in.split("\n");
207206
StringBuilder result = new StringBuilder();
208207
// remove all whitespace at the end of the string, this especially includes \r created when the field content has \r\n as line separator
209-
addWrappedLine(result, CharMatcher.whitespace().trimTrailingFrom(lines[0]), wrapAmount, newline); // See
208+
addWrappedLine(result, CharMatcher.whitespace().trimTrailingFrom(lines[0]), wrapAmount, newline);
210209
for (int i = 1; i < lines.length; i++) {
211210

212211
if (lines[i].trim().isEmpty()) {
@@ -225,22 +224,30 @@ public static String wrap(String in, int wrapAmount, String newline) {
225224
return result.toString();
226225
}
227226

228-
private static void addWrappedLine(StringBuilder result, String line, int wrapAmount, String newline) {
227+
/**
228+
* Appends a text to a string builder. Wraps the text so that each line is approx wrapAmount characters long.
229+
* Wrapping is done using newline and tab character.
230+
*
231+
* @param line the line of text to be wrapped and appended
232+
* @param wrapAmount the number of characters belonging to a line of text
233+
* @param newlineString a string containing the newline character(s)
234+
*/
235+
private static void addWrappedLine(StringBuilder result, String line, int wrapAmount, String newlineString) {
229236
// Set our pointer to the beginning of the new line in the StringBuffer:
230237
int length = result.length();
231238
// Add the line, unmodified:
232239
result.append(line);
233240

241+
// insert newlines and one tab character at each position, where wrapping is necessary
234242
while (length < result.length()) {
235243
int current = result.indexOf(" ", length + wrapAmount);
236244
if ((current < 0) || (current >= result.length())) {
237245
break;
238246
}
239247

240248
result.deleteCharAt(current);
241-
result.insert(current, newline + "\t");
242-
length = current + newline.length();
243-
249+
result.insert(current, newlineString + "\t");
250+
length = current + newlineString.length();
244251
}
245252
}
246253

‎src/main/java/org/jabref/preferences/JabRefPreferences.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,6 @@
5959
import org.jabref.logic.bibtexkeypattern.BibtexKeyPatternPreferences;
6060
import org.jabref.logic.citationstyle.CitationStyle;
6161
import org.jabref.logic.citationstyle.CitationStylePreviewLayout;
62-
import org.jabref.logic.citationstyle.PreviewLayout;
63-
import org.jabref.logic.citationstyle.TextBasedPreviewLayout;
6462
import org.jabref.logic.cleanup.CleanupPreferences;
6563
import org.jabref.logic.cleanup.CleanupPreset;
6664
import org.jabref.logic.cleanup.Cleanups;
@@ -74,13 +72,15 @@
7472
import org.jabref.logic.l10n.Language;
7573
import org.jabref.logic.l10n.Localization;
7674
import org.jabref.logic.layout.LayoutFormatterPreferences;
75+
import org.jabref.logic.layout.TextBasedPreviewLayout;
7776
import org.jabref.logic.layout.format.FileLinkPreferences;
7877
import org.jabref.logic.layout.format.NameFormatterPreferences;
7978
import org.jabref.logic.net.ProxyPreferences;
8079
import org.jabref.logic.openoffice.OpenOfficePreferences;
8180
import org.jabref.logic.openoffice.StyleLoader;
8281
import org.jabref.logic.preferences.OwnerPreferences;
8382
import org.jabref.logic.preferences.TimestampPreferences;
83+
import org.jabref.logic.preview.PreviewLayout;
8484
import org.jabref.logic.protectedterms.ProtectedTermsList;
8585
import org.jabref.logic.protectedterms.ProtectedTermsLoader;
8686
import org.jabref.logic.protectedterms.ProtectedTermsPreferences;

‎src/main/java/org/jabref/preferences/PreviewPreferences.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
import java.util.List;
44

55
import org.jabref.Globals;
6-
import org.jabref.logic.citationstyle.PreviewLayout;
7-
import org.jabref.logic.citationstyle.TextBasedPreviewLayout;
86
import org.jabref.logic.layout.LayoutFormatterPreferences;
7+
import org.jabref.logic.layout.TextBasedPreviewLayout;
8+
import org.jabref.logic.preview.PreviewLayout;
99

1010
public class PreviewPreferences {
1111

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package org.jabref.logic.bst;
2+
3+
import java.nio.file.Paths;
4+
5+
import org.jabref.model.database.BibDatabase;
6+
import org.jabref.model.entry.BibEntry;
7+
import org.jabref.model.entry.field.StandardField;
8+
import org.jabref.model.entry.types.StandardEntryType;
9+
10+
import org.junit.jupiter.api.Test;
11+
12+
import static org.junit.jupiter.api.Assertions.assertEquals;
13+
import static org.mockito.Mockito.mock;
14+
15+
class BstPreviewLayoutTest {
16+
17+
private BibDatabase bibDatabase = mock(BibDatabase.class);
18+
19+
@Test
20+
public void generatePreviewForSimpleEntryUsingAbbr() throws Exception {
21+
BstPreviewLayout bstPreviewLayout = new BstPreviewLayout(Paths.get(BstPreviewLayoutTest.class.getResource("abbrv.bst").toURI()));
22+
BibEntry entry = new BibEntry().withField(StandardField.AUTHOR, "Oliver Kopp")
23+
.withField(StandardField.TITLE, "Thoughts on Development");
24+
BibDatabase bibDatabase = mock(BibDatabase.class);
25+
String preview = bstPreviewLayout.generatePreview(entry, bibDatabase);
26+
assertEquals("O. Kopp. Thoughts on development.", preview);
27+
}
28+
29+
@Test
30+
public void monthMayIsCorrectlyRendered() throws Exception {
31+
BstPreviewLayout bstPreviewLayout = new BstPreviewLayout(Paths.get(BstPreviewLayoutTest.class.getResource("abbrv.bst").toURI()));
32+
BibEntry entry = new BibEntry().withField(StandardField.AUTHOR, "Oliver Kopp")
33+
.withField(StandardField.TITLE, "Thoughts on Development")
34+
.withField(StandardField.MONTH, "#May#");
35+
BibDatabase bibDatabase = mock(BibDatabase.class);
36+
String preview = bstPreviewLayout.generatePreview(entry, bibDatabase);
37+
assertEquals("O. Kopp. Thoughts on development, May.", preview);
38+
}
39+
40+
@Test
41+
public void generatePreviewForSliceTheoremPaperUsingAbbr() throws Exception {
42+
BstPreviewLayout bstPreviewLayout = new BstPreviewLayout(Paths.get(BstPreviewLayoutTest.class.getResource("abbrv.bst").toURI()));
43+
String preview = bstPreviewLayout.generatePreview(getSliceTheoremPaper(), bibDatabase);
44+
assertEquals("T. Diez. Slice theorem for fréchet group actions and covariant symplectic field theory. May 2014.", preview);
45+
}
46+
47+
@Test
48+
public void generatePreviewForSliceTheoremPaperUsingIEEE() throws Exception {
49+
BstPreviewLayout bstPreviewLayout = new BstPreviewLayout(Paths.get(ClassLoader.getSystemResource("bst/IEEEtran.bst").toURI()));
50+
String preview = bstPreviewLayout.generatePreview(getSliceTheoremPaper(), bibDatabase);
51+
assertEquals("T. Diez, \"Slice theorem for fréchet group actions and covariant symplectic field theory\" May 2014.", preview);
52+
}
53+
54+
private static BibEntry getSliceTheoremPaper() {
55+
return new BibEntry(StandardEntryType.Article)
56+
.withField(StandardField.AUTHOR, "Tobias Diez")
57+
.withField(StandardField.TITLE, "Slice theorem for Fréchet group actions and covariant symplectic field theory")
58+
.withField(StandardField.DATE, "2014-05-09")
59+
.withField(StandardField.ABSTRACT, "A general slice theorem for the action of a Fr\\'echet Lie group on a Fr\\'echet manifolds is established. The Nash-Moser theorem provides the fundamental tool to generalize the result of Palais to this infinite-dimensional setting. The presented slice theorem is illustrated by its application to gauge theories: the action of the gauge transformation group admits smooth slices at every point and thus the gauge orbit space is stratified by Fr\\'echet manifolds. Furthermore, a covariant and symplectic formulation of classical field theory is proposed and extensively discussed. At the root of this novel framework is the incorporation of field degrees of freedom F and spacetime M into the product manifold F * M. The induced bigrading of differential forms is used in order to carry over the usual symplectic theory to this new setting. The examples of the Klein-Gordon field and general Yang-Mills theory illustrate that the presented approach conveniently handles the occurring symmetries.")
60+
.withField(StandardField.EPRINT, "1405.2249v1")
61+
.withField(StandardField.FILE, ":http\\://arxiv.org/pdf/1405.2249v1:PDF")
62+
.withField(StandardField.EPRINTTYPE, "arXiv")
63+
.withField(StandardField.EPRINTCLASS, "math-ph")
64+
.withField(StandardField.KEYWORDS, "math-ph, math.DG, math.MP, math.SG, 58B99, 58Z05, 58B25, 22E65, 58D19, 53D20, 53D42");
65+
}
66+
}

‎src/test/java/org/jabref/logic/bst/TestVM.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public void testVMSimple() throws RecognitionException, IOException {
5454
assertEquals(2, vm.getStrings().size());
5555
assertEquals(7, vm.getIntegers().size());
5656
assertEquals(1, vm.getEntries().size());
57-
assertEquals(5, vm.getEntries().get(0).getFields().size());
57+
assertEquals(5, vm.getEntries().get(0).fields.size());
5858
assertEquals(38, vm.getFunctions().size());
5959
}
6060

@@ -366,10 +366,10 @@ public void testSort() throws RecognitionException, IOException {
366366
vm.run(v);
367367

368368
List<BstEntry> v2 = vm.getEntries();
369-
assertEquals(Optional.of("a"), v2.get(0).getBibtexEntry().getCiteKeyOptional());
370-
assertEquals(Optional.of("b"), v2.get(1).getBibtexEntry().getCiteKeyOptional());
371-
assertEquals(Optional.of("c"), v2.get(2).getBibtexEntry().getCiteKeyOptional());
372-
assertEquals(Optional.of("d"), v2.get(3).getBibtexEntry().getCiteKeyOptional());
369+
assertEquals(Optional.of("a"), v2.get(0).entry.getCiteKeyOptional());
370+
assertEquals(Optional.of("b"), v2.get(1).entry.getCiteKeyOptional());
371+
assertEquals(Optional.of("c"), v2.get(2).entry.getCiteKeyOptional());
372+
assertEquals(Optional.of("d"), v2.get(3).entry.getCiteKeyOptional());
373373
}
374374

375375
@Test

0 commit comments

Comments
 (0)
Please sign in to comment.