From 41d15510cf3ba893e1a8254dedab995ecc43371d Mon Sep 17 00:00:00 2001 From: Linus Dietz Date: Tue, 21 Feb 2017 17:31:22 +0100 Subject: [PATCH 1/8] [WIP] Refactored around the FileAnnotationCache. (#2557) * Refactored quite much around the FileAnnotationCache. The Cache now works as intended, i.e., fully automatically instead of manual maintenance. * Reverted an incorrect renaming. * Reverted an incorrect renaming to the original * Fixed wrong locale message * fixing @koppor's remarks * fixed imports, consitent naming * minor change --- src/main/java/org/jabref/gui/BasePanel.java | 2 +- .../jabref/gui/entryeditor/EntryEditor.java | 256 ++++++++++-------- .../gui/entryeditor/FileAnnotationTab.java | 224 +++++++-------- .../jabref/logic/pdf/AnnotationImporter.java | 11 + .../logic/pdf/EntryAnnotationImporter.java | 54 ++++ .../jabref/logic/pdf/FileAnnotationCache.java | 27 +- ...erImpl.java => PdfAnnotationImporter.java} | 29 +- .../org/jabref/model/pdf/FileAnnotation.java | 14 +- 8 files changed, 330 insertions(+), 287 deletions(-) create mode 100644 src/main/java/org/jabref/logic/pdf/AnnotationImporter.java create mode 100644 src/main/java/org/jabref/logic/pdf/EntryAnnotationImporter.java rename src/main/java/org/jabref/logic/pdf/{PdfAnnotationImporterImpl.java => PdfAnnotationImporter.java} (88%) diff --git a/src/main/java/org/jabref/gui/BasePanel.java b/src/main/java/org/jabref/gui/BasePanel.java index b53fab464e3..a163d9c6db1 100644 --- a/src/main/java/org/jabref/gui/BasePanel.java +++ b/src/main/java/org/jabref/gui/BasePanel.java @@ -206,7 +206,7 @@ public BasePanel(JabRefFrame frame, BibDatabaseContext bibDatabaseContext) { this.tableModel = new MainTableDataModel(getBibDatabaseContext()); citationStyleCache = new CitationStyleCache(bibDatabaseContext); - annotationCache = new FileAnnotationCache(); + annotationCache = new FileAnnotationCache(bibDatabaseContext); setupMainPanel(); diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java index 401590ec466..a6fc2a3b5d9 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java @@ -26,6 +26,7 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; import javax.swing.AbstractAction; @@ -128,30 +129,50 @@ public class EntryEditor extends JPanel implements EntryContainer { private static final Log LOGGER = LogFactory.getLog(EntryEditor.class); - /** A reference to the entry this object works on. */ + /** + * A reference to the entry this object works on. + */ private final BibEntry entry; - /** The currently displayed type */ + /** + * The currently displayed type + */ private final String displayedBibEntryType; - /** The action concerned with closing the window. */ + /** + * The action concerned with closing the window. + */ private final CloseAction closeAction = new CloseAction(); - /** The action that deletes the current entry, and closes the editor. */ + /** + * The action that deletes the current entry, and closes the editor. + */ private final DeleteAction deleteAction = new DeleteAction(); - /** The action for switching to the next entry. */ + /** + * The action for switching to the next entry. + */ private final AbstractAction nextEntryAction = new NextEntryAction(); - /** The action for switching to the previous entry. */ + /** + * The action for switching to the previous entry. + */ private final AbstractAction prevEntryAction = new PrevEntryAction(); - /** The action concerned with storing a field value. */ + /** + * The action concerned with storing a field value. + */ private final StoreFieldAction storeFieldAction = new StoreFieldAction(); - /** The action for switching to the next tab */ + /** + * The action for switching to the next tab + */ private final SwitchLeftAction switchLeftAction = new SwitchLeftAction(); - /** The action for switching to the previous tab */ + /** + * The action for switching to the previous tab + */ private final SwitchRightAction switchRightAction = new SwitchRightAction(); - /** The action which generates a BibTeX key for this entry. */ + /** + * The action which generates a BibTeX key for this entry. + */ private final GenerateKeyAction generateKeyAction = new GenerateKeyAction(); // UGLY HACK to have a pointer to the fileListEditor to call autoSetLinks() @@ -160,8 +181,6 @@ public class EntryEditor extends JPanel implements EntryContainer { private final AbstractAction writeXmp; - private final SaveDatabaseAction saveDatabaseAction = new SaveDatabaseAction(); - private final JPanel srcPanel = new JPanel(); private final JPanel relatedArticlePanel = new JPanel(); @@ -184,7 +203,9 @@ public class EntryEditor extends JPanel implements EntryContainer { * source couldn't be parsed, and the user is given the option to edit it. */ private boolean updateSource = true; - /** Indicates that we are about to go to the next or previous entry */ + /** + * Indicates that we are about to go to the next or previous entry + */ private boolean movingToDifferentEntry; private boolean validEntry = true; @@ -194,26 +215,29 @@ public class EntryEditor extends JPanel implements EntryContainer { private boolean lastFieldAccepted = true; /** - * This indicates whether the last attempt at parsing the source was successful. It is used to determine whether - * the dialog should close; it should stay open if the user received an error message about the source, - * whatever he or she chose to do about it. + * This indicates whether the last attempt at parsing the source was successful. It is used to determine whether + * the dialog should close; it should stay open if the user received an error message about the source, + * whatever he or she chose to do about it. */ private boolean lastSourceAccepted = true; - /** This is used to prevent double updates after editing source. */ + /** + * This is used to prevent double updates after editing source. + */ private String lastSourceStringAccepted; - /** The index the source panel has in tabbed. */ + /** + * The index the source panel has in tabbed. + */ private int sourceIndex = -1; private final HelpAction helpAction = new HelpAction(HelpFile.ENTRY_EDITOR, IconTheme.JabRefIcon.HELP.getIcon()); - private final UndoAction undoAction = new UndoAction(); - private final RedoAction redoAction = new RedoAction(); + private Action saveDatabaseAction; - private final TabListener tabListener = new TabListener(); + private final TabListener tabListener = new TabListener(); private final List searchListeners = new ArrayList<>(); public EntryEditor(JabRefFrame frame, BasePanel panel, BibEntry entry) { @@ -331,7 +355,7 @@ private void setupFieldPanels() { addSpecialTabs(); // pdf annotations tab - addPdfTab(); + addPDFAnnotationTab(); //related articles if (Globals.prefs.getBoolean(JabRefPreferences.SHOW_RECOMMENDATIONS)) { @@ -439,27 +463,24 @@ private void addOptionalTab(EntryType type) { fileListEditor = optionalPanel.fileListEditor; } tabbed.addTab(Localization.lang("Optional fields"), IconTheme.JabRefIcon.OPTIONAL.getSmallIcon(), - optionalPanel - .getPane(), - Localization.lang("Show optional fields")); + optionalPanel.getPane(), Localization.lang("Show optional fields")); tabs.add(optionalPanel); } /** * Add a tab for displaying comments from a PDF */ - private void addPdfTab() { + private void addPDFAnnotationTab() { tabbed.remove(fileAnnotationTab); tabs.remove(fileAnnotationTab); Optional field = entry.getField(FieldName.FILE); if (field.isPresent()) { - fileAnnotationTab = new FileAnnotationTab(this, panel, tabbed); - tabbed.addTab(Localization.lang("File annotations"), IconTheme.JabRefIcon.COMMENT.getSmallIcon(), - fileAnnotationTab, + fileAnnotationTab = new FileAnnotationTab(this); + tabbed.addTab(Localization.lang("File annotations"), IconTheme.JabRefIcon.OPTIONAL.getSmallIcon(), fileAnnotationTab, + Localization.lang("Show file annotations")); tabs.add(fileAnnotationTab); } - } public String getDisplayedBibEntryType() { @@ -495,21 +516,21 @@ private void setupToolBar() { inputMap.put(Globals.getKeyPrefs().getKey(KeyBinding.CLOSE_ENTRY_EDITOR), "close"); actionMap.put("close", closeAction); inputMap.put(Globals.getKeyPrefs().getKey(KeyBinding.ENTRY_EDITOR_STORE_FIELD), "store"); - actionMap.put("store", getStoreFieldAction()); + actionMap.put("store", storeFieldAction); inputMap.put(Globals.getKeyPrefs().getKey(KeyBinding.AUTOGENERATE_BIBTEX_KEYS), "generateKey"); - actionMap.put("generateKey", getGenerateKeyAction()); + actionMap.put("generateKey", generateKeyAction); inputMap.put(Globals.getKeyPrefs().getKey(KeyBinding.AUTOMATICALLY_LINK_FILES), "autoLink"); actionMap.put("autoLink", autoLinkAction); inputMap.put(Globals.getKeyPrefs().getKey(KeyBinding.ENTRY_EDITOR_PREVIOUS_ENTRY), "prev"); - actionMap.put("prev", getPrevEntryAction()); + actionMap.put("prev", prevEntryAction); inputMap.put(Globals.getKeyPrefs().getKey(KeyBinding.ENTRY_EDITOR_NEXT_ENTRY), "next"); - actionMap.put("next", getNextEntryAction()); + actionMap.put("next", nextEntryAction); inputMap.put(Globals.getKeyPrefs().getKey(KeyBinding.UNDO), "undo"); actionMap.put("undo", undoAction); inputMap.put(Globals.getKeyPrefs().getKey(KeyBinding.REDO), "redo"); actionMap.put("redo", redoAction); inputMap.put(Globals.getKeyPrefs().getKey(KeyBinding.HELP), "help"); - actionMap.put("help", getHelpAction()); + actionMap.put("help", helpAction); toolBar.setFloatable(false); @@ -526,12 +547,13 @@ private void setupToolBar() { TypeButton typeButton = new TypeButton(); toolBar.add(typeButton); - toolBar.add(getGenerateKeyAction()); + toolBar.add(generateKeyAction); toolBar.add(autoLinkAction); toolBar.add(writeXmp); JPopupMenu fetcherPopup = new JPopupMenu(); + for (EntryBasedFetcher fetcher : EntryFetchers .getEntryBasedFetchers(Globals.prefs.getImportFormatPreferences())) { fetcherPopup.add(new JMenuItem(new AbstractAction(fetcher.getName()) { @@ -556,12 +578,12 @@ public void mousePressed(MouseEvent e) { toolBar.addSeparator(); toolBar.add(deleteAction); - toolBar.add(getPrevEntryAction()); - toolBar.add(getNextEntryAction()); + toolBar.add(prevEntryAction); + toolBar.add(nextEntryAction); toolBar.addSeparator(); - toolBar.add(getHelpAction()); + toolBar.add(helpAction); Component[] comps = toolBar.getComponents(); @@ -614,11 +636,10 @@ public Optional getExtra(final FieldEditor editor) { // Add controls for switching between abbreviated and full journal names. // If this field also has a FieldContentSelector, we need to combine these. return FieldExtraComponents.getJournalExtraComponent(frame, panel, editor, entry, contentSelectors, - getStoreFieldAction()); + storeFieldAction); } else if (!panel.getBibDatabaseContext().getMetaData().getContentSelectorValuesForField(fieldName).isEmpty()) { return FieldExtraComponents.getSelectorExtraComponent(frame, panel, editor, contentSelectors, - getStoreFieldAction()); - + storeFieldAction); } else if (fieldExtras.contains(FieldProperty.DOI)) { return FieldExtraComponents.getDoiExtraComponent(panel, this, editor); } else if (fieldExtras.contains(FieldProperty.EPRINT)) { @@ -626,7 +647,7 @@ public Optional getExtra(final FieldEditor editor) { } else if (fieldExtras.contains(FieldProperty.ISBN)) { return FieldExtraComponents.getIsbnExtraComponent(panel, this, editor); } else if (fieldExtras.contains(FieldProperty.OWNER)) { - return FieldExtraComponents.getSetOwnerExtraComponent(editor, getStoreFieldAction()); + return FieldExtraComponents.getSetOwnerExtraComponent(editor, storeFieldAction); } else if (fieldExtras.contains(FieldProperty.YES_NO)) { return FieldExtraComponents.getYesNoExtraComponent(editor, this); } else if (fieldExtras.contains(FieldProperty.MONTH)) { @@ -692,7 +713,6 @@ public void updateSource() { source.setEditable(false); LOGGER.debug("Incorrect entry", ex); } - } } @@ -716,18 +736,18 @@ private void setupJTextComponent(JTextComponent textComponent) { ActionMap actionMap = textComponent.getActionMap(); inputMap.put(Globals.getKeyPrefs().getKey(KeyBinding.ENTRY_EDITOR_STORE_FIELD), "store"); - actionMap.put("store", getStoreFieldAction()); + actionMap.put("store", storeFieldAction); inputMap.put(Globals.getKeyPrefs().getKey(KeyBinding.ENTRY_EDITOR_NEXT_PANEL), "right"); inputMap.put(Globals.getKeyPrefs().getKey(KeyBinding.ENTRY_EDITOR_NEXT_PANEL_2), "right"); - actionMap.put("right", getSwitchRightAction()); + actionMap.put("right", switchRightAction); inputMap.put(Globals.getKeyPrefs().getKey(KeyBinding.ENTRY_EDITOR_PREVIOUS_PANEL), "left"); inputMap.put(Globals.getKeyPrefs().getKey(KeyBinding.ENTRY_EDITOR_PREVIOUS_PANEL_2), "left"); - actionMap.put("left", getSwitchLeftAction()); + actionMap.put("left", switchLeftAction); inputMap.put(Globals.getKeyPrefs().getKey(KeyBinding.HELP), "help"); - actionMap.put("help", getHelpAction()); + actionMap.put("help", helpAction); inputMap.put(Globals.getKeyPrefs().getKey(KeyBinding.NEXT_TAB), "nexttab"); actionMap.put("nexttab", frame.nextTab); @@ -783,7 +803,6 @@ public void setEnabled(boolean enabled) { } } source.setEnabled(enabled); - } /** @@ -795,7 +814,7 @@ public void storeCurrentEdit() { if (comp instanceof FieldEditor) { ((FieldEditor) comp).clearAutoCompleteSuggestion(); } - getStoreFieldAction().actionPerformed(new ActionEvent(comp, 0, "")); + storeFieldAction.actionPerformed(new ActionEvent(comp, 0, "")); } } @@ -975,7 +994,6 @@ public void updateAllContentSelectors() { for (FieldContentSelector contentSelector : contentSelectors) { contentSelector.rebuildComboBox(); } - } } @@ -994,7 +1012,7 @@ public void listen(FieldChangedEvent fieldChangedEvent) { } public void updateField(final Object sourceObject) { - getStoreFieldAction().actionPerformed(new ActionEvent(sourceObject, 0, "")); + storeFieldAction.actionPerformed(new ActionEvent(sourceObject, 0, "")); } public void setMovingToDifferentEntry() { @@ -1007,9 +1025,40 @@ private void unregisterListeners() { removeSearchListeners(); } - private class TypeButton extends JButton { + public GenerateKeyAction getGenerateKeyAction() { + return generateKeyAction; + } + + public AbstractAction getPrevEntryAction() { + return prevEntryAction; + } + + public AbstractAction getNextEntryAction() { + return nextEntryAction; + } + + public StoreFieldAction getStoreFieldAction() { + return storeFieldAction; + } + + public SwitchLeftAction getSwitchLeftAction() { + return switchLeftAction; + } + + public SwitchRightAction getSwitchRightAction() { + return switchRightAction; + } - public TypeButton() { + public HelpAction getHelpAction() { + return helpAction; + } + + public Action getSaveDatabaseAction() { + return saveDatabaseAction; + } + + private class TypeButton extends JButton { + private TypeButton() { super(IconTheme.JabRefIcon.EDIT.getIcon()); setToolTipText(Localization.lang("Change entry type")); addActionListener(e -> showChangeEntryTypePopupMenu()); @@ -1022,8 +1071,7 @@ private void showChangeEntryTypePopupMenu() { } private class TypeLabel extends JLabel { - - public TypeLabel(String type) { + private TypeLabel(String type) { super(type); setUI(new VerticalLabelUI(false)); setForeground(GUIGlobals.ENTRY_EDITOR_LABEL_COLOR); @@ -1084,9 +1132,14 @@ public void stateChanged(ChangeEvent event) { Object activeTab = tabs.get(tabbed.getSelectedIndex()); if ((activeTab instanceof FileAnnotationTab) && !((FileAnnotationTab) activeTab).isInitialized()) { //Initialize by getting notes from cache if they are cached - FileAnnotationTab.initializeTab((FileAnnotationTab) activeTab, - panel.getAnnotationCache().getFromCache(Optional.of(entry))); - panel.getAnnotationCache().addToCache(entry, ((FileAnnotationTab) activeTab).getAllNotes()); + + FileAnnotationTab tab = (FileAnnotationTab) activeTab; + try { + tab.initializeTab(tab, + panel.getAnnotationCache().getFromCache(entry)); + } catch (ExecutionException e) { + tab.initializeTab((FileAnnotationTab) activeTab); + } } if (activeTab instanceof EntryEditorTab) { @@ -1102,9 +1155,9 @@ public void stateChanged(ChangeEvent event) { } } - class DeleteAction extends AbstractAction { - public DeleteAction() { + private class DeleteAction extends AbstractAction { + private DeleteAction() { super(Localization.lang("Delete"), IconTheme.JabRefIcon.DELETE_ENTRY.getIcon()); putValue(Action.SHORT_DESCRIPTION, Localization.lang("Delete entry")); } @@ -1145,9 +1198,10 @@ public void close() { } } - class CloseAction extends AbstractAction { - public CloseAction() { + private class CloseAction extends AbstractAction { + + private CloseAction() { super(Localization.lang("Close window"), IconTheme.JabRefIcon.CLOSE.getSmallIcon()); putValue(Action.SHORT_DESCRIPTION, Localization.lang("Close window")); } @@ -1158,7 +1212,7 @@ public void actionPerformed(ActionEvent e) { } } - class StoreFieldAction extends AbstractAction { + public class StoreFieldAction extends AbstractAction { public StoreFieldAction() { super("Store field value"); @@ -1292,7 +1346,6 @@ public void actionPerformed(ActionEvent event) { ce.end(); panel.getUndoManager().addEdit(ce); - } else { panel.getUndoManager().addEdit(undoableFieldChange); } @@ -1324,9 +1377,10 @@ public void actionPerformed(ActionEvent event) { } } - class SwitchLeftAction extends AbstractAction { - public SwitchLeftAction() { + private class SwitchLeftAction extends AbstractAction { + + private SwitchLeftAction() { super("Switch to the panel to the left"); } @@ -1339,9 +1393,10 @@ public void actionPerformed(ActionEvent e) { } } - class SwitchRightAction extends AbstractAction { - public SwitchRightAction() { + private class SwitchRightAction extends AbstractAction { + + private SwitchRightAction() { super("Switch to the panel to the right"); } @@ -1350,13 +1405,13 @@ public void actionPerformed(ActionEvent e) { int i = tabbed.getSelectedIndex(); tabbed.setSelectedIndex(i < (tabbed.getTabCount() - 1) ? i + 1 : 0); activateVisible(); - } } - class NextEntryAction extends AbstractAction { - public NextEntryAction() { + private class NextEntryAction extends AbstractAction { + + private NextEntryAction() { super(Localization.lang("Next entry"), IconTheme.JabRefIcon.DOWN.getIcon()); putValue(Action.SHORT_DESCRIPTION, Localization.lang("Next entry")); @@ -1368,9 +1423,10 @@ public void actionPerformed(ActionEvent e) { } } - class PrevEntryAction extends AbstractAction { - public PrevEntryAction() { + private class PrevEntryAction extends AbstractAction { + + private PrevEntryAction() { super(Localization.lang("Previous entry"), IconTheme.JabRefIcon.UP.getIcon()); putValue(Action.SHORT_DESCRIPTION, Localization.lang("Previous entry")); @@ -1382,13 +1438,12 @@ public void actionPerformed(ActionEvent e) { } } - class GenerateKeyAction extends AbstractAction { + private class GenerateKeyAction extends AbstractAction { - public GenerateKeyAction() { + private GenerateKeyAction() { super(Localization.lang("Generate BibTeX key"), IconTheme.JabRefIcon.MAKE_KEY.getIcon()); putValue(Action.SHORT_DESCRIPTION, Localization.lang("Generate BibTeX key")); - } @Override @@ -1443,9 +1498,9 @@ public void actionPerformed(ActionEvent e) { } } - class UndoAction extends AbstractAction { - public UndoAction() { + private class UndoAction extends AbstractAction { + private UndoAction() { super("Undo", IconTheme.JabRefIcon.UNDO.getIcon()); putValue(Action.SHORT_DESCRIPTION, "Undo"); } @@ -1456,9 +1511,9 @@ public void actionPerformed(ActionEvent e) { } } - class RedoAction extends AbstractAction { + private class RedoAction extends AbstractAction { - public RedoAction() { + private RedoAction() { super("Redo", IconTheme.JabRefIcon.REDO.getIcon()); putValue(Action.SHORT_DESCRIPTION, "Redo"); } @@ -1469,9 +1524,10 @@ public void actionPerformed(ActionEvent e) { } } - class SaveDatabaseAction extends AbstractAction { - public SaveDatabaseAction() { + private class SaveDatabaseAction extends AbstractAction { + + private SaveDatabaseAction() { super("Save library"); } @@ -1505,41 +1561,10 @@ private void warnEmptyBibtexkey() { + Localization.lang("Grouping may not work for this entry.")); } - public AbstractAction getNextEntryAction() { - return nextEntryAction; - } - - public AbstractAction getPrevEntryAction() { - return prevEntryAction; - } - - public SwitchLeftAction getSwitchLeftAction() { - return switchLeftAction; - } - - public SwitchRightAction getSwitchRightAction() { - return switchRightAction; - } - - public SaveDatabaseAction getSaveDatabaseAction() { - return saveDatabaseAction; - } - - public HelpAction getHelpAction() { - return helpAction; - } - - public GenerateKeyAction getGenerateKeyAction() { - return generateKeyAction; - } - - public StoreFieldAction getStoreFieldAction() { - return storeFieldAction; - } private class AutoLinkAction extends AbstractAction { - public AutoLinkAction() { + private AutoLinkAction() { putValue(Action.SMALL_ICON, IconTheme.JabRefIcon.AUTO_FILE_LINK.getIcon()); putValue(Action.SHORT_DESCRIPTION, Localization.lang("Automatically set file links for this entry") + " (Alt-F)"); @@ -1570,5 +1595,4 @@ private Optional doUpdateTimeStamp() { String timestamp = DateTimeFormatter.ofPattern(timeStampFormat).format(LocalDateTime.now()); return UpdateField.updateField(entry, timeStampField, timestamp); } - } diff --git a/src/main/java/org/jabref/gui/entryeditor/FileAnnotationTab.java b/src/main/java/org/jabref/gui/entryeditor/FileAnnotationTab.java index 46d51b228a6..b0ba6a6b9a7 100644 --- a/src/main/java/org/jabref/gui/entryeditor/FileAnnotationTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/FileAnnotationTab.java @@ -3,15 +3,11 @@ import java.awt.Component; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; -import java.io.IOException; import java.util.Arrays; import java.util.Comparator; -import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.StringJoiner; -import java.util.stream.Collectors; import javax.swing.BoxLayout; import javax.swing.DefaultListCellRenderer; @@ -22,30 +18,27 @@ import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; -import javax.swing.JTabbedPane; import javax.swing.JTextArea; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; -import org.jabref.gui.BasePanel; import org.jabref.gui.ClipBoardManager; import org.jabref.gui.GUIGlobals; import org.jabref.gui.IconTheme; import org.jabref.logic.l10n.Localization; -import org.jabref.logic.pdf.PdfAnnotationImporterImpl; +import org.jabref.logic.pdf.EntryAnnotationImporter; import org.jabref.model.entry.FieldName; -import org.jabref.model.entry.FileField; -import org.jabref.model.entry.ParsedFileField; import org.jabref.model.pdf.FileAnnotation; import com.jgoodies.forms.builder.FormBuilder; import com.jgoodies.forms.factories.Paddings; import org.apache.pdfbox.pdmodel.fdf.FDFAnnotationHighlight; -public class FileAnnotationTab extends JPanel { - private final JList commentList = new JList<>(); - private final JScrollPane commentScrollPane = new JScrollPane(); +class FileAnnotationTab extends JPanel { + + private final JList annotationList = new JList<>(); + private final JScrollPane annotationScrollPane = new JScrollPane(); private final JLabel fileNameLabel = new JLabel(Localization.lang("Filename"),JLabel.CENTER); private final JComboBox fileNameComboBox = new JComboBox<>(); private final JScrollPane fileNameScrollPane = new JScrollPane(); @@ -58,104 +51,93 @@ public class FileAnnotationTab extends JPanel { private final JLabel pageLabel = new JLabel(Localization.lang("Page"), JLabel.CENTER); private final JTextArea pageArea = new JTextArea("page"); private final JScrollPane pageScrollPane = new JScrollPane(); - private final JLabel commentTxtLabel = new JLabel(Localization.lang("Content"),JLabel.CENTER); + private final JLabel annotationTextLabel = new JLabel(Localization.lang("Content"), JLabel.CENTER); private final JTextArea contentTxtArea = new JTextArea(); private final JLabel highlightTxtLabel = new JLabel(Localization.lang("Highlight"), JLabel.CENTER); private final JTextArea highlightTxtArea = new JTextArea(); - private final JScrollPane commentTxtScrollPane = new JScrollPane(); + private final JScrollPane annotationTextScrollPane = new JScrollPane(); private final JScrollPane highlightScrollPane = new JScrollPane(); private final JButton copyToClipboardButton = new JButton(); private final JButton reloadAnnotationsButton = new JButton(); - DefaultListModel listModel; + private DefaultListModel listModel; private final EntryEditor parent; - private final BasePanel basePanel; - private final JTabbedPane tabbed; - private int commentListSelectedIndex = 0; + private Map> annotationsOfFiles; private boolean isInitialized; - private Map> allNotes = new HashMap<>(); - - public FileAnnotationTab(EntryEditor parent, BasePanel basePanel, JTabbedPane tabbed) { + FileAnnotationTab(EntryEditor parent) { this.parent = parent; - this.basePanel = basePanel; - this.tabbed = tabbed; setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); listModel = new DefaultListModel<>(); this.isInitialized = false; } - public static FileAnnotationTab initializeTab(FileAnnotationTab tab, Optional>> notes){ + public FileAnnotationTab initializeTab(FileAnnotationTab tab) { + if (tab.isInitialized) { + return tab; + } - if(!tab.isInitialized) { + tab.setUpGui(); + tab.isInitialized = true; + tab.parent.repaint(); + return tab; + } - try { - tab.addComments(notes); - } catch (IOException e) { - e.printStackTrace(); - } - tab.setUpGui(); + public FileAnnotationTab initializeTab(FileAnnotationTab tab, Map> cachedFileAnnotations) { + this.annotationsOfFiles = cachedFileAnnotations; - tab.isInitialized = true; - tab.parent.repaint(); + if (tab.isInitialized) { return tab; } + + tab.addAnnotations(); + tab.setUpGui(); + tab.isInitialized = true; + tab.parent.repaint(); return tab; + } /** - * Adds pdf comments from all attached pdf files belonging to the entry selected in the main table and - * shows those from the first file in the comments tab - * @throws IOException + * Adds pdf annotations from all attached pdf files belonging to the entry selected in the main table and + * shows those from the first file in the file annotations tab */ - public void addComments(Optional>> notes) throws IOException { - Optional field = parent.getEntry().getField(FieldName.FILE); - if (field.isPresent()) { - if (!commentList.getModel().equals(listModel)) { - commentList.setModel(listModel); - commentList.addListSelectionListener(new CommentListSelectionListener()); - commentList.setCellRenderer(new CommentsListCellRenderer()); + private void addAnnotations() { + if (parent.getEntry().getField(FieldName.FILE).isPresent()) { + if (!annotationList.getModel().equals(listModel)) { + annotationList.setModel(listModel); + annotationList.addListSelectionListener(new AnnotationListSelectionListener()); + annotationList.setCellRenderer(new AnnotationListCellRenderer()); } - PdfAnnotationImporterImpl annotationImporter; - - if(notes.isPresent()) { - allNotes = notes.get(); - } else { - annotationImporter = new PdfAnnotationImporterImpl(); - //import notes if the selected file is a pdf - getFilteredFileList().forEach(parsedFileField -> allNotes.put( - parsedFileField.getLink(), - annotationImporter.importAnnotations(parsedFileField.getLink(), basePanel.getDatabaseContext()))); - } //set up the comboBox for representing the selected file fileNameComboBox.removeAllItems(); - getFilteredFileList() - .forEach(((parsedField) -> fileNameComboBox.addItem(parsedField.getLink()))); - //show the annotations attached to the selected file - updateShownAnnotations(allNotes.get(fileNameComboBox.getSelectedItem() == null ? - fileNameComboBox.getItemAt(0).toString() : fileNameComboBox.getSelectedItem().toString())); + new EntryAnnotationImporter(parent.getEntry()).getFilteredFileList(). + forEach(((parsedField) -> fileNameComboBox.addItem(parsedField.getLink()))); + //show the annotationsOfFiles attached to the selected file + updateShownAnnotations(annotationsOfFiles.get(fileNameComboBox.getSelectedItem() == null ? + fileNameComboBox.getItemAt(0) : fileNameComboBox.getSelectedItem().toString())); //select the first annotation - if(commentList.isSelectionEmpty()){ - commentList.setSelectedIndex(0); + if (annotationList.isSelectionEmpty()) { + annotationList.setSelectedIndex(0); } } } /** * Updates the list model to show the given notes without those with no content - * @param importedNotes value is the comments name and the value is a pdfComment object to add to the list model + * @param annotations value is the annotation name and the value is a pdfAnnotation object to add to the list model */ - private void updateShownAnnotations(List importedNotes){ + private void updateShownAnnotations(List annotations) { listModel.clear(); - if(importedNotes.isEmpty()){ + if (annotations.isEmpty()) { listModel.addElement(new FileAnnotation("", "", "", 0, Localization.lang("File has no attached annotations"), "")); } else { - Comparator byPage = (annotation1, annotation2) -> Integer.compare(annotation1.getPage(), annotation2.getPage()); - importedNotes.stream() + Comparator byPage = Comparator.comparingInt(FileAnnotation::getPage); + annotations.stream() .filter(annotation -> !(null == annotation.getContent())) .filter(annotation -> annotation.getAnnotationType().equals(FDFAnnotationHighlight.SUBTYPE) || (null == annotation.getLinkedFileAnnotation())) @@ -165,15 +147,14 @@ private void updateShownAnnotations(List importedNotes){ } /** - * Updates the text fields showing meta data and the content from the selected comment - * @param comment pdf comment which data should be shown in the text fields + * Updates the text fields showing meta data and the content from the selected annotation + * @param annotation pdf annotation which data should be shown in the text fields */ - private void updateTextFields(FileAnnotation comment) { - authorArea.setText(comment.getAuthor()); - dateArea.setText(comment.getDate()); - pageArea.setText(String.valueOf(comment.getPage())); - updateContentAndHighlightTextfields(comment); - + private void updateTextFields(FileAnnotation annotation) { + authorArea.setText(annotation.getAuthor()); + dateArea.setText(annotation.getDate()); + pageArea.setText(String.valueOf(annotation.getPage())); + updateContentAndHighlightTextfields(annotation); } /** @@ -187,22 +168,22 @@ private void updateFileNameComboBox() { indexSelectedByComboBox = fileNameComboBox.getSelectedIndex(); } fileNameComboBox.removeAllItems(); - getFilteredFileList().stream().filter(parsedFileField -> parsedFileField.getLink().toLowerCase().endsWith(".pdf") ) + new EntryAnnotationImporter(parent.getEntry()).getFilteredFileList().stream().filter(parsedFileField -> parsedFileField.getLink().toLowerCase().endsWith(".pdf")) .forEach(((parsedField) -> fileNameComboBox.addItem(parsedField.getLink()))); fileNameComboBox.setSelectedIndex(indexSelectedByComboBox); - updateShownAnnotations(allNotes.get(fileNameComboBox.getSelectedItem().toString())); + updateShownAnnotations(annotationsOfFiles.get(fileNameComboBox.getSelectedItem().toString())); } private void setUpGui() { - JPanel commentListPanel = FormBuilder.create() + JPanel annotationPanel = FormBuilder.create() .columns("pref, $lcgap, pref:grow") .rows("pref, $lg, fill:pref:grow, $lg, pref") .padding(Paddings.DIALOG) .add(fileNameLabel).xy(1,1, "left, top") .add(fileNameScrollPane).xyw(2, 1, 2) - .add(commentScrollPane).xyw(1, 3, 3) + .add(annotationScrollPane).xyw(1, 3, 3) .build(); - commentScrollPane.setViewportView(commentList); + annotationScrollPane.setViewportView(annotationList); JPanel informationPanel = FormBuilder.create() .columns("pref, $lcgap, pref:grow") @@ -214,8 +195,8 @@ private void setUpGui() { .add(dateScrollPane).xy(3,5) .add(pageLabel).xy(1,7, "left, top") .add(pageScrollPane).xy(3,7) - .add(commentTxtLabel).xy(1,9, "left, top") - .add(commentTxtScrollPane).xywh(3,9, 1, 2) + .add(annotationTextLabel).xy(1, 9, "left, top") + .add(annotationTextScrollPane).xywh(3, 9, 1, 2) .add(highlightTxtLabel).xy(1, 11, "left, top") .add(highlightScrollPane).xywh(3, 11, 1, 2) .add(this.setUpButtons()).xyw(1, 13, 3) @@ -226,7 +207,7 @@ private void setUpGui() { authorLabel.setForeground(GUIGlobals.ENTRY_EDITOR_LABEL_COLOR); dateLabel.setForeground(GUIGlobals.ENTRY_EDITOR_LABEL_COLOR); pageLabel.setForeground(GUIGlobals.ENTRY_EDITOR_LABEL_COLOR); - commentTxtLabel.setForeground(GUIGlobals.ENTRY_EDITOR_LABEL_COLOR); + annotationTextLabel.setForeground(GUIGlobals.ENTRY_EDITOR_LABEL_COLOR); highlightTxtLabel.setForeground(GUIGlobals.ENTRY_EDITOR_LABEL_COLOR); fileNameScrollPane.setBorder(null); authorScrollPane.setViewportView(authorArea); @@ -235,7 +216,7 @@ private void setUpGui() { dateScrollPane.setBorder(null); pageScrollPane.setViewportView(pageArea); pageScrollPane.setBorder(null); - commentTxtScrollPane.setViewportView(contentTxtArea); + annotationTextScrollPane.setViewportView(contentTxtArea); highlightScrollPane.setViewportView(highlightTxtArea); authorArea.setEditable(false); dateArea.setEditable(false); @@ -250,7 +231,7 @@ private void setUpGui() { this.add(FormBuilder.create() .columns("0:grow, $lcgap, 0:grow") .rows("fill:pref:grow") - .add(commentListPanel).xy(1, 1) + .add(annotationPanel).xy(1, 1) .add(informationPanel).xy(3, 1) .build()); } @@ -293,99 +274,90 @@ private void copyToClipboard(){ private void reloadAnnotations() { isInitialized = false; - Arrays.stream(this.getComponents()).forEach(component -> this.remove(component)); - initializeTab(this, Optional.empty()); + Arrays.stream(this.getComponents()).forEach(this::remove); + initializeTab(this); this.repaint(); } + /** - * Fills the highlight and comment texts and enables/disables the highlight area if there is no highlighted text + * Fills the highlight and annotation texts and enables/disables the highlight area if there is no highlighted text * - * @param comment either a text comment or a highlighting from a pdf + * @param annotation either a text annotation or a highlighting from a pdf */ - private void updateContentAndHighlightTextfields(final FileAnnotation comment){ + private void updateContentAndHighlightTextfields(final FileAnnotation annotation) { - if(comment.hasLinkedComment()){ - String textComment = ""; - String highlightedText = ""; + if (annotation.hasLinkedAnnotation()) { + String annotationText; + String highlightedText; - if(comment.getAnnotationType().equals(FDFAnnotationHighlight.SUBTYPE)){ - highlightedText = comment.getContent(); - textComment = comment.getLinkedFileAnnotation().getContent(); + if (annotation.getAnnotationType().equals(FDFAnnotationHighlight.SUBTYPE)) { + highlightedText = annotation.getContent(); + annotationText = annotation.getLinkedFileAnnotation().getContent(); } else { - highlightedText = comment.getLinkedFileAnnotation().getContent(); - textComment = comment.getContent(); + highlightedText = annotation.getLinkedFileAnnotation().getContent(); + annotationText = annotation.getContent(); } highlightTxtArea.setEnabled(true); - contentTxtArea.setText(textComment); + contentTxtArea.setText(annotationText); highlightTxtArea.setText(highlightedText); } else { - contentTxtArea.setText(comment.getContent()); + contentTxtArea.setText(annotation.getContent()); highlightTxtArea.setText("N/A"); highlightTxtArea.setEnabled(false); } } - /** - * Filter files with a web address containing "www." - * @return a list of file parsed files - */ - private List getFilteredFileList(){ - return FileField.parse(parent.getEntry().getField(FieldName.FILE).get()).stream() - .filter(parsedFileField -> parsedFileField.getLink().toLowerCase().endsWith(".pdf")) - .filter(parsedFileField -> !parsedFileField.getLink().contains("www.")).collect(Collectors.toList()); - } - private class CommentListSelectionListener implements ListSelectionListener { + private class AnnotationListSelectionListener implements ListSelectionListener { @Override public void valueChanged(ListSelectionEvent e) { int index; - if (commentList.getSelectedIndex() >= 0) { - index = commentList.getSelectedIndex(); + int annotationListSelectedIndex = 0; + if (annotationList.getSelectedIndex() >= 0) { + index = annotationList.getSelectedIndex(); updateTextFields(listModel.get(index)); - commentListSelectedIndex = index; - } else { - commentListSelectedIndex = 0; + annotationListSelectedIndex = index; } - commentList.setSelectedIndex(commentListSelectedIndex); + annotationList.setSelectedIndex(annotationListSelectedIndex); //repaint the list to refresh the linked annotation highlighting - commentList.repaint(); + annotationList.repaint(); } } /** * Cell renderer that shows different icons dependent on the annotation subtype */ - class CommentsListCellRenderer extends DefaultListCellRenderer { + class AnnotationListCellRenderer extends DefaultListCellRenderer { JLabel label; - CommentsListCellRenderer() { + AnnotationListCellRenderer() { this.label = new JLabel(); } @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - FileAnnotation comment = (FileAnnotation) value; + FileAnnotation annotation = (FileAnnotation) value; //call the super method so that the cell selection is done as usual label = (JLabel)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - //If more different comment types should be reflected by icons in the list, add them here - switch(comment.getAnnotationType()){ + //If more different annotation types should be reflected by icons in the list, add them here + switch (annotation.getAnnotationType()) { case FDFAnnotationHighlight.SUBTYPE: label.setIcon(IconTheme.JabRefIcon.MARKER.getSmallIcon()); break; default: - label.setIcon(IconTheme.JabRefIcon.COMMENT.getSmallIcon()); + label.setIcon(IconTheme.JabRefIcon.OPTIONAL.getSmallIcon()); break; } - label.setToolTipText(comment.getAnnotationType()); - label.setText(comment.toString()); + label.setToolTipText(annotation.getAnnotationType()); + label.setText(annotation.toString()); return label; } @@ -394,8 +366,4 @@ public Component getListCellRendererComponent(JList list, Object value, int i public boolean isInitialized() { return isInitialized; } - - public Map> getAllNotes() { - return allNotes; - } } diff --git a/src/main/java/org/jabref/logic/pdf/AnnotationImporter.java b/src/main/java/org/jabref/logic/pdf/AnnotationImporter.java new file mode 100644 index 00000000000..ac52e0edac3 --- /dev/null +++ b/src/main/java/org/jabref/logic/pdf/AnnotationImporter.java @@ -0,0 +1,11 @@ +package org.jabref.logic.pdf; + +import java.util.List; + +import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.pdf.FileAnnotation; + +public interface AnnotationImporter { + + List importAnnotations(final String path, final BibDatabaseContext context); +} diff --git a/src/main/java/org/jabref/logic/pdf/EntryAnnotationImporter.java b/src/main/java/org/jabref/logic/pdf/EntryAnnotationImporter.java new file mode 100644 index 00000000000..49ce9c196d2 --- /dev/null +++ b/src/main/java/org/jabref/logic/pdf/EntryAnnotationImporter.java @@ -0,0 +1,54 @@ +package org.jabref.logic.pdf; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.FieldName; +import org.jabref.model.entry.FileField; +import org.jabref.model.entry.ParsedFileField; +import org.jabref.model.pdf.FileAnnotation; + + +/** + * Here all PDF files attached to a BibEntry are scanned for annotations using a PdfAnnotationImporter. + */ +public class EntryAnnotationImporter { + + private final BibEntry entry; + + /** + * @param entry The BibEntry whose attached files are scanned for annotations. + */ + public EntryAnnotationImporter(BibEntry entry) { + this.entry = entry; + } + + /** + * Filter files with a web address containing "www." + * + * @return a list of file parsed files + */ + public List getFilteredFileList() { + return FileField.parse(this.entry.getField(FieldName.FILE).get()).stream() + .filter(parsedFileField -> parsedFileField.getLink().toLowerCase().endsWith(".pdf")) + .filter(parsedFileField -> !parsedFileField.getLink().contains("www.")).collect(Collectors.toList()); + } + + /** + * Reads the annotations from the files that are attached to a BibEntry. + * + * @param context The context is needed for the importer. + * @return Map from each PDF to a list of file annotations + */ + public Map> importAnnotationsFromFiles(BibDatabaseContext context) { + Map> annotations = new HashMap<>(); + AnnotationImporter importer = new PdfAnnotationImporter(); + //import annotationsOfFiles if the selected files are valid which is checked in getFilteredFileList() + this.getFilteredFileList().forEach(parsedFileField -> annotations.put(parsedFileField.getLink(), importer.importAnnotations(parsedFileField.getLink(), context))); + return annotations; + } +} diff --git a/src/main/java/org/jabref/logic/pdf/FileAnnotationCache.java b/src/main/java/org/jabref/logic/pdf/FileAnnotationCache.java index 5f1da00058d..44bbdb633d0 100644 --- a/src/main/java/org/jabref/logic/pdf/FileAnnotationCache.java +++ b/src/main/java/org/jabref/logic/pdf/FileAnnotationCache.java @@ -1,11 +1,10 @@ package org.jabref.logic.pdf; -import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.concurrent.ExecutionException; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.model.pdf.FileAnnotation; @@ -13,6 +12,7 @@ import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; + public class FileAnnotationCache { //cache size in entries @@ -20,35 +20,22 @@ public class FileAnnotationCache { //the inner list holds the annotations per file, the outer collection maps this to a BibEntry. private LoadingCache>> annotationCache; - public FileAnnotationCache() { + public FileAnnotationCache(BibDatabaseContext context) { annotationCache = CacheBuilder.newBuilder().maximumSize(CACHE_SIZE).build(new CacheLoader>>() { @Override - public Map> load(BibEntry notUsed) throws Exception { - // Automated reloading of entries is not supported. - return new HashMap<>(); + public Map> load(BibEntry entry) throws Exception { + return new EntryAnnotationImporter(entry).importAnnotationsFromFiles(context); } }); } - public void addToCache(BibEntry entry, final Map> annotations) { - annotationCache.put(entry, annotations); - } - /** * Note that entry becomes the most recent entry in the cache * * @param entry entry for which to get the annotations * @return Map containing a list of annotations in a list for each file */ - public Optional>> getFromCache(Optional entry) { - Optional>> emptyAnnotation = Optional.empty(); - try { - if (entry.isPresent() && annotationCache.get(entry.get()).size() > 0) { - return Optional.of(annotationCache.get(entry.get())); - } - } catch (ExecutionException failure) { - return emptyAnnotation; - } - return emptyAnnotation; + public Map> getFromCache(BibEntry entry) throws ExecutionException { + return annotationCache.get(entry); } } diff --git a/src/main/java/org/jabref/logic/pdf/PdfAnnotationImporterImpl.java b/src/main/java/org/jabref/logic/pdf/PdfAnnotationImporter.java similarity index 88% rename from src/main/java/org/jabref/logic/pdf/PdfAnnotationImporterImpl.java rename to src/main/java/org/jabref/logic/pdf/PdfAnnotationImporter.java index bf03ba19ec6..6489dfa174b 100644 --- a/src/main/java/org/jabref/logic/pdf/PdfAnnotationImporterImpl.java +++ b/src/main/java/org/jabref/logic/pdf/PdfAnnotationImporter.java @@ -6,6 +6,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Optional; import org.jabref.logic.util.io.FileUtil; @@ -24,14 +25,10 @@ import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation; import org.apache.pdfbox.util.PDFTextStripperByArea; -public class PdfAnnotationImporterImpl implements AnnotationImporterInterface { +import static org.jabref.gui.importer.actions.OpenDatabaseAction.LOGGER; - private List pdfPages; - private PDPage page; +public class PdfAnnotationImporter implements AnnotationImporter { - public PdfAnnotationImporterImpl() { - - } /** * Imports the comments from a pdf specified by its path @@ -62,12 +59,12 @@ public List importAnnotations(final String path, final BibDataba } } catch (IOException e) { - e.printStackTrace(); + LOGGER.error(String.format("Failed to read file %s.", path) , e); } - pdfPages = document.getDocumentCatalog().getAllPages(); + List pdfPages = document.getDocumentCatalog().getAllPages(); for (int i = 0; i < pdfPages.size(); i++) { - page = (PDPage) pdfPages.get(i); + PDPage page = (PDPage) pdfPages.get(i); try { for (PDAnnotation annotation : page.getAnnotations()) { @@ -82,7 +79,10 @@ public List importAnnotations(final String path, final BibDataba PDFTextStripperByArea stripperByArea = new PDFTextStripperByArea(); COSArray quadsArray = (COSArray) annotation.getDictionary().getDictionaryObject(COSName.getPDFName("QuadPoints")); String highlightedText = null; - for (int j = 1, k = 0; j <= (quadsArray.size() / 8); j++) { + for (int j = 1, + k = 0; + j <= (quadsArray.size() / 8); + j++) { COSFloat upperLeftX = (COSFloat) quadsArray.get(k); COSFloat upperLeftY = (COSFloat) quadsArray.get(1 + k); @@ -124,14 +124,13 @@ public List importAnnotations(final String path, final BibDataba annotationsList.add(new FileAnnotation(annotation, i + 1)); } } - } catch (IOException e1) { - e1.printStackTrace(); + } catch (IOException e) { + LOGGER.error(String.format("Failed to read file %s.", path) , e); } } try { document.close(); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException ignored) { } return annotationsList; } @@ -144,7 +143,7 @@ public List importAnnotations(final String path, final BibDataba */ public PDDocument importPdfFile(final String path) throws IOException { - if(path.toLowerCase().endsWith(".pdf")){ + if(path.toLowerCase(Locale.ROOT).endsWith(".pdf")){ return PDDocument.load("/"+ path); } return null; diff --git a/src/main/java/org/jabref/model/pdf/FileAnnotation.java b/src/main/java/org/jabref/model/pdf/FileAnnotation.java index 62a764954fe..eb0c33dda5e 100644 --- a/src/main/java/org/jabref/model/pdf/FileAnnotation.java +++ b/src/main/java/org/jabref/model/pdf/FileAnnotation.java @@ -16,7 +16,7 @@ public class FileAnnotation { private FileAnnotation linkedFileAnnotation; private final static int ABBREVIATED_ANNOTATION_NAME_LENGTH = 45; - private boolean linkedComment; + private boolean linkedAnnotation; public FileAnnotation(final String commentId, final String author, final String date, final int page, final String content, final String annotationType) { @@ -56,8 +56,8 @@ private String abbreviateAnnotationName(final String annotationName ){ public void linkComments(FileAnnotation commentToLinkTo){ linkedFileAnnotation = commentToLinkTo; commentToLinkTo.setLinkedFileAnnotation(this); - commentToLinkTo.setLinkedComment(true); - linkedComment = true; + commentToLinkTo.setLinkedAnnotation(true); + linkedAnnotation = true; } @Override @@ -117,11 +117,11 @@ public String getAnnotationType() { return annotationType; } - public boolean hasLinkedComment() { - return linkedComment; + public boolean hasLinkedAnnotation() { + return linkedAnnotation; } - public void setLinkedComment(boolean linkedComment) { - this.linkedComment = linkedComment; + public void setLinkedAnnotation(boolean linkedAnnotation) { + this.linkedAnnotation = linkedAnnotation; } } From 428ae436af374e9b5b168eafff3230603ce71fa1 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Tue, 21 Feb 2017 18:55:54 +0100 Subject: [PATCH 2/8] Add logic for new Sciencedirect pages (#2576) * Fixes #2574 Add logic for new Sciencedirect pages * Add changelog --- CHANGELOG.md | 12 +++++++++ .../logic/importer/fetcher/ScienceDirect.java | 25 ++++++++++++++----- .../importer/fetcher/ScienceDirectTest.java | 15 ++++++++++- 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfe8ebc7708..68228bd83b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,18 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - The field `issue` is now always exported to the corresponding `issue` field in MS-Office XML. - We fixed an issue with repeated escaping of the %-sign when running the LaTeXCleanup more than once. [#2451](https://github.com/JabRef/jabref/issues/2451) - We fixed the import of MS-Office XML files, when the `month` field contained an invalid value. + + + + - Sciencedirect/Elsevier fetcher is now able to scrape new HTML structure [#2576](https://github.com/JabRef/jabref/issues/2576) + + + + + + + + ### Removed diff --git a/src/main/java/org/jabref/logic/importer/fetcher/ScienceDirect.java b/src/main/java/org/jabref/logic/importer/fetcher/ScienceDirect.java index bb041776c9d..ce63112b1c0 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/ScienceDirect.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/ScienceDirect.java @@ -36,7 +36,6 @@ public class ScienceDirect implements FulltextFetcher { @Override public Optional findFullText(BibEntry entry) throws IOException { Objects.requireNonNull(entry); - Optional pdfLink = Optional.empty(); // Try unique DOI first Optional doi = entry.getField(FieldName.DOI).flatMap(DOI::build); @@ -46,21 +45,35 @@ public Optional findFullText(BibEntry entry) throws IOException { try { String sciLink = getUrlByDoi(doi.get().getDOI()); + // scrape the web page not as mobile client! if (!sciLink.isEmpty()) { - // Retrieve PDF link - Document html = Jsoup.connect(sciLink).ignoreHttpErrors(true).get(); + Document html = Jsoup.connect(sciLink) + .userAgent("Mozilla/5.0 (Windows; U; WindowsNT 5.1; en-US; rv1.8.1.6) Gecko/20070725 Firefox/2.0.0.6") + .referrer("http://www.google.com") + .ignoreHttpErrors(true).get(); + + // Retrieve PDF link (old page) Element link = html.getElementById("pdfLink"); if (link != null) { - LOGGER.info("Fulltext PDF found @ ScienceDirect."); - pdfLink = Optional.of(new URL(link.attr("pdfurl"))); + LOGGER.info("Fulltext PDF found @ ScienceDirect (old page)."); + Optional pdfLink = Optional.of(new URL(link.attr("pdfurl"))); + return pdfLink; + } + // Retrieve PDF link (new page) + String url = html.getElementsByClass("pdf-download-btn-link").attr("href"); + + if (url != null) { + LOGGER.info("Fulltext PDF found @ ScienceDirect (new page)."); + Optional pdfLink = Optional.of(new URL("http://www.sciencedirect.com" + url)); + return pdfLink; } } } catch(UnirestException e) { LOGGER.warn("ScienceDirect API request failed", e); } } - return pdfLink; + return Optional.empty(); } private String getUrlByDoi(String doi) throws UnirestException { diff --git a/src/test/java/org/jabref/logic/importer/fetcher/ScienceDirectTest.java b/src/test/java/org/jabref/logic/importer/fetcher/ScienceDirectTest.java index 56d8e9a114f..b2202167687 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/ScienceDirectTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/ScienceDirectTest.java @@ -38,7 +38,7 @@ public void doiNotPresent() throws IOException { } @Test - public void findByDOI() throws IOException { + public void findByDOIOldPage() throws IOException { // CI server is blocked Assume.assumeFalse(DevEnvironment.isCIServer()); @@ -50,6 +50,19 @@ public void findByDOI() throws IOException { ); } + @Test + public void findByDOINewPage() throws IOException { + // CI server is blocked + Assume.assumeFalse(DevEnvironment.isCIServer()); + + entry.setField("doi", "10.1016/j.aasri.2014.09.002"); + + Assert.assertEquals( + Optional.of(new URL("http://www.sciencedirect.com/science/article/pii/S2212671614001024/pdf?md5=4e2e9a369b4d5b3db5100aba599bef8b&pid=1-s2.0-S2212671614001024-main.pdf")), + finder.findFullText(entry) + ); + } + @Test public void notFoundByDOI() throws IOException { // CI server is blocked From fc1e4baeeeb9e562efaac0cb5de38460e1a0a911 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Tue, 21 Feb 2017 19:02:56 +0100 Subject: [PATCH 3/8] Check similarity of entry when using DOI retrieval with ArXiV (#2575) * Resolves #2570 Disable DOI retrieval with ArXiV * Keep DOI retrieval for ArXiv but check similarity based on title #2570 * Changelog --- CHANGELOG.md | 9 +------ .../jabref/logic/importer/fetcher/ArXiv.java | 25 ++++++++++++----- .../logic/importer/fetcher/CrossRef.java | 17 +++--------- .../logic/util/strings/StringSimilarity.java | 27 +++++++++++++++++++ .../logic/importer/fetcher/ArXivTest.java | 15 +++++++++-- 5 files changed, 64 insertions(+), 29 deletions(-) create mode 100644 src/main/java/org/jabref/logic/util/strings/StringSimilarity.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 68228bd83b4..62cb1e5e539 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,18 +43,11 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - The field `issue` is now always exported to the corresponding `issue` field in MS-Office XML. - We fixed an issue with repeated escaping of the %-sign when running the LaTeXCleanup more than once. [#2451](https://github.com/JabRef/jabref/issues/2451) - We fixed the import of MS-Office XML files, when the `month` field contained an invalid value. - - - + - ArXiV fetcher now checks similarity of entry when using DOI retrieval to avoid false positives [#2575](https://github.com/JabRef/jabref/issues/2575) - Sciencedirect/Elsevier fetcher is now able to scrape new HTML structure [#2576](https://github.com/JabRef/jabref/issues/2576) - - - - - ### Removed diff --git a/src/main/java/org/jabref/logic/importer/fetcher/ArXiv.java b/src/main/java/org/jabref/logic/importer/fetcher/ArXiv.java index 2b37771aade..ef0037a131e 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/ArXiv.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/ArXiv.java @@ -25,6 +25,7 @@ import org.jabref.logic.importer.util.OAI2Handler; import org.jabref.logic.util.DOI; import org.jabref.logic.util.io.XMLUtil; +import org.jabref.logic.util.strings.StringSimilarity; import org.jabref.model.entry.ArXivIdentifier; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.BibtexEntryTypes; @@ -63,13 +64,14 @@ public ArXiv(ImportFormatPreferences importFormatPreferences) { @Override public Optional findFullText(BibEntry entry) throws IOException { Objects.requireNonNull(entry); + Optional pdfUrl = Optional.empty(); // 1. Eprint Optional identifier = entry.getField(FieldName.EPRINT); if (StringUtil.isNotBlank(identifier)) { try { // Get pdf of entry with the specified id - Optional pdfUrl = searchForEntryById(identifier.get()).flatMap(ArXivEntry::getPdfUrl); + pdfUrl = searchForEntryById(identifier.get()).flatMap(ArXivEntry::getPdfUrl); if (pdfUrl.isPresent()) { LOGGER.info("Fulltext PDF found @ arXiv."); return pdfUrl; @@ -85,17 +87,28 @@ public Optional findFullText(BibEntry entry) throws IOException { String doiString = doi.get().getDOI(); // Search for an entry in the ArXiv which is linked to the doi try { - Optional pdfUrl = searchForEntry("doi:" + doiString).flatMap(ArXivEntry::getPdfUrl); - if (pdfUrl.isPresent()) { - LOGGER.info("Fulltext PDF found @ arXiv."); - return pdfUrl; + Optional arxivEntry = searchForEntry("doi:" + doiString); + + if (arxivEntry.isPresent()) { + // Check if entry is a match + StringSimilarity match = new StringSimilarity(); + String arxivTitle = arxivEntry.get().title.orElse(""); + String entryTitle = entry.getField(FieldName.TITLE).orElse(""); + + if (match.isSimilar(arxivTitle, entryTitle)) { + pdfUrl = arxivEntry.get().getPdfUrl(); + if (pdfUrl.isPresent()) { + LOGGER.info("Fulltext PDF found @ arXiv."); + return pdfUrl; + } + } } } catch (FetcherException e) { LOGGER.warn("arXiv DOI API request failed", e); } } - return Optional.empty(); + return pdfUrl; } private Optional searchForEntry(String searchQuery) throws FetcherException { diff --git a/src/main/java/org/jabref/logic/importer/fetcher/CrossRef.java b/src/main/java/org/jabref/logic/importer/fetcher/CrossRef.java index a73361056fc..7f2eb496947 100644 --- a/src/main/java/org/jabref/logic/importer/fetcher/CrossRef.java +++ b/src/main/java/org/jabref/logic/importer/fetcher/CrossRef.java @@ -1,11 +1,11 @@ package org.jabref.logic.importer.fetcher; -import java.util.Locale; import java.util.Objects; import java.util.Optional; import org.jabref.logic.formatter.bibtexfields.RemoveBracesFormatter; import org.jabref.logic.util.DOI; +import org.jabref.logic.util.strings.StringSimilarity; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.FieldName; @@ -13,7 +13,6 @@ import com.mashape.unirest.http.JsonNode; import com.mashape.unirest.http.Unirest; import com.mashape.unirest.http.exceptions.UnirestException; -import info.debatty.java.stringsimilarity.Levenshtein; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.json.JSONArray; @@ -32,10 +31,6 @@ public class CrossRef { // number of results to lookup from crossref API private static final int API_RESULTS = 5; - private static final Levenshtein METRIC_DISTANCE = new Levenshtein(); - // edit distance threshold for entry title comnparison - private static final int METRIC_THRESHOLD = 4; - private static final RemoveBracesFormatter REMOVE_BRACES_FORMATTER = new RemoveBracesFormatter(); public static Optional findDOI(BibEntry entry) { @@ -92,6 +87,7 @@ private static String enhanceQuery(String query, BibEntry entry) { private static Optional findMatchingEntry(BibEntry entry, JSONArray results) { final String entryTitle = REMOVE_BRACES_FORMATTER.format(entry.getLatexFreeField(FieldName.TITLE).orElse("")); + final StringSimilarity stringSimilarity = new StringSimilarity(); for (int i = 0; i < results.length(); i++) { // currently only title-based @@ -102,7 +98,7 @@ private static Optional findMatchingEntry(BibEntry entry, JSONArray resu JSONObject data = results.getJSONObject(i); String dataTitle = data.getJSONArray("title").getString(0); - if (editDistanceIgnoreCase(entryTitle, dataTitle) <= METRIC_THRESHOLD) { + if (stringSimilarity.isSimilar(entryTitle, dataTitle)) { return Optional.of(data.getString("DOI")); } @@ -111,7 +107,7 @@ private static Optional findMatchingEntry(BibEntry entry, JSONArray resu if (data.getJSONArray("subtitle").length() > 0) { String dataWithSubTitle = dataTitle + " " + data.getJSONArray("subtitle").getString(0); - if (editDistanceIgnoreCase(entryTitle, dataWithSubTitle) <= METRIC_THRESHOLD) { + if (stringSimilarity.isSimilar(entryTitle, dataWithSubTitle)) { return Optional.of(data.getString("DOI")); } } @@ -123,9 +119,4 @@ private static Optional findMatchingEntry(BibEntry entry, JSONArray resu return Optional.empty(); } - - private static double editDistanceIgnoreCase(String a, String b) { - // TODO: locale is dependent on the language of the strings?! - return METRIC_DISTANCE.distance(a.toLowerCase(Locale.ENGLISH), b.toLowerCase(Locale.ENGLISH)); - } } diff --git a/src/main/java/org/jabref/logic/util/strings/StringSimilarity.java b/src/main/java/org/jabref/logic/util/strings/StringSimilarity.java new file mode 100644 index 00000000000..c17443f07fb --- /dev/null +++ b/src/main/java/org/jabref/logic/util/strings/StringSimilarity.java @@ -0,0 +1,27 @@ +package org.jabref.logic.util.strings; + +import java.util.Locale; + +import info.debatty.java.stringsimilarity.Levenshtein; + +public class StringSimilarity { + private final Levenshtein METRIC_DISTANCE = new Levenshtein(); + // edit distance threshold for entry title comnparison + private final int METRIC_THRESHOLD = 4; + + /** + * String similarity based on Levenshtein, ignoreCase, and fixed metric threshold of 4. + * + * @param a String to compare + * @param b String to compare + * @return true if Strings are considered as similar by the algorithm + */ + public boolean isSimilar(String a, String b) { + return editDistanceIgnoreCase(a, b) <= METRIC_THRESHOLD; + } + + private double editDistanceIgnoreCase(String a, String b) { + // TODO: locale is dependent on the language of the strings?! + return METRIC_DISTANCE.distance(a.toLowerCase(Locale.ENGLISH), b.toLowerCase(Locale.ENGLISH)); + } +} diff --git a/src/test/java/org/jabref/logic/importer/fetcher/ArXivTest.java b/src/test/java/org/jabref/logic/importer/fetcher/ArXivTest.java index e43528c4537..47af5898eea 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/ArXivTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/ArXivTest.java @@ -9,6 +9,7 @@ import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.BiblatexEntryTypes; +import org.jabref.model.entry.FieldName; import org.jabref.testutils.category.FetcherTests; import org.junit.Assert; @@ -51,7 +52,7 @@ public void setUp() { } @Test - public void doiNotPresent() throws IOException { + public void noIdentifierPresent() throws IOException { assertEquals(Optional.empty(), finder.findFullText(entry)); } @@ -63,7 +64,8 @@ public void rejectNullParameter() throws IOException { @Test public void findByDOI() throws IOException { - entry.setField("doi", "10.1529/biophysj.104.047340"); + entry.setField(FieldName.DOI, "10.1529/biophysj.104.047340"); + entry.setField(FieldName.TITLE, "Pause Point Spectra in DNA Constant-Force Unzipping"); assertEquals(Optional.of(new URL("http://arxiv.org/pdf/cond-mat/0406246v1")), finder.findFullText(entry)); } @@ -103,6 +105,15 @@ public void notFoundByUnknownId() throws IOException { assertEquals(Optional.empty(), finder.findFullText(entry)); } + @Test + public void findByDOINotAvailableInCatalog() throws IOException { + entry.setField(FieldName.DOI, "10.1016/0370-2693(77)90015-6"); + entry.setField(FieldName.TITLE, "Superspace formulation of supergravity"); + + + assertEquals(Optional.empty(), finder.findFullText(entry)); + } + @Test public void searchEntryByPartOfTitle() throws Exception { assertEquals(Collections.singletonList(sliceTheoremPaper), From bdc535f0f13fdd0f5558f3bc11c9b4a5c533c2b0 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Tue, 21 Feb 2017 19:37:30 +0100 Subject: [PATCH 4/8] Update gradle from 3.3 to 3.4 --- gradle/wrapper/gradle-wrapper.jar | Bin 54227 -> 52928 bytes gradle/wrapper/gradle-wrapper.properties | 4 ++-- gradlew | 19 ++++++++----------- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 51288f9c2f05faf8d42e1a751a387ca7923882c3..6ffa237849ef3607e39c3b334a92a65367962071 100644 GIT binary patch delta 13979 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 delta 15239 zcmZX51yo!?lQkZk;O_3ho#5{7?(Pml2<|Yr1qkl$uEAYHaCf&LKOwu{ZuXzUJFlp| zeXF{v`%O=udR>{|Glk#?3ew;Zupl7N&>$sVZgB_{2yZt@PEFTfK@boSwKxG4^aJcm zrwb=gkpDquzaa~W!T;PwsNQe4pAg>ulU#lY0Ud+}0Z9Osb8-UW=sY#ye_&NHg@J$z z#WT4##iQXWuRJQy<66xOXi8gqhn1n1qOY@B3VG!n=q}e0x66AC))`DS!SLnCp8e*3 zjrGg)Y%NnW%DKMUyIXBby-VL38`W;V{D!FyRfYeGxKaI)0BLKC`S4r>T7DRMGXow* z{$gBP$io`T9&Q70!kjh0W5T+QjUD005a>Rv5$=pY_P{`}I@arbzwYhnLFl|jIPk%P ze}ac_doHBMBWVxm>OAgK*46`9?YF%-@!or^3BtV%R70QmJ^73CgOB{E1LjNq6V>;7 zrpJAli+vGok0g~HXamVhPnA_&>caOp6Z+=2EW~X@#z?z>6ko{!j&oV4cDgOtUDE_d zwn%$P3$B%P0)oR69PCqkJS;-&LtJ?TgaWVNU~zJhN4b*1x$%s&Z-+A41zF#?i3}wh z;~2H9R=EpyrP2cDY5XgM4+xNi*jQXG?u$a2Tf$TMy)1kNPx-bE;{0Gr2fUQG4mP@T zvb02y3Zdix3@KuQEcCjxQW}=&dNtQN=EJ`zuW)IV#INy|)-0qC#VBXU6u&WD0v{6s z>3xH_=D18tmNMo&2UOr(Dz2LN+~HE=i?v$f3Wa5X!IEBbR@g^XcGDIqwJ2`=CEaI% zi_U5z3Hw-IAX}p7G#l#VC#=EqQ(?yN)F>C{CBDT06rBfEl+BlyOgiz~(Ufa?L1pGR zwEzkeNAut)>KH^vz?wQ6rFD=O|92d4|7wutb`}^0(Nm~gRTX!WY!~Q^|7hBk_1+*3% z?c*XQVSdJfbFKve)hcSYQb+BlW7Ul1415IuwrS-=bF1jE70`;>y;l6Bl{Sw_zo@D> zlSWa}yclnQ3_|{A>{!A?u;tBBKgp14M&b;K=SjS_qB68Lwtmm!t1k0)K%*FWpVhW) zO)qhyT1#30Ylm#fb9kC3up2zE9T8{MJ!i^4n@0{6&vDw+x{=$ox)rZ!JW|H+ z`%?l4*F*9skErJu>WiqGqH$qiiC+Es(n`pbO4!QR2k94_uj{1juW0~s%#=1JY?a`m2)jL0suT9&i{vNIFE<_vMoE`IV^vXAwG(H$3mj7wY2T(W{ zf1(cjOnVPUDT-lC{G{5wc7FHqC1?HHeR7~MxR?r=&vm4otT^G6*~thaMqMO7pxAn; zDC^Gkz${Hcuj~RRDQisoP*dI~ZKZ;Df9coyZxPi*KDJI#CW0eTFbqg8wZz~CD#^+3 zoZq!xe7k;fowVK9Q;+%SM$R(Q&+`+E7|)$yNVCoHGG(Z$yd_dqR`m0R7W8wdQ(6`Sbzo7dd1_3!)SkGp()Dj=(kO zN0J}fZeN{0L(u3Oja7Iok2k{OXIsN-LG{<8SlnHO6N*$YUo!9hUWq6@H~eTuVO~{O z-Uy%?x`Kz%-Xs+xoB8F3w6dA1&v@;vF;tOD?qhfN99iT@c(i{6V0s?51PH(pbbS?R z4=>`jA$^Pu(Gzt^4$%{KX$94d=8C*HDaI5QWhBJ%Tn=mv%Zq9I5N za|S&z(hYj@HdFN~-mJC&30_A?Ss3O`uyM+G^=cBoR8CXY3FCYXF|`ZUm^stB(eHDs z+Qw(~VeR#|t9-Ys?Pw|cyz@)xM<-(lLRG(3e_EW`qIjn>=DG@abOQQs`MX!$6OcRI z!j5A$HF-l)w%jq3rkbMKmIOY7HX1{^DY&@D&)T&N^Yt~yRCqJ$#rURl`(^Zka=(HQ zb-e6AKof72HrUuaOPH`m{t*D8Jbf)`t5I_Nt$|&(|`lWD3rttgPIlpkko^qg| zXFm{c#LlVI zdsH~jQ(c_H3Z~{JAVtT|BMq$kAtv=mteF+jf*z)hQGN(vHq^~4ucCnVft*UU=l1za zQkUy&BgAg}0k(?9ll#+;+5j!6YlxU%M~aGqz&jI&B=FKf9qjud*&AFc1&{2oMlf zV4NxefK0*3-osPS)y2Zp&c)K$(8b<~!Pv&o**Q`9#12IejSoDb-_+7kwQ63<);g$! z?j9XsAkaWYCe%{N*67h17FDD67jZAqj;4$c)Uz?JtPcp`u*ZiY6se-qm}d7=uDexd zb2Grp<1M%Vc8o1qTyBmF)(i@KY+`<0F?a ztNx;K=$wi2C%U<3g|<_C0_dAyLI^a+qnhrod=);mgddDsPTXOBDqdPBoE$Vj*RQQ> z(Ln8~V!^7yc{I|7DwjylU227MfN$KOpSc8H>izJ;l2~2g)z0pzT0!v&nf|TBM)^rU z7yys^AoR@l+SRULVb5M{w7~$5HGk#oolI+X{zEa0*c~yhdo_`7?jxfwi{Bv{4GuM; zl13iR-VY-U8|z=xZlgc!TZJ^6_OhX4#xEEh(yU|SgKED1_Aub)tve6Rxd(&{#Xfwu zg4M|6VG{OA!8)(nIYDgE!eb^IYp0Tw;R6^f4lhtrX+0R0Dskc(c`$#yk10MlzzUnJ zncpobL8C;j_A%@nh|Qcb>NKlxHyuyW_})42Lm_k~yWbVj84xQGky z3$+ezvbPjF^L&q)^-v_VG5vsc_l@E5VJrYVd8lQZT(OIMu}KQ!pwIrF=~nBA{0jo{ z&!oyM#k!w`0s&!10!BmN06Szp0)Bg=sbl-e-!hMw`G3@M(6*QoTcksP%Ta*&0t;g+ zoGgGV1Yzu2!(#(Q!E$s=mt1la+}L1Ms+Mont`gy198ZpBdsM#s81d@g`KW$hbjDGe z{>vr_de`$dgKNzv`OasJXN}AA_gZBKlmYHb1HATm6FgzUhA=Z0v&>MeJb)x30E#6H zLe7ecB2GjQW9HI?+(Bx0hNRjwC9XTJTh<6ApNt=#@k@<_Pn-%0Cn<$FkTc|p#4{I_ zuv=Vo!??z$29H++CipjfF0{TVl9xluohh#xk6bo!aD&G-ye*A$cWshf( zX5ww}{3qiXvDfHK<3#MB(@!b3oc+gG=ouskn=f^$r%NSO6}kz?g@9w+270frNyZP} z=nQ$uN;)ZlZl#ZU_Fl>nigyIcp@_|pX1=E5PNP%9qX`H2Yz29UzqqJJn0jkXbWz1j zlVKGm#qmOrZNBTUQ#V_Oja}Ppb$oXj5OU4;);>zVHkZ1Zi$Tl#fv*gLnDcBhSVOe2bAQ`Wn`bfE)`WVrre*9E z(L(br+@R0Xt=v5*`JUlw$v|P+nN%9^I55~Jk(p`ssy7Ec+I=k}%;GlPC7-TgD&5EO z>;Jys8-bp-8Qc93zLy&P4d3VmLZY?G*sgyh-B9XUYrZiQ2M*xfHT2Uib%)>NafU&= zf5C+}rt%1@%P#XdUw_aI`?MDkpU1H?`pzIZTF~cfN1E`#Jq3Y^#!sp5&*&ozDOu4G z9)g37=eBB&5#CyZ?k0Spn65sUYcm(V*nUJc$>+idpQkUF8L0aj65uBmE{r{&QJ)eN zk8bj=5H>H&ar^)kTbTFx(fS)T!RjtgIGt0DkhR<;O(lkMgKTXj8!gdm;osK2%SK`SYWhdu>&_nOvVk~F}+^>Sf?Vso221pa(6G1Q=k!B%ahmMYc&TEW}+YH?kHC;C2=;aNlb*R?9` zNX&02v=~xYKT9%YdAX0)W4gl->o^}K zvW@&4SLuhHR*+pQhjj7fXgU0!c zj+@!H77%KpG^HuRQoKlKl&a!`aWSfDQK?W1j^q$ILlF6@7wvW4hWz^zeDl`}iCm0! zcix~B4|PU;@lB6iSnd)HH~gV3^(pL%YnmkY%5{bQ;nKEe1)O4|InlB;9nm|{vK)c1 zPd?RNh>g04^sV~-80~=;CP)iYTr2!7rzCQW*Z}h}pNuaSG+O=3FcGX!zOVudzB zG=~T(Ii8Y>D8nU$Pvn?yP6PBRJ)>1GPH9SeJf1Fg3NSb<(?Trz6y5EcBI_Q@xrioZ z@Bu9DO>v%hp^%Qo&WocuYdmq`x`>O!bG~@iT(_jMawjC;oJ^+4JXMH73Wjp`wh6=# zbqy2O^7_}R317QDz62T86MUGZ(34{J&_LM8E?Gx*1r3?K!ct}2tnz}1fhtSwV}A4m zL1L0iNJ_u>^lkH=Qj;~{s|li~@|KDgUl>6AUd>PmpDayyTV3#EkSdkHaJ$hVMJAeg zfX3^r@Whx+FZgT#YlDhhQEH&|HZEsSC>TmVu8Je6IQQ%l*mHnt{{-v(Z^nPV2qn+Fw35%>HdJ#kARzQ_M^yGswLUClkbibwKx)v9 z_Z^rbMl9I-m*ua=HEJvb5Rg@DV6-YFAX5Xz2W`RkC9AHL1qX^4<0IW-)#3m&KJC^b z-ey%?tU)zHorFpEVx$_W<%N|w9}ChPYuf^}p8-Yz_meSe&w3y{{Rv+j!N2ts?wqGmSUr?QPhj8kc4TivaCevxg)@H0 zd4U&q_37_Yzur2XjDL#AcrJz5S%b$L=sdbd0)GvAoxWJZ@gr+| z5g&X#ysr*cx3~`@CJJQ0p;BeFBFPTRW)NzbWX(Cs9qMv4+&2nhkQqj&1z3hz%=gpi z*6kbBGxW4*e2=Ja(V&E^vodO@V7DM40Rd&n8e6v0AGqZGi3%OlGT#3n>_Oo z;i(X~+F$$;SN$TgdD`)PtJi%pt*L96pYrHIZT?#ovuCTK5LH#KyN^LO;P_PJN#%26 zLnCw`^Z00_EOj~*zI%c90HD5r+3gN;VR*-;(OUuk6m_zRpkdc0?UTnix4o-**|Cg! zkNeCLHUTbgR+TQ}i3zn6fIIyb3HG`{S9I5jX~f-41{&fqgSteQEoFSU_n}$xC!e9L zSpu=#@UV=AomPc(Iw*i$Hlw1v@V?5KINh;~df8iccu20${Ia4Q4WQuqb%4EC^BWBl zw2dV#PICS8=|#22&}`idU+nneu*_Imnv-ozOS-jW*ki)U!-0*Yn=?IQ^-*U^jq_#f zD18L?mgbsUty=KF_ODTt;;$yw*XSvG!lqe%^w!_DK7 ztmP9!(m9ba#tDbpzJM?DHB6+QpOf#xT5ZP^z5GF@77^IAu$44<$mz*Nh12$qhMz8M z*jjfrXKtI)F&5h(n(?KlHg2ZV7A3Sp4Jvo?m8ILOzcbvA*v8v^Qrcm|ry>qFFT~%S z%G+6LwL6$7P+|SG_;&nv2A zTsA#!$k`;GKf${(y6HJ7T~fNlRaIrDN`q`gR}?FriG=c~lv5=YOXb71=Gd{s4oi}K zOtN89MF)q~S((8|iOGUE0N;)wwp z9{tPH+a7c2AuE7cx*+n5w)7g)hN?1p3P+h?CP&6yS(8uZByfWwa)_8r@_lB$pD{;< zj+1V!jDXY?-K1dEr7FR=Ny+LZ9~Z2QYN;DSizph>Hn|=G)6S~&=?PxqiD*t^Mp(1o>^bx9?m zXpwaUE*6KS%U+;3Mo`$X^)poeMDxy*t;Fz#@zkPdNuPMQO`!0Ssg^&+)KDIui*vGp z5y4<2Y=7Hh&^(~b}Qz~C?IV!{d*a+pc z3UA852lfK+@u=)4`?Sv~!2}NoCeVb9G}d!~Ap^l%z2doB1Y49|*L`7AMI{hZ%Ss$W?oY(=HL*WbPZCM8;Eli8OO^C*EQu0zD;BBcjc0=0S&c^Ha&Ed^8P7 z2G-*b@i=_-i_gpSahBU3T*ORui!8E4O#Aw9&qD#!VmtIP5lqTteJ~h^L%83UWy;hO z31lPFjf67t#A(@r<~$`I(>C)-G+~phZgGe4#`@EodZ?FGlvH&!SsjPb3i~qyJ)imn z76_Cxklp7d>1!&AmF*yMo$ic|H+3l3Q^)1{5w$yZCiZORwYUY^h1B+_x){^uN8Hm# z6czy*$m|0gvR>mA@t$T(qh#x@K3k%UdCyCw_xvZKwb6t(m(3Z%xCOZ@>E@=P1nF2x zIbIyrDomBe`E5z5y?0V4yB5W{l53f4LFCRdiA9SKO5M!TrAowFsygGUZmfe5=ttkX zHOCtArREE4_3qdimm9`@7QUPmrKK4uZ(P zOLY|SKU`(m*Rq!zNYvaaMt`ncMNwDHUac!P#g|@I?5%z7y{$`}IESn*J`7S8E;LD* zBaeHaEU(g;Mq8kduuqn%MN4Znr#bN|5#{N>zs0`=QB6pEv2gu)NkKoY*11-^sI&<% zPeP8g(N|@ub_@$oGb^fpfgz1Ih+MkcT>@1*|D{*>yJ+o+9W}0GJe<53HhwwDS~k=6 z*0JIc^s8;5w|k$p4#23vqb@#3MW~~x!Z#n&o!ZZIIYNCEVJ>s6s0?CctZ2EwPnF?^ zYUNpc^h4?zj7zhQS@C6o)ozF8h^z#_pq9F|Ac`xmXlDVWTvL1E7wcX?`YpBrj$znf zK4{bv{H7nxmPZW|@p0H}8NIU3)>F~eL;n($bqs8Who$YqsC#DZmZvs`V5%f|1shA@ ziE8BDSZr z1JUaM8BQ(lNwI{Ei+!U*?7ma3oz45bVMm$RL>8!Unp2}D@)5o*i zPYn%@%fFr-aK|oKKat0_Uv)g?*_XQuKR_<{-7FfKabv2aNLT95%)7G@4i}aAKn51z zyN_Qc>*OFRxmGCT_NZlu;(=iR0v1CpM;-X#vOz5?CREGM1U20DGeS&(65=iM~oGFwZ;D^%bIPTjnCwST`Q`-$*$+p&=6YXL?VHV_u`4g0`WEpKIauf9DkA6TWxud1e(mXTTe*#ri%#?33aBZDSR) z`A+rJ7f6uIFlq>S1Ly$ljQoII&M{M=Z`fuz>kfsqf$nk#A$CzZ3ZyvvEUH@>K&-3o z_84JW*s0;<1>W&ReTxk~+SY@hGg#jo8sdWO35sC176ql{iHg2|4WDMjzdU&=)rK)! z+9C8}VQfwI>16wC7qV?TjM;~{-$7l~z@8kQam!h;|43qp5ilDc&Y{#S)AaQOAFj!? z>F61n7rUeWYYXh+4OO_^iY$j)@SV=U>Nc2H&u`epwbgoma32hZSV#4t(6K<6lstTD zA!bpc!qjD!(QsCLw+fnmq@-?c4X7g`zmP80SZ^dh_5AzXImOdUDihZWAcm${E_jNVJ zCdBmgA}n2a-rr61_Bdb?3(4aZU;d!d##cnt0?b+y2nUE?cthl**I(Rm!8w?NzX))h z;2F}N@=1ty!T^3~26$eGXAFT|J7BMdpeOj)Ga0>N*{fCmIJ;N+<)d2cbO!&;;1?cj zj5FS8TLAs&yexT4?bC_<0kuJH>HY;J79k}q(?WPQ3Yw9BI{ZaF{Fxk-TmJ&j$iT76 z)Q<%$?i4^$O-8y*=%CcjQ@KZ*$$T=kveax7|fl=rwA>?sM!1 z=%6#JsYGwAs;Dp%{}=%hNk+=}9EneHvm`kpN@o&e+CrIlbrpT&E6;uLRlf9NUijO9 z^}tjjWGLf=MO*Xrp;A109F-O+Xvz!rpi;@0PF-1D^3h1&kQOP3kPEqSumlGXz<_3~ zlUp?`*S3v-;uTQl?f;iH0p98-gU5CP*LFyD?J zp@5%ypa7YgFg_|f^`9wOQh8E!h#-Wp=8?lpka%!DB1pzAevGZc`glR%4Ae;_Uu_mf zIZ`83(>f9RW!sN$Wr>~$5fyIxtG+?4w7kB)Vg9!Mw!I_&?ColMZFVEgX5mhMl;+Dg&9=jqNFfw7{8wIX~c4 z_maxv65j9xO&i++*BLeiE!lEACGj#B-Z4KSNxBlp(zUz;>m=LEOK=vGrT8-~96m^`+a6BL{BoT)y8b z^+YH%swyW&wwwlvEblk(duB_SAXL!hp{QvMW~SnEh9Gb7SyJb%6-u~A(Ww#eC(RBa z{>s=!+I~uPDj#%IrefLZ6uWuxIuRlHPms7c>I=43t4-f?ie0yY3slqD*~_h$0M#9K zTQ~(hyVCW#TCyS$u5)!-1;|HQqswKY@sm4N6#8VVbNT5qGwEAq>axkj zL8M-?mBlyL`)0DWe4&Xi4s9G5Vb+EPns%t^I7(YR`Qo)LM?^+-d?X2bP4pVy_&!7w z9QfkLne;5?SF)3M>57MBNtDeQ0n+HTqi}-;wirOT)?i7^G-y*97@i^8`89#45xNbj zL)wH$M>42sQ7NnOkqt+?VhCS1zj%aTES04O`xJ7wt2Kg7j5+Mkb%co!`DXXdvPs*2 zLcy5PtiZ8x%yO_OoJwS68wnjuO6HQ|*km(8brco96?;mk9<{3c6qI+ZFUv)?KbJm3C<&k0S)9 zB3o&g&zW`1?Z??KqHs=mn`jDcOmx#@9ZQHAtkQkiONh=>+Qs0@vTKhCLwI8A24=E9 zWKani6|nH-xRc5D9#(3?0qDR&5yXjcynaUSkt>T8 z848$5;IxHRdXOo}R{-)g&*Ee+t_%I~c3&WRG-WybN89<*Ei;u`I`06E06ZvezLOt= znqs>41LUn0QaH#VD7UO>tZo63`=kyX45&UMEJRi6to>cnGPhm#OUht!BpRqO0ppx| z-}womte8Yn!_gg`Z3jxlj3SVGJ0QyW@=djK40xwiQ`o(7hrc_K=-;ZQPaP7)wE znZvZmyy*>`b$UKW*@#>=w63t*%O>4$RJDo9go*9WrOPHQ!3ZDZ6b$}F)=L>)pNj5b zTKY=9Qx%l8C%}f)lfPwZ=8vaa~ z&RwgFB9Nj^0lJ*iRcJ|6K5af1b%xu}PI5+zuC7EbXnua9U)tmXlCt_<<;qHKE!U7i zI%wol+0EUpE>Du4$JEx;u{3iWzpu2|bBkv=#R_%~yZPMTQuy1<|)*Hb=W}JjP z$Fh`m5PxM8B(xMHWT7W%q(_CffSRMR0-N(x$4ZJZZSgy`4OWWCR^YZ8i;m<< z5)pFEZ!;bDG8r)1_F^@Q)%&ziuODugNVxrM1gHY10Yuy}*?zA0NWBVE6&jNJO%5!P zaMQlDF6LD2fe0YJbJjz%VwyR3+RVJg2LRQVZwAf>YDN1{Xz;wx?w`0e6$)NLTkLT;TY_9p0Zk;tVCB!fB=%F;7*z4o!2_gx zs8U5L9OIsueI$1;;gzs2^$Gl@@F3}l3kaClFAUfgXhoJ5&FQhcELTzY<|^3vg7?O{`vPZg}?3I{E{;FOcKVZ<?Qo-6U&9{52KzH0?IFHX0ohOd;uJq#W+ocCFEP3mK#6 zbw+fi^t4#$1dm+q;AOcT!pkGrSBV|MD_ok_z_mV&N@b{$CyZB>oyG_J+3bq?7^%*^ zZ`4oDiEHRCPXTMv+FmkI1(%E)#(k3^DWe z9wGBhzuQ9;M5iUV4rJ*ZdX*q%O0X2*7dnAo7FVFciig>L!(%=~P|pP&9RaM+9ly+) zPDqqy);XQtq{vHWnjY#PQLxukW4e*WT^Os$@&y8+@f`;@Y$_BS9w~K9*1OAPU&{sOe zzJCE;KM5_7y?JviWJ@Y}4q!X@^a%*3lvRFZ=!(r$|E0Rbgt< zDXf!f2mWiZ0zQ~*o+cIyR8)_$@%qcnQz|N|Ff9yraCx8Irl3HcUDY9?Nfh{w(~-QuM=MyE*ikpa!>)4$<=_C^n0 zm=<>MHYXzs{9GU~HD=Jcj1m!UG589tg*DFm+;^vIpa_zASg*kwti-TM#g;$21JyO2 zEYNPL&HOXA7n2Zm&}Dca4;!OF@3)4t(z&F56-11;P2!cCj)7^2ks3U@xoK(KU4-&4 zq`Ta?yp5b$wz%s@ay&r#NozKGVc;kehg3Wx3nqI!-+ZBzY5|MfFxkiqr!$y@Qsat( zt<~652&uI}b0&D&R=Y$76>G4k$%NxhPIkcL?|D}O%8az**6P45zXjS{1Iq>&F})$Q zW<;XAmioTsreY4UYbs_I5Fp{q@3PsweFPTNTG-Kj9p{H!o=iaL;(8VC;L7Z*$xnkm z`q_(f=B214m9DrZEVf3>RNcavqHn{YRLKD@kh+pG>Kn8n6$L_E+FR`kh|9OA;wHbt zu9&lcpWKmrK~FF*ToI@|E;6+FB|LY8(JW|3zezA6#CxR-B&y?4miAfHtU(I&+hqZRzVJe;vd2tk6`zUKii}V=KoQSUa zRfSbRIV*otTx>`a3V%ef8Kp*T%B3WD`^uJUfpdk~sUi9EUmKSP|?l;$&q0D#@Ad;ENLW=nb0SQ0ng(UkxsSTC1F$ z;|4+4Ihrg${tF3U@@}-96+nUy_Za>ZQNb-#IJXOV1!WO^XE%&Q19|mf|C(M16MDP!EX)T!q;tX^s{7BPfHAI)2l80K32O{PaE{w#>MWvj-~sQnCAjM} z`K&0E>x`)jb#@`Rh2qb^OoellvW^d8!{4tgVSY&i?&9=Qq-kG7!bAiXWxJ*h`TUrf7U_VeCr3D{5ah9cSXN{Fqy z4Jv$s=AV36T|;;4(UZKs71XfHn;s#9wa`Wz)u9xd=vy^eU03bFl#J(~`SWUmFi%ks z)k01JPQiSQ`w5pPzUvkU^>qq&I~6G1_zM$0DLd%Wa!g%WXTd)m4hed=oI> zvXVSvCZ{)2GL3n5q&~H!T_VQ-k>dnKwo*R=UUWj&K#tce2K|wIX^bwUpyOjCJbLsX zzc5>|PXpb?<2bqj(a-EAgOUwO@`Bjn#T@4e8l||ord^k*C@bc_U0jiWh2G z8=t|eEtCEFJ1WnsHucSnWHrwIC!YV6jicLu*p93O;Iq5})^{_9#8#HL zxvsX%fM+7zPZGFf%5_HF16rb^jm72juVCmO5_`rFXTQG8gD%%VdWxd-1kwMt4DWTL z)w{}Eh|mIQt+CntDbAAI-4k))1l@v3oQp&h^W%zX8~K9`rZUrVtKqY^LG|w{z`;rk zHqtbSh%fzarO;?2X^%JZ-U3mFy@1S_a38Nf6(RV{c{OdWV{mfz9w5+Qa;D(g(MU9tPoDc zOt~-mdG`k2iepazL_SyZeGXgg1Ds_x1lvz)v)4IqGt<^P+Vv-Q`DtxLle!Fj&qGk~ zb`~`p1PO9JEz~&^oamO>M_=ZR2KziQjh1aoqdh!<^hJ)*$_JXfd!jl#} z?4M@j4wIhYi3p{1UHGhWkHl@`&J3<~Y5Z3OE%-6H)r3ZB55P@EkpvG&Cm+H44+sSh zkcxU=ptT6US3Iy#`9}IY%BPaCV*Wh&aE-g@#?!F0W>lYd-;T|53JEC7j51~{f<1VcM#khY)GxZ?X<8W1qHVasaYSD*J0n?21IWHU+8e zkbSRGuW_((IJ~B66=W3d(bx0x%Oo!tWCo69OF=Sw>wzpW^L_+pp) zM5|?AeZKCrb7}h^A2} zpxEgyq~Btg?yuCX@m=6APxB<6FX-cjG3iW;nYWISf?RYZI}QxK^W&{t63*ij<-Cyf zps%0*Iclq|6x@S-uVt`>%maHD5)qf)1>jFz9h9WEN8U z`@w_Q^9degvRz%UWb-KjUUN}HV;xNHI8;JbdyaZ91a$R&c-|YAL#o>ZS0~zlcF8JI zSm~H=Ucvx*s70U!jbo>l{@Nzf)L;#$whmec^ z4p{=))5~SCk|t=t|9US7{LL-kjvn2gd#!HnI@r5l`R(Gb5a%%i`L6jGUiz*9elt9H zSD5=fg1!s9p;Ms9e+EYhApwsK3IbyORzFJ(G<3zU#jj%iixJ3gfOrQhyYhg)3muU~ zDDMK26(RJykW@eU7u?kh{EK-g2LCIV_|JWK$3z&tg1y@kp2FBY1P1}}fdc{IeX~VY z8(59>*Mw!G%3t53Ob`AFuVv?d1y2j$UlUADgnyaQ^h5s+ORZf2{OvU=U~xO^zpqmP z58K%k|5S0lr3~b4WbdE1VwV5Un!2iCP^?!T3`T4(kbO9YY zaNg@*qB^j_PXv$NPG&KHogMH*fBOCBm8`dOTdM!=_IA(vLI4UR?n4JobbSDhb0Pxw zyW!tS;ySS*^1jf*zBd*^AkqC_PmJy@Y4_hMP;n4JKq&rUM2CCtG}(&)-0VhqXXEYq z!zPIG-eA{7_pZ$9{iE!``Y$xoyQBY9OaDVVit`4<2PFeqb&|b9O}s|e;@`r?_f`Y+ z=^rRP{yQg4H}yO4e~M*6KuG=pB9OcT{d;lWf&aIv=)bXfUx=ySfl(|t|B29e#~=5# z8UA<$gziLpXUO;b)S~t$rH~*Xg#X?B?Vk7LGvhl$XgAh7@PBHOKtPE90Zuc$0U6&x z|D3e{1ET)?&gS3y;qBlZ8`lc}jZ-D)` z>)%BY7ptWCNi~82%GyZ4bMYgbyGfgUJ8a$+_=uKoX$X(EIZkxYGZ} zm-5ngGwnvWK%2q8nfm9E`;V#0iZ?JnkbdkhkRIJ4;KQ3wt#8Yn`5)j_%{yy)<9kBh zN7_~<%N+Lx{`ximzJI_{_3z+6Q!8?SCjK zeh+hJ+kYr5oj(4_;=9e*AJ<8|Z#I?RY%=|0bEESu-Pl0geu{S%oAE!?Ha)JUI%QC diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 265787b282e..e30f5fd5ae3 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Jan 05 09:52:38 CET 2017 +#Tue Feb 21 19:36:11 CET 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.4-bin.zip diff --git a/gradlew b/gradlew index 4453ccea33d..9aa616c273d 100755 --- a/gradlew +++ b/gradlew @@ -1,4 +1,4 @@ -#!/usr/bin/env sh +#!/usr/bin/env bash ############################################################################## ## @@ -154,19 +154,16 @@ if $cygwin ; then esac fi -# Escape application args -save ( ) { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") } -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then +if [[ "$(uname)" == "Darwin" ]] && [[ "$HOME" == "$PWD" ]]; then cd "$(dirname "$0")" fi -exec "$JAVACMD" "$@" +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" From 1aa1ad0c9ef1db81ad2667efd1b21094146f9c33 Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Wed, 22 Feb 2017 18:24:43 +0100 Subject: [PATCH 5/8] Keyword - Special field synchronization (#2583) * Fixes #2580 Keyword - Special field synchronization * Changelog --- CHANGELOG.md | 2 +- src/main/java/org/jabref/gui/FileDialog.java | 1 - .../SpecialFieldDatabaseChangeListener.java | 26 +++++++++---------- .../SpecialFieldUpdateListener.java | 16 ++++++------ .../specialfields/SpecialFieldsUtils.java | 17 ++++++------ .../specialfields/SpecialFieldsUtilsTest.java | 8 +++--- 6 files changed, 34 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62cb1e5e539..ed83bb94f8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,7 +45,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - We fixed the import of MS-Office XML files, when the `month` field contained an invalid value. - ArXiV fetcher now checks similarity of entry when using DOI retrieval to avoid false positives [#2575](https://github.com/JabRef/jabref/issues/2575) - Sciencedirect/Elsevier fetcher is now able to scrape new HTML structure [#2576](https://github.com/JabRef/jabref/issues/2576) - + - Fixed the synchronization logic of keywords and special fields and vice versa [#2580](https://github.com/JabRef/jabref/issues/2580) ### Removed diff --git a/src/main/java/org/jabref/gui/FileDialog.java b/src/main/java/org/jabref/gui/FileDialog.java index 5b22f554534..c1e3e0d9359 100644 --- a/src/main/java/org/jabref/gui/FileDialog.java +++ b/src/main/java/org/jabref/gui/FileDialog.java @@ -35,7 +35,6 @@ */ @Deprecated public class FileDialog { - private static final Log LOGGER = LogFactory.getLog(FileDialog.class); private final FileChooser fileChooser; diff --git a/src/main/java/org/jabref/gui/specialfields/SpecialFieldDatabaseChangeListener.java b/src/main/java/org/jabref/gui/specialfields/SpecialFieldDatabaseChangeListener.java index 0c49f90a3d4..1ede5e8007e 100644 --- a/src/main/java/org/jabref/gui/specialfields/SpecialFieldDatabaseChangeListener.java +++ b/src/main/java/org/jabref/gui/specialfields/SpecialFieldDatabaseChangeListener.java @@ -26,19 +26,19 @@ public static SpecialFieldDatabaseChangeListener getInstance() { @Subscribe public void listen(EntryAddedEvent event) { - if (Globals.prefs.isKeywordSyncEnabled()) { - final BibEntry entry = event.getBibEntry(); - // NamedCompount code similar to SpecialFieldUpdateListener - NamedCompound nc = new NamedCompound(Localization.lang("Synchronized special fields based on keywords")); - List changes = SpecialFieldsUtils.syncSpecialFieldsFromKeywords(entry, Globals.prefs.getKeywordDelimiter()); - for(FieldChange change: changes) { - nc.addEdit(new UndoableFieldChange(change)); - } - - // Don't insert the compound into the undoManager, - // it would be added before the component which undoes the insertion of the entry and creates heavy problems - // (which prohibits the undo the deleting multiple entries) + if (!Globals.prefs.isKeywordSyncEnabled()) { + return; } - } + final BibEntry entry = event.getBibEntry(); + // NamedCompount code similar to SpecialFieldUpdateListener + NamedCompound nc = new NamedCompound(Localization.lang("Synchronized special fields based on keywords")); + List changes = SpecialFieldsUtils.syncSpecialFieldsFromKeywords(entry, Globals.prefs.getKeywordDelimiter()); + for(FieldChange change: changes) { + nc.addEdit(new UndoableFieldChange(change)); + } + // Don't insert the compound into the undoManager, + // it would be added before the component which undoes the insertion of the entry and creates heavy problems + // (which prohibits the undo the deleting multiple entries) + } } diff --git a/src/main/java/org/jabref/gui/specialfields/SpecialFieldUpdateListener.java b/src/main/java/org/jabref/gui/specialfields/SpecialFieldUpdateListener.java index 46f3fb5c540..30abd646262 100644 --- a/src/main/java/org/jabref/gui/specialfields/SpecialFieldUpdateListener.java +++ b/src/main/java/org/jabref/gui/specialfields/SpecialFieldUpdateListener.java @@ -23,6 +23,11 @@ public class SpecialFieldUpdateListener { @Subscribe public void listen(FieldChangedEvent fieldChangedEvent) { + // only sync if keyword sync is enabled + if (!Globals.prefs.isKeywordSyncEnabled()) { + return; + } + final BibEntry entry = fieldChangedEvent.getBibEntry(); final String fieldName = fieldChangedEvent.getFieldName(); // Source editor cycles through all entries @@ -32,15 +37,10 @@ public void listen(FieldChangedEvent fieldChangedEvent) { SwingUtilities.invokeLater(() -> { if (FieldName.KEYWORDS.equals(fieldName)) { SpecialFieldsUtils.syncSpecialFieldsFromKeywords(entry, Globals.prefs.getKeywordDelimiter()); - SwingUtilities - .invokeLater(() -> JabRefGUI.getMainFrame().getCurrentBasePanel().updateEntryEditorIfShowing()); - } else { - if (SpecialField.isSpecialField(fieldName)) { - SpecialFieldsUtils.syncKeywordsFromSpecialFields(entry, Globals.prefs.isKeywordSyncEnabled(), Globals.prefs.getKeywordDelimiter()); - SwingUtilities.invokeLater( - () -> JabRefGUI.getMainFrame().getCurrentBasePanel().updateEntryEditorIfShowing()); - } + } else if (SpecialField.isSpecialField(fieldName)) { + SpecialFieldsUtils.syncKeywordsFromSpecialFields(entry, Globals.prefs.getKeywordDelimiter()); } + SwingUtilities.invokeLater(() -> JabRefGUI.getMainFrame().getCurrentBasePanel().updateEntryEditorIfShowing()); }); } diff --git a/src/main/java/org/jabref/logic/specialfields/SpecialFieldsUtils.java b/src/main/java/org/jabref/logic/specialfields/SpecialFieldsUtils.java index bb6870c5b25..125a153c710 100644 --- a/src/main/java/org/jabref/logic/specialfields/SpecialFieldsUtils.java +++ b/src/main/java/org/jabref/logic/specialfields/SpecialFieldsUtils.java @@ -35,18 +35,16 @@ public static List updateField(SpecialField field, String value, Bi UpdateField.updateField(entry, field.getFieldName(), value, nullFieldIfValueIsTheSame) .ifPresent(fieldChange -> fieldChanges.add(fieldChange)); // we cannot use "value" here as updateField has side effects: "nullFieldIfValueIsTheSame" nulls the field if value is the same - fieldChanges.addAll(SpecialFieldsUtils.exportFieldToKeywords(field, entry, isKeywordSyncEnabled, keywordDelimiter)); + if (isKeywordSyncEnabled) { + fieldChanges.addAll(SpecialFieldsUtils.exportFieldToKeywords(field, entry, keywordDelimiter)); + } return fieldChanges; } - private static List exportFieldToKeywords(SpecialField specialField, BibEntry entry, boolean isKeywordSyncEnabled, Character keywordDelimiter) { + private static List exportFieldToKeywords(SpecialField specialField, BibEntry entry, Character keywordDelimiter) { List fieldChanges = new ArrayList<>(); - if (!isKeywordSyncEnabled) { - return fieldChanges; - } - Optional newValue = entry.getField(specialField.getFieldName()).map(Keyword::new); KeywordList keyWords = specialField.getKeyWords(); @@ -59,11 +57,11 @@ private static List exportFieldToKeywords(SpecialField specialField /** * Update keywords according to values of special fields */ - public static List syncKeywordsFromSpecialFields(BibEntry entry, boolean isKeywordSyncEnabled, Character keywordDelimiter) { + public static List syncKeywordsFromSpecialFields(BibEntry entry, Character keywordDelimiter) { List fieldChanges = new ArrayList<>(); for(SpecialField field: SpecialField.values()) { - fieldChanges.addAll(SpecialFieldsUtils.exportFieldToKeywords(field, entry, isKeywordSyncEnabled, keywordDelimiter)); + fieldChanges.addAll(SpecialFieldsUtils.exportFieldToKeywords(field, entry, keywordDelimiter)); } return fieldChanges; @@ -71,6 +69,7 @@ public static List syncKeywordsFromSpecialFields(BibEntry entry, bo private static List importKeywordsForField(KeywordList keywordList, SpecialField field, BibEntry entry) { List fieldChanges = new ArrayList<>(); + KeywordList values = field.getKeyWords(); Optional newValue = Optional.empty(); for (Keyword keyword : values) { @@ -88,7 +87,7 @@ private static List importKeywordsForField(KeywordList keywordList, } /** - * updates field values according to keywords + * Updates special field values according to keywords */ public static List syncSpecialFieldsFromKeywords(BibEntry entry, Character keywordDelimiter) { List fieldChanges = new ArrayList<>(); diff --git a/src/test/java/org/jabref/logic/specialfields/SpecialFieldsUtilsTest.java b/src/test/java/org/jabref/logic/specialfields/SpecialFieldsUtilsTest.java index d99c1e0219e..26ea98db537 100644 --- a/src/test/java/org/jabref/logic/specialfields/SpecialFieldsUtilsTest.java +++ b/src/test/java/org/jabref/logic/specialfields/SpecialFieldsUtilsTest.java @@ -19,7 +19,7 @@ public class SpecialFieldsUtilsTest { public void syncKeywordsFromSpecialFieldsWritesToKeywords() { BibEntry entry = new BibEntry(); entry.setField("ranking", "rank2"); - SpecialFieldsUtils.syncKeywordsFromSpecialFields(entry, true, ','); + SpecialFieldsUtils.syncKeywordsFromSpecialFields(entry, ','); assertEquals(Optional.of("rank2"), entry.getField("keywords")); } @@ -27,7 +27,7 @@ public void syncKeywordsFromSpecialFieldsWritesToKeywords() { public void syncKeywordsFromSpecialFieldsCausesChange() { BibEntry entry = new BibEntry(); entry.setField("ranking", "rank2"); - List changes = SpecialFieldsUtils.syncKeywordsFromSpecialFields(entry, true, ','); + List changes = SpecialFieldsUtils.syncKeywordsFromSpecialFields(entry, ','); assertTrue(changes.size() > 0); } @@ -36,14 +36,14 @@ public void syncKeywordsFromSpecialFieldsOverwritesKeywords() { BibEntry entry = new BibEntry(); entry.setField("ranking", "rank2"); entry.setField("keywords", "rank3"); - SpecialFieldsUtils.syncKeywordsFromSpecialFields(entry, true, ','); + SpecialFieldsUtils.syncKeywordsFromSpecialFields(entry, ','); assertEquals(Optional.of("rank2"), entry.getField("keywords")); } @Test public void syncKeywordsFromSpecialFieldsForEmptyFieldCausesNoChange() { BibEntry entry = new BibEntry(); - List changes = SpecialFieldsUtils.syncKeywordsFromSpecialFields(entry, true, ','); + List changes = SpecialFieldsUtils.syncKeywordsFromSpecialFields(entry, ','); assertFalse(changes.size() > 0); } From 546423ad048a12e1a81f6ad9999fa8727ef33a9e Mon Sep 17 00:00:00 2001 From: Eduard Braun Date: Wed, 22 Feb 2017 22:41:18 +0100 Subject: [PATCH 6/8] Update IEEEJournalList (#2579) lists compiled from http://tug.ctan.org/tex-archive/macros/latex/contrib/IEEEtran/bibtex/ --- .../journals/IEEEJournalListCode.txt | 114 ++++-- .../journals/IEEEJournalListText.txt | 343 +++++++++--------- src/main/resources/journals/journalList.txt | 1 - 3 files changed, 252 insertions(+), 206 deletions(-) diff --git a/src/main/resources/journals/IEEEJournalListCode.txt b/src/main/resources/journals/IEEEJournalListCode.txt index 804a82ff730..c448f17599f 100644 --- a/src/main/resources/journals/IEEEJournalListCode.txt +++ b/src/main/resources/journals/IEEEJournalListCode.txt @@ -1,9 +1,13 @@ +# list compiled from http://tug.ctan.org/tex-archive/macros/latex/contrib/IEEEtran/bibtex/IEEEfull.bib (2015/08/26 V1.14) Canadian Journal of Electrical and Computer Engineering=#IEEE_J_CJECE# +China Communications Magazine=#IEEE_M_CHINAC# +Computer=#IEEE_M_C# +IEEE ASSP Magazine=#IEEE_M_ASSP# +IEEE Access=#IEEE_O_ACC# IEEE Aerospace and Electronics Systems Magazine=#IEEE_M_AES# IEEE Annals of the History of Computing=#IEEE_M_HIST# IEEE Antennas and Propagation Magazine=#IEEE_M_AP# IEEE Antennas and Wireless Propagation Letters=#IEEE_J_AWPL# -IEEE ASSP Magazine=#IEEE_M_ASSP# IEEE Circuits and Devices Magazine=#IEEE_M_CD# IEEE Circuits and Systems Magazine=#IEEE_M_CAS# IEEE Communications Letters=#IEEE_J_COML# @@ -15,76 +19,105 @@ IEEE Computational Science and Engineering Magazine=#IEEE_M_CSEM# IEEE Computer Applications in Power=#IEEE_M_CAP# IEEE Computer Architecture Letters=#IEEE_J_CAL# IEEE Computer Graphics and Applications=#IEEE_M_CGA# -IEEE Computer=#IEEE_M_C# IEEE Computing in Science and Engineering=#IEEE_M_CSE# IEEE Concurrency=#IEEE_M_CONC# IEEE Control Systems Magazine=#IEEE_M_CS# -IEEE Control Systems=#IEEE_M_CS# +IEEE Design & Test=#IEEE_M_DT# IEEE Design and Test of Computers=#IEEE_M_DTC# IEEE Distributed Systems Online=#IEEE_O_DSO# IEEE Electrical Insulation Magazine=#IEEE_M_EI# -IEEE Electron Device Letters=#IEEE_J_EDL# +IEEE Electrification Magazine=#IEEE_M_ETF# IEEE ElectroTechnology Review=#IEEE_M_ETR# -IEEE Engineering in Medicine and Biology Magazine=#IEEE_M_EMB# +IEEE Electromagnetic Compatibility Magazine=#IEEE_M_EMC# +IEEE Electron Device Letters=#IEEE_J_EDL# +IEEE Embedded Systems Letters=#IEEE_J_ES# IEEE Engineering Management Review=#IEEE_M_EMR# +IEEE Engineering in Medicine and Biology Magazine=#IEEE_M_EMB# IEEE Expert=#IEEE_M_EXP# IEEE Geoscience and Remote Sensing Letters=#IEEE_J_GRSL# +IEEE Geoscience and Remote Sensing Magazine=#IEEE_M_GRS# +IEEE IT Professional=#IEEE_M_ITP# IEEE Industrial Electronics Magazine=#IEEE_M_IE# IEEE Industry Applications Magazine=#IEEE_M_IA# IEEE Instrumentation and Measurement Magazine=#IEEE_M_IM# IEEE Intelligent Systems=#IEEE_M_IS# IEEE Intelligent Transportation Systems Magazine=#IEEE_M_ITS# IEEE Internet Computing=#IEEE_M_IC# -IEEE IT Professional=#IEEE_M_ITP# +IEEE Internet of Things Journal=#IEEE_J_IOT# +IEEE Journal of Biomedical and Health Informatics=#IEEE_J_BHI# +IEEE Journal of Electron Devices Society=#IEEE_J_EDS# +IEEE Journal of Microelectromechanical Systems=#IEEE_J_MEMSI# IEEE Journal of Oceanic Engineering=#IEEE_J_OE# +IEEE Journal of Optical Communications and Networking=#IEEE_J_OCN# +IEEE Journal of Photovoltaics=#IEEE_J_PHOT# IEEE Journal of Product Safety Engineering=#IEEE_J_PSE# IEEE Journal of Quantum Electronics=#IEEE_J_JQE# IEEE Journal of Robotics and Automation=#IEEE_J_JRA# +IEEE Journal of Selected Topics in Applied Earth Observations and Remote Sensing=#IEEE_J_STARS# IEEE Journal of Selected Topics in Quantum Electronics=#IEEE_J_JSTQE# IEEE Journal of Selected Topics in Signal Processing=#IEEE_J_STSP# -IEEE Journal of Selected Topics on Applied Observations and Remote Sensing=#IEEE_J_STARS# IEEE Journal of Solid-State Circuits=#IEEE_J_JSSC# +IEEE Journal of Translational Engineering in Health and Medicine=#IEEE_J_TEHM# +IEEE Journal on Exploratory Solid-State Computational Devices and Circuits=#IEEE_J_XCDC# +IEEE Journal on Multiscale and Multiphysics Computational Techniques=#IEEE_J_MMCT# IEEE Journal on Selected Areas in Communications=#IEEE_J_JSAC# IEEE Journal on Technology in Computer Aided Design=#IEEE_J_TCAD# +IEEE Life Sciences Letters=#IEEE_J_LS# +IEEE Magnetics Letters=#IEEE_J_MAGL# IEEE Micro=#IEEE_M_MICRO# +IEEE Microwave Magazine=#IEEE_M_MW# IEEE Microwave and Guided Wave Letters=#IEEE_J_MGWL# IEEE Microwave and Wireless Components Letters=#IEEE_J_MWCL# -IEEE Microwave Magazine=#IEEE_M_MW# IEEE Multimedia=#IEEE_M_MM# +IEEE Nanotechnology Express=#IEEE_J_ENANO# IEEE Nanotechnology Magazine=#IEEE_M_NANO# IEEE Network=#IEEE_M_NET# IEEE Personal Communications Magazine=#IEEE_M_PCOM# IEEE Pervasive Computing=#IEEE_M_PVC# +IEEE Photonics Journal=#IEEE_J_PJ# IEEE Photonics Technology Letters=#IEEE_J_PTL# IEEE Potentials=#IEEE_M_POT# -IEEE Power and Energy Magazine=#IEEE_M_PE# IEEE Power Electronics Letters=#IEEE_J_PEL# +IEEE Power Electronics Magazine=#IEEE_M_PEL# IEEE Power Engineering Review=#IEEE_M_PER# +IEEE Power and Energy Magazine=#IEEE_M_PE# +IEEE Power and Energy Technology Systems Journal=#IEEE_J_PETS# +IEEE Pulse=#IEEE_M_PULSE# +IEEE RFIC Journal=#IEEE_J_RFIC# +IEEE RFID Journal=#IEEE_J_RFID# IEEE Reviews in Biomedical Engineering=#IEEE_J_RBME# +IEEE Revista Iberoamericana de Technolog'ias del Aprendizaje=#IEEE_J_RITA# +IEEE Robotics and Automation Letters=#IEEE_J_RAL# IEEE Robotics and Automation Magazine=#IEEE_M_RA# IEEE Security and Privacy=#IEEE_M_SAP# IEEE Sensors Journal=#IEEE_J_SENSOR# IEEE Signal Processing Letters=#IEEE_J_SPL# IEEE Signal Processing Magazine=#IEEE_M_SP# IEEE Software=#IEEE_M_S# +IEEE Solid-State Circuits Magazine=#IEEE_M_SSC# IEEE Spectrum=#IEEE_M_SPECT# +IEEE Sustainable Computing=#IEEE_J_SUSC# IEEE Systems Journal=#IEEE_J_SYST# +IEEE Systems, Man, and Cybernetics Magazine=#IEEE_M_SMC# IEEE Technology and Society Magazine=#IEEE_M_TS# -IEEE Transactions on Acoustics, Speech and Signal Processing=#IEEE_J_ASSP# IEEE Transactions on Acoustics, Speech, and Signal Processing=#IEEE_J_ASSP# IEEE Transactions on Advanced Packaging=#IEEE_J_ADVP# IEEE Transactions on Aeronautical and Navigational Electronics=#IEEE_J_ANNE# +IEEE Transactions on Aerospace=#IEEE_J_AS# IEEE Transactions on Aerospace and Electronic Systems=#IEEE_J_AES# IEEE Transactions on Aerospace and Navigational Electronics=#IEEE_J_ANE# -IEEE Transactions on Aerospace=#IEEE_J_AS# +IEEE Transactions on Affective Computing=#IEEE_J_AFFC# IEEE Transactions on Airborne Electronics=#IEEE_J_AIRE# IEEE Transactions on Antennas and Propagation=#IEEE_J_AP# IEEE Transactions on Applications and Industry=#IEEE_J_APPIND# IEEE Transactions on Applied Superconductivity=#IEEE_J_ASC# -IEEE Transactions on Audio and Electroacoustics=#IEEE_J_AUEA# IEEE Transactions on Audio=#IEEE_J_AU# +IEEE Transactions on Audio and Electroacoustics=#IEEE_J_AUEA# +IEEE Transactions on Audio, Speech, and Language Processing=#IEEE_J_ASL# IEEE Transactions on Automatic Control=#IEEE_J_AC# IEEE Transactions on Automation Science and Engineering=#IEEE_J_ASE# +IEEE Transactions on Autonomous Mental Development=#IEEE_J_AMD# +IEEE Transactions on Big Data=#IEEE_J_BD# IEEE Transactions on Bio-Medical Electronics=#IEEE_J_BMELC# IEEE Transactions on Bio-Medical Engineering=#IEEE_J_B-ME# IEEE Transactions on Biomedical Circuits and Systems=#IEEE_J_BCAS# @@ -92,25 +125,33 @@ IEEE Transactions on Biomedical Engineering=#IEEE_J_BME# IEEE Transactions on Broadcast and Television Receivers=#IEEE_J_BCTV# IEEE Transactions on Broadcasting=#IEEE_J_BC# IEEE Transactions on Circuit Theory=#IEEE_J_CT# -IEEE Transactions on Circuits and Systems for Video Technology=#IEEE_J_CASVT# +IEEE Transactions on Circuits and Systems=#IEEE_J_CAS# IEEE Transactions on Circuits and Systems I: Fundamental Theory and Applications=#IEEE_J_CASI# IEEE Transactions on Circuits and Systems I: Regular Papers=#IEEE_J_CASI_RP# IEEE Transactions on Circuits and Systems II: Analog and Digital Signal Processing=#IEEE_J_CASII# IEEE Transactions on Circuits and Systems II: Express Briefs=#IEEE_J_CASII_EB# -IEEE Transactions on Circuits and Systems=#IEEE_J_CAS# +IEEE Transactions on Circuits and Systems for Video Technology=#IEEE_J_CASVT# +IEEE Transactions on Cloud Computing=#IEEE_J_CC# +IEEE Transactions on Cognitive Communications and Networking=#IEEE_J_CCN# +IEEE Transactions on Cognitive and Developmental Systems=#IEEE_J_CDS# IEEE Transactions on Communication Technology=#IEEE_J_COMT# IEEE Transactions on Communications=#IEEE_J_COM# IEEE Transactions on Component Parts=#IEEE_J_CPART# IEEE Transactions on Components and Packaging Technologies=#IEEE_J_CAPTS# IEEE Transactions on Components and Packaging Technology=#IEEE_J_CAPT# IEEE Transactions on Components, Hybrids and Manufacturing Technology=#IEEE_J_CHMT# -IEEE Transactions on Components, Packaging and Manufacturing Technology, Part A=#IEEE_J_CPMTA# -IEEE Transactions on Components, Packaging and Manufacturing Technology, Part B: Advanced Packaging=#IEEE_J_CPMTB# -IEEE Transactions on Components, Packaging and Manufacturing Technology, Part C: Manufacturing=#IEEE_J_CPMTC# +IEEE Transactions on Components, Packaging and Manufacturing Technology=#IEEE_J_CPMT# +IEEE Transactions on Components, Packaging and Manufacturing Technology A=#IEEE_J_CPMTA# +IEEE Transactions on Components, Packaging and Manufacturing Technology B: Advanced Packaging=#IEEE_J_CPMTB# +IEEE Transactions on Components, Packaging and Manufacturing Technology C: Manufacturing=#IEEE_J_CPMTC# +IEEE Transactions on Computational Intelligence and AI in Games=#IEEE_J_CIAIG# +IEEE Transactions on Computational Social Systems=#IEEE_J_CSS# IEEE Transactions on Computer-Aided Design of Integrated Circuits and Systems=#IEEE_J_CAD# IEEE Transactions on Computers=#IEEE_J_C# IEEE Transactions on Consumer Electronics=#IEEE_J_CE# IEEE Transactions on Control Systems Technology=#IEEE_J_CST# +IEEE Transactions on Control of Network Systems=#IEEE_J_CNS# +IEEE Transactions on Cybernetics=#IEEE_J_CYB# IEEE Transactions on Dependable and Secure Computing=#IEEE_J_DSC# IEEE Transactions on Device and Materials Reliability=#IEEE_J_DMR# IEEE Transactions on Dielectrics and Electrical Insulation=#IEEE_J_DEI# @@ -120,26 +161,31 @@ IEEE Transactions on Electromagnetic Compatibility=#IEEE_J_EMC# IEEE Transactions on Electron Devices=#IEEE_J_ED# IEEE Transactions on Electronic Computers=#IEEE_J_ECOMP# IEEE Transactions on Electronics Packaging Manufacturing=#IEEE_J_EPM# +IEEE Transactions on Emerging Topics in Computing=#IEEE_J_ETC# +IEEE Transactions on Emerging and Selected Topics in Circuits and Systems=#IEEE_J_ETCAS# +IEEE Transactions on Emerging and Selected Topics in Power Electronics=#IEEE_J_ESTPE# IEEE Transactions on Energy Conversion=#IEEE_J_EC# IEEE Transactions on Engineering Management=#IEEE_J_EM# IEEE Transactions on Engineering Writing and Speech=#IEEE_J_EWS# IEEE Transactions on Evolutionary Computation=#IEEE_J_EVC# IEEE Transactions on Fuzzy Systems=#IEEE_J_FUZZ# -IEEE Transactions on Geoscience and Remote Sensing=#IEEE_J_GRS# IEEE Transactions on Geoscience Electronics=#IEEE_J_GE# +IEEE Transactions on Geoscience and Remote Sensing=#IEEE_J_GRS# IEEE Transactions on Haptics=#IEEE_J_H# IEEE Transactions on Human Factors in Electronics=#IEEE_J_HFE# +IEEE Transactions on Human-Machine Systems=#IEEE_J_HMS# IEEE Transactions on Image Processing=#IEEE_J_IP# -IEEE Transactions on Industrial Electronics and Control Instrumentation=#IEEE_J_IECI# IEEE Transactions on Industrial Electronics=#IEEE_J_IE# +IEEE Transactions on Industrial Electronics and Control Instrumentation=#IEEE_J_IECI# IEEE Transactions on Industrial Informatics=#IEEE_J_IINF# -IEEE Transactions on Industry and General Applications=#IEEE_J_IGA# IEEE Transactions on Industry Applications=#IEEE_J_IA# +IEEE Transactions on Industry and General Applications=#IEEE_J_IGA# IEEE Transactions on Information Forensics and Security=#IEEE_J_IFS# IEEE Transactions on Information Technology in Biomedicine=#IEEE_J_ITBM# IEEE Transactions on Information Theory=#IEEE_J_IT# IEEE Transactions on Instrumentation and Measurement=#IEEE_J_IM# IEEE Transactions on Intelligent Transportation Systems=#IEEE_J_ITS# +IEEE Transactions on Intelligent Vehicles=#IEEE_J_IV# IEEE Transactions on Knowledge and Data Engineering=#IEEE_J_KDE# IEEE Transactions on Learning Technologies=#IEEE_J_LT# IEEE Transactions on Magnetics=#IEEE_J_MAG# @@ -150,11 +196,15 @@ IEEE Transactions on Medical Imaging=#IEEE_J_MI# IEEE Transactions on Microwave Theory and Techniques=#IEEE_J_MTT# IEEE Transactions on Military Electronics=#IEEE_J_MIL# IEEE Transactions on Mobile Computing=#IEEE_J_MC# +IEEE Transactions on Molecular, Biological and Multi-Scale Communications=#IEEE_J_MBSC# +IEEE Transactions on Multi-Scale Computing Systems=#IEEE_J_MSCS# IEEE Transactions on Multimedia=#IEEE_J_MM# IEEE Transactions on NanoBioscience=#IEEE_J_NB# IEEE Transactions on Nanotechnology=#IEEE_J_NANO# +IEEE Transactions on Network Science and Engineering=#IEEE_J_NSE# IEEE Transactions on Network and Service Management=#IEEE_J_NSM# IEEE Transactions on Neural Networks=#IEEE_J_NN# +IEEE Transactions on Neural Networks and Learning Systems=#IEEE_J_NNLS# IEEE Transactions on Neural Systems and Rehabilitation Engineering=#IEEE_J_NSRE# IEEE Transactions on Nuclear Science=#IEEE_J_NS# IEEE Transactions on Parallel and Distributed Systems=#IEEE_J_PDS# @@ -170,22 +220,26 @@ IEEE Transactions on Professional Communication=#IEEE_J_PC# IEEE Transactions on Radio Frequency Interference=#IEEE_J_RFI# IEEE Transactions on Rehabilitation Engineering=#IEEE_J_RE# IEEE Transactions on Reliability=#IEEE_J_R# -IEEE Transactions on Robotics and Automation=#IEEE_J_RA# IEEE Transactions on Robotics=#IEEE_J_RO# +IEEE Transactions on Robotics and Automation=#IEEE_J_RA# IEEE Transactions on Semiconductor Manufacturing=#IEEE_J_SM# IEEE Transactions on Services Computing=#IEEE_J_SC# IEEE Transactions on Signal Processing=#IEEE_J_SP# +IEEE Transactions on Signal and Information Processing over Networks=#IEEE_J_SIPN# +IEEE Transactions on Smart Grid=#IEEE_J_SG# IEEE Transactions on Software Engineering=#IEEE_J_SE# IEEE Transactions on Sonics and Ultrasonics=#IEEE_J_SU# IEEE Transactions on Speech and Audio Processing=#IEEE_J_SAP# +IEEE Transactions on Sustainable Energy=#IEEE_J_STE# IEEE Transactions on Systems Science and Cybernetics=#IEEE_J_SSC# -IEEE Transactions on Systems, Man and Cybernetics=#IEEE_J_SMC# -IEEE Transactions on Systems, Man, and Cybernetics, Part A: Systems and Humans=#IEEE_J_SMCA# -IEEE Transactions on Systems, Man, and Cybernetics, Part B: Cybernetics=#IEEE_J_SMCB# -IEEE Transactions on Systems, Man, and Cybernetics, Part C: Applications and Reviews=#IEEE_J_SMCC# IEEE Transactions on Systems, Man, and Cybernetics=#IEEE_J_SMC# +IEEE Transactions on Systems, Man, and Cybernetics A: Systems and Humans=#IEEE_J_SMCA# +IEEE Transactions on Systems, Man, and Cybernetics B: Cybernetics=#IEEE_J_SMCB# +IEEE Transactions on Systems, Man, and Cybernetics C: Applications and Reviews=#IEEE_J_SMCC# +IEEE Transactions on Systems, Man, and Cybernetics: Systems=#IEEE_J_SMCS# +IEEE Transactions on Terahertz Science and Technology=#IEEE_J_TTHZ# +IEEE Transactions on Transportation Electrification=#IEEE_J_TTE# IEEE Transactions on Ultrasonics Engineering=#IEEE_J_UE# -IEEE Transactions on Ultrasonics, Ferroelectrics and Frequency Control=#IEEE_J_UFFC# IEEE Transactions on Ultrasonics, Ferroelectrics, and Frequency Control=#IEEE_J_UFFC# IEEE Transactions on Vehicular Communications=#IEEE_J_VC# IEEE Transactions on Vehicular Technology=#IEEE_J_VT# @@ -194,19 +248,17 @@ IEEE Transactions on Visualization and Computer Graphics=#IEEE_J_VCG# IEEE Transactions on Wireless Communications=#IEEE_J_WCOM# IEEE Translation Journal on Magnetics in Japan=#IEEE_J_TJMJ# IEEE Vehicular Technology Magazine=#IEEE_M_VT# -IEEE Wireless Communications Magazine=#IEEE_M_WC# IEEE Wireless Communications=#IEEE_M_WC# +IEEE Wireless Communications Letters=#IEEE_J_WCOML# +IEEE/ACM Transactions on Audio, Speech, and Language Processing=#IEEE_J_ASLP# IEEE/ACM Transactions on Computational Biology and Bioinformatics=#IEEE_J_CBB# IEEE/ACM Transactions on Networking=#IEEE_J_NET# IEEE/ASME Journal of Microelectromechanical Systems=#IEEE_J_MEMS# IEEE/ASME Transactions on Mechatronics=#IEEE_J_MECH# +IEEE/CAA Journal of Automatica Sinica=#IEEE_J_JAS# IEEE/ECS Electrochemical and Solid-State Letters=#IEEE_J_ESSL# IEEE/OSA Journal of Display Technology=#IEEE_J_JDT# IEEE/OSA Journal of Lightwave Technology=#IEEE_J_JLT# IEEE/TMS Journal of Electronic Materials=#IEEE_J_JEM# -Journal of Lightwave Technology=#IEEE_J_JLT# -Journal of Microelectromechanical Systems=#IEEE_J_MEMS# Proceedings of the IEEE=#IEEE_J_PROC# Today's Engineer=#IEEE_M_TODAY# -Transactions on Computers=#IEEE_J_C# - diff --git a/src/main/resources/journals/IEEEJournalListText.txt b/src/main/resources/journals/IEEEJournalListText.txt index e83b72547c6..6bc31a3ea59 100644 --- a/src/main/resources/journals/IEEEJournalListText.txt +++ b/src/main/resources/journals/IEEEJournalListText.txt @@ -1,269 +1,264 @@ -Canadian Journal of Electrical and Computer Engineering = Can. J. Electr. Comput. Eng. +# list compiled from http://tug.ctan.org/tex-archive/macros/latex/contrib/IEEEtran/bibtex/IEEEabrv.bib (2015/08/26 V1.14) +Canadian Journal of Electrical and Computer Engineering = Canadian J. Elect. Comput. Eng. +China Communications = China Commun. +Computer = Computer +IEEE ASSP Magazine = IEEE ASSP Mag. IEEE Access = IEEE Access -IEEE Aerospace and Electronic Systems Magazine = IEEE Aerosp. Electron. Syst. Mag. +IEEE Aerospace and Electronics Systems Magazine = IEEE Aerosp. Electron. Syst. Mag. IEEE Annals of the History of Computing = IEEE Ann. Hist. Comput. -IEEE Antennas and Propagation Magazine = IEEE Antennas. Propag. -IEEE Antennas and Wireless Propagation Letters = IEEE Antennas Wirel. Propag. Lett. -IEEE Biometrics Compendium = IEEE Biometrics Compend. -IEEE Circuits & Devices = IEEE Circuits. Device. +IEEE Antennas and Propagation Magazine = IEEE Antennas Propag. Mag. +IEEE Antennas and Wireless Propagation Letters = IEEE Antennas Wireless Propag. Lett. IEEE Circuits and Devices Magazine = IEEE Circuits Devices Mag. IEEE Circuits and Systems Magazine = IEEE Circuits Syst. Mag. -IEEE Cloud Computing = IEEE Cloud Comput. IEEE Communications Letters = IEEE Commun. Lett. IEEE Communications Magazine = IEEE Commun. Mag. -IEEE Communications Surveys and Tutorials = IEEE Commun. Surv. Tutorials +IEEE Communications Society Magazine = IEEE Commun. Soc. Mag. +IEEE Communications Surveys and Tutorials = IEEE Commun. Surveys Tuts. IEEE Computational Intelligence Magazine = IEEE Comput. Intell. Mag. -IEEE Computational Science & Engineering = IEEE Comput. Sci. Eng. +IEEE Computational Science and Engineering Magazine = IEEE Comput. Sci. Eng. Mag. IEEE Computer Applications in Power = IEEE Comput. Appl. Power IEEE Computer Architecture Letters = IEEE Comput. Archit. Lett. -IEEE Computer Graphics and Applications = IEEE Comput. Graphics Appl. -IEEE Computer Group News = IEEE Comput. Group. N. +IEEE Computer Graphics and Applications = IEEE Comput. Graph. Appl. +IEEE Computing in Science and Engineering = IEEE Comput. Sci. Eng. IEEE Concurrency = IEEE Concurrency -IEEE Consumer Electronics Magazine = IEEE Consum. Electron. Mag. -IEEE Control Systems = IEEE Control Syst. IEEE Control Systems Magazine = IEEE Control Syst. Mag. IEEE Design & Test = IEEE Des. Test -IEEE Design & Test of Computers = IEEE Des. Test. Comput. -IEEE Design and Test of Computers = IEEE Des. Test Comput. +IEEE Design and Test of Computers = IEEE Des. Test. Comput. IEEE Distributed Systems Online = IEEE Distrib. Syst. Online IEEE Electrical Insulation Magazine = IEEE Electr. Insul. Mag. -IEEE Electrification Magazine = IEEE Electrif. Mag. -IEEE Electromagnetic Compatibility Magazine = IEEE Electromagn. Compat. Mag. -IEEE Electromagnetic Compatibility Symposium Record = IEEE Electroman. Comp. +IEEE Electrification Magazine = IEEE Electrific. Mag. +IEEE ElectroTechnology Review = IEEE ElectroTechnol. Rev. +IEEE Electromagnetic Compatibility Magazine = IEEE Electromagn. Compat. IEEE Electron Device Letters = IEEE Electron Device Lett. -IEEE Embedded Systems Letters = IEEE Embedded Sys. Lett. +IEEE Embedded Systems Letters = IEEE Embedded Syst. Lett. +IEEE Engineering Management Review = IEEE Eng. Manag. Rev. IEEE Engineering in Medicine and Biology Magazine = IEEE Eng. Med. Biol. Mag. -IEEE Engineering Management Review = IEEE Eng. Manage. Rev. -IEEE Expert-intelligent Systems & their Applications = IEEE Expert. -IEEE Geoscience and Remote Sensing Letters = IEEE Geosci. Remote. S. +IEEE Expert = IEEE Expert +IEEE Geoscience and Remote Sensing Letters = IEEE Geosci. Remote Sens. Lett. IEEE Geoscience and Remote Sensing Magazine = IEEE Geosci. Remote Sens. Mag. +IEEE IT Professional = IEEE IT Prof. IEEE Industrial Electronics Magazine = IEEE Ind. Electron. Mag. IEEE Industry Applications Magazine = IEEE Ind. Appl. Mag. -IEEE Instrumentation & Measurement Magazine = IEEE Instru. Meas. Mag. IEEE Instrumentation and Measurement Magazine = IEEE Instrum. Meas. Mag. -IEEE Intelligent Systems & their Applications = IEEE Intell. Syst. App. IEEE Intelligent Systems = IEEE Intell. Syst. IEEE Intelligent Transportation Systems Magazine = IEEE Intell. Transp. Syst. Mag. -IEEE Internet Computing = IEEE Internet. Comput. -IEEE Internet of Things Journal = IEEE IoT J. -IEEE Journal of Biomedical and Health Informatics = IEEE J. Biomed. Health. Inf. -IEEE Journal of Oceanic Engineering = IEEE J. Oceanic. Eng. -IEEE Journal of Photovoltaics = IEEE J. Photovoltaics -IEEE Journal of Quantum Electronics = IEEE J. Quantum. Electron. -IEEE Journal of Robotics and Automation = IEEE T. Robotic. Autom. -IEEE Journal of Selected Topics in Applied Earth Observations and Remote Sensing = IEEE J. Sel. Top. Appl. Earth Obs. Remote Sens. -IEEE Journal of Selected Topics in Quantum Electronics = IEEE J. Sel. Topics in Quantum Electron. -IEEE Journal of Selected Topics in Signal Processing = IEEE J. Sel. Top. Signal Process. +IEEE Internet Computing = IEEE Internet Comput. +IEEE Internet of Things Journal = IEEE Internet Things J. +IEEE Journal of Biomedical and Health Informatics = IEEE J. Biomed. Health Inform. +IEEE Journal of Electron Devices Society = IEEE J. Electron Devices Soc. +IEEE Journal of Microelectromechanical Systems = J. Microelectromech. Syst. +IEEE Journal of Oceanic Engineering = IEEE J. Ocean. Eng. +IEEE Journal of Optical Communications and Networking = IEEE J. Opt. Commun. Netw. +IEEE Journal of Photovoltaics = IEEE J. Photovolt. +IEEE Journal of Product Safety Engineering = IEEE J. Product Safety Eng. +IEEE Journal of Quantum Electronics = IEEE J. Quantum Electron. +IEEE Journal of Robotics and Automation = IEEE J. Robot. Autom. +IEEE Journal of Selected Topics in Applied Earth Observations and Remote Sensing = IEEE J. Sel. Topics Appl. Earth Observ. Remote Sens. +IEEE Journal of Selected Topics in Quantum Electronics = IEEE J. Sel. Topics Quantum Electron. +IEEE Journal of Selected Topics in Signal Processing = IEEE J. Sel. Topics Signal Process. IEEE Journal of Solid-State Circuits = IEEE J. Solid-State Circuits -IEEE Journal of the Electron Devices Society = IEEE J. Electron Devices Soc. -IEEE Journal on Electronic Circuits and Systems = IEE J. Electron. Circuits Syst. -IEEE Journal on Emerging and Selected Topics in Circuits and Systems = IEEE J. Emerging Sel. Top. Circuits Syst. -IEEE Journal on Emerging and Selected Topics in Power Electronics = IEEE J. Emerging Sel. Top. Power Electron. +IEEE Journal of Translational Engineering in Health and Medicine = IEEE J. Transl. Eng. Health Med. +IEEE Journal on Exploratory Solid-State Computational Devices and Circuits = IEEE J. Explor. Solid-State Computat. Devices Circuits +IEEE Journal on Multiscale and Multiphysics Computational Techniques = IEEE J. Multiscale and Multiphys. Comput. Techn. IEEE Journal on Selected Areas in Communications = IEEE J. Sel. Areas Commun. -IEEE Latin America Transactions = IEEE Lat. Am. Trans. -IEEE Learning Technology = IEEE Learn. Technol. +IEEE Journal on Technology in Computer Aided Design = IEEE J. Technol. Comput. Aided Design IEEE Life Sciences Letters = IEEE Life Sci. Lett. IEEE Magnetics Letters = IEEE Magn. Lett. -IEEE Micro = IEEE Micro. -IEEE Microwave and Guided Wave Letters = IEEE Microw. Guided. W. -IEEE Microwave and Wireless Components Letters = IEEE Microwave Wireless Compon. Lett. -IEEE Microwave Magazine = IEEE Microwave Mag. -IEEE Multimedia = IEEE Multimedia. -IEEE Nanotechnology Magazine = IEEE Nanatechnol. Mag. -IEEE Network = IEEE Network. -IEEE Parallel & Distributed Technology = IEEE Parall. Distrib. -IEEE Personal Communications = IEEE Pers. Commun. +IEEE Micro = IEEE Micro +IEEE Microwave Magazine = IEEE Microw. Mag. +IEEE Microwave and Guided Wave Letters = IEEE Microw. Guided Wave Lett. +IEEE Microwave and Wireless Components Letters = IEEE Microw. Wireless Compon. Lett. +IEEE Multimedia = IEEE Multimedia +IEEE Nanotechnology Express = IEEE Nanotechnol. Express +IEEE Nanotechnology Magazine = IEEE Nanotechnol. Mag. +IEEE Network = IEEE Netw. +IEEE Personal Communications Magazine = IEEE Personal Commun. Mag. IEEE Pervasive Computing = IEEE Pervasive Comput. -IEEE Photonics Journal = IEEE Photonics J. -IEEE Photonics Technology Letters = IEEE Photonics Technol. Lett. -IEEE Potentials = IEEE Potentials. -IEEE Power and Energy Magazine = IEEE Power Energy Mag. -IEEE Power and Energy Technology Systems Journal = IEEE Power Energy Technol. Syst. J. +IEEE Photonics Journal = IEEE Photon. J. +IEEE Photonics Technology Letters = IEEE Photon. Technol. Lett. +IEEE Potentials = IEEE Potentials IEEE Power Electronics Letters = IEEE Power Electron. Lett. IEEE Power Electronics Magazine = IEEE Power Electron. Mag. IEEE Power Engineering Review = IEEE Power Eng. Rev. +IEEE Power and Energy Magazine = IEEE Power Energy Mag. +IEEE Power and Energy Technology Systems Journal = IEEE Power Energy Technol. Syst. J. IEEE Pulse = IEEE Pulse +IEEE RFIC Journal = IEEE RFIC J. +IEEE RFID Journal = IEEE RFID J. IEEE Reviews in Biomedical Engineering = IEEE Rev. Biomed. Eng. -IEEE RFIC Virtual Journal = IEEE RFIC Virtual J. -IEEE RFID Virtual Journal = IEEE RFID Virtual J. -IEEE Robotics & Automation Magazine = IEEE Robot. Autom. Mag. -IEEE Robotics and Automation Magazine = IEEE Rob. Autom Mag. -IEEE Security & Privacy = IEEE Secur. Priv. -IEEE Security and Privacy = IEEE Secur. Privacy -IEEE Sensors Journal = IEEE Sens. J. -IEEE Signal Processing Letters = IEEE Signal. Proc. Let. -IEEE Signal Processing Magazine = IEEE Signal. Proc. Mag. -IEEE Software = IEEE Software. +IEEE Revista Iberoamericana de Technolog'ias del Aprendizaje = IEEE Revista Iberoamericana de Technolog'ias del Aprendizaje +IEEE Robotics and Automation Letters = IEEE Robot. Autom. Lett. +IEEE Robotics and Automation Magazine = IEEE Robot. Autom. Mag. +IEEE Security and Privacy = IEEE Security Privacy +IEEE Sensors Journal = IEEE Sensors J. +IEEE Signal Processing Letters = IEEE Signal Process. Lett. +IEEE Signal Processing Magazine = IEEE Signal Process. Mag. +IEEE Software = IEEE Softw. IEEE Solid-State Circuits Magazine = IEEE Solid-State Circuits Mag. -IEEE Spectrum = IEEE Spectrum. +IEEE Spectrum = IEEE Spectr. +IEEE Sustainable Computing = IEEE Sustain. Comput. IEEE Systems Journal = IEEE Syst. J. +IEEE Systems, Man, and Cybernetics Magazine = IEEE Syst., Man, Cybern. Mag. IEEE Technology and Society Magazine = IEEE Technol. Soc. Mag. -IEEE Transactions on Acoustics Speech and Signal Processing = IEEE T. Acoust. Speech. -IEEE Transactions on Acoustics, Speech, and Signal Processing = IEEE Trans. Acoust. Speech Signal Process. +IEEE Transactions on Acoustics, Speech, and Signal Processing = IEEE Trans. Acoust., Speech, Signal Process. IEEE Transactions on Advanced Packaging = IEEE Trans. Adv. Packag. -IEEE Transactions on Aerospace = IEEE T. Aerosp. +IEEE Transactions on Aeronautical and Navigational Electronics = IEEE Trans. Aeronaut. Navig. Electron. +IEEE Transactions on Aerospace = IEEE Trans. Aerosp. IEEE Transactions on Aerospace and Electronic Systems = IEEE Trans. Aerosp. Electron. Syst. -IEEE Transactions on Aerospace and Naval Electronics = IEEE T. Aero. Nav. Elec. -IEEE Transactions on Aerospace and Navigation Electronics = IEEE Trans. Aerosp. Navig. Electron. -IEEE Transactions on Aerospace and Navigational Electronics = IEEE Trans. Aerosp. N. -IEEE Transactions on Affective Computing = IEEE Trans. Affective Comput. +IEEE Transactions on Aerospace and Navigational Electronics = IEEE Trans. Aerosp. Navig. Electron. +IEEE Transactions on Affective Computing = IEEE Trans. Affect. Comput. +IEEE Transactions on Airborne Electronics = IEEE Trans. Airborne Electron. IEEE Transactions on Antennas and Propagation = IEEE Trans. Antennas Propag. -IEEE Transactions on Applications and Industry = IEEE Trans. Appl. Indus. +IEEE Transactions on Applications and Industry = IEEE Trans. Appl. Ind. IEEE Transactions on Applied Superconductivity = IEEE Trans. Appl. Supercond. -IEEE Transactions on Audio = IEEE Trans. Audio. +IEEE Transactions on Audio = IEEE Trans. Audio IEEE Transactions on Audio and Electroacoustics = IEEE Trans. Audio Electroacoust. -IEEE Transactions on Audio Speech and Language Processing = IEEE T. Audio. Speech. -IEEE Transactions on Audio, Speech and Language Processing = IEEE Trans. Audio Speech Lang. Process. +IEEE Transactions on Audio, Speech, and Language Processing = IEEE Audio, Speech, Language Process. IEEE Transactions on Automatic Control = IEEE Trans. Autom. Control IEEE Transactions on Automation Science and Engineering = IEEE Trans. Autom. Sci. Eng. -IEEE Transactions on Autonomous Mental Development = IEEE Trans. Auton. Ment. Dev. -IEEE Transactions on Bio-Medical Electronics = IEEE Trans. Bio-med. Electron. +IEEE Transactions on Autonomous Mental Development = IEEE Trans. Auton. Mental Develop. +IEEE Transactions on Big Data = IEEE Trans. Big Data +IEEE Transactions on Bio-Medical Electronics = IEEE Trans. Bio-Med. Electron. +IEEE Transactions on Bio-Medical Engineering = IEEE Trans. Bio-Med. Eng. IEEE Transactions on Biomedical Circuits and Systems = IEEE Trans. Biomed. Circuits Syst. IEEE Transactions on Biomedical Engineering = IEEE Trans. Biomed. Eng. -IEEE Transactions on Broadcast and Television Receivers = IEEE Trans. Broadcast Telev. Receivers +IEEE Transactions on Broadcast and Television Receivers = IEEE Trans. Broadcast Television Receivers IEEE Transactions on Broadcasting = IEEE Trans. Broadcast. -IEEE Transactions on Cable Television = IEEE Trans. Cable Telev. -IEEE Transactions on Circuit Theory = IEEE T. Circuits. Syst. -IEEE Transactions on Circuits and Systems = IEEE T. Circuits. Syst. +IEEE Transactions on Circuit Theory = IEEE Trans. Circuit Theory +IEEE Transactions on Circuits and Systems = IEEE Trans. Circuits Syst. +IEEE Transactions on Circuits and Systems I: Fundamental Theory and Applications = IEEE Trans. Circuits Syst. I +IEEE Transactions on Circuits and Systems I: Regular Papers = IEEE Trans. Circuits Syst. I +IEEE Transactions on Circuits and Systems II: Analog and Digital Signal Processing = IEEE Trans. Circuits Syst. II +IEEE Transactions on Circuits and Systems II: Express Briefs = IEEE Trans. Circuits Syst. II IEEE Transactions on Circuits and Systems for Video Technology = IEEE Trans. Circuits Syst. Video Technol. -IEEE Transactions on Circuits and Systems I-Fundamental Theory and Applications = IEEE T. Circuits-I. -IEEE Transactions on Circuits and Systems I-Regular Papers = IEEE T. Circuits-I. -IEEE Transactions on Circuits and Systems I: Regular Papers = IEEE Trans. Circuits Syst. I Regul. Pap. -IEEE Transactions on Circuits and Systems Ii-Analog and Digital Signal Processing = IEEE T. Circuits-Ii. -IEEE Transactions on Circuits and Systems Ii-Express Briefs = IEEE T. Circuits-Ii. -IEEE Transactions on Circuits and Systems II: Express Briefs = IEEE Trans. Circuits Syst. II Express Briefs -IEEE Transactions on Cloud Computing = IEEE Trans. Cloud Comput. -IEEE Transactions on Communication and Electronics = IEEE T. Commun. Electr. -IEEE Transactions on Communication Technology = IEEE T. Commun. Techn. +IEEE Transactions on Cloud Computing = IEEE Trans. on Cloud Comput. +IEEE Transactions on Cognitive Communications and Networking = IEEE Trans. on Cogn. Commun. Netw. +IEEE Transactions on Cognitive and Developmental Systems = IEEE Trans. Cogn. Develop. Syst. +IEEE Transactions on Communication Technology = IEEE Trans. Commun. Technol. IEEE Transactions on Communications = IEEE Trans. Commun. -IEEE Transactions on Communications Systems = IEEE T. Commun. Syst. -IEEE Transactions on Component Parts = IEEE T. Compon. Parts. +IEEE Transactions on Component Parts = IEEE Trans. Compon. Parts IEEE Transactions on Components and Packaging Technologies = IEEE Trans. Compon. Packag. Technol. -IEEE Transactions on Components Hybrids and Manufacturing Technology = IEEE T. Compon. Hybr. -IEEE Transactions on Components Packaging and Manufacturing Technology Part A = IEEE T. Compon. Pack. A. -IEEE Transactions on Components Packaging and Manufacturing Technology Part B-Advanced Packaging = IEEE T. Compon. Pack. B. +IEEE Transactions on Components and Packaging Technology = IEEE Trans. Compon. Packag. Technol. +IEEE Transactions on Components, Hybrids and Manufacturing Technology = IEEE Trans. Compon., Hybrids, Manuf. Technol. IEEE Transactions on Components, Packaging and Manufacturing Technology = IEEE Trans. Compon. Packag. Manuf. Technol. -IEEE Transactions on Components, Packaging, and Manufacturing Technology, Part A: = IEEE Trans. Compon. Packag. Manuf. Technol. Part A: -IEEE Transactions on Components, Packaging, and Manufacturing Technology, Part B: = IEEE Trans. Compon. Packag. Manuf. Technol. Part B: -IEEE Transactions on Components, Packaging, and Manufacturing Technology, Part C: = IEEE Trans. Compon. Packag. Manuf. Technol. Part C: -IEEE Transactions on Computational Imaging = IEEE Trans. Comput. Imaging -IEEE Transactions on Computational Intelligence and AI in Games = IEEE Trans. Comput. Intell. AI Games +IEEE Transactions on Components, Packaging and Manufacturing Technology A = IEEE Trans. Compon., Packag., Manuf. Technol. A +IEEE Transactions on Components, Packaging and Manufacturing Technology B: Advanced Packaging = IEEE Trans. Compon., Packag., Manuf. Technol. B +IEEE Transactions on Components, Packaging and Manufacturing Technology C: Manufacturing = IEEE Trans. Compon., Packag., Manuf. Technol. C +IEEE Transactions on Computational Intelligence and AI in Games = IEEE Trans. Comput. Intell. AI in Games IEEE Transactions on Computational Social Systems = IEEE Trans. Comput. Social Syst. -IEEE Transactions on Computer-Aided Design of Integrated Circuits and Systems = IEEE Trans. Comput. Aided Des. Integr. Circuits Syst. +IEEE Transactions on Computer-Aided Design of Integrated Circuits and Systems = IEEE Trans. Comput.-Aided Design Integr. Circuits Syst. IEEE Transactions on Computers = IEEE Trans. Comput. IEEE Transactions on Consumer Electronics = IEEE Trans. Consum. Electron. -IEEE Transactions on Control of Network Systems = IEEE Trans. Control Network Syst. IEEE Transactions on Control Systems Technology = IEEE Trans. Control Syst. Technol. +IEEE Transactions on Control of Network Systems = IEEE Trans. Control Netw. Syst. IEEE Transactions on Cybernetics = IEEE Trans. Cybern. -IEEE Transactions on Dependable and Secure Computing = IEEE Trans. Dependable Secure Comput. -IEEE Transactions on Device and Materials Reliability = IEEE Trans. Device Mater. Reliab. +IEEE Transactions on Dependable and Secure Computing = IEEE Trans. Depend. Sec. Comput. +IEEE Transactions on Device and Materials Reliability = IEEE Trans. Device Mater. Rel. IEEE Transactions on Dielectrics and Electrical Insulation = IEEE Trans. Dielectr. Electr. Insul. IEEE Transactions on Education = IEEE Trans. Educ. -IEEE Transactions on Electrical Insulation = IEEE T. Electr. Insul. +IEEE Transactions on Electrical Insulation = IEEE Trans. Electr. Insul. IEEE Transactions on Electromagnetic Compatibility = IEEE Trans. Electromagn. Compat. IEEE Transactions on Electron Devices = IEEE Trans. Electron Devices -IEEE Transactions on Electronic Computers = IEEE Trans. Electron. +IEEE Transactions on Electronic Computers = IEEE Trans. Electron. Comput. IEEE Transactions on Electronics Packaging Manufacturing = IEEE Trans. Electron. Packag. Manuf. -IEEE Transactions on Emerging Topics in Computing = IEEE Trans. Emerging Top. Comput. +IEEE Transactions on Emerging Topics in Computing = IEEE Trans. Emerg. Topics Comput. +IEEE Transactions on Emerging and Selected Topics in Circuits and Systems = IEEE Trans. Emerg. Sel. Topics Circuits Syst. +IEEE Transactions on Emerging and Selected Topics in Power Electronics = IEEE Trans. Emerg. Sel. Topics Power Electron. IEEE Transactions on Energy Conversion = IEEE Trans. Energy Convers. -IEEE Transactions on Engineering Management = IEEE Trans. Eng. Manage. -IEEE Transactions on Engineering Writing and Speech = IEEE T. Prof. Commun. +IEEE Transactions on Engineering Management = IEEE Trans. Eng. Manag. +IEEE Transactions on Engineering Writing and Speech = IEEE Trans. Eng. Writing Speech IEEE Transactions on Evolutionary Computation = IEEE Trans. Evol. Comput. IEEE Transactions on Fuzzy Systems = IEEE Trans. Fuzzy Syst. +IEEE Transactions on Geoscience Electronics = IEEE Trans. Geosci. Electron. IEEE Transactions on Geoscience and Remote Sensing = IEEE Trans. Geosci. Remote Sens. -IEEE Transactions on Geoscience Electronics = IEEE T. Geosci. Elect. -IEEE Transactions on Haptics = IEEE Trans. Haptic -IEEE Transactions on Human Factors in Electronics = IEEE Trans. Hum. Fact. -IEEE Transactions on Human Factors in Engineering = IEEE T. Hum. Fact. Eng. -IEEE Transactions on Human-Machine Systems = IEEE Trans. Hum.-Mach. Syst. +IEEE Transactions on Haptics = IEEE Trans. Haptics +IEEE Transactions on Human Factors in Electronics = IEEE Trans. Hum. Factors Electron. +IEEE Transactions on Human-Machine Systems = IEEE Trans. Human-Mach. Syst. IEEE Transactions on Image Processing = IEEE Trans. Image Process. IEEE Transactions on Industrial Electronics = IEEE Trans. Ind. Electron. -IEEE Transactions on Industrial Electronics and Control Instrumentation = IEEE T. Ind. El. Con. In. -IEEE Transactions on Industrial Informatics = IEEE Trans. Ind. Inf. -IEEE Transactions on Industry and General Applications = IEEE Trans. Ind. Gen. A. +IEEE Transactions on Industrial Electronics and Control Instrumentation = IEEE Trans. Ind. Electron. Contr. Instrum. +IEEE Transactions on Industrial Informatics = IEEE Trans. Ind. Informat. IEEE Transactions on Industry Applications = IEEE Trans. Ind. Appl. -IEEE Transactions on Information Forensics and Security = IEEE Trans. Inf. Forensics Secur. +IEEE Transactions on Industry and General Applications = IEEE Trans. Ind. Gen. Appl. +IEEE Transactions on Information Forensics and Security = IEEE Trans. Inf. Forensics Security IEEE Transactions on Information Technology in Biomedicine = IEEE Trans. Inf. Technol. Biomed. IEEE Transactions on Information Theory = IEEE Trans. Inf. Theory IEEE Transactions on Instrumentation and Measurement = IEEE Trans. Instrum. Meas. IEEE Transactions on Intelligent Transportation Systems = IEEE Trans. Intell. Transp. Syst. +IEEE Transactions on Intelligent Vehicles = IEEE Trans. Intell. Veh. IEEE Transactions on Knowledge and Data Engineering = IEEE Trans. Knowl. Data Eng. IEEE Transactions on Learning Technologies = IEEE Trans. Learn. Technol. IEEE Transactions on Magnetics = IEEE Trans. Magn. -IEEE Transactions on Man-Machine Systems = IEEE T. Man. Machine. -IEEE Transactions on Manufacturing Technology = IEEE T. Manuf. Tech. -IEEE Transactions on Medical Imaging = IEEE Trans. Med. Imaging -IEEE Transactions on Microwave Theory and Techniques = IEEE Trans. Microwave Theory Tech. -IEEE Transactions on Military Electronics = IEEE T. Mil. Electron. -IEEE Transactions on Mobile Computing = IEEE Trans. Mob. Comput. +IEEE Transactions on Man-Machine Systems = IEEE Trans. Man-Mach. Syst. +IEEE Transactions on Manufacturing Technology = IEEE Trans. Manuf. Technol. +IEEE Transactions on Medical Electronics = IEEE Trans. Med. Electron. +IEEE Transactions on Medical Imaging = IEEE Trans. Med. Imag. +IEEE Transactions on Microwave Theory and Techniques = IEEE Trans. Microw. Theory Techn. +IEEE Transactions on Military Electronics = IEEE Trans. Mil. Electron. +IEEE Transactions on Mobile Computing = IEEE Trans. Mobile Comput. +IEEE Transactions on Molecular, Biological and Multi-Scale Communications = IEEE Trans. Mol. Biol. Multi-Scale Commun. +IEEE Transactions on Multi-Scale Computing Systems = IEEE Trans. Multi-Scale Comput. Syst. IEEE Transactions on Multimedia = IEEE Trans. Multimedia -IEEE Transactions on Nanobioscience = IEEE Trans. Nanobioscience +IEEE Transactions on NanoBioscience = IEEE Trans. Nanobiosci. IEEE Transactions on Nanotechnology = IEEE Trans. Nanotechnol. -IEEE Transactions on Network and Service Management = IEEE Trans. Netw. Serv. Manage. -IEEE Transactions on Network Science and Engineering = IEEE Trans. Network Sci. Eng. -IEEE Transactions on Neural Networks = IEEE Trans. Neural Networks -IEEE Transactions on Neural Networks and Learning Systems = IEEE Trans. Neural Networks Learn. Syst. +IEEE Transactions on Network Science and Engineering = IEEE Trans. Netw. Sci. Eng. +IEEE Transactions on Network and Service Management = IEEE Trans. Netw. Service Manag. +IEEE Transactions on Neural Networks = IEEE Trans. Neural Netw. +IEEE Transactions on Neural Networks and Learning Systems = IEEE Trans. Neural Netw. Learn. Syst. IEEE Transactions on Neural Systems and Rehabilitation Engineering = IEEE Trans. Neural Syst. Rehabil. Eng. IEEE Transactions on Nuclear Science = IEEE Trans. Nucl. Sci. IEEE Transactions on Parallel and Distributed Systems = IEEE Trans. Parallel Distrib. Syst. -IEEE Transactions on Parts Hybrids and Packaging = IEEE T. Parts. Hyb. Pac. -IEEE Transactions on Parts Materials and Packaging = IEEE Tr. Parts. Mater. +IEEE Transactions on Parts, Hybrids and Packaging = IEEE Trans. Parts, Hybrids, Packag. +IEEE Transactions on Parts, Materials and Packaging = IEEE Trans. Parts, Mater., Packag. IEEE Transactions on Pattern Analysis and Machine Intelligence = IEEE Trans. Pattern Anal. Mach. Intell. IEEE Transactions on Plasma Science = IEEE Trans. Plasma Sci. -IEEE Transactions on Power Apparatus and Systems = IEEE T. Power. Ap. Syst. -IEEE Transactions on Power Delivery = IEEE Trans. Power Delivery +IEEE Transactions on Power Apparatus and Systems = IEEE Trans. Power App. Syst. +IEEE Transactions on Power Delivery = IEEE Trans. Power Del. IEEE Transactions on Power Electronics = IEEE Trans. Power Electron. IEEE Transactions on Power Systems = IEEE Trans. Power Syst. -IEEE Transactions on Product Engineering and Production = IEEE T. Prod. Eng. Prod. IEEE Transactions on Professional Communication = IEEE Trans. Prof. Commun. +IEEE Transactions on Radio Frequency Interference = IEEE Trans. Radio Freq. Interference IEEE Transactions on Rehabilitation Engineering = IEEE Trans. Rehabil. Eng. -IEEE Transactions on Reliability = IEEE Trans. Reliab. -IEEE Transactions on Robotics = IEEE Trans. Rob. -IEEE Transactions on Robotics and Automation = IEEE T. Robotic. Autom. +IEEE Transactions on Reliability = IEEE Trans. Rel. +IEEE Transactions on Robotics = IEEE Trans. Robot. +IEEE Transactions on Robotics and Automation = IEEE Trans. Robot. Autom. IEEE Transactions on Semiconductor Manufacturing = IEEE Trans. Semicond. Manuf. IEEE Transactions on Services Computing = IEEE Trans. Serv. Comput. IEEE Transactions on Signal Processing = IEEE Trans. Signal Process. +IEEE Transactions on Signal and Information Processing over Networks = IEEE Trans. Signal Inf. Process. Netw. IEEE Transactions on Smart Grid = IEEE Trans. Smart Grid -IEEE Transactions on Software Engineering = IEEE Trans. Software Eng. -IEEE Transactions on Sonics and Ultrasonics = IEEE T. Son. Ultrason. -IEEE Transactions on Space Electronics and Telemetry = IEEE Trans. Space Electron. Telem. -IEEE Transactions on Speech and Audio Processing = IEEE T. Speech. Audi. P. -IEEE Transactions on Sustainable Energy = IEEE Trans. Sustainable Energy -IEEE Transactions on Systems Man and Cybernetics = IEEE T. Syst. Man. Cyb. -IEEE Transactions on Systems Man and Cybernetics Part A-Systems and Humans = IEEE T. Syst. Man. Cy. A. -IEEE Transactions on Systems Man and Cybernetics Part B-Cybernetics = IEEE T. Syst. Man. Cy. B. -IEEE Transactions on Systems Man and Cybernetics Part C-Applications and Reviews = IEEE T. Syst. Man. Cy. C. -IEEE Transactions on Systems Science and Cybernetics = IEEE T. Syst. Sci. Cyb. -IEEE Transactions on Systems, Man and Cybernetics = IEEE Trans. Syst. Man Cybern. -IEEE Transactions on Systems, Man, and Cybernetics Part A: Systems and Humans = IEEE Trans. Syst. Man Cybern. Part A Syst. Humans -IEEE Transactions on Systems, Man, and Cybernetics Part B: Cybernetics = IEEE Trans. Syst. Man Cybern. Part B Cybern. -IEEE Transactions on Systems, Man, and Cybernetics Part C: Applications and Reviews = IEEE Trans. Syst. Man Cybern. Part C Appl. Rev. -IEEE Transactions on Terahertz Science and Technology = IEEE Trans. Terahertz Sci. Technol. -IEEE Transactions on Ultrasonics Ferroelectrics and Frequency Control = IEEE T. Ultrason. Ferr. -IEEE Transactions on Ultrasonics, Ferroelectrics, and Frequency Control = IEEE Trans. Ultrason. Ferroelectr. Freq. Control -IEEE Transactions on Vehicular Communications = IEEE T. Veh. Commun. +IEEE Transactions on Software Engineering = IEEE Trans. Softw. Eng. +IEEE Transactions on Sonics and Ultrasonics = IEEE Trans. Sonics Ultrason. +IEEE Transactions on Speech and Audio Processing = IEEE Trans. Speech Audio Process. +IEEE Transactions on Sustainable Energy = IEEE Trans. Sustain. Energy +IEEE Transactions on Systems Science and Cybernetics = IEEE Trans. Syst. Sci. Cybern. +IEEE Transactions on Systems, Man, and Cybernetics = IEEE Trans. Syst., Man, Cybern. +IEEE Transactions on Systems, Man, and Cybernetics A: Systems and Humans = IEEE Trans. Syst., Man, Cybern. A +IEEE Transactions on Systems, Man, and Cybernetics B: Cybernetics = IEEE Trans. Syst., Man, Cybern. B +IEEE Transactions on Systems, Man, and Cybernetics C: Applications and Reviews = IEEE Trans. Syst., Man, Cybern. C +IEEE Transactions on Systems, Man, and Cybernetics: Systems = IEEE Trans. Syst., Man, Cybern., Syst. +IEEE Transactions on Terahertz Science and Technology = IEEE Trans. THz Sci. Technol. +IEEE Transactions on Transportation Electrification = IEEE Trans. Transport. Electrific. +IEEE Transactions on Ultrasonics Engineering = IEEE Trans. Ultrason. Eng. +IEEE Transactions on Ultrasonics, Ferroelectrics, and Frequency Control = IEEE Trans. Ultrason., Ferroelectr., Freq. Control +IEEE Transactions on Vehicular Communications = IEEE Trans. Veh. Commun. IEEE Transactions on Vehicular Technology = IEEE Trans. Veh. Technol. -IEEE Transactions on Very Large Scale Integration (VLSI) Systems = IEEE Trans. Very Large Scale Integr. VLSI Syst. -IEEE Transactions on Very Large Scale Integration Vlsi Systems = IEEE T. Vlsi. Syst. -IEEE Transactions on Visualization and Computer Graphics = IEEE Trans. Visual Comput. Graphics +IEEE Transactions on Very Large Scale Integration (VLSI) Systems = IEEE Trans. VLSI Syst. +IEEE Transactions on Visualization and Computer Graphics = IEEE Trans. Vis. Comput. Graphics IEEE Transactions on Wireless Communications = IEEE Trans. Wireless Commun. IEEE Translation Journal on Magnetics in Japan = IEEE Transl. J. Magn. Jpn. -IEEE Vehicular Technology Group-Annual Conference = IEEE Veh. Technol. Gr. IEEE Vehicular Technology Magazine = IEEE Veh. Technol. Mag. IEEE Wireless Communications = IEEE Wireless Commun. IEEE Wireless Communications Letters = IEEE Wireless Commun. Lett. -IEEE Women in Engineering Magazine = IEEE Women Eng. Mag. -IEEE-ACM Transactions on Computational Biology and Bioinformatics = IEEE-ACM T. Comput. Bi. -IEEE-ACM Transactions on Computational Biology and Bioinformatiocs = IEEE-ACM T. Comput. Bi. -IEEE-ACM Transactions on Networking = IEEE ACM T. Network. -IEEE-ASMETransactions on Mechatronics = IEEE-ASME T. Mech. -IEEE/ACM Transactions on Audio, Speech and Language Processing = IEEE/ACM Trans. Audio Speech Lang. Process. -IEEE/ACM Transactions on Computational Biology and Bioinformatics = IEEE/ACM Trans. Comput. Biol. Bioinform. -IEEE/ACM Transactions on Networking = IEEE/ACM Trans. Networking -IEEE/ASME Transactions on Mechatronics = IEEE/ASME Trans. Mechatron. -IEEE/CAA Journal of Automatica Sinica = IEEE/CAA J. Autom. Sin. -IEEE/OSA Journal of Display Technology = IEEE/OSA J. Disp. Technol. -IEEE/OSA Journal of Optical Communications and Networking = IEEE/OSA J. Opt. Commun. Networking -Journal of Lightwave Technology = J. Lightwave Technol. -Journal of Microelectromechanical Systems = J. Microelectromech. Syst. +IEEE/ACM Transactions on Audio, Speech, and Language Processing = IEEE/ACM Trans. Audio, Speech, Language Process. +IEEE/ACM Transactions on Computational Biology and Bioinformatics = IEEE/ACM Trans. Comput. Biol. Bioinformatics +IEEE/ACM Transactions on Networking = IEEE/ACM Trans. Netw. +IEEE/ASME Journal of Microelectromechanical Systems = J. Microelectromech. Syst. +IEEE/ASME Transactions on Mechatronics = IEEE/ASME Trans. Mechatronics +IEEE/CAA Journal of Automatica Sinica = IEEE/CAA J. Autom. Sinica +IEEE/ECS Electrochemical and Solid-State Letters = IEEE/ECS Electrochem. Solid-State Lett. +IEEE/OSA Journal of Display Technology = IEEE/OSA J. Display Technol. +IEEE/OSA Journal of Lightwave Technology = J. Lightw. Technol. +IEEE/TMS Journal of Electronic Materials = IEEE/TMS J. Electron. Mater. Proceedings of the IEEE = Proc. IEEE +Today's Engineer = Today's Engineer diff --git a/src/main/resources/journals/journalList.txt b/src/main/resources/journals/journalList.txt index 1a7a8e17d61..26fa5ac15e2 100644 --- a/src/main/resources/journals/journalList.txt +++ b/src/main/resources/journals/journalList.txt @@ -3211,7 +3211,6 @@ Chimica e l'Industria = Chim. Ind. Chimica Oggi = Chim. Oggi Chimie et Industrie, Genie Chimique = Chim. Ind. Genie Chim. Chimie Nouvelle = Chim. Nouv. -China Communications = China Commun. China's Medicine = Chinas Med. Chinese Astronomy and Astrophysics = Chin. Astron. Astrophy Chinese Chemical Letters = Chin. Chem. Lett. From a754df4387a5b6b259171ccea1c9a6cba3bf5eaf Mon Sep 17 00:00:00 2001 From: Stefan Kolb Date: Wed, 22 Feb 2017 23:02:22 +0100 Subject: [PATCH 7/8] Localization tests (#2582) Test for #1985 --- .../l10n/LocalizationConsistencyTest.java | 20 +++++ .../jabref/logic/l10n/LocalizationParser.java | 87 ++++++++++++++----- .../logic/l10n/LocalizationParserTest.java | 43 ++++++--- 3 files changed, 115 insertions(+), 35 deletions(-) diff --git a/src/test/java/org/jabref/logic/l10n/LocalizationConsistencyTest.java b/src/test/java/org/jabref/logic/l10n/LocalizationConsistencyTest.java index 8f066201e03..52bdb1e755b 100644 --- a/src/test/java/org/jabref/logic/l10n/LocalizationConsistencyTest.java +++ b/src/test/java/org/jabref/logic/l10n/LocalizationConsistencyTest.java @@ -16,6 +16,7 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; public class LocalizationConsistencyTest { @@ -168,4 +169,23 @@ public void findObsoleteMenuLocalizationKeys() throws IOException { Collections.emptySet(), obsoleteKeys); } + @Test + public void localizationParameterMustIncludeAString() throws IOException { + // Must start or end with " + // Localization.lang("test"), Localization.lang("test" + var), Localization.lang(var + "test") + // TODO: Localization.lang(var1 + "test" + var2) not covered + // Localization.lang("Problem downloading from %1", address) + Set keys = LocalizationParser.findLocalizationParametersStringsInJavaFiles(LocalizationBundleForTest.LANG); + for(LocalizationEntry e : keys) { + assertTrue("Illegal localization parameter found. Must include a String with potential concatenation or replacement parameters. Illegal parameter: Localization.lang(" + e.getKey(), + e.getKey().startsWith("\"") || e.getKey().endsWith("\"")); + } + + keys = LocalizationParser.findLocalizationParametersStringsInJavaFiles(LocalizationBundleForTest.MENU); + for(LocalizationEntry e : keys) { + assertTrue("Illegal localization parameter found. Must include a String with potential concatenation or replacement parameters. Illegal parameter: Localization.lang(" + e.getKey(), + e.getKey().startsWith("\"") || e.getKey().endsWith("\"")); + } + } + } diff --git a/src/test/java/org/jabref/logic/l10n/LocalizationParser.java b/src/test/java/org/jabref/logic/l10n/LocalizationParser.java index 428fe8c129c..a02bee4d0eb 100644 --- a/src/test/java/org/jabref/logic/l10n/LocalizationParser.java +++ b/src/test/java/org/jabref/logic/l10n/LocalizationParser.java @@ -75,6 +75,14 @@ private static Set findLocalizationEntriesInFiles(Localizatio } } + public static Set findLocalizationParametersStringsInJavaFiles(LocalizationBundleForTest type) + throws IOException { + return Files.walk(Paths.get("src/main")) + .filter(LocalizationParser::isJavaFile) + .flatMap(path -> getLocalizationParametersInJavaFile(path, type).stream()) + .collect(Collectors.toSet()); + } + private static Set findLocalizationEntriesInJavaFiles(LocalizationBundleForTest type) throws IOException { return Files.walk(Paths.get("src/main")) @@ -141,6 +149,26 @@ private static List getLanguageKeysInJavaFile(Path path, Loca return result; } + private static List getLocalizationParametersInJavaFile(Path path, LocalizationBundleForTest type) { + List result = new LinkedList<>(); + + try { + List lines = Files.readAllLines(path, StandardCharsets.UTF_8); + String content = String.join("\n", lines); + + List keys = JavaLocalizationEntryParser.getLocalizationParameter(content, type); + + for (String key : keys) { + result.add(new LocalizationEntry(path, key, type)); + } + + } catch (IOException ignore) { + ignore.printStackTrace(); + } + + return result; + } + /** * Loads the fxml file and returns all used language resources. */ @@ -192,31 +220,13 @@ static class JavaLocalizationEntryParser { private static final Pattern QUOTATION_SYMBOL = Pattern.compile("QUOTATIONPLACEHOLDER"); public static List getLanguageKeysInString(String content, LocalizationBundleForTest type) { + List parameters = getLocalizationParameter(content, type); + List result = new LinkedList<>(); - Matcher matcher; - if (type == LocalizationBundleForTest.LANG) { - matcher = LOCALIZATION_START_PATTERN.matcher(content); - } else { - matcher = LOCALIZATION_MENU_START_PATTERN.matcher(content); - } - while (matcher.find()) { - // find contents between the brackets, covering multi-line strings as well - int index = matcher.end(); - int brackets = 1; - StringBuilder buffer = new StringBuilder(); - while (brackets != 0) { - char c = content.charAt(index); - if (c == '(') { - brackets++; - } else if (c == ')') { - brackets--; - } - buffer.append(c); - index++; - } + for (String param : parameters) { - String parsedContentsOfLangMethod = ESCAPED_QUOTATION_SYMBOL.matcher(buffer.toString()).replaceAll("QUOTATIONPLACEHOLDER"); + String parsedContentsOfLangMethod = ESCAPED_QUOTATION_SYMBOL.matcher(param).replaceAll("QUOTATIONPLACEHOLDER"); // only retain what is within quotation StringBuilder b = new StringBuilder(); @@ -259,6 +269,39 @@ public static List getLanguageKeysInString(String content, LocalizationB return result; } + public static List getLocalizationParameter(String content, LocalizationBundleForTest type) { + List result = new LinkedList<>(); + + Matcher matcher; + if (type == LocalizationBundleForTest.LANG) { + matcher = LOCALIZATION_START_PATTERN.matcher(content); + } else { + matcher = LOCALIZATION_MENU_START_PATTERN.matcher(content); + } + while (matcher.find()) { + // find contents between the brackets, covering multi-line strings as well + int index = matcher.end(); + int brackets = 1; + StringBuilder buffer = new StringBuilder(); + while (brackets != 0) { + char c = content.charAt(index); + if (c == '(') { + brackets++; + } else if (c == ')') { + brackets--; + } + // skip closing brackets + if (brackets != 0) { + buffer.append(c); + } + index++; + } + // trim newlines and whitespace + result.add(buffer.toString().trim()); + } + + return result; + } } } diff --git a/src/test/java/org/jabref/logic/l10n/LocalizationParserTest.java b/src/test/java/org/jabref/logic/l10n/LocalizationParserTest.java index 54b6e6bdc27..dd781a9599b 100644 --- a/src/test/java/org/jabref/logic/l10n/LocalizationParserTest.java +++ b/src/test/java/org/jabref/logic/l10n/LocalizationParserTest.java @@ -11,27 +11,44 @@ public class LocalizationParserTest { @Test - public void testParsingCode() { - assertLocalizationParsing("Localization.lang(\"one per line\")", "one_per_line"); - assertLocalizationParsing("Localization.lang(\n \"Copy \\\\cite{BibTeX key}\")", "Copy_\\cite{BibTeX_key}"); - assertLocalizationParsing("Localization.lang(\"two per line\") Localization.lang(\"two per line\")", Arrays.asList("two_per_line", "two_per_line")); - assertLocalizationParsing("Localization.lang(\"multi \" + \n\"line\")", "multi_line"); - assertLocalizationParsing("Localization.lang(\"one per line with var\", var)", "one_per_line_with_var"); - assertLocalizationParsing("Localization.lang(\"Search %0\", \"Springer\")", "Search_%0"); - assertLocalizationParsing("Localization.lang(\"Reset preferences (key1,key2,... or 'all')\")", "Reset_preferences_(key1,key2,..._or_'all')"); - assertLocalizationParsing("Localization.lang(\"Multiple entries selected. Do you want to change the type of all these to '%0'?\")", + public void testKeyParsingCode() { + assertLocalizationKeyParsing("Localization.lang(\"one per line\")", "one_per_line"); + assertLocalizationKeyParsing("Localization.lang(\n \"Copy \\\\cite{BibTeX key}\")", "Copy_\\cite{BibTeX_key}"); + assertLocalizationKeyParsing("Localization.lang(\"two per line\") Localization.lang(\"two per line\")", Arrays.asList("two_per_line", "two_per_line")); + assertLocalizationKeyParsing("Localization.lang(\"multi \" + \n\"line\")", "multi_line"); + assertLocalizationKeyParsing("Localization.lang(\"one per line with var\", var)", "one_per_line_with_var"); + assertLocalizationKeyParsing("Localization.lang(\"Search %0\", \"Springer\")", "Search_%0"); + assertLocalizationKeyParsing("Localization.lang(\"Reset preferences (key1,key2,... or 'all')\")", "Reset_preferences_(key1,key2,..._or_'all')"); + assertLocalizationKeyParsing("Localization.lang(\"Multiple entries selected. Do you want to change the type of all these to '%0'?\")", "Multiple_entries_selected._Do_you_want_to_change_the_type_of_all_these_to_'%0'?"); - assertLocalizationParsing("Localization.lang(\"Run fetcher, e.g. \\\"--fetch=Medline:cancer\\\"\");", + assertLocalizationKeyParsing("Localization.lang(\"Run fetcher, e.g. \\\"--fetch=Medline:cancer\\\"\");", "Run_fetcher,_e.g._\"--fetch\\=Medline\\:cancer\""); } - private void assertLocalizationParsing(String code, String expectedLanguageKeys) { - assertLocalizationParsing(code, Collections.singletonList(expectedLanguageKeys)); + @Test + public void testParameterParsingCode() { + assertLocalizationParameterParsing("Localization.lang(\"one per line\")", "\"one per line\""); + assertLocalizationParameterParsing("Localization.lang(\"one per line\" + var)", "\"one per line\" + var"); + assertLocalizationParameterParsing("Localization.lang(var + \"one per line\")", "var + \"one per line\""); + assertLocalizationParameterParsing("Localization.lang(\"Search %0\", \"Springer\")", "\"Search %0\", \"Springer\""); + } + + private void assertLocalizationKeyParsing(String code, String expectedLanguageKeys) { + assertLocalizationKeyParsing(code, Collections.singletonList(expectedLanguageKeys)); } - private void assertLocalizationParsing(String code, List expectedLanguageKeys) { + private void assertLocalizationKeyParsing(String code, List expectedLanguageKeys) { List languageKeysInString = LocalizationParser.JavaLocalizationEntryParser.getLanguageKeysInString(code, LocalizationBundleForTest.LANG); assertEquals(expectedLanguageKeys, languageKeysInString); } + private void assertLocalizationParameterParsing(String code, List expectedParameter) { + List languageKeysInString = LocalizationParser.JavaLocalizationEntryParser.getLocalizationParameter(code, LocalizationBundleForTest.LANG); + assertEquals(expectedParameter, languageKeysInString); + } + + private void assertLocalizationParameterParsing(String code, String expectedParameter) { + assertLocalizationParameterParsing(code, Collections.singletonList(expectedParameter)); + } + } From 28d4a45e997a3124155da1fe8d52555f23274276 Mon Sep 17 00:00:00 2001 From: Oliver Kopp Date: Thu, 23 Feb 2017 14:20:02 +0100 Subject: [PATCH 8/8] Revert "Update gradle from 3.3 to 3.4" This reverts commit bdc535f0f13fdd0f5558f3bc11c9b4a5c533c2b0. --- gradle/wrapper/gradle-wrapper.jar | Bin 52928 -> 54227 bytes gradle/wrapper/gradle-wrapper.properties | 4 ++-- gradlew | 19 +++++++++++-------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 6ffa237849ef3607e39c3b334a92a65367962071..51288f9c2f05faf8d42e1a751a387ca7923882c3 100644 GIT binary patch delta 15239 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 delta 13979 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e30f5fd5ae3..265787b282e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Feb 21 19:36:11 CET 2017 +#Thu Jan 05 09:52:38 CET 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip diff --git a/gradlew b/gradlew index 9aa616c273d..4453ccea33d 100755 --- a/gradlew +++ b/gradlew @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh ############################################################################## ## @@ -154,16 +154,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save ( ) { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [[ "$(uname)" == "Darwin" ]] && [[ "$HOME" == "$PWD" ]]; then +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then cd "$(dirname "$0")" fi -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@"