package org.jabref.model.entry;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedSet;
import java.util.StringJoiner;
import java.util.TreeSet;
public class CanonicalBibtexEntry {
private CanonicalBibtexEntry() {
}
/**
* This returns a canonical BibTeX serialization. Special characters such as "{" or "&" are NOT escaped, but written
* as is
*
* Serializes all fields, even the JabRef internal ones. Does NOT serialize "KEY_FIELD" as field, but as key
*/
public static String getCanonicalRepresentation(BibEntry e) {
StringBuilder sb = new StringBuilder();
// generate first line: type and bibtex key
String citeKey = e.getCiteKeyOptional().orElse("");
sb.append(String.format("@%s{%s,", e.getType().toLowerCase(Locale.US), citeKey)).append('\n');
// we have to introduce a new Map as fields are stored case-sensitive in JabRef (see https://github.com/koppor/jabref/issues/45).
Map<String, String> mapFieldToValue = new HashMap<>();
// determine sorted fields -- all fields lower case
SortedSet<String> sortedFields = new TreeSet<>();
for (Entry<String, String> field : e.getFieldMap().entrySet()) {
String fieldName = field.getKey();
String fieldValue = field.getValue();
// JabRef stores the key in the field KEY_FIELD, which must not be serialized
if (!fieldName.equals(BibEntry.KEY_FIELD)) {
String lowerCaseFieldName = fieldName.toLowerCase(Locale.US);
sortedFields.add(lowerCaseFieldName);
mapFieldToValue.put(lowerCaseFieldName, fieldValue);
}
}
// generate field entries
StringJoiner sj = new StringJoiner(",\n", "", "\n");
for (String fieldName : sortedFields) {
String line = String.format(" %s = {%s}", fieldName, String.valueOf(mapFieldToValue.get(fieldName)).replaceAll("\\r\\n","\n"));
sj.add(line);
}
sb.append(sj);
// append the closing entry bracket
sb.append('}');
return sb.toString();
}
}