package org.jabref.model.database; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.jabref.model.database.event.EntryRemovedEvent; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.FieldProperty; import org.jabref.model.entry.InternalBibtexFields; import org.jabref.model.entry.event.FieldChangedEvent; import com.google.common.eventbus.Subscribe; public class KeyChangeListener { private final BibDatabase database; private final List<String> keyFields = new ArrayList<>(); public KeyChangeListener(BibDatabase database) { this.database = database; // Look for fields with FieldProperies.SINGLE_ENTRY_LINK or FieldProperties.MULTIPLE_ENTRY_LINK to speed up the search later for (String fieldName : InternalBibtexFields.getAllPublicFieldNames()) { if (InternalBibtexFields.getFieldProperties(fieldName).contains(FieldProperty.SINGLE_ENTRY_LINK) || InternalBibtexFields.getFieldProperties(fieldName).contains(FieldProperty.MULTIPLE_ENTRY_LINK)) { keyFields.add(fieldName); } } } @Subscribe public void listen(FieldChangedEvent event) { if (event.getFieldName().equals(BibEntry.KEY_FIELD)) { String newKey = event.getNewValue(); String oldKey = event.getOldValue(); updateEntryLinks(newKey, oldKey); } } @Subscribe public void listen(EntryRemovedEvent event) { event.getBibEntry().getCiteKeyOptional().ifPresent(oldKey -> updateEntryLinks(null, oldKey)); } private void updateEntryLinks(String newKey, String oldKey) { for (BibEntry entry : database.getEntries()) { for (String field : keyFields) { entry.getField(field).ifPresent(fieldContent -> { if (InternalBibtexFields.getFieldProperties(field).contains(FieldProperty.SINGLE_ENTRY_LINK)) { replaceSingleKeyInField(newKey, oldKey, entry, field, fieldContent); } else { // MULTIPLE_ENTRY_LINK replaceKeyInMultiplesKeyField(newKey, oldKey, entry, field, fieldContent); } }); } } } private void replaceKeyInMultiplesKeyField(String newKey, String oldKey, BibEntry entry, String field, String fieldContent) { List<String> keys = new ArrayList<>(Arrays.asList(fieldContent.split(","))); int index = keys.indexOf(oldKey); if (index != -1) { if (newKey == null) { keys.remove(index); } else { keys.set(index, newKey); } entry.setField(field, String.join(",", keys)); } } private void replaceSingleKeyInField(String newKey, String oldKey, BibEntry entry, String field, String fieldContent) { if (fieldContent.equals(oldKey)) { if (newKey == null) { entry.clearField(field); } else { entry.setField(field, newKey); } } } }