Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
- Make (un)abbreviating journal titles also work on the journaltitle field
- Fix edits getting lost in Biblatex mode
- Fix error when setting a previously unset field via the source panel of the entry editor
- Improved BibLatex support (alias fields, option to convert old entries to the new format via the cleanup menu)
- Fixes bug #1087 "jabref does not follow biblatex specification"
- Fixes bug #1014 'journal' not recognized as alias for 'journaltitle''
- Fixes bug #874 Support of biblatex "date" field
- Fixes bug that prevented the secondary optional fields to update properly in the "Customize entry fields" dialog (in BibLatex mode)
2.10
- Made IEEEXploreFetcher author parsing work again.
- Added a few more characters in the HTML/Unicode to LaTeX conversion.
Expand Down
79 changes: 40 additions & 39 deletions src/main/java/net/sf/jabref/BibLatexEntryTypes.java

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion src/main/java/net/sf/jabref/BibtexDatabase.java
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,10 @@ public static String getResolvedField(String field, BibtexEntry bibtex,
if (field.equals("bibtextype"))
return bibtex.getType().getName();

Object o = bibtex.getField(field);
// TODO: Changed this to also consider alias fields, which is the expected
// behavior for the preview layout and for the check whatever all fields are present.
// But there might be unwanted side-effects?!
Object o = bibtex.getFieldOrAlias(field);

// If this field is not set, and the entry has a crossref, try to look up the
// field in the referred entry: Do not do this for the bibtex key.
Expand Down
139 changes: 137 additions & 2 deletions src/main/java/net/sf/jabref/BibtexEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@
import java.beans.VetoableChangeSupport;
import java.io.IOException;
import java.io.Writer;
import java.text.DateFormat;
import java.text.FieldPosition;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.*;

import net.sf.jabref.export.FieldFormatter;
Expand All @@ -44,6 +49,9 @@
public class BibtexEntry
{
public final static String ID_FIELD = "id";
public static Map<String,String> FieldAliasesOldToNew = new HashMap<String, String>(); // Bibtex to BibLatex
public static Map<String,String> FieldAliasesNewToOld = new HashMap<String, String>(); // BibLatex to Bibtex

private String _id;
private BibtexEntryType _type;
private Map<String, String> _fields = new HashMap<String, String>();
Expand Down Expand Up @@ -83,6 +91,30 @@ public class BibtexEntry
}
}
maxFieldLength = max;

FieldAliasesOldToNew.put("address", "location");
FieldAliasesNewToOld.put("location", "address");

FieldAliasesOldToNew.put("annote", "annotation");
FieldAliasesNewToOld.put("annotation", "annote");

FieldAliasesOldToNew.put("archiveprefix", "eprinttype");
FieldAliasesNewToOld.put("eprinttype", "archiveprefix");

FieldAliasesOldToNew.put("journal", "journaltitle");
FieldAliasesNewToOld.put("journaltitle", "journal");

FieldAliasesOldToNew.put("key", "sortkey");
FieldAliasesNewToOld.put("sortkey", "key");

FieldAliasesOldToNew.put("pdf", "file");
FieldAliasesNewToOld.put("file", "pdf");

FieldAliasesOldToNew.put("primaryclass", "eprintclass");
FieldAliasesNewToOld.put("eprintclass", "primaryclass");

FieldAliasesOldToNew.put("school", "institution");
FieldAliasesNewToOld.put("institution", "school");
}

/**
Expand Down Expand Up @@ -283,7 +315,111 @@ public String getId()
public String getField(String name) {
return _fields.get(name);
}


/**
* Returns the contents of the given field, its alias or null if both are
* not set.
*
* The following aliases are considered (old bibtex <-> new biblatex) based
* on the BibLatex documentation, chapter 2.2.5:
* address <-> location
* annote <-> annotation
* archiveprefix <-> eprinttype
* journal <-> journaltitle
* key <-> sortkey
* pdf <-> file
* primaryclass <-> eprintclass
* school <-> institution
* These work bidirectional.
*
* Special attention is paid to dates: (see the BibLatex documentation,
* chapter 2.3.8)
* The fields 'year' and 'month' are used if the 'date'
* field is empty. Conversely, getFieldOrAlias("year") also tries to
* extract the year from the 'date' field (analogously for 'month').
*/
public String getFieldOrAlias(String name) {
String fieldValue = getField(name);
if (fieldValue != null && fieldValue.length() > 0)
return fieldValue;

// No value of this field found, so look at the alias

// Create bidirectional dictionary between field names and their aliases
Map<String,String> aliases = new HashMap<String, String>();
aliases.putAll(FieldAliasesOldToNew);
aliases.putAll(FieldAliasesNewToOld);

String aliasForField = aliases.get(name);
if(aliasForField != null)
return getField(aliasForField);

// So we did not found the field itself or its alias...
// Finally, handle dates
if(name.equals("date"))
{
String year = getField("year");
int month = Globals.ParseMonthToInteger(getField("month"));
if(year != null)
{
if(month == 0)
return year;
else
return year + "-" + month;
}
}
if(name.equals("year") || name.equals("month"))
{
String date = getField("date");
if(date == null)
return null;

// Create date format matching dates with year and month
DateFormat df = new DateFormat() {
static final String FORMAT1 = "yyyy-MM-dd";
static final String FORMAT2 = "yyyy-MM";
final SimpleDateFormat sdf1 = new SimpleDateFormat(FORMAT1);
final SimpleDateFormat sdf2 = new SimpleDateFormat(FORMAT2);
@Override
public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
throw new UnsupportedOperationException();
}

@Override
public Date parse(String source, ParsePosition pos) {
if (source.length() - pos.getIndex() == FORMAT1.length())
return sdf1.parse(source, pos);
return sdf2.parse(source, pos);
}
};

try {
Date parsedDate = df.parse(date);
Calendar calendar = Calendar.getInstance();
calendar.setTime(parsedDate);
if(name.equals("year"))
return Integer.toString(calendar.get(Calendar.YEAR));
if(name.equals("month"))
return Integer.toString(calendar.get(Calendar.MONTH) + 1); // Shift by 1 since in this calendar Jan = 0
} catch (ParseException e) {
// So not a date with year and month, try just to parse years
df = new SimpleDateFormat("yyyy");

try {
Date parsedDate = df.parse(date);
Calendar calendar = Calendar.getInstance();
calendar.setTime(parsedDate);
if(name.equals("year"))
return Integer.toString(calendar.get(Calendar.YEAR));
} catch (ParseException e2) {
return null; // Date field not in valid format
}
}
}

return null;
}

public String getCiteKey() {
return (_fields.containsKey(BibtexFields.KEY_FIELD) ?
_fields.get(BibtexFields.KEY_FIELD) : null);
Expand Down Expand Up @@ -676,5 +812,4 @@ public String getAuthorTitleYear(int maxCharacters) {
return text;
return text.substring(0, maxCharacters + 1) + "...";
}

}
40 changes: 38 additions & 2 deletions src/main/java/net/sf/jabref/EntryEditor.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,11 @@
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

Expand Down Expand Up @@ -256,14 +259,47 @@ private void setupFieldPanels() {
tabbed.addTab(Globals.lang("Optional fields"), GUIGlobals.getImage("optional"), optPan
.getPane(), Globals.lang("Show optional fields"));
tabs.add(optPan);

Set<String> deprecatedFields = new HashSet<String>(entry.FieldAliasesOldToNew.keySet());
deprecatedFields.add("year");
deprecatedFields.add("month");
String[] optionalFieldsNotPrimaryOrDeprecated = Util.getRemainder(entry.getOptionalFields(),
entry.getType().getPrimaryOptionalFields());
optionalFieldsNotPrimaryOrDeprecated = Util.getRemainder(optionalFieldsNotPrimaryOrDeprecated,
deprecatedFields.toArray(new String[0]));

// Get list of all optional fields of this entry and their aliases
Set<String> optionalFieldsAndAliases = new HashSet<String>();
for(String field : entry.getOptionalFields())
{
optionalFieldsAndAliases.add(field);
if(entry.FieldAliasesNewToOld.containsKey(field))
optionalFieldsAndAliases.add(entry.FieldAliasesNewToOld.get(field));
}

// Get all optional fields which are deprecated
Set<String> usedOptionalFieldsDeprecated = new HashSet<String>(deprecatedFields);
usedOptionalFieldsDeprecated.retainAll(optionalFieldsAndAliases);

// Add tabs
optPan = new EntryEditorTab(frame, panel,
java.util.Arrays.asList(Util.getRemainder(entry.getOptionalFields(),
entry.getType().getPrimaryOptionalFields())), this,
java.util.Arrays.asList(optionalFieldsNotPrimaryOrDeprecated), this,
false, true, Globals.lang("Optional fields 2"));
if (optPan.fileListEditor != null) fileListEditor = optPan.fileListEditor;
tabbed.addTab(Globals.lang("Optional fields 2"), GUIGlobals.getImage("optional"), optPan
.getPane(), Globals.lang("Show optional fields"));
tabs.add(optPan);

if(!usedOptionalFieldsDeprecated.isEmpty())
{
optPan = new EntryEditorTab(frame, panel,
java.util.Arrays.asList(usedOptionalFieldsDeprecated.toArray(new String[0])), this,
false, true, Globals.lang("Deprecated fields"));
if (optPan.fileListEditor != null) fileListEditor = optPan.fileListEditor;
tabbed.addTab(Globals.lang("Deprecated fields"), GUIGlobals.getImage("optional"), optPan
.getPane(), Globals.lang("Show deprecated bibtex fields"));
tabs.add(optPan);
}
}
}

Expand Down
31 changes: 31 additions & 0 deletions src/main/java/net/sf/jabref/Globals.java
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,37 @@ public ResourceBundle newBundle(String baseName, Locale locale,
"ISO8859_6", "ISO8859_7", "ISO8859_8", "ISO8859_9", "ISO8859_13", "ISO8859_15" };
public static Map<String,String> ENCODING_NAMES_LOOKUP;

/**
* Parses month expressions (like 1, jan, #jan#) to the numerical representation
* (with January corresponding to 1)
* Returns 0 if the month could not be parsed.
* TODO: Move this method along with the two arrays 'MONTHS' and 'MONTH_STRINGS' to a seperate class?
*/
public static int ParseMonthToInteger(String value)
{
// implementation based on patch 3470076 by Mathias Walter
// originally, this code was present in the CleanUp-doCleanUpMonth method
if (value == null)
return 0;

try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
// Much more liberal matching covering most known abbreviations etc.
String testString = value.replace("#", "").trim().substring(0, 3).toLowerCase();
if (Globals.MONTH_STRINGS.containsKey(testString)) {
int i = 0;
for(String month : MONTHS)
{
if(testString.equals(MONTHS[i]))
return i + 1;
i++;
}
}
}
return 0;
}

// String array that maps from month number to month string label:
public static String[] MONTHS = new String[] { "jan", "feb", "mar", "apr", "may", "jun", "jul",
"aug", "sep", "oct", "nov", "dec" };
Expand Down
Loading