Skip to content

Commit 357be5c

Browse files
tschechlovdevstefan-kolb
authored andcommitted
Remove teamscale findings in the database package (JabRef#1577)
1 parent c71a66c commit 357be5c

File tree

6 files changed

+124
-65
lines changed

6 files changed

+124
-65
lines changed

src/main/java/net/sf/jabref/model/database/BibDatabase.java

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import java.util.TreeSet;
1414
import java.util.concurrent.ConcurrentHashMap;
1515
import java.util.regex.Pattern;
16+
import java.util.stream.Collectors;
1617

1718
import net.sf.jabref.event.source.EntryEventSource;
1819
import net.sf.jabref.model.EntryTypes;
@@ -21,7 +22,6 @@
2122
import net.sf.jabref.model.entry.EntryType;
2223
import net.sf.jabref.model.entry.EntryUtil;
2324
import net.sf.jabref.model.entry.FieldName;
24-
import net.sf.jabref.model.entry.InternalBibtexFields;
2525
import net.sf.jabref.model.entry.MonthUtil;
2626
import net.sf.jabref.model.event.EntryAddedEvent;
2727
import net.sf.jabref.model.event.EntryChangedEvent;
@@ -59,7 +59,6 @@ public class BibDatabase {
5959
*/
6060
private final Set<String> internalIDs = new HashSet<>();
6161

62-
6362
private final EventBus eventBus = new EventBus();
6463

6564

@@ -100,22 +99,22 @@ public List<BibEntry> getEntries() {
10099
return Collections.unmodifiableList(entries);
101100
}
102101

102+
/**
103+
* Returns a set of Strings, that contains all field names that are visible. This means that the fields
104+
* are not internal fields. Internal fields are fields, that are starting with "_".
105+
*
106+
* @return set of fieldnames, that are visible
107+
*/
103108
public Set<String> getAllVisibleFields() {
104109
Set<String> allFields = new TreeSet<>();
105110
for (BibEntry e : getEntries()) {
106111
allFields.addAll(e.getFieldNames());
107112
}
108-
Set<String> toberemoved = new TreeSet<>();
109-
for (String field : allFields) {
110-
if (InternalBibtexFields.isInternalField(field)) {
111-
toberemoved.add(field);
112-
}
113-
}
113+
return allFields.stream().filter(field -> !isInternalField(field)).collect(Collectors.toSet());
114+
}
114115

115-
for (String field : toberemoved) {
116-
allFields.remove(field);
117-
}
118-
return allFields;
116+
public static boolean isInternalField(String field) {
117+
return field.startsWith("__");
119118
}
120119

121120
/**
@@ -130,6 +129,13 @@ public synchronized Optional<BibEntry> getEntryByKey(String key) {
130129
return Optional.empty();
131130
}
132131

132+
/**
133+
* Collects entries having the specified BibTeX key and returns these entries as list.
134+
* The order of the entries is the order they appear in the database.
135+
*
136+
* @param key
137+
* @return list of entries that contains the given key
138+
*/
133139
public synchronized List<BibEntry> getEntriesByKey(String key) {
134140
List<BibEntry> result = new ArrayList<>();
135141

@@ -163,8 +169,7 @@ public synchronized boolean insertEntry(BibEntry entry) throws KeyCollisionExcep
163169
* @param eventSource Source the event is sent from
164170
* @return false if the insert was done without a duplicate warning
165171
*/
166-
public synchronized boolean insertEntry(BibEntry entry, EntryEventSource eventSource)
167-
throws KeyCollisionException {
172+
public synchronized boolean insertEntry(BibEntry entry, EntryEventSource eventSource) throws KeyCollisionException {
168173
Objects.requireNonNull(entry);
169174

170175
String id = entry.getId();
@@ -177,7 +182,7 @@ public synchronized boolean insertEntry(BibEntry entry, EntryEventSource eventSo
177182
entry.registerListener(this);
178183

179184
eventBus.post(new EntryAddedEvent(entry, eventSource));
180-
return duplicationChecker.checkForDuplicateKeyAndAdd(null, entry.getCiteKeyOptional().orElse(null));
185+
return duplicationChecker.checkForDuplicateKeyAndAdd(null, entry.getCiteKey());
181186
}
182187

183188
/**
@@ -192,13 +197,14 @@ public synchronized void removeEntry(BibEntry toBeDeleted) {
192197
/**
193198
* Removes the given entry.
194199
* The Entry is removed based on the id {@link BibEntry#id}
200+
*
195201
* @param toBeDeleted Entry to delete
196202
* @param eventSource Source the event is sent from
197203
*/
198204
public synchronized void removeEntry(BibEntry toBeDeleted, EntryEventSource eventSource) {
199205
Objects.requireNonNull(toBeDeleted);
200206

201-
boolean anyRemoved = entries.removeIf(entry -> entry.getId().equals(toBeDeleted.getId()));
207+
boolean anyRemoved = entries.removeIf(entry -> entry.getId().equals(toBeDeleted.getId()));
202208
if (anyRemoved) {
203209
internalIDs.remove(toBeDeleted.getId());
204210
toBeDeleted.getCiteKeyOptional().ifPresent(duplicationChecker::removeKeyFromSet);
@@ -210,8 +216,14 @@ public int getNumberOfKeyOccurrences(String key) {
210216
return duplicationChecker.getNumberOfKeyOccurrences(key);
211217
}
212218

219+
/**
220+
* Sets the given key to the given entry.
221+
* If the key is null, the entry field will be cleared.
222+
*
223+
* @return true, if the entry contains the key, false if not
224+
*/
213225
public synchronized boolean setCiteKeyForEntry(BibEntry entry, String key) {
214-
String oldKey = entry.getCiteKeyOptional().orElse(null);
226+
String oldKey = entry.getCiteKey();
215227
if (key == null) {
216228
entry.clearField(BibEntry.KEY_FIELD);
217229
} else {
@@ -237,8 +249,7 @@ public synchronized Optional<String> getPreamble() {
237249
/**
238250
* Inserts a Bibtex String.
239251
*/
240-
public synchronized void addString(BibtexString string)
241-
throws KeyCollisionException {
252+
public synchronized void addString(BibtexString string) throws KeyCollisionException {
242253
if (hasStringLabel(string.getName())) {
243254
throw new KeyCollisionException("A string with that label already exists");
244255
}
@@ -478,8 +489,6 @@ private String resolveContent(String result, Set<String> usedIds) {
478489
return res;
479490
}
480491

481-
482-
483492
/**
484493
* Returns the text stored in the given field of the given bibtex entry
485494
* which belongs to the given database.
@@ -511,9 +520,9 @@ public static Optional<String> getResolvedField(String field, BibEntry entry, Bi
511520
return entry.getCiteKeyOptional();
512521
}
513522

514-
// TODO: Changed this to also consider alias fields, which is the expected
523+
// Changed this to also consider alias fields, which is the expected
515524
// behavior for the preview layout and for the check whatever all fields are present.
516-
// But there might be unwanted side-effects?!
525+
// TODO: But there might be unwanted side-effects?!
517526
Optional<String> result = entry.getFieldOrAlias(field);
518527

519528
// If this field is not set, and the entry has a crossref, try to look up the

src/main/java/net/sf/jabref/model/database/BibDatabaseMode.java

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,66 @@
22

33
import java.util.Locale;
44

5+
/**
6+
* An enum which contains the possible {@link BibDatabase} Modes.
7+
* Possible are BibTeX and BibLaTeX.
8+
*/
59
public enum BibDatabaseMode {
610
BIBTEX,
711
BIBLATEX;
812

13+
/**
14+
* @return the name of the current mode as String
15+
*/
916
public String getFormattedName() {
10-
if(this == BIBTEX) {
17+
if (this == BIBTEX) {
1118
return "BibTeX";
1219
} else {
1320
return "BibLaTeX";
1421
}
1522
}
1623

24+
/**
25+
* Returns the opposite mode of the current mode as {@link BibDatabaseMode}.
26+
*
27+
* @return BibLaTeX if the current mode is BIBTEX, BibTeX else
28+
*/
1729
public BibDatabaseMode getOppositeMode() {
18-
if(this == BIBTEX) {
30+
if (this == BIBTEX) {
1931
return BIBLATEX;
2032
} else {
2133
return BIBTEX;
2234
}
2335
}
2436

37+
/**
38+
* Returns the {@link BibDatabaseMode} from a given boolean.
39+
*
40+
* @return BIBLATEX if isBibLatex is true, else BIBTEX
41+
*/
2542
public static BibDatabaseMode fromPreference(boolean isBibLatex) {
26-
return isBibLatex ? BIBLATEX : BIBTEX;
43+
if (isBibLatex) {
44+
return BIBLATEX;
45+
} else {
46+
return BIBTEX;
47+
}
2748
}
2849

50+
/**
51+
* Returns the {@link BibDatabaseMode} that equals the given string. The use of capital and small letters
52+
* in the string doesn't matter.If neither "bibtex" nor "biblatex" is the given string, then an
53+
* {@link IllegalArgumentException} will be thrown.
54+
*
55+
* @return BIBTEX, if the string is bibtex<br>
56+
* BIBLATEX, if the string is biblatex<br>
57+
*/
2958
public static BibDatabaseMode parse(String data) {
3059
return BibDatabaseMode.valueOf(data.toUpperCase(Locale.ENGLISH));
3160
}
3261

62+
/**
63+
* @return The current mode as String in lowercase
64+
*/
3365
public String getAsString() {
3466
return getFormattedName().toLowerCase(Locale.ENGLISH);
3567
}

src/main/java/net/sf/jabref/model/database/BibDatabaseModeDetection.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package net.sf.jabref.model.database;
22

33
import java.util.List;
4+
import java.util.Locale;
45
import java.util.function.Predicate;
56
import java.util.stream.Collectors;
67
import java.util.stream.Stream;
@@ -11,9 +12,10 @@
1112
import net.sf.jabref.model.entry.EntryType;
1213

1314
public class BibDatabaseModeDetection {
14-
private static final List<EntryType> bibtex = BibtexEntryTypes.ALL;
15-
private static final List<EntryType> biblatex = BibLatexEntryTypes.ALL;
16-
private static final List<String> exclusiveBiblatex = filterEntryTypesNames(biblatex, isNotIncludedIn(bibtex));
15+
16+
private static final List<EntryType> BIBTEX = BibtexEntryTypes.ALL;
17+
private static final List<EntryType> BIBLATEX = BibLatexEntryTypes.ALL;
18+
private static final List<String> EXCLUSIVE_BIBLATEX = filterEntryTypesNames(BIBLATEX, isNotIncludedIn(BIBTEX));
1719

1820
/**
1921
* Tries to infer the database type by examining a BibDatabase database.
@@ -32,7 +34,7 @@ public static BibDatabaseMode inferMode(BibDatabase database) {
3234
final Stream<String> entryTypes = database.getEntries().stream().map(BibEntry::getType);
3335

3436
// type-based check
35-
if (entryTypes.anyMatch(type -> exclusiveBiblatex.contains(type.toLowerCase()))) {
37+
if (entryTypes.anyMatch(type -> EXCLUSIVE_BIBLATEX.contains(type.toLowerCase(Locale.ENGLISH)))) {
3638
return BibDatabaseMode.BIBLATEX;
3739
} else {
3840
// field-based check

src/main/java/net/sf/jabref/model/database/BibDatabases.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@
99

1010
public class BibDatabases {
1111

12+
/**
13+
* Gets a collection of bibentries and sets an ID for every entry. After that
14+
* all entries will be inserted into a new BibDatabase.
15+
*
16+
* @param bibentries a collection that contains {@link BibEntry}
17+
* @return BibDatabase that contains the entries
18+
*/
1219
public static BibDatabase createDatabase(Collection<BibEntry> bibentries) {
1320
BibDatabase database = new BibDatabase();
1421

src/main/java/net/sf/jabref/model/database/DuplicationChecker.java

Lines changed: 44 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import org.apache.commons.logging.LogFactory;
88

99
/**
10-
* Determines which bibtex cite keys are duplicates in a single {@link BibDatabase}
10+
* Determines which bibtex cite keys are duplicates in a single {@link BibDatabase}.
1111
*/
1212
class DuplicationChecker {
1313

@@ -16,33 +16,29 @@ class DuplicationChecker {
1616
// use a map instead of a set since i need to know how many of each key is in there
1717
private final Map<String, Integer> allKeys = new HashMap<>();
1818

19-
//##########################################
20-
// usage:
21-
// isDuplicate=checkForDuplicateKeyAndAdd( null, b.getKey() , issueDuplicateWarning);
22-
//############################################
23-
// if the newkey already exists and is not the same as oldkey it will give a warning
24-
// else it will add the newkey to the to set and remove the oldkey
19+
/**
20+
* Usage:
21+
* <br>
22+
* isDuplicate=checkForDuplicateKeyAndAdd( null, b.getKey() , issueDuplicateWarning);
23+
*
24+
* If the newkey already exists and is not the same as oldkey it will give a warning
25+
* else it will add the newkey to the to set and remove the oldkey
26+
*
27+
* @return true, if there is a duplicate key, else false
28+
*/
2529
public boolean checkForDuplicateKeyAndAdd(String oldKey, String newKey) {
26-
// LOGGER.debug(" checkForDuplicateKeyAndAdd [oldKey = " + oldKey + "] [newKey = " + newKey + "]");
2730

28-
boolean duplicate;
29-
if (oldKey == null) {// this is a new entry so don't bother removing oldKey
31+
boolean duplicate = false;
32+
if (oldKey == null) { // No old key
3033
duplicate = addKeyToSet(newKey);
3134
} else {
3235
if (oldKey.equals(newKey)) {// were OK because the user did not change keys
3336
duplicate = false;
34-
} else {// user changed the key
35-
36-
// removed the oldkey
37-
// But what if more than two have the same key?
38-
// this means that user can add another key and would not get a warning!
39-
// consider this: i add a key xxx, then i add another key xxx . I get a warning. I delete the key xxx. JBM
40-
// removes this key from the allKey. then I add another key xxx. I don't get a warning!
41-
// i need a way to count the number of keys of each type
42-
// hashmap=>int (increment each time)
43-
44-
removeKeyFromSet(oldKey);
45-
duplicate = addKeyToSet(newKey);
37+
} else {
38+
removeKeyFromSet(oldKey); // Get rid of old key
39+
if (newKey != null) { // Add new key if any
40+
duplicate = addKeyToSet(newKey);
41+
}
4642
}
4743
}
4844
if (duplicate) {
@@ -64,38 +60,52 @@ public int getNumberOfKeyOccurrences(String key) {
6460

6561
}
6662

67-
//========================================================
68-
// keep track of all the keys to warn if there are duplicates
69-
//========================================================
70-
public boolean addKeyToSet(String key) {
63+
/**
64+
* Helper function for counting the number of the key usages.
65+
* Adds the given key to the internal keyset together with the count of it.
66+
* The counter is increased if the key already exists, otherwise set to 1.
67+
* <br>
68+
* Special case: If a null or empty key is passed, it is not counted and thus not added.
69+
*
70+
* Reasoning:
71+
* Consider this: I add a key xxx, then I add another key xxx. I get a warning. I delete the key xxx.
72+
* Consider JabRef simply removing this key from a set of allKeys.
73+
* Then I add another key xxx. I don't get a warning!
74+
* Thus, I need a way to count the number of keys of each type.
75+
* Solution: hashmap=>int (increment each time at add and decrement each time at remove)
76+
*/
77+
protected boolean addKeyToSet(String key) {
7178
if ((key == null) || key.isEmpty()) {
7279
return false;//don't put empty key
7380
}
7481
boolean exists = false;
7582
if (allKeys.containsKey(key)) {
7683
// warning
7784
exists = true;
78-
allKeys.put(key, allKeys.get(key) + 1);// incrementInteger( allKeys.get(key)));
85+
allKeys.put(key, allKeys.get(key) + 1);
7986
} else {
8087
allKeys.put(key, 1);
8188
}
8289
return exists;
8390
}
8491

85-
//========================================================
86-
// reduce the number of keys by 1. if this number goes to zero then remove from the set
87-
// note: there is a good reason why we should not use a hashset but use hashmap instead
88-
//========================================================
89-
public void removeKeyFromSet(String key) {
92+
/**
93+
* Helper function for counting the number of the key usages.
94+
* Removes the given key from the internal keyset together with the count of it, if the key is set to 1.
95+
* If it is not set to 1, the counter will be decreased.
96+
* <br>
97+
* Special case: If a null or empty key is passed, it is not counted and thus not removed.
98+
*/
99+
protected void removeKeyFromSet(String key) {
90100
if ((key == null) || key.isEmpty()) {
91101
return;
92102
}
93103
if (allKeys.containsKey(key)) {
94-
Integer tI = allKeys.get(key); // if(allKeys.get(key) instanceof Integer)
104+
Integer tI = allKeys.get(key);
95105
if (tI == 1) {
96106
allKeys.remove(key);
97107
} else {
98-
allKeys.put(key, tI - 1);//decrementInteger( tI ));
108+
allKeys.put(key, tI - 1);
99109
}
100110
}
101111
}

0 commit comments

Comments
 (0)