Skip to content

Commit

Permalink
Merge pull request #391 from JabRef/stable-serialization
Browse files Browse the repository at this point in the history
Write unmodified entries to bib file in the same format as they were read
  • Loading branch information
koppor committed Dec 6, 2015
2 parents c43389d + d89eb00 commit 741c40e
Show file tree
Hide file tree
Showing 17 changed files with 732 additions and 504 deletions.
37 changes: 21 additions & 16 deletions src/main/java/net/sf/jabref/MetaData.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import java.util.*;

import net.sf.jabref.groups.GroupTreeNode;
import net.sf.jabref.gui.GUIGlobals;
import net.sf.jabref.migrations.VersionHandling;
import net.sf.jabref.logic.labelPattern.AbstractLabelPattern;
import net.sf.jabref.logic.labelPattern.DatabaseLabelPattern;
Expand All @@ -29,6 +28,7 @@

public class MetaData implements Iterable<String> {

public static final String META_FLAG = "jabref-meta: ";
private static final String PREFIX_KEYPATTERN = "keypattern_";
private static final String KEYPATTERNDEFAULT = "keypatterndefault";

Expand Down Expand Up @@ -104,7 +104,8 @@ public MetaData(HashMap<String, String> inData, BibtexDatabase db) {
/**
* The MetaData object can be constructed with no data in it.
*/
public MetaData() {}
public MetaData() {
}

/**
* Add default metadata for new database:
Expand Down Expand Up @@ -158,6 +159,7 @@ public void putData(String key, Vector<String> orderedData) {
/**
* Look up the directory set up for the given field type for this database.
* If no directory is set up, return that defined in global preferences.
*
* @param fieldName The field type
* @return The default directory for this field type.
*/
Expand Down Expand Up @@ -195,8 +197,7 @@ public String[] getFileDirectory(String fieldName) {
}
}
dirs.add(dir);
}
else {
} else {
String dir = Globals.prefs.get(fieldName + "Directory");
if (dir != null) {
dirs.add(dir);
Expand All @@ -218,9 +219,10 @@ public String[] getFileDirectory(String fieldName) {

/**
* Parse the groups metadata string
*
* @param orderedData The vector of metadata strings
* @param db The BibtexDatabase this metadata belongs to
* @param version The group tree version
* @param db The BibtexDatabase this metadata belongs to
* @param version The group tree version
* @return true if parsing was successful, false otherwise
*/
private void putGroups(Vector<String> orderedData, BibtexDatabase db, int version) {
Expand Down Expand Up @@ -255,16 +257,18 @@ public void setGroups(GroupTreeNode root) {
public void writeMetaData(Writer out) throws IOException {
// write all meta data except groups
SortedSet<String> sortedKeys = new TreeSet<>(metaData.keySet());

for (String key : sortedKeys) {

StringBuffer sb = new StringBuffer();
sb.append(Globals.NEWLINE);
sb.append(Globals.NEWLINE);
Vector<String> orderedData = metaData.get(key);
sb.append("@comment{").append(GUIGlobals.META_FLAG).append(key).append(":");
sb.append("@comment{").append(META_FLAG).append(key).append(":");
for (int j = 0; j < orderedData.size(); j++) {
sb.append(StringUtil.quote(orderedData.elementAt(j), ";", '\\')).append(";");
}
sb.append("}");
sb.append(Globals.NEWLINE);
sb.append(Globals.NEWLINE);

out.write(sb.toString());
}
Expand All @@ -273,16 +277,19 @@ public void writeMetaData(Writer out) throws IOException {
if ((groupsRoot != null) && (groupsRoot.getChildCount() > 0)) {
StringBuffer sb = new StringBuffer();
// write version first
sb.append("@comment{").append(GUIGlobals.META_FLAG).append("groupsversion:");
sb.append("" + VersionHandling.CURRENT_VERSION + ";");
sb.append("}");
sb.append(Globals.NEWLINE);
sb.append(Globals.NEWLINE);
sb.append("@comment{").append(META_FLAG).append("groupsversion:");
sb.append("" + VersionHandling.CURRENT_VERSION + ";");
sb.append("}");

out.write(sb.toString());

// now write actual groups
sb = new StringBuffer();
sb.append("@comment{").append(GUIGlobals.META_FLAG).append("groupstree:");
sb.append(Globals.NEWLINE);
sb.append(Globals.NEWLINE);
sb.append("@comment{").append(META_FLAG).append("groupstree:");
sb.append(Globals.NEWLINE);
// GroupsTreeNode.toString() uses "\n" for separation
StringTokenizer tok = new StringTokenizer(groupsRoot.getTreeAsString(), Globals.NEWLINE);
Expand All @@ -293,8 +300,6 @@ public void writeMetaData(Writer out) throws IOException {
sb.append(Globals.NEWLINE);
}
sb.append("}");
sb.append(Globals.NEWLINE);
sb.append(Globals.NEWLINE);
out.write(sb.toString());
}
}
Expand Down Expand Up @@ -374,7 +379,7 @@ public AbstractLabelPattern getLabelPattern() {
* Updates the stored key patterns to the given key patterns.
*
* @param labelPattern the key patterns to update to. <br />
* A reference to this object is stored internally and is returned at getLabelPattern();
* A reference to this object is stored internally and is returned at getLabelPattern();
*/
public void setLabelPattern(DatabaseLabelPattern labelPattern) {
// remove all keypatterns from metadata
Expand Down
13 changes: 10 additions & 3 deletions src/main/java/net/sf/jabref/bibtex/BibtexEntryWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ public BibtexEntryWriter(LatexFieldFormatter fieldFormatter, boolean write) {
}

public void write(BibtexEntry entry, Writer out) throws IOException {
// if the entry has not been modified, write it as it was
if(!entry.hasChanged()){
out.write(entry.getParsedSerialization());
return;
}
out.write(Globals.NEWLINE + Globals.NEWLINE);

switch (writeFieldSortStyle) {
case 0:
writeRequiredFieldsFirstOptionalFieldsSecondRemainingFieldsThird(entry, out);
Expand Down Expand Up @@ -166,7 +173,7 @@ private void writeRequiredFieldsFirstOptionalFieldsSecondRemainingFieldsThird(Bi
}

// Finally, end the entry.
out.write((hasWritten ? Globals.NEWLINE : "") + '}' + Globals.NEWLINE);
out.write((hasWritten ? Globals.NEWLINE : "") + '}');
}

private List<String> getRequiredFieldsSorted(BibtexEntry entry) {
Expand Down Expand Up @@ -245,7 +252,7 @@ private void writeRequiredFieldsFirstRemainingFieldsSecond(BibtexEntry entry, Wr
}

// Finally, end the entry.
out.write((hasWritten ? Globals.NEWLINE : "") + '}' + Globals.NEWLINE);
out.write((hasWritten ? Globals.NEWLINE : "") + '}');
}

private void writeUserDefinedOrder(BibtexEntry entry, Writer out) throws IOException {
Expand Down Expand Up @@ -290,7 +297,7 @@ private void writeUserDefinedOrder(BibtexEntry entry, Writer out) throws IOExcep
}

// Finally, end the entry.
out.write((hasWritten ? Globals.NEWLINE : "") + '}' + Globals.NEWLINE);
out.write((hasWritten ? Globals.NEWLINE : "") + '}');

}

Expand Down
43 changes: 28 additions & 15 deletions src/main/java/net/sf/jabref/exporter/FileActions.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ private static void writePreamble(Writer fw, String preamble) throws IOException
* Write all strings in alphabetical order, modified to produce a safe (for
* BibTeX) order of the strings if they reference each other.
*
* @param fw The Writer to send the output to.
* @param fw The Writer to send the output to.
* @param database The database whose strings we should write.
* @throws IOException If anthing goes wrong in writing.
*/
Expand All @@ -96,13 +96,18 @@ private static void writeStrings(Writer fw, BibtexDatabase database) throws IOEx
}
}
}
fw.write(Globals.NEWLINE);
}

private static void writeString(Writer fw, BibtexString bs, HashMap<String, BibtexString> remaining, int maxKeyLength) throws IOException {
// First remove this from the "remaining" list so it can't cause problem with circular refs:
remaining.remove(bs.getName());

//if the string has not been modified, write it back as it was
if (!bs.hasChanged()) {
fw.write(bs.getParsedSerialization());
return;
}

// Then we go through the string looking for references to other strings. If we find references
// to strings that we will write, but still haven't, we write those before proceeding. This ensures
// that the string order will be acceptable for BibTeX.
Expand Down Expand Up @@ -155,7 +160,7 @@ private static void writeString(Writer fw, BibtexString bs, HashMap<String, Bibt
*/
private static void writeBibFileHeader(Writer out, Charset encoding) throws IOException {
out.write("% ");
out.write(Globals.encPrefix + encoding + Globals.NEWLINE + Globals.NEWLINE);
out.write(Globals.encPrefix + encoding + Globals.NEWLINE + Globals.NEWLINE + Globals.NEWLINE);
}

/**
Expand All @@ -166,9 +171,9 @@ private static void writeBibFileHeader(Writer out, Charset encoding) throws IOEx
* entries are saved.
*/
public static SaveSession saveDatabase(BibtexDatabase database,
MetaData metaData, File file, JabRefPreferences prefs,
boolean checkSearch, boolean checkGroup, Charset encoding, boolean suppressBackup)
throws SaveException {
MetaData metaData, File file, JabRefPreferences prefs,
boolean checkSearch, boolean checkGroup, Charset encoding, boolean suppressBackup)
throws SaveException {

TreeMap<String, EntryType> types = new TreeMap<>();

Expand Down Expand Up @@ -238,7 +243,6 @@ public static SaveSession saveDatabase(BibtexDatabase database,

if (write) {
bibtexEntryWriter.write(entry, writer);
writer.write(Globals.NEWLINE);
}
}

Expand All @@ -254,13 +258,19 @@ public static SaveSession saveDatabase(BibtexDatabase database,
if (type instanceof CustomEntryType) {
CustomEntryType tp = (CustomEntryType) type;
CustomEntryTypesManager.save(tp, writer);
writer.write(Globals.NEWLINE);
}
}

}
} catch (Throwable ex) {
ex.printStackTrace();

//finally write whatever remains of the file, but at least a concluding newline
if (database.getEpilog() != null && database.getEpilog() != "") {
writer.write(database.getEpilog());
} else {
writer.write(Globals.NEWLINE);
}
} catch (IOException ex) {
LOGGER.error("Could not write file", ex);
session.cancel();
// repairAfterError(file, backup, INIT_OK);
throw new SaveException(ex.getMessage(), ex.getLocalizedMessage(), exceptionCause);
Expand Down Expand Up @@ -357,9 +367,9 @@ private static List<Comparator<BibtexEntry>> getSaveComparators(boolean isSaveOp
* @return A List containing warnings, if any.
*/
public static SaveSession savePartOfDatabase(BibtexDatabase database, MetaData metaData,
File file,
JabRefPreferences prefs, BibtexEntry[] bes, Charset encoding, DatabaseSaveType saveType)
throws SaveException {
File file,
JabRefPreferences prefs, BibtexEntry[] bes, Charset encoding, DatabaseSaveType saveType)
throws SaveException {

TreeMap<String, EntryType> types = new TreeMap<>(); // Map
// to
Expand Down Expand Up @@ -418,7 +428,10 @@ public static SaveSession savePartOfDatabase(BibtexDatabase database, MetaData m
}

bibtexEntryWriter.write(be, fw);
fw.write(Globals.NEWLINE);
//only append newline if the entry has changed
if (!be.hasChanged()) {
fw.write(Globals.NEWLINE);
}
}

// Write meta data.
Expand Down Expand Up @@ -514,7 +527,7 @@ public static List<BibtexEntry> getSortedEntries(BibtexDatabase database, MetaDa
if (keySet != null) {
Iterator<String> i = keySet.iterator();

for (; i.hasNext();) {
for (; i.hasNext(); ) {
sorter.add(database.getEntryById(i.next()));
}
}
Expand Down
3 changes: 0 additions & 3 deletions src/main/java/net/sf/jabref/gui/GUIGlobals.java
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,6 @@ public class GUIGlobals {
public static Color activeBackground;
public static Color invalidFieldBackgroundColor;

public static final String META_FLAG = "jabref-meta: ";
public static final String META_FLAG_OLD = "bibkeeper-meta: ";

// some fieldname constants
public static final double DEFAULT_FIELD_WEIGHT = 1;
public static final double MAX_FIELD_WEIGHT = 2;
Expand Down
48 changes: 6 additions & 42 deletions src/main/java/net/sf/jabref/importer/ParserResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;

import net.sf.jabref.model.database.BibtexDatabase;
import net.sf.jabref.model.entry.BibtexEntry;
import net.sf.jabref.MetaData;
Expand All @@ -45,10 +46,6 @@ public class ParserResult {
private boolean invalid;
private boolean toOpenTab;

// Which JabRef version wrote the file, if any?
private String jabrefVersion;
private int jabrefMajorVersion;
private int jabrefMinorVersion;

public ParserResult(Collection<BibtexEntry> entries) {
this(ImportFormatReader.createDatabase(entries), null, new HashMap<>());
Expand All @@ -62,6 +59,7 @@ public ParserResult(BibtexDatabase base, MetaData metaData, HashMap<String, Entr

/**
* Check if this base is marked to be added to the currently open tab. Default is false.
*
* @return
*/
public boolean toOpenTab() {
Expand All @@ -72,44 +70,6 @@ public void setToOpenTab(boolean toOpenTab) {
this.toOpenTab = toOpenTab;
}

/**
* Find which version of JabRef, if any, produced this bib file.
* @return The version number string, or null if no JabRef signature could be read.
*/
public String getJabrefVersion() {
return jabrefVersion;
}

/**
* Set the JabRef version number string for this parser result.
* @param jabrefVersion The version number string.
*/
public void setJabrefVersion(String jabrefVersion) {
this.jabrefVersion = jabrefVersion;
}

/**
* @return 0 if not known (e.g., no version header in file)
*/
public int getJabrefMajorVersion() {
return jabrefMajorVersion;
}

public void setJabrefMajorVersion(int jabrefMajorVersion) {
this.jabrefMajorVersion = jabrefMajorVersion;
}

/**
* @return 0 if not known (e.g., no version header in file)
*/
public int getJabrefMinorVersion() {
return jabrefMinorVersion;
}

public void setJabrefMinorVersion(int jabrefMinorVersion) {
this.jabrefMinorVersion = jabrefMinorVersion;
}

public BibtexDatabase getDatabase() {
return base;
}
Expand Down Expand Up @@ -176,6 +136,7 @@ public String[] warnings() {

/**
* Add a key to the list of duplicated BibTeX keys found in the database.
*
* @param key The duplicated key
*/
public void addDuplicateKey(String key) {
Expand All @@ -186,6 +147,7 @@ public void addDuplicateKey(String key) {

/**
* Query whether any duplicated BibTeX keys have been found in the database.
*
* @return true if there is at least one duplicate key.
*/
public boolean hasDuplicateKeys() {
Expand All @@ -194,6 +156,7 @@ public boolean hasDuplicateKeys() {

/**
* Get all duplicated keys found in the database.
*
* @return An array containing the duplicated keys.
*/
public String[] getDuplicateKeys() {
Expand Down Expand Up @@ -223,4 +186,5 @@ public String getErrorMessage() {
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}

}
Loading

0 comments on commit 741c40e

Please sign in to comment.