From 47885f61543486076bd10b25842b9e933671688d Mon Sep 17 00:00:00 2001 From: Jan Frederik Maas Date: Thu, 14 Aug 2014 21:09:00 +0200 Subject: [PATCH 01/12] GVK-Plugin source as available at http://jabref.tempelb.de/ --- .../jabref/importer/fetcher/GVKFetcher.java | 299 ++++++++++++ .../sf/jabref/importer/fetcher/GVKParser.java | 436 ++++++++++++++++++ 2 files changed, 735 insertions(+) create mode 100644 src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java create mode 100644 src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java new file mode 100644 index 00000000000..658212176ee --- /dev/null +++ b/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java @@ -0,0 +1,299 @@ +package gvkPlugin; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import javax.swing.JPanel; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +import net.sf.jabref.BibtexEntry; +import net.sf.jabref.GUIGlobals; +import net.sf.jabref.Globals; +import net.sf.jabref.OutputPrinter; +import net.sf.jabref.Util; +import net.sf.jabref.gui.ImportInspectionDialog; +import net.sf.jabref.imports.EntryFetcher; +import net.sf.jabref.imports.ImportInspector; + +import java.net.URLEncoder; + +/** + * Fetch or search from GVK http://gso.gbv.de/sru/DB=2.1/ + */ +public class GVKFetcher implements EntryFetcher { + + HashMap searchKeys = new HashMap(); + + public GVKFetcher() + { + searchKeys.put("all", "pica.all%3D"); + searchKeys.put("tit", "pica.tit%3D"); + searchKeys.put("per", "pica.per%3D"); + searchKeys.put("thm", "pica.thm%3D"); + searchKeys.put("slw", "pica.slw%3D"); + searchKeys.put("txt", "pica.txt%3D"); + searchKeys.put("num", "pica.num%3D"); + searchKeys.put("kon", "pica.kon%3D"); + searchKeys.put("ppn", "pica.ppn%3D"); + searchKeys.put("bkl", "pica.bkl%3D"); + searchKeys.put("erj", "pica.erj%3D"); + } + + + boolean shouldContinue; + + //OutputPrinter frame; + + ImportInspector dialog; + + /** + * Necessary for JabRef + */ + + public void stopFetching() + { + shouldContinue = false; + } + + /** + * Get the name of the help page for this fetcher. + * + * If given, a question mark is displayed in the side pane which leads to + * the help page. + * + * @return The name of the help file or null if this fetcher does not have + * any help. + */ + + public String getHelpPage() + { + //return GUIGlobals.medlineHelp; + return null; + } + + /** + * Get the appropriate icon URL for this fetcher. + * + * @return The icon URL + */ + public URL getIcon() { + return GUIGlobals.getIconUrl("www"); + } + + /** + * Get the name of the key binding for this fetcher, if any. + * + * @return The name of the key binding or null, if no keybinding should be + * created. + */ + public String getKeyName() { + // return "Fetch GVK"; + return null; + } + + /** + * If this fetcher requires additional options, a panel for setting up these + * should be returned in a JPanel by this method. This JPanel will be added + * to the side pane component automatically. + * + * @return Options panel for this fetcher or null if this fetcher does not + * have any options. + */ + + public JPanel getOptionsPanel() + { + return null; + } + + + /** + * The title for this fetcher, displayed in the menu and in the side pane. + * + * @return The title + */ + public String getTitle() + { + return Globals.menuTitle("Search GVK"); + } + + /** + * Handle a query entered by the user. + * + * The method is expected to block the caller until all entries have been + * reported to the inspector. + * + * @param query + * The query text. + * @param inspector + * The dialog to add imported entries to. + * @param status + * An OutputPrinter passed to the fetcher for reporting about the + * status of the fetching. + * + * @return True if the query was completed successfully, false if an error + * occurred. + */ + + public boolean processQuery(String query, ImportInspector dialog, OutputPrinter frame) { + + String gvkQuery = ""; + boolean shouldContinue = true; + + query = query.trim(); + + String[] qterms = query.split("\\s"); + + // Null abfangen! + if (qterms.length == 0) + { + return false; + } + + // Jeden einzelnen Suchbegriff URL-Encodieren + for (int x=0; x bibs = fetchGVK(gvkQuery); + + for (BibtexEntry entry : bibs) + { + dialog.addEntry(entry); + } + + if (bibs.size() == 0) + { + frame.showMessage(Globals.lang("No references found")); + } + + return true; + } + + private String processComplexQuery(String[] s) + { + String result = ""; + boolean lastWasKey = false; + + for (int x=0; x fetchGVK(String query) + { + List result= null; + + String urlPrefix = "http://sru.gbv.de/gvk?version=1.1&operation=searchRetrieve&query="; + String urlQuery = query; + String urlSuffix = "&maximumRecords=50&recordSchema=picaxml&sortKeys=Year%2C%2C1"; + //Systemmeldung zum Debugging (JabRef über bash starten) + //System.out.println(urlPrefix+query+urlSuffix); + + String searchstring = (urlPrefix + urlQuery + urlSuffix); + //Systemmeldung zum Debugging (JabRef über bash starten) + //System.out.println(searchstring); + try + { + URI uri = null; + try + { + uri = new URI(searchstring); + } + catch (URISyntaxException e) + { + System.out.println("URI malformed error"); + return (new ArrayList()); + } + // URL url = new URL(urlPrefix + urlQuery + urlSuffix); + URL url = uri.toURL(); + InputStream is = url.openStream(); + DocumentBuilder dbuild = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document content = dbuild.parse(is); + result= (new GVKParser()).parseEntries(content); + is.close(); + } + + catch (IOException e) + { + System.out.println("GVK plugin: An I/O exception occurred:"); + System.out.println(e); + + return new ArrayList(); + } + catch (ParserConfigurationException e) + { + System.out.println("GVK plugin: An internal parser error occurred:"); + System.out.println(e); + + return new ArrayList(); + } + catch (SAXException e) + { + System.out.println("An internal parser error occurred:"); + System.out.println(e); + + return new ArrayList(); + } + + return result; + } +} diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java b/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java new file mode 100644 index 00000000000..bc48382e317 --- /dev/null +++ b/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java @@ -0,0 +1,436 @@ +package gvkPlugin; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import net.sf.jabref.BibtexEntry; +import net.sf.jabref.Globals; +import net.sf.jabref.Util; +import net.sf.jabref.imports.ImportFormatReader; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class GVKParser { + + public GVKParser () {} + + public List parseEntries(Document content) + { + LinkedList result = new LinkedList(); + + // Namespace srwNamespace = Namespace.getNamespace("srw","http://www.loc.gov/zing/srw/"); + + // Schleife ueber allen Teilergebnissen + //Element root = content.getDocumentElement(); + Element root = (Element) content.getElementsByTagName("zs:searchRetrieveResponse").item(0); + Element srwrecords = getChild("zs:records", root); + List records = getChildren("zs:record",srwrecords); + + for (Element record : records) + { + Element e = getChild("zs:recordData",record); + e = getChild("record",e); + + result.add(parseEntry(e)); + } + + return result; + } + + private BibtexEntry parseEntry(Element e) + { + String author = null; String editor = null; String title = null; String publisher = null; + String year = null; String address = null; String series = null; String edition = null; + String isbn = null; String issn = null; String number = null; String pagetotal = null; + String volume = null; String pages = null; String journal = null; String ppn = null; + String booktitle = null;String url = null; + + String quelle = ""; String mak = ""; String subtitle = ""; + + String entryType = "book"; // Default + + // Alle relevanten Informationen einsammeln + + List datafields = getChildren("datafield",e); + Iterator iter = datafields.iterator(); + while (iter.hasNext()) + { + Element datafield = iter.next(); + + // System.out.println(datafield.getAttributeValue("tag")); + + // mak + if (datafield.getAttribute("tag").equals("002@")) + { + mak = getSubfield("0",datafield); + } + + //ppn + if (datafield.getAttribute("tag").equals("003@")) + { + ppn = getSubfield("0",datafield); + } + + //author + if (datafield.getAttribute("tag").equals("028A")) + { + String vorname = getSubfield("d",datafield); + String nachname = getSubfield("a",datafield); + + if (!(author == null)) + { + author = author.concat(" and "); + } + else + { + author = ""; + } + author = author.concat(vorname + " " + nachname ); + } + //author (weiterer) + if (datafield.getAttribute("tag").equals("028B")) + { + String vorname = getSubfield("d",datafield); + String nachname = getSubfield("a",datafield); + + if (!(author == null)) + { + author = author.concat(" and "); + } + else + { + author = ""; + } + author = author.concat(vorname + " " + nachname ); + } + + //editor + if (datafield.getAttribute("tag").equals("028C")) + { + String vorname = getSubfield("d",datafield); + String nachname = getSubfield("a",datafield); + + if (!(editor == null)) + { + editor = editor.concat(" and "); + } + else + { + editor = ""; + } + editor = editor.concat(vorname + " " + nachname ); + } + + //title and subtitle + if (datafield.getAttribute("tag").equals("021A")) + { + title = getSubfield("a",datafield); + subtitle = getSubfield("d",datafield); + } + + //publisher and address + if (datafield.getAttribute("tag").equals("033A")) + { + publisher = getSubfield("n",datafield); + address = getSubfield("p",datafield); + } + + //year + if (datafield.getAttribute("tag").equals("011@")) + { + year = getSubfield("a",datafield); + } + + //year, volume, number, pages (year bei Zeitschriften (evtl. redundant mit 011@)) + if (datafield.getAttribute("tag").equals("031A")) + { + year = getSubfield("j",datafield); + volume = getSubfield("e",datafield); + number = getSubfield("a",datafield); + pages = getSubfield("h",datafield); + + } + + //series and number + if (datafield.getAttribute("tag").equals("036E")) + { + series = getSubfield("a",datafield); + number = getSubfield("l",datafield); + String kor = getSubfield("b",datafield); + + if (kor != null) + { + series = series + " / " + kor; + } + } + + //edition + if (datafield.getAttribute("tag").equals("032@")) + { + edition = getSubfield("a",datafield); + } + + //isbn + if (datafield.getAttribute("tag").equals("004A")) + { + String isbn_10 = getSubfield("0",datafield); + String isbn_13 = getSubfield("A",datafield); + + if (isbn_10 != null) { isbn = isbn_10; }; + if (isbn_13 != null) { isbn = isbn_13; }; + } + + // Hochschulschriftenvermerk + // Bei einer Verlagsdissertation ist der Ort schon eingetragen + if (datafield.getAttribute("tag").equals("037C")) + { + if (address == null) + { + address = getSubfield("b",datafield); + address = removeSortCharacters(address); + } + + String st = getSubfield("a",datafield); + if (st != null) + { + if (st.contains("Diss")) { entryType = "phdthesis";}; + } + } + + //journal oder booktitle + + /* Problematiken hier: Sowohl für Artikel in + * Zeitschriften als für Beiträge in Büchern + * wird 027D verwendet. Der Titel muß je nach + * Fall booktitle oder journal zugeordnet + * werden. Auch bei Zeitschriften werden hier + * ggf. Verlag und Ort angegeben (sind dann + * eigentlich überflüssig), während bei + * Buchbeiträgen Verlag und Ort wichtig sind + * (sonst in Kategorie 033A). + + */ + if (datafield.getAttribute("tag").equals("027D")) + { + journal = getSubfield("a",datafield); + booktitle = getSubfield("a",datafield); + address = getSubfield("p",datafield); + publisher = getSubfield("n",datafield); + } + + //pagetotal + if (datafield.getAttribute("tag").equals("034D")) + { + pagetotal = getSubfield("a",datafield); + + // S, S. etc. entfernen + pagetotal = pagetotal.replaceAll(" S\\.?$", ""); + } + + // Behandlung von Konferenzen + if (datafield.getAttribute("tag").equals("030F")) + { + address = getSubfield("k",datafield); + + if (!entryType.equals("proceedings")) + { + subtitle = getSubfield("a",datafield); + } + + entryType = "proceedings"; + } + + // Wenn eine Verlagsdiss vorliegt + if (entryType.equals("phdthesis")) + { + if (isbn != null) + { + entryType = "book"; + } + } + + //Hilfskategorien zur Entscheidung @article + //oder @incollection; hier könnte man auch die + //ISBN herausparsen als Erleichterung für das + //Auffinden der Quelle, die über die + //SRU-Schnittstelle gelieferten Daten zur + //Quelle unvollständig sind (z.B. nicht Serie + //und Nummer angegeben werden) + if (datafield.getAttribute("tag").equals("039B")) + { + quelle = getSubfield("8",datafield); + } + if (datafield.getAttribute("tag").equals("046R")) + { + if (quelle.equals("") || quelle == null) + { + quelle = getSubfield("a",datafield); + } + } + + // URLs behandeln + if (datafield.getAttribute("tag").equals("009P")) + { + if (datafield.getAttribute("occurrence").equals("03") || datafield.getAttribute("occurrence").equals("05")) + { + if (url == null) + { + url = getSubfield("a",datafield); + } + } + } + } + + // Abfangen von Nulleintraegen + if (quelle == null) { quelle = ""; } + + // Nichtsortierzeichen entfernen + if (!(author == null)) { author = removeSortCharacters(author); }; + if (!(editor == null)) { editor = removeSortCharacters(editor); }; + if (!(title == null)) { title = removeSortCharacters(title); }; + if (!(subtitle == null)) { subtitle = removeSortCharacters(subtitle); }; + + // Dokumenttyp bestimmen und Eintrag anlegen + + if (mak.startsWith("As")) + { + entryType = "misc"; + + if (quelle.contains("ISBN")) + { + entryType = "incollection"; + } + if (quelle.contains("ZDB-ID")) + { + entryType = "article"; + } + } + + if (mak.equals("")) + { + entryType = "misc"; + } + + if (mak.startsWith("O")) + { + entryType = "online"; + } + + /* + * Wahrscheinlichkeit, dass ZDB-ID + * vorhanden ist, ist größer als ISBN bei + * Buchbeiträgen. Daher bei As?-Sätzen am besten immer + * dann @incollection annehmen, wenn weder ISBN noch + * ZDB-ID vorhanden sind. + */ + BibtexEntry result = new BibtexEntry(Util.createNeutralId(), Globals.getEntryType(entryType)); + + // Zuordnung der Felder in Abhängigkeit vom Dokumenttyp + + if (!(author == null)) { result.setField("author",ImportFormatReader.expandAuthorInitials(author)); } + if (!(editor == null)) { result.setField("editor",ImportFormatReader.expandAuthorInitials(editor)); } + if (!(title == null)) { result.setField("title",title); } + if (!(subtitle == null)) { result.setField("subtitle",subtitle); } + if (!(publisher == null)) { result.setField("publisher",publisher); } + if (!(year == null)) { result.setField("year",year); } + if (!(address == null)) { result.setField("address",address);} + if (!(series == null)) { result.setField("series",series);} + if (!(edition == null)) { result.setField("edition",edition);} + if (!(isbn == null)) { result.setField("isbn",isbn);} + if (!(issn == null)) { result.setField("issn",issn);} + if (!(number == null)) { result.setField("number",number);} + if (!(pagetotal == null)) { result.setField("pagetotal",pagetotal);} + if (!(pages == null)) { result.setField("pages",pages);} + if (!(volume == null)) { result.setField("volume",volume);} + if (!(journal == null)) { result.setField("journal",journal);} + if (!(ppn == null)) { result.setField("ppn_GVK",ppn); } + if (!(url == null)) { result.setField("url",url); } + + if (entryType.equals("article")) + { + if (!(journal == null)) { result.setField("journal",journal);} + } + + if (entryType.equals("incollection")) + { + if (!(booktitle == null)) { result.setField("booktitle",booktitle);} + } + + return result; + } + + private String getSubfield(Element datafield) + { + return(getChild("subfield",datafield).getTextContent()); + } + + private String getSubfield(String a, Element datafield) + { + List liste = getChildren("subfield",datafield); + Iterator iter = liste.iterator(); + + while (iter.hasNext()) + { + Element subfield = iter.next(); + if (subfield.getAttribute("code").equals(a)) + { + return (subfield.getTextContent()); + } + } + return null; + } + + private Element getChild(String name, Element e) + { + Element result = null; + + NodeList children = e.getChildNodes(); + + int j = children.getLength(); + for (int i = 0; i < j; i++) + { + Node test = (Node) children.item(i); + if (test.getNodeType() == Node.ELEMENT_NODE) + { + Element entry = (Element) test; + if (entry.getTagName().equals(name)) + { + return entry; + } + } + } + return result; + } + + private LinkedList getChildren(String name, Element e) + { + LinkedList result = new LinkedList(); + NodeList children = e.getChildNodes(); + + int j = children.getLength(); + for (int i = 0; i < j; i++) + { + Node test = (Node) children.item(i); + if (test.getNodeType() == Node.ELEMENT_NODE) + { + Element entry = (Element) test; + if (entry.getTagName().equals(name)) + { + result.add(entry); + } + } + } + + return result; + } + + private String removeSortCharacters(String input) + { + input = input.replaceAll("\\@", ""); + return input; + } +} From 37664eebe7e6c4884f6c42a669f722dabf1dbd35 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Fri, 20 Nov 2015 22:12:31 +0100 Subject: [PATCH 02/12] Reformat according to styleguide, use new JabRef classes, and enable it --- CHANGELOG.md | 1 + .../importer/fetcher/EntryFetchers.java | 1 + .../jabref/importer/fetcher/GVKFetcher.java | 342 +++---- .../sf/jabref/importer/fetcher/GVKParser.java | 845 +++++++++--------- 4 files changed, 548 insertions(+), 641 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1296b25cc6..f3bd145150d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ to [sourceforge feature requests](https://sourceforge.net/p/jabref/features/) by - Feature: New LabelPattern `[keywordsN]`, where N is optional. Returns the first N keywords. If no N is specified ("`[keywords]`"), all keywords are returned. Spaces are removed. - Update supported LookAndFeels - Show replaced journal abbreviations on console + - Integrated [GVK-Plugin](http://www.gbv.de/wikis/cls/Jabref-GVK-Plugin) ### Fixed - Fixed the bug that the file encoding was not correctly determined from the first (or second) line diff --git a/src/main/java/net/sf/jabref/importer/fetcher/EntryFetchers.java b/src/main/java/net/sf/jabref/importer/fetcher/EntryFetchers.java index 1b5d2410294..41f1ff05bdf 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/EntryFetchers.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/EntryFetchers.java @@ -31,6 +31,7 @@ public EntryFetchers() { entryFetchers.add(new DBLPFetcher()); entryFetchers.add(new DiVAtoBibTeXFetcher()); entryFetchers.add(new DOItoBibTeXFetcher()); + entryFetchers.add(new GVKFetcher()); entryFetchers.add(new IEEEXploreFetcher()); entryFetchers.add(new INSPIREFetcher()); entryFetchers.add(new ISBNtoBibTeXFetcher()); diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java index 658212176ee..6813bdf6a94 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java @@ -1,4 +1,7 @@ -package gvkPlugin; +/** + * License: GPLv2, but Jan Frederik Maas agreed to change license upon request + */ +package net.sf.jabref.importer.fetcher; import java.io.IOException; import java.io.InputStream; @@ -6,7 +9,7 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URL; -import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -15,17 +18,15 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.w3c.dom.Document; import org.xml.sax.SAXException; -import net.sf.jabref.BibtexEntry; -import net.sf.jabref.GUIGlobals; -import net.sf.jabref.Globals; -import net.sf.jabref.OutputPrinter; -import net.sf.jabref.Util; -import net.sf.jabref.gui.ImportInspectionDialog; -import net.sf.jabref.imports.EntryFetcher; -import net.sf.jabref.imports.ImportInspector; +import net.sf.jabref.importer.ImportInspector; +import net.sf.jabref.importer.OutputPrinter; +import net.sf.jabref.logic.l10n.Localization; +import net.sf.jabref.model.entry.BibtexEntry; import java.net.URLEncoder; @@ -33,11 +34,13 @@ * Fetch or search from GVK http://gso.gbv.de/sru/DB=2.1/ */ public class GVKFetcher implements EntryFetcher { - - HashMap searchKeys = new HashMap(); - - public GVKFetcher() - { + + private static final Log LOGGER = LogFactory.getLog(GVKFetcher.class); + + HashMap searchKeys = new HashMap<>(); + + + public GVKFetcher() { searchKeys.put("all", "pica.all%3D"); searchKeys.put("tit", "pica.tit%3D"); searchKeys.put("per", "pica.per%3D"); @@ -49,251 +52,140 @@ public GVKFetcher() searchKeys.put("ppn", "pica.ppn%3D"); searchKeys.put("bkl", "pica.bkl%3D"); searchKeys.put("erj", "pica.erj%3D"); - } - - - boolean shouldContinue; - - //OutputPrinter frame; - - ImportInspector dialog; + } /** * Necessary for JabRef */ - - public void stopFetching() - { - shouldContinue = false; + @Override + public void stopFetching() { + // not supported } - - /** - * Get the name of the help page for this fetcher. - * - * If given, a question mark is displayed in the side pane which leads to - * the help page. - * - * @return The name of the help file or null if this fetcher does not have - * any help. - */ - public String getHelpPage() - { - //return GUIGlobals.medlineHelp; - return null; - } - - /** - * Get the appropriate icon URL for this fetcher. - * - * @return The icon URL - */ - public URL getIcon() { - return GUIGlobals.getIconUrl("www"); + @Override + public String getHelpPage() { + return null; } - /** - * Get the name of the key binding for this fetcher, if any. - * - * @return The name of the key binding or null, if no keybinding should be - * created. - */ - public String getKeyName() { - // return "Fetch GVK"; - return null; + @Override + public JPanel getOptionsPanel() { + return null; } - /** - * If this fetcher requires additional options, a panel for setting up these - * should be returned in a JPanel by this method. This JPanel will be added - * to the side pane component automatically. - * - * @return Options panel for this fetcher or null if this fetcher does not - * have any options. - */ - - public JPanel getOptionsPanel() - { - return null; - } - - - /** - * The title for this fetcher, displayed in the menu and in the side pane. - * - * @return The title - */ - public String getTitle() - { - return Globals.menuTitle("Search GVK"); + @Override + public String getTitle() { + return "GVKFetcher"; } - /** - * Handle a query entered by the user. - * - * The method is expected to block the caller until all entries have been - * reported to the inspector. - * - * @param query - * The query text. - * @param inspector - * The dialog to add imported entries to. - * @param status - * An OutputPrinter passed to the fetcher for reporting about the - * status of the fetching. - * - * @return True if the query was completed successfully, false if an error - * occurred. - */ - + @Override public boolean processQuery(String query, ImportInspector dialog, OutputPrinter frame) { + String gvkQuery = ""; - String gvkQuery = ""; - boolean shouldContinue = true; + query = query.trim(); - query = query.trim(); - String[] qterms = query.split("\\s"); - + // Null abfangen! - if (qterms.length == 0) - { - return false; + if (qterms.length == 0) { + return false; } - + // Jeden einzelnen Suchbegriff URL-Encodieren - for (int x=0; x bibs = fetchGVK(gvkQuery); - - for (BibtexEntry entry : bibs) - { + + for (BibtexEntry entry : bibs) { dialog.addEntry(entry); } - - if (bibs.size() == 0) - { - frame.showMessage(Globals.lang("No references found")); + + if (bibs.size() == 0) { + frame.showMessage(Localization.lang("No references found")); } return true; } - - private String processComplexQuery(String[] s) - { - String result = ""; - boolean lastWasKey = false; - - for (int x=0; x fetchGVK(String query) - { - List result= null; - + + private List fetchGVK(String query) { + List result = null; + String urlPrefix = "http://sru.gbv.de/gvk?version=1.1&operation=searchRetrieve&query="; String urlQuery = query; String urlSuffix = "&maximumRecords=50&recordSchema=picaxml&sortKeys=Year%2C%2C1"; - //Systemmeldung zum Debugging (JabRef über bash starten) - //System.out.println(urlPrefix+query+urlSuffix); - + String searchstring = (urlPrefix + urlQuery + urlSuffix); - //Systemmeldung zum Debugging (JabRef über bash starten) - //System.out.println(searchstring); - try - { - URI uri = null; - try - { - uri = new URI(searchstring); - } - catch (URISyntaxException e) - { - System.out.println("URI malformed error"); - return (new ArrayList()); - } - // URL url = new URL(urlPrefix + urlQuery + urlSuffix); - URL url = uri.toURL(); - InputStream is = url.openStream(); - DocumentBuilder dbuild = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - Document content = dbuild.parse(is); - result= (new GVKParser()).parseEntries(content); - is.close(); - } - - catch (IOException e) - { - System.out.println("GVK plugin: An I/O exception occurred:"); - System.out.println(e); - - return new ArrayList(); - } - catch (ParserConfigurationException e) - { - System.out.println("GVK plugin: An internal parser error occurred:"); - System.out.println(e); - - return new ArrayList(); - } - catch (SAXException e) - { - System.out.println("An internal parser error occurred:"); - System.out.println(e); - - return new ArrayList(); - } + LOGGER.debug(searchstring); + try { + URI uri = null; + try { + uri = new URI(searchstring); + } catch (URISyntaxException e) { + LOGGER.error("URI malformed error", e); + return Collections.EMPTY_LIST; + } + URL url = uri.toURL(); + try (InputStream is = url.openStream()) { + DocumentBuilder dbuild = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document content = dbuild.parse(is); + result = (new GVKParser()).parseEntries(content); + } + } catch (IOException e) { + LOGGER.error("GVK plugin: An I/O exception occurred", e); + return Collections.EMPTY_LIST; + } catch (ParserConfigurationException e) { + LOGGER.error("GVK plugin: An internal parser error occurred", e); + return Collections.EMPTY_LIST; + } catch (SAXException e) { + LOGGER.error("An internal parser error occurred", e); + return Collections.EMPTY_LIST; + } return result; } -} + +} diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java b/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java index bc48382e317..a7b415ea2cf 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java @@ -1,13 +1,16 @@ -package gvkPlugin; +/** + * License: GPLv2, but Jan Frederik Maas agreed to change license upon request + */ +package net.sf.jabref.importer.fetcher; import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import net.sf.jabref.BibtexEntry; -import net.sf.jabref.Globals; -import net.sf.jabref.Util; -import net.sf.jabref.imports.ImportFormatReader; +import net.sf.jabref.bibtex.EntryTypes; +import net.sf.jabref.importer.ImportFormatReader; +import net.sf.jabref.model.entry.BibtexEntry; +import net.sf.jabref.model.entry.IdGenerator; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -15,422 +18,432 @@ import org.w3c.dom.NodeList; public class GVKParser { - - public GVKParser () {} - - public List parseEntries(Document content) - { - LinkedList result = new LinkedList(); - - // Namespace srwNamespace = Namespace.getNamespace("srw","http://www.loc.gov/zing/srw/"); - - // Schleife ueber allen Teilergebnissen - //Element root = content.getDocumentElement(); - Element root = (Element) content.getElementsByTagName("zs:searchRetrieveResponse").item(0); - Element srwrecords = getChild("zs:records", root); - List records = getChildren("zs:record",srwrecords); - - for (Element record : records) - { - Element e = getChild("zs:recordData",record); - e = getChild("record",e); - - result.add(parseEntry(e)); - } - - return result; + + public List parseEntries(Document content) { + List result = new LinkedList<>(); + + // Namespace srwNamespace = Namespace.getNamespace("srw","http://www.loc.gov/zing/srw/"); + + // Schleife ueber allen Teilergebnissen + //Element root = content.getDocumentElement(); + Element root = (Element) content.getElementsByTagName("zs:searchRetrieveResponse").item(0); + Element srwrecords = getChild("zs:records", root); + List records = getChildren("zs:record", srwrecords); + + for (Element record : records) { + Element e = getChild("zs:recordData", record); + e = getChild("record", e); + + result.add(parseEntry(e)); + } + + return result; } - private BibtexEntry parseEntry(Element e) - { - String author = null; String editor = null; String title = null; String publisher = null; - String year = null; String address = null; String series = null; String edition = null; - String isbn = null; String issn = null; String number = null; String pagetotal = null; - String volume = null; String pages = null; String journal = null; String ppn = null; - String booktitle = null;String url = null; - - String quelle = ""; String mak = ""; String subtitle = ""; - - String entryType = "book"; // Default - - // Alle relevanten Informationen einsammeln - - List datafields = getChildren("datafield",e); - Iterator iter = datafields.iterator(); - while (iter.hasNext()) - { - Element datafield = iter.next(); - - // System.out.println(datafield.getAttributeValue("tag")); - - // mak - if (datafield.getAttribute("tag").equals("002@")) - { - mak = getSubfield("0",datafield); - } - - //ppn - if (datafield.getAttribute("tag").equals("003@")) - { - ppn = getSubfield("0",datafield); - } - - //author - if (datafield.getAttribute("tag").equals("028A")) - { - String vorname = getSubfield("d",datafield); - String nachname = getSubfield("a",datafield); - - if (!(author == null)) - { - author = author.concat(" and "); - } - else - { - author = ""; - } - author = author.concat(vorname + " " + nachname ); - } - //author (weiterer) - if (datafield.getAttribute("tag").equals("028B")) - { - String vorname = getSubfield("d",datafield); - String nachname = getSubfield("a",datafield); - - if (!(author == null)) - { - author = author.concat(" and "); - } - else - { - author = ""; - } - author = author.concat(vorname + " " + nachname ); - } - - //editor - if (datafield.getAttribute("tag").equals("028C")) - { - String vorname = getSubfield("d",datafield); - String nachname = getSubfield("a",datafield); - - if (!(editor == null)) - { - editor = editor.concat(" and "); - } - else - { - editor = ""; - } - editor = editor.concat(vorname + " " + nachname ); - } - - //title and subtitle - if (datafield.getAttribute("tag").equals("021A")) - { - title = getSubfield("a",datafield); - subtitle = getSubfield("d",datafield); - } - - //publisher and address - if (datafield.getAttribute("tag").equals("033A")) - { - publisher = getSubfield("n",datafield); - address = getSubfield("p",datafield); - } - - //year - if (datafield.getAttribute("tag").equals("011@")) - { - year = getSubfield("a",datafield); - } - - //year, volume, number, pages (year bei Zeitschriften (evtl. redundant mit 011@)) - if (datafield.getAttribute("tag").equals("031A")) - { - year = getSubfield("j",datafield); - volume = getSubfield("e",datafield); - number = getSubfield("a",datafield); - pages = getSubfield("h",datafield); - - } - - //series and number - if (datafield.getAttribute("tag").equals("036E")) - { - series = getSubfield("a",datafield); - number = getSubfield("l",datafield); - String kor = getSubfield("b",datafield); - - if (kor != null) - { - series = series + " / " + kor; - } - } - - //edition - if (datafield.getAttribute("tag").equals("032@")) - { - edition = getSubfield("a",datafield); - } - - //isbn - if (datafield.getAttribute("tag").equals("004A")) - { - String isbn_10 = getSubfield("0",datafield); - String isbn_13 = getSubfield("A",datafield); - - if (isbn_10 != null) { isbn = isbn_10; }; - if (isbn_13 != null) { isbn = isbn_13; }; - } - - // Hochschulschriftenvermerk - // Bei einer Verlagsdissertation ist der Ort schon eingetragen - if (datafield.getAttribute("tag").equals("037C")) - { - if (address == null) - { - address = getSubfield("b",datafield); - address = removeSortCharacters(address); - } - - String st = getSubfield("a",datafield); - if (st != null) - { - if (st.contains("Diss")) { entryType = "phdthesis";}; - } - } - - //journal oder booktitle - - /* Problematiken hier: Sowohl für Artikel in - * Zeitschriften als für Beiträge in Büchern - * wird 027D verwendet. Der Titel muß je nach - * Fall booktitle oder journal zugeordnet - * werden. Auch bei Zeitschriften werden hier - * ggf. Verlag und Ort angegeben (sind dann - * eigentlich überflüssig), während bei - * Buchbeiträgen Verlag und Ort wichtig sind - * (sonst in Kategorie 033A). - - */ - if (datafield.getAttribute("tag").equals("027D")) - { - journal = getSubfield("a",datafield); - booktitle = getSubfield("a",datafield); - address = getSubfield("p",datafield); - publisher = getSubfield("n",datafield); - } - - //pagetotal - if (datafield.getAttribute("tag").equals("034D")) - { - pagetotal = getSubfield("a",datafield); - - // S, S. etc. entfernen - pagetotal = pagetotal.replaceAll(" S\\.?$", ""); - } - - // Behandlung von Konferenzen - if (datafield.getAttribute("tag").equals("030F")) - { - address = getSubfield("k",datafield); - - if (!entryType.equals("proceedings")) - { - subtitle = getSubfield("a",datafield); - } - - entryType = "proceedings"; - } - - // Wenn eine Verlagsdiss vorliegt - if (entryType.equals("phdthesis")) - { - if (isbn != null) - { - entryType = "book"; - } - } - - //Hilfskategorien zur Entscheidung @article - //oder @incollection; hier könnte man auch die - //ISBN herausparsen als Erleichterung für das - //Auffinden der Quelle, die über die - //SRU-Schnittstelle gelieferten Daten zur - //Quelle unvollständig sind (z.B. nicht Serie - //und Nummer angegeben werden) - if (datafield.getAttribute("tag").equals("039B")) - { - quelle = getSubfield("8",datafield); - } - if (datafield.getAttribute("tag").equals("046R")) - { - if (quelle.equals("") || quelle == null) - { - quelle = getSubfield("a",datafield); - } - } - - // URLs behandeln - if (datafield.getAttribute("tag").equals("009P")) - { - if (datafield.getAttribute("occurrence").equals("03") || datafield.getAttribute("occurrence").equals("05")) - { - if (url == null) - { - url = getSubfield("a",datafield); - } - } - } - } - - // Abfangen von Nulleintraegen - if (quelle == null) { quelle = ""; } - - // Nichtsortierzeichen entfernen - if (!(author == null)) { author = removeSortCharacters(author); }; - if (!(editor == null)) { editor = removeSortCharacters(editor); }; - if (!(title == null)) { title = removeSortCharacters(title); }; - if (!(subtitle == null)) { subtitle = removeSortCharacters(subtitle); }; - - // Dokumenttyp bestimmen und Eintrag anlegen - - if (mak.startsWith("As")) - { - entryType = "misc"; - - if (quelle.contains("ISBN")) - { - entryType = "incollection"; - } - if (quelle.contains("ZDB-ID")) - { - entryType = "article"; - } - } - - if (mak.equals("")) - { - entryType = "misc"; - } - - if (mak.startsWith("O")) - { - entryType = "online"; - } - - /* - * Wahrscheinlichkeit, dass ZDB-ID - * vorhanden ist, ist größer als ISBN bei - * Buchbeiträgen. Daher bei As?-Sätzen am besten immer - * dann @incollection annehmen, wenn weder ISBN noch - * ZDB-ID vorhanden sind. - */ - BibtexEntry result = new BibtexEntry(Util.createNeutralId(), Globals.getEntryType(entryType)); - - // Zuordnung der Felder in Abhängigkeit vom Dokumenttyp - - if (!(author == null)) { result.setField("author",ImportFormatReader.expandAuthorInitials(author)); } - if (!(editor == null)) { result.setField("editor",ImportFormatReader.expandAuthorInitials(editor)); } - if (!(title == null)) { result.setField("title",title); } - if (!(subtitle == null)) { result.setField("subtitle",subtitle); } - if (!(publisher == null)) { result.setField("publisher",publisher); } - if (!(year == null)) { result.setField("year",year); } - if (!(address == null)) { result.setField("address",address);} - if (!(series == null)) { result.setField("series",series);} - if (!(edition == null)) { result.setField("edition",edition);} - if (!(isbn == null)) { result.setField("isbn",isbn);} - if (!(issn == null)) { result.setField("issn",issn);} - if (!(number == null)) { result.setField("number",number);} - if (!(pagetotal == null)) { result.setField("pagetotal",pagetotal);} - if (!(pages == null)) { result.setField("pages",pages);} - if (!(volume == null)) { result.setField("volume",volume);} - if (!(journal == null)) { result.setField("journal",journal);} - if (!(ppn == null)) { result.setField("ppn_GVK",ppn); } - if (!(url == null)) { result.setField("url",url); } - - if (entryType.equals("article")) - { - if (!(journal == null)) { result.setField("journal",journal);} - } - - if (entryType.equals("incollection")) - { - if (!(booktitle == null)) { result.setField("booktitle",booktitle);} - } - - return result; - } - - private String getSubfield(Element datafield) - { - return(getChild("subfield",datafield).getTextContent()); + private BibtexEntry parseEntry(Element e) { + String author = null; + String editor = null; + String title = null; + String publisher = null; + String year = null; + String address = null; + String series = null; + String edition = null; + String isbn = null; + String issn = null; + String number = null; + String pagetotal = null; + String volume = null; + String pages = null; + String journal = null; + String ppn = null; + String booktitle = null; + String url = null; + + String quelle = ""; + String mak = ""; + String subtitle = ""; + + String entryType = "book"; // Default + + // Alle relevanten Informationen einsammeln + + List datafields = getChildren("datafield", e); + Iterator iter = datafields.iterator(); + while (iter.hasNext()) { + Element datafield = iter.next(); + + // System.out.println(datafield.getAttributeValue("tag")); + + // mak + if (datafield.getAttribute("tag").equals("002@")) { + mak = getSubfield("0", datafield); + } + + //ppn + if (datafield.getAttribute("tag").equals("003@")) { + ppn = getSubfield("0", datafield); + } + + //author + if (datafield.getAttribute("tag").equals("028A")) { + String vorname = getSubfield("d", datafield); + String nachname = getSubfield("a", datafield); + + if (!(author == null)) { + author = author.concat(" and "); + } else { + author = ""; + } + author = author.concat(vorname + " " + nachname); + } + //author (weiterer) + if (datafield.getAttribute("tag").equals("028B")) { + String vorname = getSubfield("d", datafield); + String nachname = getSubfield("a", datafield); + + if (!(author == null)) { + author = author.concat(" and "); + } else { + author = ""; + } + author = author.concat(vorname + " " + nachname); + } + + //editor + if (datafield.getAttribute("tag").equals("028C")) { + String vorname = getSubfield("d", datafield); + String nachname = getSubfield("a", datafield); + + if (!(editor == null)) { + editor = editor.concat(" and "); + } else { + editor = ""; + } + editor = editor.concat(vorname + " " + nachname); + } + + //title and subtitle + if (datafield.getAttribute("tag").equals("021A")) { + title = getSubfield("a", datafield); + subtitle = getSubfield("d", datafield); + } + + //publisher and address + if (datafield.getAttribute("tag").equals("033A")) { + publisher = getSubfield("n", datafield); + address = getSubfield("p", datafield); + } + + //year + if (datafield.getAttribute("tag").equals("011@")) { + year = getSubfield("a", datafield); + } + + //year, volume, number, pages (year bei Zeitschriften (evtl. redundant mit 011@)) + if (datafield.getAttribute("tag").equals("031A")) { + year = getSubfield("j", datafield); + volume = getSubfield("e", datafield); + number = getSubfield("a", datafield); + pages = getSubfield("h", datafield); + + } + + //series and number + if (datafield.getAttribute("tag").equals("036E")) { + series = getSubfield("a", datafield); + number = getSubfield("l", datafield); + String kor = getSubfield("b", datafield); + + if (kor != null) { + series = series + " / " + kor; + } + } + + //edition + if (datafield.getAttribute("tag").equals("032@")) { + edition = getSubfield("a", datafield); + } + + //isbn + if (datafield.getAttribute("tag").equals("004A")) { + String isbn_10 = getSubfield("0", datafield); + String isbn_13 = getSubfield("A", datafield); + + if (isbn_10 != null) { + isbn = isbn_10; + } + + if (isbn_13 != null) { + isbn = isbn_13; + } + + } + + // Hochschulschriftenvermerk + // Bei einer Verlagsdissertation ist der Ort schon eingetragen + if (datafield.getAttribute("tag").equals("037C")) { + if (address == null) { + address = getSubfield("b", datafield); + address = removeSortCharacters(address); + } + + String st = getSubfield("a", datafield); + if (st != null) { + if (st.contains("Diss")) { + entryType = "phdthesis"; + } + } + } + + //journal oder booktitle + + /* Problematiken hier: Sowohl für Artikel in + * Zeitschriften als für Beiträge in Büchern + * wird 027D verwendet. Der Titel muß je nach + * Fall booktitle oder journal zugeordnet + * werden. Auch bei Zeitschriften werden hier + * ggf. Verlag und Ort angegeben (sind dann + * eigentlich überflüssig), während bei + * Buchbeiträgen Verlag und Ort wichtig sind + * (sonst in Kategorie 033A). + + */ + if (datafield.getAttribute("tag").equals("027D")) { + journal = getSubfield("a", datafield); + booktitle = getSubfield("a", datafield); + address = getSubfield("p", datafield); + publisher = getSubfield("n", datafield); + } + + //pagetotal + if (datafield.getAttribute("tag").equals("034D")) { + pagetotal = getSubfield("a", datafield); + + // S, S. etc. entfernen + pagetotal = pagetotal.replaceAll(" S\\.?$", ""); + } + + // Behandlung von Konferenzen + if (datafield.getAttribute("tag").equals("030F")) { + address = getSubfield("k", datafield); + + if (!entryType.equals("proceedings")) { + subtitle = getSubfield("a", datafield); + } + + entryType = "proceedings"; + } + + // Wenn eine Verlagsdiss vorliegt + if (entryType.equals("phdthesis")) { + if (isbn != null) { + entryType = "book"; + } + } + + //Hilfskategorien zur Entscheidung @article + //oder @incollection; hier könnte man auch die + //ISBN herausparsen als Erleichterung für das + //Auffinden der Quelle, die über die + //SRU-Schnittstelle gelieferten Daten zur + //Quelle unvollständig sind (z.B. nicht Serie + //und Nummer angegeben werden) + if (datafield.getAttribute("tag").equals("039B")) { + quelle = getSubfield("8", datafield); + } + if (datafield.getAttribute("tag").equals("046R")) { + if (quelle.equals("") || (quelle == null)) { + quelle = getSubfield("a", datafield); + } + } + + // URLs behandeln + if (datafield.getAttribute("tag").equals("009P")) { + if (datafield.getAttribute("occurrence").equals("03") + || datafield.getAttribute("occurrence").equals("05")) { + if (url == null) { + url = getSubfield("a", datafield); + } + } + } + } + + // Abfangen von Nulleintraegen + if (quelle == null) { + quelle = ""; + } + + // Nichtsortierzeichen entfernen + if (!(author == null)) { + author = removeSortCharacters(author); + } + + if (!(editor == null)) { + editor = removeSortCharacters(editor); + } + + if (!(title == null)) { + title = removeSortCharacters(title); + } + + if (!(subtitle == null)) { + subtitle = removeSortCharacters(subtitle); + } + + // Dokumenttyp bestimmen und Eintrag anlegen + + if (mak.startsWith("As")) { + entryType = "misc"; + + if (quelle.contains("ISBN")) { + entryType = "incollection"; + } + if (quelle.contains("ZDB-ID")) { + entryType = "article"; + } + } + + if (mak.equals("")) { + entryType = "misc"; + } + + if (mak.startsWith("O")) { + entryType = "online"; + } + + /* + * Wahrscheinlichkeit, dass ZDB-ID + * vorhanden ist, ist größer als ISBN bei + * Buchbeiträgen. Daher bei As?-Sätzen am besten immer + * dann @incollection annehmen, wenn weder ISBN noch + * ZDB-ID vorhanden sind. + */ + BibtexEntry result = new BibtexEntry(IdGenerator.next(), EntryTypes.getType(entryType)); + + // Zuordnung der Felder in Abhängigkeit vom Dokumenttyp + + if (!(author == null)) { + result.setField("author", ImportFormatReader.expandAuthorInitials(author)); + } + if (!(editor == null)) { + result.setField("editor", ImportFormatReader.expandAuthorInitials(editor)); + } + if (!(title == null)) { + result.setField("title", title); + } + if (!(subtitle == null)) { + result.setField("subtitle", subtitle); + } + if (!(publisher == null)) { + result.setField("publisher", publisher); + } + if (!(year == null)) { + result.setField("year", year); + } + if (!(address == null)) { + result.setField("address", address); + } + if (!(series == null)) { + result.setField("series", series); + } + if (!(edition == null)) { + result.setField("edition", edition); + } + if (!(isbn == null)) { + result.setField("isbn", isbn); + } + if (!(issn == null)) { + result.setField("issn", issn); + } + if (!(number == null)) { + result.setField("number", number); + } + if (!(pagetotal == null)) { + result.setField("pagetotal", pagetotal); + } + if (!(pages == null)) { + result.setField("pages", pages); + } + if (!(volume == null)) { + result.setField("volume", volume); + } + if (!(journal == null)) { + result.setField("journal", journal); + } + if (!(ppn == null)) { + result.setField("ppn_GVK", ppn); + } + if (!(url == null)) { + result.setField("url", url); + } + + if (entryType.equals("article")) { + if (!(journal == null)) { + result.setField("journal", journal); + } + } + + if (entryType.equals("incollection")) { + if (!(booktitle == null)) { + result.setField("booktitle", booktitle); + } + } + + return result; } - - private String getSubfield(String a, Element datafield) - { - List liste = getChildren("subfield",datafield); - Iterator iter = liste.iterator(); - - while (iter.hasNext()) - { - Element subfield = iter.next(); - if (subfield.getAttribute("code").equals(a)) - { - return (subfield.getTextContent()); - } - } - return null; + + private String getSubfield(String a, Element datafield) { + List liste = getChildren("subfield", datafield); + Iterator iter = liste.iterator(); + + while (iter.hasNext()) { + Element subfield = iter.next(); + if (subfield.getAttribute("code").equals(a)) { + return (subfield.getTextContent()); + } + } + return null; } - - private Element getChild(String name, Element e) - { - Element result = null; - - NodeList children = e.getChildNodes(); - - int j = children.getLength(); - for (int i = 0; i < j; i++) - { - Node test = (Node) children.item(i); - if (test.getNodeType() == Node.ELEMENT_NODE) - { - Element entry = (Element) test; - if (entry.getTagName().equals(name)) - { - return entry; - } - } - } - return result; + + private Element getChild(String name, Element e) { + Element result = null; + + NodeList children = e.getChildNodes(); + + int j = children.getLength(); + for (int i = 0; i < j; i++) { + Node test = children.item(i); + if (test.getNodeType() == Node.ELEMENT_NODE) { + Element entry = (Element) test; + if (entry.getTagName().equals(name)) { + return entry; + } + } + } + return result; } - - private LinkedList getChildren(String name, Element e) - { - LinkedList result = new LinkedList(); - NodeList children = e.getChildNodes(); - - int j = children.getLength(); - for (int i = 0; i < j; i++) - { - Node test = (Node) children.item(i); - if (test.getNodeType() == Node.ELEMENT_NODE) - { - Element entry = (Element) test; - if (entry.getTagName().equals(name)) - { - result.add(entry); - } - } - } - - return result; + + private List getChildren(String name, Element e) { + List result = new LinkedList<>(); + NodeList children = e.getChildNodes(); + + int j = children.getLength(); + for (int i = 0; i < j; i++) { + Node test = children.item(i); + if (test.getNodeType() == Node.ELEMENT_NODE) { + Element entry = (Element) test; + if (entry.getTagName().equals(name)) { + result.add(entry); + } + } + } + + return result; } - - private String removeSortCharacters(String input) - { - input = input.replaceAll("\\@", ""); - return input; + + private String removeSortCharacters(String input) { + input = input.replaceAll("\\@", ""); + return input; } } From 6293b4d8ee9409afb25b402643a31904b56e33a0 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sat, 21 Nov 2015 01:25:27 +0100 Subject: [PATCH 03/12] Add GVKParserTest and improve GVKParser * add initial support of 036D and 037A * move is to document conversion from GVKFetcher to GVKParser * add XMLUtil * minor code style changes --- .../jabref/importer/fetcher/GVKFetcher.java | 9 +- .../sf/jabref/importer/fetcher/GVKParser.java | 127 ++-- src/main/java/net/sf/jabref/util/XMLUtil.java | 40 ++ .../net/sf/jabref/bibtex/BibtexEntryUtil.java | 42 ++ .../importer/fetcher/GVKParserTest.java | 49 ++ .../gvk_empty_result_becaue_of_bad_query.xml | 13 + .../sf/jabref/importer/fetcher/gvk_gmp.1.bib | 13 + .../sf/jabref/importer/fetcher/gvk_gmp.2.bib | 13 + .../sf/jabref/importer/fetcher/gvk_gmp.xml | 566 ++++++++++++++++++ .../fetcher/gvk_result_for_797485368.bib | 12 + .../fetcher/gvk_result_for_797485368.xml | 131 ++++ 11 files changed, 963 insertions(+), 52 deletions(-) create mode 100644 src/main/java/net/sf/jabref/util/XMLUtil.java create mode 100644 src/test/java/net/sf/jabref/bibtex/BibtexEntryUtil.java create mode 100644 src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java create mode 100644 src/test/resources/net/sf/jabref/importer/fetcher/gvk_empty_result_becaue_of_bad_query.xml create mode 100644 src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.1.bib create mode 100644 src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.2.bib create mode 100644 src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.xml create mode 100644 src/test/resources/net/sf/jabref/importer/fetcher/gvk_result_for_797485368.bib create mode 100644 src/test/resources/net/sf/jabref/importer/fetcher/gvk_result_for_797485368.xml diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java index 6813bdf6a94..75ee59d03aa 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java @@ -14,13 +14,10 @@ import java.util.List; import javax.swing.JPanel; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.w3c.dom.Document; import org.xml.sax.SAXException; import net.sf.jabref.importer.ImportInspector; @@ -152,7 +149,7 @@ private String processComplexQuery(String[] s) { } private List fetchGVK(String query) { - List result = null; + List result; String urlPrefix = "http://sru.gbv.de/gvk?version=1.1&operation=searchRetrieve&query="; String urlQuery = query; @@ -170,9 +167,7 @@ private List fetchGVK(String query) { } URL url = uri.toURL(); try (InputStream is = url.openStream()) { - DocumentBuilder dbuild = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - Document content = dbuild.parse(is); - result = (new GVKParser()).parseEntries(content); + result = (new GVKParser()).parseEntries(is); } } catch (IOException e) { LOGGER.error("GVK plugin: An I/O exception occurred", e); diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java b/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java index a7b415ea2cf..f6df8ca3f0c 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java @@ -3,40 +3,57 @@ */ package net.sf.jabref.importer.fetcher; +import java.io.IOException; +import java.io.InputStream; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + import net.sf.jabref.bibtex.EntryTypes; import net.sf.jabref.importer.ImportFormatReader; import net.sf.jabref.model.entry.BibtexEntry; import net.sf.jabref.model.entry.IdGenerator; - import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; public class GVKParser { + public List parseEntries(InputStream is) + throws ParserConfigurationException, SAXException, IOException { + DocumentBuilder dbuild = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document content = dbuild.parse(is); + return this.parseEntries(content); + } + public List parseEntries(Document content) { List result = new LinkedList<>(); + // used for creating test cases + // XMLUtil.printDocument(content); + // Namespace srwNamespace = Namespace.getNamespace("srw","http://www.loc.gov/zing/srw/"); // Schleife ueber allen Teilergebnissen //Element root = content.getDocumentElement(); Element root = (Element) content.getElementsByTagName("zs:searchRetrieveResponse").item(0); Element srwrecords = getChild("zs:records", root); + if (srwrecords == null) { + // no records found -> return empty list + return result; + } List records = getChildren("zs:record", srwrecords); - for (Element record : records) { Element e = getChild("zs:recordData", record); e = getChild("record", e); - result.add(parseEntry(e)); } - return result; } @@ -59,6 +76,7 @@ private BibtexEntry parseEntry(Element e) { String ppn = null; String booktitle = null; String url = null; + String note = null; String quelle = ""; String mak = ""; @@ -90,7 +108,7 @@ private BibtexEntry parseEntry(Element e) { String vorname = getSubfield("d", datafield); String nachname = getSubfield("a", datafield); - if (!(author == null)) { + if (author != null) { author = author.concat(" and "); } else { author = ""; @@ -102,7 +120,7 @@ private BibtexEntry parseEntry(Element e) { String vorname = getSubfield("d", datafield); String nachname = getSubfield("a", datafield); - if (!(author == null)) { + if (author != null) { author = author.concat(" and "); } else { author = ""; @@ -115,7 +133,7 @@ private BibtexEntry parseEntry(Element e) { String vorname = getSubfield("d", datafield); String nachname = getSubfield("a", datafield); - if (!(editor == null)) { + if (editor != null) { editor = editor.concat(" and "); } else { editor = ""; @@ -149,6 +167,27 @@ private BibtexEntry parseEntry(Element e) { } + // 036D seems to contain more information than the other fields + // overwrite information using that field + // 036D also contains information normally found in 036E + if (datafield.getAttribute("tag").equals("036D")) { + // 021 might have been present + if (title != null) { + // convert old title (contained in "a" of 021A) to volume + if (title.startsWith("@")) { + // "@" indicates a number + title = title.substring(1); + } else { + // we nevertheless keep the old title data + } + number = title; + } + //title and subtitle + title = getSubfield("a", datafield); + subtitle = getSubfield("d", datafield); + volume = getSubfield("l", datafield); + } + //series and number if (datafield.getAttribute("tag").equals("036E")) { series = getSubfield("a", datafield); @@ -160,6 +199,11 @@ private BibtexEntry parseEntry(Element e) { } } + //note + if (datafield.getAttribute("tag").equals("037A")) { + note = getSubfield("a", datafield); + } + //edition if (datafield.getAttribute("tag").equals("032@")) { edition = getSubfield("a", datafield); @@ -207,7 +251,6 @@ private BibtexEntry parseEntry(Element e) { * eigentlich überflüssig), während bei * Buchbeiträgen Verlag und Ort wichtig sind * (sonst in Kategorie 033A). - */ if (datafield.getAttribute("tag").equals("027D")) { journal = getSubfield("a", datafield); @@ -275,19 +318,16 @@ private BibtexEntry parseEntry(Element e) { } // Nichtsortierzeichen entfernen - if (!(author == null)) { + if (author != null) { author = removeSortCharacters(author); } - - if (!(editor == null)) { + if (editor != null) { editor = removeSortCharacters(editor); } - - if (!(title == null)) { + if (title != null) { title = removeSortCharacters(title); } - - if (!(subtitle == null)) { + if (subtitle != null) { subtitle = removeSortCharacters(subtitle); } @@ -302,13 +342,9 @@ private BibtexEntry parseEntry(Element e) { if (quelle.contains("ZDB-ID")) { entryType = "article"; } - } - - if (mak.equals("")) { + } else if (mak.equals("")) { entryType = "misc"; - } - - if (mak.startsWith("O")) { + } else if (mak.startsWith("O")) { entryType = "online"; } @@ -322,70 +358,70 @@ private BibtexEntry parseEntry(Element e) { BibtexEntry result = new BibtexEntry(IdGenerator.next(), EntryTypes.getType(entryType)); // Zuordnung der Felder in Abhängigkeit vom Dokumenttyp - - if (!(author == null)) { + if (author != null) { result.setField("author", ImportFormatReader.expandAuthorInitials(author)); } - if (!(editor == null)) { + if (editor != null) { result.setField("editor", ImportFormatReader.expandAuthorInitials(editor)); } - if (!(title == null)) { + if (title != null) { result.setField("title", title); } - if (!(subtitle == null)) { + if (subtitle != null) { result.setField("subtitle", subtitle); } - if (!(publisher == null)) { + if (publisher != null) { result.setField("publisher", publisher); } - if (!(year == null)) { + if (year != null) { result.setField("year", year); } - if (!(address == null)) { + if (address != null) { result.setField("address", address); } - if (!(series == null)) { + if (series != null) { result.setField("series", series); } - if (!(edition == null)) { + if (edition != null) { result.setField("edition", edition); } - if (!(isbn == null)) { + if (isbn != null) { result.setField("isbn", isbn); } - if (!(issn == null)) { + if (issn != null) { result.setField("issn", issn); } - if (!(number == null)) { + if (number != null) { result.setField("number", number); } - if (!(pagetotal == null)) { + if (pagetotal != null) { result.setField("pagetotal", pagetotal); } - if (!(pages == null)) { + if (pages != null) { result.setField("pages", pages); } - if (!(volume == null)) { + if (volume != null) { result.setField("volume", volume); } - if (!(journal == null)) { + if (journal != null) { result.setField("journal", journal); } - if (!(ppn == null)) { + if (ppn != null) { result.setField("ppn_GVK", ppn); } - if (!(url == null)) { + if (url != null) { result.setField("url", url); } + if (note != null) { + result.setField("note", note); + } if (entryType.equals("article")) { - if (!(journal == null)) { + if (journal != null) { result.setField("journal", journal); } - } - - if (entryType.equals("incollection")) { - if (!(booktitle == null)) { + } else if (entryType.equals("incollection")) { + if (booktitle != null) { result.setField("booktitle", booktitle); } } @@ -446,4 +482,5 @@ private String removeSortCharacters(String input) { input = input.replaceAll("\\@", ""); return input; } + } diff --git a/src/main/java/net/sf/jabref/util/XMLUtil.java b/src/main/java/net/sf/jabref/util/XMLUtil.java new file mode 100644 index 00000000000..ff79a95226b --- /dev/null +++ b/src/main/java/net/sf/jabref/util/XMLUtil.java @@ -0,0 +1,40 @@ +package net.sf.jabref.util; + +import java.io.StringWriter; + +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Document; + +/** + * Currently used for debugging only + */ +public class XMLUtil { + + private static final Log LOGGER = LogFactory.getLog(XMLUtil.class); + + + public static void printDocument(Document doc) { + // code by http://stackoverflow.com/a/10356322/873282 + try { + DOMSource domSource = new DOMSource(doc); + StringWriter writer = new StringWriter(); + StreamResult result = new StreamResult(writer); + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer transformer = tf.newTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.transform(domSource, result); + System.out.println(writer.toString()); + } catch (TransformerException ex) { + LOGGER.error("", ex); + } + } + +} diff --git a/src/test/java/net/sf/jabref/bibtex/BibtexEntryUtil.java b/src/test/java/net/sf/jabref/bibtex/BibtexEntryUtil.java new file mode 100644 index 00000000000..af88a487a9e --- /dev/null +++ b/src/test/java/net/sf/jabref/bibtex/BibtexEntryUtil.java @@ -0,0 +1,42 @@ +package net.sf.jabref.bibtex; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringWriter; + +import org.junit.Assert; + +import com.google.common.base.Charsets; +import com.google.common.io.CharStreams; + +import net.sf.jabref.exporter.LatexFieldFormatter; +import net.sf.jabref.importer.fetcher.GVKParser; +import net.sf.jabref.model.entry.BibtexEntry; + +public class BibtexEntryUtil { + + private final static BibtexEntryWriter writer = new BibtexEntryWriter(new LatexFieldFormatter(), true); + + + public static String bibtexEntryToString(BibtexEntry entry) { + StringWriter stringWriter = new StringWriter(); + try { + writer.write(entry, stringWriter); + } catch (IOException e) { + // Quick hack as this should never happen + return "ERROR: " + e.getMessage(); + } + return stringWriter.toString(); + } + + public static void doAssertEquals(Class clazz, String resourceName, BibtexEntry entry) + throws IOException { + try (InputStream shouldBeIs = clazz.getResourceAsStream(resourceName)) { + Assert.assertNotNull(shouldBeIs); + String shouldBeEntry = CharStreams.toString(new InputStreamReader(shouldBeIs, Charsets.UTF_8)); + Assert.assertEquals(shouldBeEntry, BibtexEntryUtil.bibtexEntryToString(entry)); + } + + } +} diff --git a/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java b/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java new file mode 100644 index 00000000000..547dd599e4b --- /dev/null +++ b/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java @@ -0,0 +1,49 @@ +package net.sf.jabref.importer.fetcher; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import javax.xml.parsers.ParserConfigurationException; + +import org.junit.Assert; +import org.junit.Test; +import org.xml.sax.SAXException; + +import net.sf.jabref.bibtex.BibtexEntryUtil; +import net.sf.jabref.model.entry.BibtexEntry; + +public class GVKParserTest { + + private void doTest(String xmlName, int expectedSize, List resourceNames) + throws ParserConfigurationException, SAXException, IOException { + try (InputStream is = GVKParser.class.getResourceAsStream(xmlName)) { + GVKParser parser = new GVKParser(); + List entries = parser.parseEntries(is); + Assert.assertNotNull(entries); + Assert.assertEquals(entries.size(), expectedSize); + int i = 0; + for (String resourceName : resourceNames) { + BibtexEntryUtil.doAssertEquals(GVKParser.class, resourceName, entries.get(i)); + i++; + } + } + } + + @Test + public void emptyResult() throws Exception { + doTest("gvk_empty_result_becaue_of_bad_query.xml", 0, Collections.EMPTY_LIST); + } + + @Test + public void resultFor797485368() throws Exception { + doTest("gvk_result_for_797485368.xml", 1, Arrays.asList(new String[] {"gvk_result_for_797485368.bib"})); + } + + @Test + public void GMP() throws Exception { + doTest("gvk_gmp.xml", 2, Arrays.asList(new String[] {"gvk_gmp.1.bib", "gvk_gmp.2.bib"})); + } +} diff --git a/src/test/resources/net/sf/jabref/importer/fetcher/gvk_empty_result_becaue_of_bad_query.xml b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_empty_result_becaue_of_bad_query.xml new file mode 100644 index 00000000000..58a1c44df98 --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_empty_result_becaue_of_bad_query.xml @@ -0,0 +1,13 @@ + + +1.1 +0 + +1.1 +pica.all=797485368 Zitierlink +50 +xml +picaxml +Year,,1 + + \ No newline at end of file diff --git a/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.1.bib b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.1.bib new file mode 100644 index 00000000000..4d847f18c43 --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.1.bib @@ -0,0 +1,13 @@ +@Book{, + Title = {GMP-Regelwerke für Arzneimittel}, + Publisher = {Maas \& Peither, GMP-Verl.}, + Year = {2014}, + Address = {Schopfheim}, + Edition = {7., aktualisierte Aufl.}, + Note = {Text teilw. dt., teilw. engl.}, + Number = {7}, + Series = {Kleiner GMP-Berater}, + ISBN = {9783943267914}, + Pagetotal = {310}, + Ppn_GVK = {785759913} +} diff --git a/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.2.bib b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.2.bib new file mode 100644 index 00000000000..4ab860a18ee --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.2.bib @@ -0,0 +1,13 @@ +@Book{, + Title = {GMP-Regelwerke für computergestützte Systeme}, + Publisher = {Maas \& Peither, GMP-Verl}, + Year = {2014}, + Address = {Schopfheim}, + Edition = {4., aktual. Aufl.}, + Note = {Text teilw. dt. und engl}, + Number = {Bd. 5}, + Series = {Kleiner GMP-Berater}, + ISBN = {9783958070011}, + Pagetotal = {142}, + Ppn_GVK = {810635399} +} diff --git a/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.xml b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.xml new file mode 100644 index 00000000000..1eb2cf49d02 --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.xml @@ -0,0 +1,566 @@ + + +1.1 +2 + + +picaxml +xml + + + + 20 + + + 2001:14-05-14 + + + 0084:07-11-14 + 14:03:00.000 + + + 0084:20-10-14 + + + utf8 + + + 0 + + + Aau0z + + + 785759913 + + + 9783943267914 + spiralgeh. : EUR 20.87 + DE + + + 9783943267914 + + + 1050792157 + + + DNB + 1050792157 + + + 14A22 + + + OCoLC + 879880337 + + + DNB + 1050792157 + + + http://d-nb.info/1050792157/04 + DE-101 + application/pdf + 2014-05-28 + 04 + 2 + DNB + 2 + + + http://deposit.d-nb.de/cgi-bin/dokserv?id=4659669&prov=M&dok_var=1&dok_ext=htm + Verlag: MVB + text/html + 2014-05-28 + 01 + 2 + DNB + 2 + + + ger + eng + + + 2014 + + + XA-DE + + + GMP-Regelwerke f�r Arzneimittel + + + 7., aktualisierte Aufl. + + + Schopfheim + Maas & Peither, GMP-Verl. + + + 310 S. + + + 14 cm + + + Kleiner GMP-Berater + 7 + + + 700 + 496510126 + Kleiner GMP-Berater + Schopfheim + Maas & Peither, GMP-Verl + 2000- + 21989291 + 7 + + + Text teilw. dt., teilw. engl. + + + 528183451 + Tuv1 + Arzneimittel- und Wirkstoffherstellungsverordnung + gnd/7568112-2 + + + DE-101 + + + 104616016 + Tgv1 + Europ�ische Union + gnd/4131753-1 + + + 104161949 + Tsv1 + GMP-Regeln + gnd/4113765-6 + + + 104962720 + Tsv1 + Produktinformation + gnd/4227582-9 + + + DE-101 + + + c + Deutschland + + + 22/ger + 615.19002184 + + + 23sdnb + 610 + 340 + + + 23sdnb + 610 + + + 610 + 340 + DNB + + + 106416995 + 86.56 + Gesundheitsrecht + Lebensmittelrecht + + + 106423304 + 44.40 + Pharmazie + Pharmazeutika + + + 15,3 + + + pha + + + 20 + PICA + + + 20-10-14 + 10:29:15.000 + + + 20-10-14 + 1014 + 0084 + + + utf8 + + + 1458093670 + + + 15-07-14 + k + + + 1452-1627 + 00 + + + 84$014521627 + + + +1 + + +picaxml +xml + + + + 20,293 + + + 3293:04-12-14 + + + 2004:19-11-15 + 02:28:21.000 + + + 3293:04-12-14 + + + utf8 + + + 0 + + + Aau + + + 810635399 + + + 9783958070011 + + + GBV + 810635399 + + + ger + eng + eng + + + 2014 + + + XA-DE + + + GMP-Regelwerke für computergestützte Systeme + + + 4., aktual. Aufl. + + + Schopfheim + Maas & Peither, GMP-Verl + + + 142 S. + + + Kleiner GMP-Berater + Bd. 5 + + + 500 + 496510126 + Kleiner GMP-Berater + Schopfheim + Maas & Peither, GMP-Verl + 2000- + 21989291 + Bd. 5 + + + Text teilw. dt. und engl + + + 106200690 + Tsv1 + Pharmazeutische Industrie + gnd/4045696-1 + + + 104451939 + Tsv1 + Betriebliches Informationssystem + gnd/4069386-7 + + + 104467525 + Tsv1 + Computersicherheit + gnd/4274324-2 + + + 104212543 + Tsv1 + Softwareschutz + gnd/4131649-6 + + + DE-101 + + + 23sdnb + 610 + + + 22/ger + 658.4038011 + + + 23sdnb + 650 + 004 + + + 650 + 004 + DNB + + + 15,3 + + + pha + + + 20 + PICA + + + 17-11-15 + 12:06:23.000 + + + 17-11-15 + 1014 + 0084 + + + utf8 + + + 1468429450 + + + 11-12-14 + k + + + 1452-3227 + 00 + + + 84$014523227 + + + 293 + PICA + + + 04-12-14 + 14:49:02.000 + + + 04-12-14 + 5601 + 3293/0333 + + + utf8 + + + 1508486832 + + + 04-12-14 + zf + + + KSF/FHH + MED 2200 251(4):1 + s + 00 + + + fi 2014/0607 + 00 + + + 960$02115956 + + + 04-12-14 + 14:49:02.000 + + + 04-12-14 + 5601 + 3293/0333 + + + utf8 + + + 1513287834 + + + 04-12-14 + zf + + + KSF/FHH + MED 2200 251(4):2 + u + 00 + + + fi 2014/0608 + 00 + + + 960$02115913 + + + 04-12-14 + 14:49:02.000 + + + 04-12-14 + 5601 + 3293/0333 + + + utf8 + + + 1513287842 + + + 04-12-14 + zf + + + KSF/FHH + MED 2200 251(4):3 + u + 00 + + + fi 2014/0609 + 00 + + + 960$02115964 + + + 04-12-14 + 14:49:02.000 + + + 04-12-14 + 5601 + 3293/0333 + + + utf8 + + + 1513287850 + + + 04-12-14 + zf + + + KSF/FHH + MED 2200 251(4):4 + u + 00 + + + fi 2014/0610 + 00 + + + 960$02115921 + + + 04-12-14 + 14:49:02.000 + + + 04-12-14 + 5601 + 3293/0333 + + + utf8 + + + 1513287869 + + + 04-12-14 + zf + + + KSF/FHH + MED 2200 251(4):5 + u + 00 + + + fi 2014/0611 + 00 + + + 960$0211593X + + + +2 + + + +1.1 +pica.all=GMP-Regelwerke für Arzneimittel +50 +xml +picaxml +Year,,1 + + + diff --git a/src/test/resources/net/sf/jabref/importer/fetcher/gvk_result_for_797485368.bib b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_result_for_797485368.bib new file mode 100644 index 00000000000..8d64b1edea6 --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_result_for_797485368.bib @@ -0,0 +1,12 @@ +@Book{, + Title = {GMP-Berater}, + Publisher = {Maas und Peither GMP Verl.}, + Year = {2014}, + Address = {Schopfheim}, + Number = {L - N}, + Volume = {Bd. I}, + Editor = {Anita Maas}, + Pagetotal = {Losebl.-Ausg.}, + Ppn_GVK = {797485368}, + Subtitle = {Nachschlagewerk für Pharmaindustrie und Lieferanten. Die praxisorientierte Loseblattsammlung für die Gute Herstellungspraxis (Good Manufacturing Practice)} +} diff --git a/src/test/resources/net/sf/jabref/importer/fetcher/gvk_result_for_797485368.xml b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_result_for_797485368.xml new file mode 100644 index 00000000000..7c2b3783937 --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_result_for_797485368.xml @@ -0,0 +1,131 @@ + + +1.1 +1 + + +picaxml +xml + + + + 31 + + + 0027:26-09-14 + + + 0027:26-09-14 + 09:39:19.000 + + + 0027:26-09-14 + + + utf8 + + + 0 + + + Afu + + + 797485368 + + + GBV + 797485368 + + + ger + + + 2014 + + + XA-DE + + + @L - N + + + Anita + Maas + + + Schopfheim + Maas und Peither GMP Verl. + + + Losebl.-Ausg. + + + GMP-Berater + Nachschlagewerk für Pharmaindustrie und Lieferanten. Die praxisorientierte Loseblattsammlung für die Gute Herstellungspraxis (Good Manufacturing Practice) + hrsg. von Anita Maas ... + Bd. I + + + I.2014 + 327753609 + GMP-Berater + Nachschlagewerk für Pharmaindustrie und Lieferanten. Die praxisorientierte Loseblattsammlung für die Gute Herstellungspraxis (Good Manufacturing Practice) + Maas + Anita + Schopfheim + Maas und Peither GMP Verl. + 2000- + Bd. I + _I 2014 + + + 31 + PICA + + + 31-03-15 + 16:54:04.000 + + + 31-03-15 + 7681 + 0027 + + + utf8 + + + 150373661X + + + 26-09-14 + z + + + J 36/PT2 + PHA:RG:5500:Maa:I:2000 + f + 00 + + + U501697/2 + 00 + + + 27$027697738 + + + +1 + + + +1.1 +pica.all=797485368 +50 +xml +picaxml +Year,,1 + + \ No newline at end of file From 08e0f02406a05fe6877d81f0a03365fa2c96c2da Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sat, 21 Nov 2015 01:39:19 +0100 Subject: [PATCH 04/12] Add help based on http://jabref.tempelb.de/ --- .../jabref/importer/fetcher/GVKFetcher.java | 2 +- src/main/resources/help/en/GVKHelp.html | 45 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/help/en/GVKHelp.html diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java index 75ee59d03aa..1fdda3bbb4d 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java @@ -61,7 +61,7 @@ public void stopFetching() { @Override public String getHelpPage() { - return null; + return "GVKHelp.html"; } @Override diff --git a/src/main/resources/help/en/GVKHelp.html b/src/main/resources/help/en/GVKHelp.html new file mode 100644 index 00000000000..e7e9fb1015a --- /dev/null +++ b/src/main/resources/help/en/GVKHelp.html @@ -0,0 +1,45 @@ + + + + + + +

Search the GVK (Common Union Catalogue)

+ +

The GVK search capability can be used to query the GVK (Common Union Catalogue) and automatically import references into JabRef.

+ +

To use this feature, choose Search -> Web search, and the search + interface will appear in the side pane. Select GVKFetcher in the dropdown menu.

+ +

You can simply enter words / names / years you want to search for, or you can specify search keys.

+ +

Supported keywords are

+
    +
  • all - all words. Not specifing a search key results in an "all" search
  • +
  • tit - title words
  • +
  • per - authors, editors, etc.
  • +
  • thm - topics
  • +
  • slw - key words
  • +
  • txt - tables of content
  • +
  • num - numbers, e.g. ISBN
  • +
  • kon - names of conferences
  • +
  • ppn - Pica Production Numbers of the GVK
  • +
  • bkl - Basisklassifikation-numbers
  • +
  • erj - year of publication
  • +
+ +

Notes

+
    +
  • queries can be combined with "and". The use of "and" is optional, though.
  • +
  • in many cases you can use the truncation sign "?"
  • +
  • spaces in person names are not supported - I am working on it. Please use the truncation sign ? after the first name for several given names. E.g. "per Maas,jan?"
  • +
+ +

Sample queries

+
    +
  • "marx kapital"
  • +
  • "per grodke and tit db2"
  • +
  • "per Maas,jan?"
  • +
+ + From f308410fcf7f0e167397d514288eaa1d165acdce Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sat, 21 Nov 2015 01:41:06 +0100 Subject: [PATCH 05/12] Add GVK authors to AUTHORS --- AUTHORS | 2 ++ scripts/generate-authors.sh | 1 + 2 files changed, 3 insertions(+) diff --git a/AUTHORS b/AUTHORS index ac5ce01a291..ff698991516 100644 --- a/AUTHORS +++ b/AUTHORS @@ -13,6 +13,7 @@ Andreas Amann Andreas Rudert Behrouz Javanmardi Bernd Kalbfuss +Bernhard Tempel Brian Quistorff Brian Van Essen captain123 @@ -49,6 +50,7 @@ Hannes Restel Igor Chernyavsky Igor Steinmacher Ingvar Jackal +Jan Frederik Maas Jan Kubovy Janosch Kutscherauer Jason Pickering diff --git a/scripts/generate-authors.sh b/scripts/generate-authors.sh index 51396fcd634..ee0d51e7d7a 100755 --- a/scripts/generate-authors.sh +++ b/scripts/generate-authors.sh @@ -51,6 +51,7 @@ cd "$(dirname "$(readlink -f "$BASH_SOURCE")")/.." John Zedlewski Samin Muhammad Ridwanul Karim Stefan Robert + Bernhard Tempel EOF # %aN = author name, %aE = author email From b2c8db5458fb46b5581b7018897f67c8cf010bcc Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sat, 21 Nov 2015 15:02:55 +0100 Subject: [PATCH 06/12] Replace "year" by "date" as the fields returned are biblatex fields --- .../net/sf/jabref/importer/fetcher/GVKParser.java | 14 +++++++------- .../net/sf/jabref/importer/fetcher/gvk_gmp.1.bib | 2 +- .../net/sf/jabref/importer/fetcher/gvk_gmp.2.bib | 2 +- .../importer/fetcher/gvk_result_for_797485368.bib | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java b/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java index f6df8ca3f0c..3fe737ea96e 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java @@ -62,7 +62,7 @@ private BibtexEntry parseEntry(Element e) { String editor = null; String title = null; String publisher = null; - String year = null; + String date = null; String address = null; String series = null; String edition = null; @@ -153,14 +153,14 @@ private BibtexEntry parseEntry(Element e) { address = getSubfield("p", datafield); } - //year + //date if (datafield.getAttribute("tag").equals("011@")) { - year = getSubfield("a", datafield); + date = getSubfield("a", datafield); } - //year, volume, number, pages (year bei Zeitschriften (evtl. redundant mit 011@)) + //date, volume, number, pages (year bei Zeitschriften (evtl. redundant mit 011@)) if (datafield.getAttribute("tag").equals("031A")) { - year = getSubfield("j", datafield); + date = getSubfield("j", datafield); volume = getSubfield("e", datafield); number = getSubfield("a", datafield); pages = getSubfield("h", datafield); @@ -373,8 +373,8 @@ private BibtexEntry parseEntry(Element e) { if (publisher != null) { result.setField("publisher", publisher); } - if (year != null) { - result.setField("year", year); + if (date != null) { + result.setField("date", date); } if (address != null) { result.setField("address", address); diff --git a/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.1.bib b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.1.bib index 4d847f18c43..f723a14d859 100644 --- a/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.1.bib +++ b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.1.bib @@ -1,12 +1,12 @@ @Book{, Title = {GMP-Regelwerke für Arzneimittel}, Publisher = {Maas \& Peither, GMP-Verl.}, - Year = {2014}, Address = {Schopfheim}, Edition = {7., aktualisierte Aufl.}, Note = {Text teilw. dt., teilw. engl.}, Number = {7}, Series = {Kleiner GMP-Berater}, + Date = {2014}, ISBN = {9783943267914}, Pagetotal = {310}, Ppn_GVK = {785759913} diff --git a/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.2.bib b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.2.bib index 4ab860a18ee..4b09eec3e8a 100644 --- a/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.2.bib +++ b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.2.bib @@ -1,12 +1,12 @@ @Book{, Title = {GMP-Regelwerke für computergestützte Systeme}, Publisher = {Maas \& Peither, GMP-Verl}, - Year = {2014}, Address = {Schopfheim}, Edition = {4., aktual. Aufl.}, Note = {Text teilw. dt. und engl}, Number = {Bd. 5}, Series = {Kleiner GMP-Berater}, + Date = {2014}, ISBN = {9783958070011}, Pagetotal = {142}, Ppn_GVK = {810635399} diff --git a/src/test/resources/net/sf/jabref/importer/fetcher/gvk_result_for_797485368.bib b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_result_for_797485368.bib index 8d64b1edea6..f76dc7f1d53 100644 --- a/src/test/resources/net/sf/jabref/importer/fetcher/gvk_result_for_797485368.bib +++ b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_result_for_797485368.bib @@ -1,10 +1,10 @@ @Book{, Title = {GMP-Berater}, Publisher = {Maas und Peither GMP Verl.}, - Year = {2014}, Address = {Schopfheim}, Number = {L - N}, Volume = {Bd. I}, + Date = {2014}, Editor = {Anita Maas}, Pagetotal = {Losebl.-Ausg.}, Ppn_GVK = {797485368}, From 7047a1db1113b4c9d29c5ed751c44ac6c1bcb85a Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sat, 21 Nov 2015 15:27:47 +0100 Subject: [PATCH 07/12] GVKFetcher: Ensure that first letter of subtitle is always capitalized Minor improvements: * replace calls to datafield.getAttribute("tag") by a single variable --- .../sf/jabref/importer/fetcher/GVKParser.java | 64 ++++++++++------ .../importer/fetcher/GVKParserTest.java | 27 ++++++- .../fetcher/gvk_artificial_subtitle_test.xml | 75 +++++++++++++++++++ 3 files changed, 141 insertions(+), 25 deletions(-) create mode 100644 src/test/resources/net/sf/jabref/importer/fetcher/gvk_artificial_subtitle_test.xml diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java b/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java index 3fe737ea96e..7d2d829d852 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/GVKParser.java @@ -17,14 +17,22 @@ import net.sf.jabref.importer.ImportFormatReader; import net.sf.jabref.model.entry.BibtexEntry; import net.sf.jabref.model.entry.IdGenerator; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; +import com.google.common.base.Strings; + public class GVKParser { + private static final Log LOGGER = LogFactory.getLog(GVKParser.class); + + public List parseEntries(InputStream is) throws ParserConfigurationException, SAXException, IOException { DocumentBuilder dbuild = DocumentBuilderFactory.newInstance().newDocumentBuilder(); @@ -91,20 +99,21 @@ private BibtexEntry parseEntry(Element e) { while (iter.hasNext()) { Element datafield = iter.next(); - // System.out.println(datafield.getAttributeValue("tag")); + String tag = datafield.getAttribute("tag"); + LOGGER.debug("tag: " + tag); // mak - if (datafield.getAttribute("tag").equals("002@")) { + if (tag.equals("002@")) { mak = getSubfield("0", datafield); } //ppn - if (datafield.getAttribute("tag").equals("003@")) { + if (tag.equals("003@")) { ppn = getSubfield("0", datafield); } //author - if (datafield.getAttribute("tag").equals("028A")) { + if (tag.equals("028A")) { String vorname = getSubfield("d", datafield); String nachname = getSubfield("a", datafield); @@ -116,7 +125,7 @@ private BibtexEntry parseEntry(Element e) { author = author.concat(vorname + " " + nachname); } //author (weiterer) - if (datafield.getAttribute("tag").equals("028B")) { + if (tag.equals("028B")) { String vorname = getSubfield("d", datafield); String nachname = getSubfield("a", datafield); @@ -129,7 +138,7 @@ private BibtexEntry parseEntry(Element e) { } //editor - if (datafield.getAttribute("tag").equals("028C")) { + if (tag.equals("028C")) { String vorname = getSubfield("d", datafield); String nachname = getSubfield("a", datafield); @@ -142,24 +151,24 @@ private BibtexEntry parseEntry(Element e) { } //title and subtitle - if (datafield.getAttribute("tag").equals("021A")) { + if (tag.equals("021A")) { title = getSubfield("a", datafield); subtitle = getSubfield("d", datafield); } //publisher and address - if (datafield.getAttribute("tag").equals("033A")) { + if (tag.equals("033A")) { publisher = getSubfield("n", datafield); address = getSubfield("p", datafield); } //date - if (datafield.getAttribute("tag").equals("011@")) { + if (tag.equals("011@")) { date = getSubfield("a", datafield); } //date, volume, number, pages (year bei Zeitschriften (evtl. redundant mit 011@)) - if (datafield.getAttribute("tag").equals("031A")) { + if (tag.equals("031A")) { date = getSubfield("j", datafield); volume = getSubfield("e", datafield); number = getSubfield("a", datafield); @@ -170,7 +179,7 @@ private BibtexEntry parseEntry(Element e) { // 036D seems to contain more information than the other fields // overwrite information using that field // 036D also contains information normally found in 036E - if (datafield.getAttribute("tag").equals("036D")) { + if (tag.equals("036D")) { // 021 might have been present if (title != null) { // convert old title (contained in "a" of 021A) to volume @@ -189,7 +198,7 @@ private BibtexEntry parseEntry(Element e) { } //series and number - if (datafield.getAttribute("tag").equals("036E")) { + if (tag.equals("036E")) { series = getSubfield("a", datafield); number = getSubfield("l", datafield); String kor = getSubfield("b", datafield); @@ -200,17 +209,17 @@ private BibtexEntry parseEntry(Element e) { } //note - if (datafield.getAttribute("tag").equals("037A")) { + if (tag.equals("037A")) { note = getSubfield("a", datafield); } //edition - if (datafield.getAttribute("tag").equals("032@")) { + if (tag.equals("032@")) { edition = getSubfield("a", datafield); } //isbn - if (datafield.getAttribute("tag").equals("004A")) { + if (tag.equals("004A")) { String isbn_10 = getSubfield("0", datafield); String isbn_13 = getSubfield("A", datafield); @@ -226,7 +235,7 @@ private BibtexEntry parseEntry(Element e) { // Hochschulschriftenvermerk // Bei einer Verlagsdissertation ist der Ort schon eingetragen - if (datafield.getAttribute("tag").equals("037C")) { + if (tag.equals("037C")) { if (address == null) { address = getSubfield("b", datafield); address = removeSortCharacters(address); @@ -252,7 +261,7 @@ private BibtexEntry parseEntry(Element e) { * Buchbeiträgen Verlag und Ort wichtig sind * (sonst in Kategorie 033A). */ - if (datafield.getAttribute("tag").equals("027D")) { + if (tag.equals("027D")) { journal = getSubfield("a", datafield); booktitle = getSubfield("a", datafield); address = getSubfield("p", datafield); @@ -260,7 +269,7 @@ private BibtexEntry parseEntry(Element e) { } //pagetotal - if (datafield.getAttribute("tag").equals("034D")) { + if (tag.equals("034D")) { pagetotal = getSubfield("a", datafield); // S, S. etc. entfernen @@ -268,7 +277,7 @@ private BibtexEntry parseEntry(Element e) { } // Behandlung von Konferenzen - if (datafield.getAttribute("tag").equals("030F")) { + if (tag.equals("030F")) { address = getSubfield("k", datafield); if (!entryType.equals("proceedings")) { @@ -292,17 +301,17 @@ private BibtexEntry parseEntry(Element e) { //SRU-Schnittstelle gelieferten Daten zur //Quelle unvollständig sind (z.B. nicht Serie //und Nummer angegeben werden) - if (datafield.getAttribute("tag").equals("039B")) { + if (tag.equals("039B")) { quelle = getSubfield("8", datafield); } - if (datafield.getAttribute("tag").equals("046R")) { + if (tag.equals("046R")) { if (quelle.equals("") || (quelle == null)) { quelle = getSubfield("a", datafield); } } // URLs behandeln - if (datafield.getAttribute("tag").equals("009P")) { + if (tag.equals("009P")) { if (datafield.getAttribute("occurrence").equals("03") || datafield.getAttribute("occurrence").equals("05")) { if (url == null) { @@ -367,8 +376,15 @@ private BibtexEntry parseEntry(Element e) { if (title != null) { result.setField("title", title); } - if (subtitle != null) { - result.setField("subtitle", subtitle); + if (!Strings.isNullOrEmpty(subtitle)) { + // ensure that first letter is an upper case letter + // there could be the edge case that the string is only one character long, therefore, this special treatment + // this is apache commons lang StringUtils.capitalize (https://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/StringUtils.html#capitalize%28java.lang.String%29), but we don't want to add an additional dependency ('org.apache.commons:commons-lang3:3.4') + String newSubtitle = Character.toString(Character.toUpperCase(subtitle.charAt(0))); + if (subtitle.length() > 1) { + newSubtitle += subtitle.substring(1); + } + result.setField("subtitle", newSubtitle); } if (publisher != null) { result.setField("publisher", publisher); diff --git a/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java b/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java index 547dd599e4b..155a6c0e3bf 100644 --- a/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java +++ b/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java @@ -23,7 +23,7 @@ private void doTest(String xmlName, int expectedSize, List resourceNames GVKParser parser = new GVKParser(); List entries = parser.parseEntries(is); Assert.assertNotNull(entries); - Assert.assertEquals(entries.size(), expectedSize); + Assert.assertEquals(expectedSize, entries.size()); int i = 0; for (String resourceName : resourceNames) { BibtexEntryUtil.doAssertEquals(GVKParser.class, resourceName, entries.get(i)); @@ -46,4 +46,29 @@ public void resultFor797485368() throws Exception { public void GMP() throws Exception { doTest("gvk_gmp.xml", 2, Arrays.asList(new String[] {"gvk_gmp.1.bib", "gvk_gmp.2.bib"})); } + + @Test + public void subTitleTest() throws Exception { + try (InputStream is = GVKParser.class.getResourceAsStream("gvk_artificial_subtitle_test.xml")) { + GVKParser parser = new GVKParser(); + List entries = parser.parseEntries(is); + Assert.assertNotNull(entries); + Assert.assertEquals(5, entries.size()); + + BibtexEntry entry = entries.get(0); + Assert.assertEquals(null, entry.getField("subtitle")); + + entry = entries.get(1); + Assert.assertEquals("C", entry.getField("subtitle")); + + entry = entries.get(2); + Assert.assertEquals("Word", entry.getField("subtitle")); + + entry = entries.get(3); + Assert.assertEquals("Word1 word2", entry.getField("subtitle")); + + entry = entries.get(4); + Assert.assertEquals("Word1 word2", entry.getField("subtitle")); + } + } } diff --git a/src/test/resources/net/sf/jabref/importer/fetcher/gvk_artificial_subtitle_test.xml b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_artificial_subtitle_test.xml new file mode 100644 index 00000000000..2451e984f85 --- /dev/null +++ b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_artificial_subtitle_test.xml @@ -0,0 +1,75 @@ + + +1.1 +1 + + +picaxml +xml + + + + + + + +1 + + +picaxml +xml + + + + c + + + +2 + + +picaxml +xml + + + + word + + + +3 + + +picaxml +xml + + + + word1 word2 + + + +4 + + +picaxml +xml + + + + Word1 word2 + + + +5 + + + +1.1 +pica.all=797485368 +50 +xml +picaxml +Year,,1 + + \ No newline at end of file From e73da684348b579472eac35a7f18cc76353614b7 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Mon, 23 Nov 2015 14:58:19 +0100 Subject: [PATCH 08/12] Change package of XMLUtil --- .../java/net/sf/jabref/{util => logic/util/io}/XMLUtil.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) rename src/main/java/net/sf/jabref/{util => logic/util/io}/XMLUtil.java (89%) diff --git a/src/main/java/net/sf/jabref/util/XMLUtil.java b/src/main/java/net/sf/jabref/logic/util/io/XMLUtil.java similarity index 89% rename from src/main/java/net/sf/jabref/util/XMLUtil.java rename to src/main/java/net/sf/jabref/logic/util/io/XMLUtil.java index ff79a95226b..5ed3d3e198d 100644 --- a/src/main/java/net/sf/jabref/util/XMLUtil.java +++ b/src/main/java/net/sf/jabref/logic/util/io/XMLUtil.java @@ -1,4 +1,4 @@ -package net.sf.jabref.util; +package net.sf.jabref.logic.util.io; import java.io.StringWriter; @@ -21,6 +21,9 @@ public class XMLUtil { private static final Log LOGGER = LogFactory.getLog(XMLUtil.class); + /** + * Prints out the document to standard out. Used to generate files for test cases. + */ public static void printDocument(Document doc) { // code by http://stackoverflow.com/a/10356322/873282 try { From 51c0c1a2e0fbfd0eb35b6e82d6705821a29ffa7b Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Mon, 23 Nov 2015 19:42:05 +0100 Subject: [PATCH 09/12] Introduce canonical BibTeX format and create BibtexEntryAssert * adapt GVKParserTest accordingly * use Guava Strings.isNullOrEmpty in hasCiteKey and getFieldOrAlias * fix UTF-8 encoding in test cases --- .../sf/jabref/model/entry/BibtexEntry.java | 52 +++++++++++--- .../sf/jabref/bibtex/BibtexEntryAssert.java | 67 +++++++++++++++++++ .../net/sf/jabref/bibtex/BibtexEntryUtil.java | 42 ------------ .../importer/fetcher/GVKParserTest.java | 4 +- .../jabref/model/entry/BibtexEntryTests.java | 29 ++++++++ .../sf/jabref/importer/fetcher/gvk_gmp.1.bib | 4 +- .../sf/jabref/importer/fetcher/gvk_gmp.2.bib | 2 +- .../sf/jabref/importer/fetcher/gvk_gmp.xml | 2 +- 8 files changed, 146 insertions(+), 56 deletions(-) create mode 100644 src/test/java/net/sf/jabref/bibtex/BibtexEntryAssert.java delete mode 100644 src/test/java/net/sf/jabref/bibtex/BibtexEntryUtil.java diff --git a/src/main/java/net/sf/jabref/model/entry/BibtexEntry.java b/src/main/java/net/sf/jabref/model/entry/BibtexEntry.java index eb94b1f5ab2..7d0d7546024 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibtexEntry.java +++ b/src/main/java/net/sf/jabref/model/entry/BibtexEntry.java @@ -26,17 +26,20 @@ import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; +import java.util.Formatter; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.SortedSet; import java.util.TreeSet; -import java.util.regex.Pattern; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.google.common.base.Strings; + import net.sf.jabref.model.database.BibtexDatabase; public class BibtexEntry { @@ -190,7 +193,7 @@ public String getField(String name) { public String getFieldOrAlias(String name) { String fieldValue = getField(name); - if ((fieldValue != null) && !fieldValue.isEmpty()) { + if (!Strings.isNullOrEmpty(fieldValue)) { return fieldValue; } @@ -279,10 +282,7 @@ public String getCiteKey() { } public boolean hasCiteKey() { - if(getCiteKey() == null || getCiteKey().isEmpty()) { - return false; - } - return true; + return !Strings.isNullOrEmpty(getCiteKey()); } /** @@ -420,9 +420,45 @@ public Object clone() { return clone; } + /** + * 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 + */ @Override public String toString() { - return getType().getName() + ':' + getCiteKey(); + StringBuilder sb = new StringBuilder(); + try (Formatter formatter = new Formatter(sb, Locale.US)) { + String citeKey = Strings.nullToEmpty(this.getCiteKey()); + formatter.format("@%s{%s,\n", this.getType().getName().toLowerCase(Locale.US), citeKey); + + // we have to introduce a new Map as fields are stored case-sensitive in JabRef (see https://github.com/koppor/jabref/issues/45). + Map mapFieldToValue = new HashMap<>(); + + // determine sorted fields -- all fields lower case + SortedSet sortedFields = new TreeSet<>(); + for (String fieldName : this.getFieldNames()) { + // JabRef stores the key in the field KEY_FIELD, which must not be serialized + if (!fieldName.equals(KEY_FIELD)) { + String lowerCaseFieldName = fieldName.toLowerCase(Locale.US); + sortedFields.add(lowerCaseFieldName); + mapFieldToValue.put(lowerCaseFieldName, this.getField(fieldName)); + } + } + + for (String fieldName : sortedFields) { + formatter.format(" %s = {%s},\n", fieldName, mapFieldToValue.get(fieldName)); + } + + if (!sortedFields.isEmpty()) { + // remove last "," + sb.deleteCharAt(sb.length() - 2); + } + + sb.append("}"); + } + return sb.toString(); } public boolean isSearchHit() { diff --git a/src/test/java/net/sf/jabref/bibtex/BibtexEntryAssert.java b/src/test/java/net/sf/jabref/bibtex/BibtexEntryAssert.java new file mode 100644 index 00000000000..37d2bd7d4fd --- /dev/null +++ b/src/test/java/net/sf/jabref/bibtex/BibtexEntryAssert.java @@ -0,0 +1,67 @@ +package net.sf.jabref.bibtex; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.UnsupportedEncodingException; + +import org.junit.Assert; + +import net.sf.jabref.importer.ParserResult; +import net.sf.jabref.importer.fetcher.GVKParser; +import net.sf.jabref.importer.fileformat.BibtexParser; +import net.sf.jabref.model.entry.BibtexEntry; + +public class BibtexEntryAssert { + + /** + * Reads a single entry from the resource using `getResourceAsStream` from the given class. The resource has to + * contain a single entry + * + * @param clazz the class where to call `getResourceAsStream` + * @param resourceName the resource to read + * @param entry the entry to compare with + */ + public static void assertEquals(Class clazz, String resourceName, BibtexEntry entry) + throws IOException { + Assert.assertNotNull(clazz); + Assert.assertNotNull(resourceName); + Assert.assertNotNull(entry); + try (InputStream shouldBeIs = clazz.getResourceAsStream(resourceName)) { + BibtexEntryAssert.assertEquals(shouldBeIs, entry); + } + + } + + /** + * Reads a bibtex database from the given InputStream. The result has to contain a single BibtexEntry. This entry is + * compared to the given entry + * + * @param shouldBeIs the inputStream reading the entry from + * @param entry the entry to compare with + */ + public static void assertEquals(InputStream shouldBeIs, BibtexEntry entry) + throws UnsupportedEncodingException, IOException { + Assert.assertNotNull(shouldBeIs); + Assert.assertNotNull(entry); + ParserResult result; + try (Reader reader = new InputStreamReader(shouldBeIs, "UTF-8")) { + BibtexParser parser = new BibtexParser(reader); + result = parser.parse(); + } + Assert.assertNotNull(result); + Assert.assertNotEquals(ParserResult.INVALID_FORMAT, result); + Assert.assertEquals(1, result.getDatabase().getEntryCount()); + BibtexEntry shouldBeEntry = result.getDatabase().getEntries().iterator().next(); + assertEquals(shouldBeEntry, entry); + } + + /** + * Compares to BibTeX entries using their canonical representation + */ + private static void assertEquals(BibtexEntry shouldBeEntry, BibtexEntry entry) { + // use the canonical string representation to compare the entries + Assert.assertEquals(shouldBeEntry.toString(), entry.toString()); + } +} diff --git a/src/test/java/net/sf/jabref/bibtex/BibtexEntryUtil.java b/src/test/java/net/sf/jabref/bibtex/BibtexEntryUtil.java deleted file mode 100644 index af88a487a9e..00000000000 --- a/src/test/java/net/sf/jabref/bibtex/BibtexEntryUtil.java +++ /dev/null @@ -1,42 +0,0 @@ -package net.sf.jabref.bibtex; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.StringWriter; - -import org.junit.Assert; - -import com.google.common.base.Charsets; -import com.google.common.io.CharStreams; - -import net.sf.jabref.exporter.LatexFieldFormatter; -import net.sf.jabref.importer.fetcher.GVKParser; -import net.sf.jabref.model.entry.BibtexEntry; - -public class BibtexEntryUtil { - - private final static BibtexEntryWriter writer = new BibtexEntryWriter(new LatexFieldFormatter(), true); - - - public static String bibtexEntryToString(BibtexEntry entry) { - StringWriter stringWriter = new StringWriter(); - try { - writer.write(entry, stringWriter); - } catch (IOException e) { - // Quick hack as this should never happen - return "ERROR: " + e.getMessage(); - } - return stringWriter.toString(); - } - - public static void doAssertEquals(Class clazz, String resourceName, BibtexEntry entry) - throws IOException { - try (InputStream shouldBeIs = clazz.getResourceAsStream(resourceName)) { - Assert.assertNotNull(shouldBeIs); - String shouldBeEntry = CharStreams.toString(new InputStreamReader(shouldBeIs, Charsets.UTF_8)); - Assert.assertEquals(shouldBeEntry, BibtexEntryUtil.bibtexEntryToString(entry)); - } - - } -} diff --git a/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java b/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java index 155a6c0e3bf..b10376e0484 100644 --- a/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java +++ b/src/test/java/net/sf/jabref/importer/fetcher/GVKParserTest.java @@ -12,7 +12,7 @@ import org.junit.Test; import org.xml.sax.SAXException; -import net.sf.jabref.bibtex.BibtexEntryUtil; +import net.sf.jabref.bibtex.BibtexEntryAssert; import net.sf.jabref.model.entry.BibtexEntry; public class GVKParserTest { @@ -26,7 +26,7 @@ private void doTest(String xmlName, int expectedSize, List resourceNames Assert.assertEquals(expectedSize, entries.size()); int i = 0; for (String resourceName : resourceNames) { - BibtexEntryUtil.doAssertEquals(GVKParser.class, resourceName, entries.get(i)); + BibtexEntryAssert.assertEquals(GVKParser.class, resourceName, entries.get(i)); i++; } } diff --git a/src/test/java/net/sf/jabref/model/entry/BibtexEntryTests.java b/src/test/java/net/sf/jabref/model/entry/BibtexEntryTests.java index ae9b92d688b..be76e499b6d 100644 --- a/src/test/java/net/sf/jabref/model/entry/BibtexEntryTests.java +++ b/src/test/java/net/sf/jabref/model/entry/BibtexEntryTests.java @@ -20,6 +20,7 @@ public void setup() { @Test public void testDefaultConstructor() { + @SuppressWarnings("unused") BibtexEntry entry = new BibtexEntry(); } @@ -90,4 +91,32 @@ public void hasAllRequiredFields() { e.setField("year", "2015"); Assert.assertTrue(e.hasAllRequiredFields(null)); } + + @Test + public void isNullOrEmptyCiteKey() { + BibtexEntry e = new BibtexEntry("id", BibtexEntryTypes.ARTICLE); + Assert.assertFalse(e.hasCiteKey()); + e.setField(BibtexEntry.KEY_FIELD, ""); + Assert.assertFalse(e.hasCiteKey()); + e.setField(BibtexEntry.KEY_FIELD, null); + Assert.assertFalse(e.hasCiteKey()); + e.setField(BibtexEntry.KEY_FIELD, "key"); + Assert.assertTrue(e.hasCiteKey()); + e.clearField(BibtexEntry.KEY_FIELD); + Assert.assertFalse(e.hasCiteKey()); + } + + /** + * Simple test for the canonical format + */ + @Test + public void canonicalFormat() { + BibtexEntry e = new BibtexEntry("id", BibtexEntryTypes.ARTICLE); + e.setField(BibtexEntry.KEY_FIELD, "key"); + e.setField("author", "abc"); + e.setField("title", "def"); + e.setField("journal", "hij"); + String canonicalForm = e.toString(); + Assert.assertEquals("@article{key,\n author = {abc},\n journal = {hij},\n title = {def}\n}", canonicalForm); + } } diff --git a/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.1.bib b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.1.bib index f723a14d859..6adf1682c64 100644 --- a/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.1.bib +++ b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.1.bib @@ -1,6 +1,6 @@ @Book{, - Title = {GMP-Regelwerke für Arzneimittel}, - Publisher = {Maas \& Peither, GMP-Verl.}, + Title = {GMP-Regelwerke für Arzneimittel}, + Publisher = {Maas & Peither, GMP-Verl.}, Address = {Schopfheim}, Edition = {7., aktualisierte Aufl.}, Note = {Text teilw. dt., teilw. engl.}, diff --git a/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.2.bib b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.2.bib index 4b09eec3e8a..1a678c0eddf 100644 --- a/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.2.bib +++ b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.2.bib @@ -1,6 +1,6 @@ @Book{, Title = {GMP-Regelwerke für computergestützte Systeme}, - Publisher = {Maas \& Peither, GMP-Verl}, + Publisher = {Maas & Peither, GMP-Verl}, Address = {Schopfheim}, Edition = {4., aktual. Aufl.}, Note = {Text teilw. dt. und engl}, diff --git a/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.xml b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.xml index 1eb2cf49d02..d5b96f19b7b 100644 --- a/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.xml +++ b/src/test/resources/net/sf/jabref/importer/fetcher/gvk_gmp.xml @@ -90,7 +90,7 @@ XA-DE - GMP-Regelwerke f�r Arzneimittel + GMP-Regelwerke für Arzneimittel 7., aktualisierte Aufl. From bee6637c2c87abb9090c00a50aefc5d0e3dad52b Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Sun, 22 Nov 2015 01:09:45 +0100 Subject: [PATCH 10/12] Change label of GVK Fetcher We use the German description instead of "GVK (Common Union Catalogue)" as GVK is typically used in Germany and (currently) the help file states the English translation. --- src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java b/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java index 1fdda3bbb4d..136a576afa7 100644 --- a/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java +++ b/src/main/java/net/sf/jabref/importer/fetcher/GVKFetcher.java @@ -71,7 +71,7 @@ public JPanel getOptionsPanel() { @Override public String getTitle() { - return "GVKFetcher"; + return "GVK (Gemeinsamer Verbundkatalog)"; } @Override From a1430d7ee741d64c0cf51e1c61070344befc0b6a Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Tue, 24 Nov 2015 00:22:41 +0100 Subject: [PATCH 11/12] Move BibtexEntry.toString() to CanonicalBibtexEntry.getCanonicalRepresentation(e) --- .../sf/jabref/model/entry/BibtexEntry.java | 35 +----------- .../model/entry/CanonicalBibtexEntry.java | 54 +++++++++++++++++++ .../sf/jabref/bibtex/BibtexEntryAssert.java | 4 +- .../jabref/model/entry/BibtexEntryTests.java | 13 ----- .../model/entry/CanonicalBibtexEntryTest.java | 23 ++++++++ 5 files changed, 81 insertions(+), 48 deletions(-) create mode 100644 src/main/java/net/sf/jabref/model/entry/CanonicalBibtexEntry.java create mode 100644 src/test/java/net/sf/jabref/model/entry/CanonicalBibtexEntryTest.java diff --git a/src/main/java/net/sf/jabref/model/entry/BibtexEntry.java b/src/main/java/net/sf/jabref/model/entry/BibtexEntry.java index 51521f0acb4..a2154dc1953 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibtexEntry.java +++ b/src/main/java/net/sf/jabref/model/entry/BibtexEntry.java @@ -26,14 +26,11 @@ import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; -import java.util.Formatter; import java.util.HashMap; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; -import java.util.SortedSet; import java.util.TreeSet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -431,37 +428,7 @@ public Object clone() { */ @Override public String toString() { - StringBuilder sb = new StringBuilder(); - try (Formatter formatter = new Formatter(sb, Locale.US)) { - String citeKey = Strings.nullToEmpty(this.getCiteKey()); - formatter.format("@%s{%s,\n", this.getType().getName().toLowerCase(Locale.US), citeKey); - - // we have to introduce a new Map as fields are stored case-sensitive in JabRef (see https://github.com/koppor/jabref/issues/45). - Map mapFieldToValue = new HashMap<>(); - - // determine sorted fields -- all fields lower case - SortedSet sortedFields = new TreeSet<>(); - for (String fieldName : this.getFieldNames()) { - // JabRef stores the key in the field KEY_FIELD, which must not be serialized - if (!fieldName.equals(KEY_FIELD)) { - String lowerCaseFieldName = fieldName.toLowerCase(Locale.US); - sortedFields.add(lowerCaseFieldName); - mapFieldToValue.put(lowerCaseFieldName, this.getField(fieldName)); - } - } - - for (String fieldName : sortedFields) { - formatter.format(" %s = {%s},\n", fieldName, mapFieldToValue.get(fieldName)); - } - - if (!sortedFields.isEmpty()) { - // remove last "," - sb.deleteCharAt(sb.length() - 2); - } - - sb.append("}"); - } - return sb.toString(); + return CanonicalBibtexEntry.getCanonicalRepresentation(this); } public boolean isSearchHit() { diff --git a/src/main/java/net/sf/jabref/model/entry/CanonicalBibtexEntry.java b/src/main/java/net/sf/jabref/model/entry/CanonicalBibtexEntry.java new file mode 100644 index 00000000000..05db26a80bd --- /dev/null +++ b/src/main/java/net/sf/jabref/model/entry/CanonicalBibtexEntry.java @@ -0,0 +1,54 @@ +package net.sf.jabref.model.entry; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.SortedSet; +import java.util.StringJoiner; +import java.util.TreeSet; + +import com.google.common.base.Strings; + +public class 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(BibtexEntry e) { + StringBuilder sb = new StringBuilder(); + + // generate first line: type and bibtex key + String citeKey = Strings.nullToEmpty(e.getCiteKey()); + sb.append(String.format("@%s{%s,\n", e.getType().getName().toLowerCase(Locale.US), citeKey)); + + // we have to introduce a new Map as fields are stored case-sensitive in JabRef (see https://github.com/koppor/jabref/issues/45). + Map mapFieldToValue = new HashMap<>(); + + // determine sorted fields -- all fields lower case + SortedSet sortedFields = new TreeSet<>(); + for (String fieldName : e.getFieldNames()) { + // JabRef stores the key in the field KEY_FIELD, which must not be serialized + if (!fieldName.equals(BibtexEntry.KEY_FIELD)) { + String lowerCaseFieldName = fieldName.toLowerCase(Locale.US); + sortedFields.add(lowerCaseFieldName); + mapFieldToValue.put(lowerCaseFieldName, e.getField(fieldName)); + } + } + + // generate field entries + StringJoiner sj = new StringJoiner(",\n", "", "\n"); + for (String fieldName : sortedFields) { + String line = String.format(" %s = {%s}", fieldName, mapFieldToValue.get(fieldName)); + sj.add(line); + } + sb.append(sj.toString()); + + // append the closing entry bracket + sb.append("}"); + return sb.toString(); + } + +} diff --git a/src/test/java/net/sf/jabref/bibtex/BibtexEntryAssert.java b/src/test/java/net/sf/jabref/bibtex/BibtexEntryAssert.java index 37d2bd7d4fd..6993e1eaf99 100644 --- a/src/test/java/net/sf/jabref/bibtex/BibtexEntryAssert.java +++ b/src/test/java/net/sf/jabref/bibtex/BibtexEntryAssert.java @@ -12,6 +12,7 @@ import net.sf.jabref.importer.fetcher.GVKParser; import net.sf.jabref.importer.fileformat.BibtexParser; import net.sf.jabref.model.entry.BibtexEntry; +import net.sf.jabref.model.entry.CanonicalBibtexEntry; public class BibtexEntryAssert { @@ -62,6 +63,7 @@ public static void assertEquals(InputStream shouldBeIs, BibtexEntry entry) */ private static void assertEquals(BibtexEntry shouldBeEntry, BibtexEntry entry) { // use the canonical string representation to compare the entries - Assert.assertEquals(shouldBeEntry.toString(), entry.toString()); + Assert.assertEquals(CanonicalBibtexEntry.getCanonicalRepresentation(shouldBeEntry), + CanonicalBibtexEntry.getCanonicalRepresentation(entry)); } } diff --git a/src/test/java/net/sf/jabref/model/entry/BibtexEntryTests.java b/src/test/java/net/sf/jabref/model/entry/BibtexEntryTests.java index be76e499b6d..520558ee7b7 100644 --- a/src/test/java/net/sf/jabref/model/entry/BibtexEntryTests.java +++ b/src/test/java/net/sf/jabref/model/entry/BibtexEntryTests.java @@ -106,17 +106,4 @@ public void isNullOrEmptyCiteKey() { Assert.assertFalse(e.hasCiteKey()); } - /** - * Simple test for the canonical format - */ - @Test - public void canonicalFormat() { - BibtexEntry e = new BibtexEntry("id", BibtexEntryTypes.ARTICLE); - e.setField(BibtexEntry.KEY_FIELD, "key"); - e.setField("author", "abc"); - e.setField("title", "def"); - e.setField("journal", "hij"); - String canonicalForm = e.toString(); - Assert.assertEquals("@article{key,\n author = {abc},\n journal = {hij},\n title = {def}\n}", canonicalForm); - } } diff --git a/src/test/java/net/sf/jabref/model/entry/CanonicalBibtexEntryTest.java b/src/test/java/net/sf/jabref/model/entry/CanonicalBibtexEntryTest.java new file mode 100644 index 00000000000..f4a44733c2a --- /dev/null +++ b/src/test/java/net/sf/jabref/model/entry/CanonicalBibtexEntryTest.java @@ -0,0 +1,23 @@ +package net.sf.jabref.model.entry; + +import org.junit.Assert; +import org.junit.Test; + +public class CanonicalBibtexEntryTest { + + /** + * Simple test for the canonical format + */ + @Test + public void canonicalRepresentation() { + BibtexEntry e = new BibtexEntry("id", BibtexEntryTypes.ARTICLE); + e.setField(BibtexEntry.KEY_FIELD, "key"); + e.setField("author", "abc"); + e.setField("title", "def"); + e.setField("journal", "hij"); + String canonicalRepresentation = CanonicalBibtexEntry.getCanonicalRepresentation(e); + Assert.assertEquals("@article{key,\n author = {abc},\n journal = {hij},\n title = {def}\n}", + canonicalRepresentation); + } + +} From 1776bb678cbf4f963a15249a3a6543a6ac097c3b Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Tue, 24 Nov 2015 00:49:53 +0100 Subject: [PATCH 12/12] Honor biblatex mode at default constructor --- src/main/java/net/sf/jabref/bibtex/EntryTypes.java | 13 ++----------- .../java/net/sf/jabref/model/entry/BibtexEntry.java | 3 ++- .../net/sf/jabref/model/entry/BibtexEntryTests.java | 6 +++++- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/main/java/net/sf/jabref/bibtex/EntryTypes.java b/src/main/java/net/sf/jabref/bibtex/EntryTypes.java index 25a8c92b5fa..d071583e381 100644 --- a/src/main/java/net/sf/jabref/bibtex/EntryTypes.java +++ b/src/main/java/net/sf/jabref/bibtex/EntryTypes.java @@ -74,11 +74,7 @@ private static void initBibtexEntryTypes() { * or null if it does not exist. */ public static EntryType getType(String name) { - EntryType entryType = ALL_TYPES.get(name.toLowerCase()); - if (entryType == null) { - return null; - } - return entryType; + return ALL_TYPES.get(name.toLowerCase()); } /** @@ -86,12 +82,7 @@ public static EntryType getType(String name) { * name of a type, or null if it does not exist. */ public static EntryType getStandardType(String name) { - EntryType entryType = STANDARD_TYPES.get(name.toLowerCase()); - if (entryType == null) { - return null; - } else { - return entryType; - } + return STANDARD_TYPES.get(name.toLowerCase()); } public static void addOrModifyCustomEntryType(CustomEntryType type) { diff --git a/src/main/java/net/sf/jabref/model/entry/BibtexEntry.java b/src/main/java/net/sf/jabref/model/entry/BibtexEntry.java index a2154dc1953..7f7fc5e20fd 100644 --- a/src/main/java/net/sf/jabref/model/entry/BibtexEntry.java +++ b/src/main/java/net/sf/jabref/model/entry/BibtexEntry.java @@ -37,6 +37,7 @@ import com.google.common.base.Strings; +import net.sf.jabref.bibtex.EntryTypes; import net.sf.jabref.model.database.BibtexDatabase; public class BibtexEntry { @@ -65,7 +66,7 @@ public BibtexEntry() { } public BibtexEntry(String id) { - this(id, BibtexEntryTypes.MISC); + this(id, EntryTypes.getBibtexEntryType("misc")); } public BibtexEntry(String id, EntryType type) { diff --git a/src/test/java/net/sf/jabref/model/entry/BibtexEntryTests.java b/src/test/java/net/sf/jabref/model/entry/BibtexEntryTests.java index 520558ee7b7..7ec9813f74a 100644 --- a/src/test/java/net/sf/jabref/model/entry/BibtexEntryTests.java +++ b/src/test/java/net/sf/jabref/model/entry/BibtexEntryTests.java @@ -7,6 +7,7 @@ import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; +import net.sf.jabref.bibtex.EntryTypes; import net.sf.jabref.importer.fileformat.BibtexParser; import java.util.ArrayList; @@ -20,8 +21,11 @@ public void setup() { @Test public void testDefaultConstructor() { - @SuppressWarnings("unused") BibtexEntry entry = new BibtexEntry(); + // we have to use `getType("misc")` in the case of biblatex mode + Assert.assertEquals(EntryTypes.getType("misc"), entry.getType()); + Assert.assertNotNull(entry.getId()); + Assert.assertNull(entry.getField("author")); } @Test