package org.jabref.gui;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jabref.Globals;
import org.jabref.gui.undo.NamedCompound;
import org.jabref.gui.undo.UndoableFieldChange;
import org.jabref.model.database.BibDatabase;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.FieldName;
import org.jabref.preferences.JabRefPreferences;
public class EntryMarker {
public static final int MARK_COLOR_LEVELS = 6;
public static final int MAX_MARKING_LEVEL = MARK_COLOR_LEVELS - 1;
public static final int IMPORT_MARK_LEVEL = MARK_COLOR_LEVELS;
private static final Pattern MARK_NUMBER_PATTERN = Pattern.compile(JabRefPreferences.getInstance().MARKING_WITH_NUMBER_PATTERN);
private EntryMarker() {
}
/**
* @param increment whether the given increment should be added to the current one. Currently never used in JabRef. Could be used to increase marking color ("Mark in specific color").
*/
public static void markEntry(BibEntry be, int markIncrement, boolean increment, NamedCompound ce) {
int prevMarkLevel;
String newValue = null;
if (be.hasField(FieldName.MARKED_INTERNAL)) {
String markerString = be.getField(FieldName.MARKED_INTERNAL).get();
int index = markerString.indexOf(Globals.prefs.getWrappedUsername());
if (index >= 0) {
// Already marked 1 for this user.
prevMarkLevel = 1;
newValue = markerString.substring(0, index)
+ markerString.substring(index + Globals.prefs.getWrappedUsername().length())
+ Globals.prefs.getWrappedUsername().substring(0,
Globals.prefs.getWrappedUsername().length() - 1)
+ ":" + (increment ? Math.min(MAX_MARKING_LEVEL, prevMarkLevel + markIncrement) : markIncrement)
+ "]";
} else {
Matcher m = MARK_NUMBER_PATTERN.matcher(markerString);
if (m.find()) {
try {
prevMarkLevel = Integer.parseInt(m.group(1));
newValue = markerString.substring(0, m.start(1)) + (increment ? Math.min(MAX_MARKING_LEVEL, prevMarkLevel + markIncrement) : markIncrement) + markerString.substring(m.end(1));
} catch (NumberFormatException ex) {
// Do nothing.
}
}
}
}
if (newValue == null) {
newValue = Globals.prefs.getWrappedUsername().substring(0, Globals.prefs.getWrappedUsername().length() - 1) + ":" + markIncrement + "]";
}
ce.addEdit(new UndoableFieldChange(be, FieldName.MARKED_INTERNAL,
be.getField(FieldName.MARKED_INTERNAL).orElse(null), newValue));
be.setField(FieldName.MARKED_INTERNAL, newValue);
}
/**
* SIDE EFFECT: Unselects given entry
*/
public static void unmarkEntry(BibEntry be, boolean onlyMaxLevel, BibDatabase database, NamedCompound ce) {
if (be.hasField(FieldName.MARKED_INTERNAL)) {
String markerString = be.getField(FieldName.MARKED_INTERNAL).get();
if ("0".equals(markerString)) {
if (!onlyMaxLevel) {
unmarkOldStyle(be, database, ce);
}
return;
}
String newValue = null;
int index = markerString.indexOf(Globals.prefs.getWrappedUsername());
if (index >= 0) {
// Marked 1 for this user.
if (onlyMaxLevel) {
return;
} else {
newValue = markerString.substring(0, index)
+ markerString.substring(index + Globals.prefs.getWrappedUsername().length());
}
} else {
Matcher m = MARK_NUMBER_PATTERN.matcher(markerString);
if (m.find()) {
try {
int prevMarkLevel = Integer.parseInt(m.group(1));
if (!onlyMaxLevel || (prevMarkLevel == MARK_COLOR_LEVELS)) {
if (prevMarkLevel > 1) {
newValue = markerString.substring(0, m.start(1)) + markerString.substring(m.end(1));
} else {
String toRemove = Globals.prefs.getWrappedUsername().substring(0,
Globals.prefs.getWrappedUsername().length() - 1) + ":1]";
index = markerString.indexOf(toRemove);
if (index >= 0) {
newValue = markerString.substring(0, index) + markerString.substring(index + toRemove.length());
}
}
} else {
return;
}
} catch (NumberFormatException ex) {
// Do nothing.
}
}
}
/*int piv = 0, hit;
StringBuffer sb = new StringBuffer();
while ((hit = s.indexOf(G047749118118
1110lobals.prefs.WRAPPED_USERNAME, piv)) >= 0) {
if (hit > 0)
sb.append(s.substring(piv, hit));
piv = hit + Globals.prefs.WRAPPED_USERNAME.length();
}
if (piv < s.length() - 1) {
sb.append(s.substring(piv));
}
String newVal = sb.length() > 0 ? sb.toString() : null;*/
ce.addEdit(new UndoableFieldChange(be, FieldName.MARKED_INTERNAL,
be.getField(FieldName.MARKED_INTERNAL).get(), newValue));
if (newValue == null) {
be.clearField(FieldName.MARKED_INTERNAL);
} else {
be.setField(FieldName.MARKED_INTERNAL, newValue);
}
}
}
/**
* An entry is marked with a "0", not in the new style with user names. We
* want to unmark it as transparently as possible. Since this shouldn't
* happen too often, we do it by scanning the "owner" fields of the entire
* database, collecting all user names. We then mark the entry for all users
* except the current one. Thus only the user who unmarks will see that it
* is unmarked, and we get rid of the old-style marking.
*
* @param be
* @param ce
*/
private static void unmarkOldStyle(BibEntry be, BibDatabase database, NamedCompound ce) {
Set<Object> owners = new TreeSet<>();
for (BibEntry entry : database.getEntries()) {
entry.getField(FieldName.OWNER).ifPresent(owners::add);
}
owners.remove(Globals.prefs.get(JabRefPreferences.DEFAULT_OWNER));
StringBuilder sb = new StringBuilder();
for (Object owner : owners) {
sb.append('[');
sb.append(owner);
sb.append(']');
}
String newVal = sb.toString();
if (newVal.isEmpty()) {
ce.addEdit(new UndoableFieldChange(be, FieldName.MARKED_INTERNAL,
be.getField(FieldName.MARKED_INTERNAL).orElse(null), null));
be.clearField(FieldName.MARKED_INTERNAL);
} else {
ce.addEdit(new UndoableFieldChange(be, FieldName.MARKED_INTERNAL,
be.getField(FieldName.MARKED_INTERNAL).orElse(null), newVal));
be.setField(FieldName.MARKED_INTERNAL, newVal);
}
}
public static int isMarked(BibEntry be) {
if (!be.hasField(FieldName.MARKED_INTERNAL)) {
return 0;
}
String s = be.getField(FieldName.MARKED_INTERNAL).get();
if ("0".equals(s)) {
return 1;
}
int index = s.indexOf(Globals.prefs.getWrappedUsername());
if (index >= 0) {
return 1;
}
Matcher m = MARK_NUMBER_PATTERN.matcher(s);
if (m.find()) {
try {
return Integer.parseInt(m.group(1));
} catch (NumberFormatException ex) {
return 1;
}
} else {
return 0;
}
}
public static boolean shouldMarkEntries() {
return Globals.prefs.getBoolean(JabRefPreferences.MARK_IMPORTED_ENTRIES);
}
}