package org.jabref.collab;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import org.jabref.gui.BasePanel;
import org.jabref.gui.undo.NamedCompound;
import org.jabref.gui.undo.UndoableFieldChange;
import org.jabref.logic.bibtex.DuplicateCheck;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.database.BibDatabase;
import org.jabref.model.entry.BibEntry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
class EntryChange extends Change {
private static final Log LOGGER = LogFactory.getLog(EntryChange.class);
public EntryChange(BibEntry memEntry, BibEntry tmpEntry, BibEntry diskEntry) {
super();
Optional<String> key = tmpEntry.getCiteKeyOptional();
if (key.isPresent()) {
name = Localization.lang("Modified entry") + ": '" + key.get() + '\'';
} else {
name = Localization.lang("Modified entry");
}
// We know that tmpEntry is not equal to diskEntry. Check if it has been modified
// locally as well, since last tempfile was saved.
boolean isModifiedLocally = (DuplicateCheck.compareEntriesStrictly(memEntry, tmpEntry) <= 1);
// Another (unlikely?) possibility is that both disk and mem version has been modified
// in the same way. Check for this, too.
boolean modificationsAgree = (DuplicateCheck.compareEntriesStrictly(memEntry, diskEntry) > 1);
LOGGER.debug("Modified entry: " + memEntry.getCiteKeyOptional().orElse("<no BibTeX key set>")
+ "\n Modified locally: " + isModifiedLocally + " Modifications agree: " + modificationsAgree);
Set<String> allFields = new TreeSet<>();
allFields.addAll(memEntry.getFieldNames());
allFields.addAll(tmpEntry.getFieldNames());
allFields.addAll(diskEntry.getFieldNames());
for (String field : allFields) {
Optional<String> mem = memEntry.getField(field);
Optional<String> tmp = tmpEntry.getField(field);
Optional<String> disk = diskEntry.getField(field);
if ((tmp.isPresent()) && (disk.isPresent())) {
if (!tmp.equals(disk)) {
// Modified externally.
add(new FieldChange(field, memEntry, tmpEntry, mem.orElse(null), tmp.get(), disk.get()));
}
} else if (((!tmp.isPresent()) && (disk.isPresent()) && !disk.get().isEmpty())
|| ((!disk.isPresent()) && (tmp.isPresent()) && !tmp.get().isEmpty()
&& (mem.isPresent()) && !mem.get().isEmpty())) {
// Added externally.
add(new FieldChange(field, memEntry, tmpEntry, mem.orElse(null), tmp.orElse(null),
disk.orElse(null)));
}
}
}
@Override
public boolean makeChange(BasePanel panel, BibDatabase secondary, NamedCompound undoEdit) {
boolean allAccepted = true;
Enumeration<Change> e = children();
for (Change c : Collections.list(e)) {
if (c.isAcceptable() && c.isAccepted()) {
c.makeChange(panel, secondary, undoEdit);
} else {
allAccepted = false;
}
}
/*panel.database().removeEntry(memEntry.getId());
try {
diskEntry.setId(Util.next());
} catch (KeyCollisionException ex) {}
panel.database().removeEntry(memEntry.getId());*/
return allAccepted;
}
@Override
public JComponent description() {
return new JLabel(name);
}
static class FieldChange extends Change {
private final BibEntry entry;
private final BibEntry tmpEntry;
private final String field;
private final String inMem;
private final String onDisk;
private final InfoPane tp = new InfoPane();
private final JScrollPane sp = new JScrollPane(tp);
public FieldChange(String field, BibEntry memEntry, BibEntry tmpEntry, String inMem, String onTmp, String onDisk) {
super(field);
entry = memEntry;
this.tmpEntry = tmpEntry;
this.field = field;
this.inMem = inMem;
this.onDisk = onDisk;
StringBuilder text = new StringBuilder(36);
text.append("<FONT SIZE=10><H2>").append(Localization.lang("Modification of field"))
.append(" <I>").append(field).append("</I></H2>");
if ((onDisk != null) && !onDisk.isEmpty()) {
text.append("<H3>").append(Localization.lang("Value set externally")).append(":</H3> ").append(onDisk);
} else {
text.append("<H3>").append(Localization.lang("Value cleared externally")).append("</H3>");
}
if ((inMem != null) && !inMem.isEmpty()) {
text.append("<H3>").append(Localization.lang("Current value")).append(":</H3> ").append(inMem);
}
if ((onTmp != null) && !onTmp.isEmpty()) {
text.append("<H3>").append(Localization.lang("Current tmp value")).append(":</H3> ").append(onTmp);
}
tp.setContentType("text/html");
tp.setText(text.toString());
}
@Override
public boolean makeChange(BasePanel panel, BibDatabase secondary, NamedCompound undoEdit) {
if (onDisk == null) {
entry.clearField(field);
} else {
entry.setField(field, onDisk);
}
undoEdit.addEdit(new UndoableFieldChange(entry, field, inMem, onDisk));
if (onDisk == null) {
tmpEntry.clearField(field);
} else {
tmpEntry.setField(field, onDisk);
}
return true;
}
@Override
public JComponent description() {
return sp;
}
}
}