package net.sf.jabref.journals;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.URL;
import java.util.*;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.undo.CompoundEdit;
import javax.swing.undo.UndoManager;
import net.sf.jabref.*;
import net.sf.jabref.undo.UndoableFieldChange;
import net.sf.jabref.util.CaseChanger;
/**
* Created by IntelliJ IDEA.
* User: alver
* Date: Sep 16, 2005
* Time: 10:49:08 PM
* To browseOld this template use File | Settings | File Templates.
*/
public class JournalAbbreviations {
static String TOOLTIPTEXT = "<HTML>"+Globals.lang("Switches between full and abbreviated journal name "
+"if the journal name is known.")
+"<BR>"+Globals.lang("To set up, go to <B>Tools -> Manage journal abbreviations</B>")+".</HTML>";
TreeMap<String, String> fullNameKeyed = new TreeMap<String, String>();
HashMap<String, String> abbrNameKeyed = new HashMap<String, String>();
HashMap<String, String> abbrNoDotsToAbbr = new HashMap<String, String>();
TreeMap<String, String> all = new TreeMap<String, String>();
CaseChanger caseChanger = new CaseChanger();
public JournalAbbreviations() {
}
public JournalAbbreviations(String resource) {
readJournalList(resource);
}
public JournalAbbreviations(File file) throws FileNotFoundException {
readJournalList(file);
}
/**
* Get an iterator for the known journals in alphabetical order.
* @return Iterator for journal full names
*/
public Iterator<String> fullNameIterator() {
return fullNameKeyed.keySet().iterator();
}
public boolean isKnownName(String journalName) {
String s = journalName.toLowerCase();
return ((fullNameKeyed.get(s) != null) || (abbrNameKeyed.get(s) != null) || (abbrNoDotsToAbbr.get(s) != null));
}
public boolean isAbbreviatedName(String journalName) {
String s = journalName.toLowerCase();
return ((abbrNameKeyed.get(s) != null) || (abbrNoDotsToAbbr.get(s) != null));
}
public String dotsToNodots(String name) {
return name.replaceAll("\\.", " ").replaceAll(" ", " ").trim();
}
/**
* Attempts to get the abbreviated name of the journal given. Returns null if no
* abbreviated name is known.
* @param journalName The journal name to abbreviate.
* @param withDots True if the abbreviation should have dots.
* if only the first character should be.
* @return The abbreviated name, or null if it couldn't be found.
*/
public String getAbbreviatedName(String journalName, boolean withDots) {
String s = journalName.toLowerCase();
String abbr;
if (fullNameKeyed.containsKey(s)) {
abbr = fullNameKeyed.get(s);
}
else if (abbrNameKeyed.containsKey(s)) {
abbr = journalName;
}
else if (abbrNoDotsToAbbr.containsKey(s)) {
abbr = abbrNoDotsToAbbr.get(s);
} else
return null;
if (!withDots) {
abbr = dotsToNodots(abbr);
}
return abbr;
}
/**
* Attempts to get the full name of the abbreviation given. Returns null if no
* full name is known.
* @param journalName The abbreviation to resolve.
* @return The full name, or null if it couldn't be found.
*/
public String getFullName(String journalName) {
// Normalize name first:
String s = getAbbreviatedName(journalName, true);
if (s != null)
s = s.toLowerCase();
else
return null;
Object o = abbrNameKeyed.get(s);
if (o == null) {
if (fullNameKeyed.containsKey(s))
o = s;
else
return null;
}
s = (String)o;
return s;//caseChanger.changeCase(s, CaseChanger.UPPER_EACH_FIRST);
}
public void readJournalList(String resourceFileName) {
URL url = JournalAbbreviations.class.getResource(resourceFileName);
try {
readJournalList(new InputStreamReader(url.openStream()));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void readJournalList(File file) throws FileNotFoundException {
readJournalList(new FileReader(file));
}
/**
* Read the given file, which should contain a list of journal names and their
* abbreviations. Each line should be formatted as: "Full Journal Name=Abbr. Journal Name"
* @param in
*/
public void readJournalList(Reader in) throws FileNotFoundException {
BufferedReader reader = new BufferedReader(in);
try {
String line;
while ((line = reader.readLine()) != null) {
//System.out.println(line);
if (line.startsWith("#"))
continue;
String[] parts = line.split("=");
if (parts.length == 2) {
String fullName = parts[0].trim();
String fullNameLC = fullName.toLowerCase();
String abbrName = parts[1].trim();
if (abbrName.indexOf(';') >= 0) {
String[] restParts = abbrName.split(";");
abbrName = restParts[0];
}
String abbrNameLC = abbrName.toLowerCase();
String abbrNoDots = dotsToNodots(abbrName);
String abbrNoDotsLC = abbrNoDots.toLowerCase();
//System.out.println(abbrNoDots);
if ((fullName.length()>0) && (abbrName.length()>0)) {
//System.out.println("'"+fullName+"' : '"+abbrNoDots+"'");
fullNameKeyed.put(fullNameLC, abbrName);
abbrNameKeyed.put(abbrNameLC, fullName);
abbrNoDotsToAbbr.put(abbrNoDotsLC, abbrName);
all.put(fullName, abbrName);
}
}
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
reader.close();
} catch (IOException ex2) {
ex2.printStackTrace();
}
}
}
/**
* Abbreviate the journal name of the given entry.
* @param database The database the entry belongs to, or null if no database.
* @param entry The entry to be treated.
* @param fieldName The field name (e.g. "journal")
* @param ce If the entry is changed, add an edit to this compound.
* @param withDots True if the abbreviations should have dots.
* @return true if the entry was changed, false otherwise.
*/
public boolean abbreviate(BibtexDatabase database, BibtexEntry entry,
String fieldName, CompoundEdit ce, boolean withDots) {
String text = entry.getField(fieldName);
if (text == null)
return false;
String origText = text;
if (database != null)
text = database.resolveForStrings(text);
if (isKnownName(text) && !isAbbreviatedName(text)) {
String newText = getAbbreviatedName(text, withDots);
if (newText == null)
return false;
entry.setField(fieldName, newText);
ce.addEdit(new UndoableFieldChange(entry, fieldName, origText, newText));
return true;
} else {
String unabbr = getFullName(text);
if (unabbr != null) {
String newText = getAbbreviatedName(unabbr, withDots);
if (newText == null)
return false;
entry.setField(fieldName, newText);
ce.addEdit(new UndoableFieldChange(entry, fieldName, origText, newText));
return true;
} else
return false;
}
}
/**
* Unabbreviate the journal name of the given entry.
* @param entry The entry to be treated.
* @param fieldName The field name (e.g. "journal")
* @param ce If the entry is changed, add an edit to this compound.
* @return true if the entry was changed, false otherwise.
*/
public boolean unabbreviate(BibtexDatabase database, BibtexEntry entry,
String fieldName, CompoundEdit ce) {
String text = entry.getField(fieldName);
if (text == null)
return false;
String origText = text;
if (database != null)
text = database.resolveForStrings(text);
if (isKnownName(text) && isAbbreviatedName(text)) {
String newText = getFullName(text);
if (newText == null)
return false;
entry.setField(fieldName, newText);
ce.addEdit(new UndoableFieldChange(entry, fieldName, origText, newText));
return true;
} else
return false;
}
public Map<String, String> getJournals() {
return Collections.unmodifiableMap(all);
}
/**
* Create a control panel for the entry editor's journal field, to toggle
* abbreviated/full journal name
* @param editor The FieldEditor for the journal field.
* @return The control panel for the entry editor.
*/
public static JComponent getNameSwitcher(final EntryEditor entryEditor, final FieldEditor editor,
final UndoManager undoManager) {
JButton button = new JButton(Globals.lang("Toggle abbreviation"));
button.setToolTipText(TOOLTIPTEXT);
button.addActionListener(new ActionListener() {
boolean withDots = true;
public void actionPerformed(ActionEvent actionEvent) {
String text = editor.getText();
if (Globals.journalAbbrev.isKnownName(text)) {
String s;
if (Globals.journalAbbrev.isAbbreviatedName(text)) {
//System.out.println(withDots);
if (!withDots) {
s = Globals.journalAbbrev.getAbbreviatedName(text, false);
withDots = true;
} else {
s = Globals.journalAbbrev.getFullName(text);
}
}
else {
s = Globals.journalAbbrev.getAbbreviatedName(text, true);
withDots = false;
}
if (s != null) {
editor.setText(s);
entryEditor.storeFieldAction.actionPerformed(new ActionEvent(editor, 0, ""));
undoManager.addEdit(new UndoableFieldChange(entryEditor.getEntry(), editor.getFieldName(),
text, s));
}
}
}
});
return button;
}
public TableModel getTableModel() {
Object[][] cells = new Object[fullNameKeyed.size()][2];
int row = 0;
for (Iterator<String> i=fullNameIterator(); i.hasNext();) {
String name = i.next();
cells[row][0] = getFullName(name);
cells[row][1] = getAbbreviatedName(name, true);
row++;
}
DefaultTableModel tableModel = new DefaultTableModel(cells, new Object[] {Globals.lang("Full name"),
Globals.lang("Abbreviation")}) {
public boolean isCellEditable(int row, int column) {
return false;
}
};
return tableModel;
}
}