package org.jabref.gui.bibtexkeypattern;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JCheckBox;
import org.jabref.Globals;
import org.jabref.gui.BasePanel;
import org.jabref.gui.undo.NamedCompound;
import org.jabref.gui.undo.UndoableKeyChange;
import org.jabref.gui.worker.AbstractWorker;
import org.jabref.logic.bibtexkeypattern.BibtexKeyPatternUtil;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.database.BibDatabase;
import org.jabref.model.entry.BibEntry;
/**
* Function for resolving duplicate BibTeX keys.
*/
public class SearchFixDuplicateLabels extends AbstractWorker {
private final BasePanel panel;
private Map<String, List<BibEntry>> dupes;
public SearchFixDuplicateLabels(BasePanel panel) {
this.panel = panel;
}
@Override
public void run() {
// Find all multiple occurrences of BibTeX keys.
dupes = new HashMap<>();
Map<String, BibEntry> foundKeys = new HashMap<>();
BibDatabase db = panel.getDatabase();
for (BibEntry entry : db.getEntries()) {
entry.getCiteKeyOptional().filter(key -> !key.isEmpty()).ifPresent(key -> {
// See whether this entry's key is already known:
if (foundKeys.containsKey(key)) {
// Already known, so we have found a dupe. See if it was already found as a dupe:
if (dupes.containsKey(key)) {
// Already in the dupe map. Add this entry as well:
dupes.get(key).add(entry);
} else {
// Construct a list of entries for this key:
List<BibEntry> al = new ArrayList<>();
// Add both the first one we found, and the one we found just now:
al.add(foundKeys.get(key));
al.add(entry);
// Add the list to the dupe map:
dupes.put(key, al);
}
} else {
// Not already known. Add key and entry to map:
foundKeys.put(key, entry);
}
});
}
}
@Override
public void init() throws Exception {
panel.output(Localization.lang("Resolving duplicate BibTeX keys..."));
}
@Override
public void update() {
List<BibEntry> toGenerateFor = new ArrayList<>();
for (Map.Entry<String, List<BibEntry>> dupeEntry : dupes.entrySet()) {
ResolveDuplicateLabelDialog rdld = new ResolveDuplicateLabelDialog(panel, dupeEntry.getKey(), dupeEntry.getValue());
rdld.show();
if (rdld.isOkPressed()) {
List<JCheckBox> cbs = rdld.getCheckBoxes();
for (int i = 0; i < cbs.size(); i++) {
if (cbs.get(i).isSelected()) {
// The checkbox for entry i has been selected, so we should generate a new key for it:
toGenerateFor.add(dupeEntry.getValue().get(i));
}
}
} else if (rdld.isCancelPressed()) {
break;
}
}
// Do the actual generation:
if (!toGenerateFor.isEmpty()) {
NamedCompound ce = new NamedCompound(Localization.lang("Resolve duplicate BibTeX keys"));
for (BibEntry entry : toGenerateFor) {
String oldKey = entry.getCiteKeyOptional().orElse(null);
BibtexKeyPatternUtil.makeAndSetLabel(panel.getBibDatabaseContext().getMetaData()
.getCiteKeyPattern(Globals.prefs.getBibtexKeyPatternPreferences().getKeyPattern()),
panel.getDatabase(), entry,
Globals.prefs.getBibtexKeyPatternPreferences());
ce.addEdit(new UndoableKeyChange(entry, oldKey, entry.getCiteKeyOptional().get()));
}
ce.end();
panel.getUndoManager().addEdit(ce);
panel.markBaseChanged();
}
panel.output(Localization.lang("Finished resolving duplicate BibTeX keys. %0 entries modified.",
String.valueOf(toGenerateFor.size())));
}
}