Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into sharelatex
Browse files Browse the repository at this point in the history
* upstream/master:
  Fix DOI resolving by using https (#2889)
  Adjust tests: Ads fetcher returns url, DBLP no longer works with negative operators (#2891)
  Fix loading of preferencesService (#2882)
  Add link to "feature branch workflow"
  Support Annotations Created by Foxit (#2878)
  Fixes jacoco by excluding the fetcher tests from analysis (#2877)

# Conflicts:
#	src/main/java/org/jabref/gui/DefaultInjector.java
  • Loading branch information
Siedlerchr committed Jun 6, 2017
2 parents da1b0b2 + ad69741 commit f7c9c61
Show file tree
Hide file tree
Showing 18 changed files with 222 additions and 99 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `#
- We added integration of the Library of Congress catalog as a fetcher based on the [LCCN identifier](https://en.wikipedia.org/wiki/Library_of_Congress_Control_Number). [Feature request 636 in the forum](http://discourse.jabref.org/t/loc-marc-mods-connection/636)

### Fixed
- We fixed the adding of a new entry from DOI which led to a connection error. The DOI resolution now uses HTTPS to protect the user's privacy [#2879](https://github.com/JabRef/jabref/issues/2897)
- We fixed the IEEE Xplore web search functionality [#2789](https://github.com/JabRef/jabref/issues/2789)
- We fixed an error in the CrossRef fetcher that occurred if one of the fetched entries had no title
- We fixed an issue that prevented new entries to be automatically assigned to the currently selected group [#2783](https://github.com/JabRef/jabref/issues/2783).
- We fixed a bug that only allowed parsing positive timezones from a FileAnnotation [#2839](https://github.com/JabRef/jabref/issues/22839)
- We fixed a bug that only allowed parsing positive timezones from a FileAnnotation [#2839](https://github.com/JabRef/jabref/issues/2839)
- We fixed a bug that did not allow the correct re-export of the MS-Office XML field `msbib-accessed` with a different date format [#2859](https://github.com/JabRef/jabref/issues/2859).

- We fixed some bugs that prevented the display of FileAnnotations that were created using the Foxit Reader. [#2839, comment](https://github.com/JabRef/jabref/issues/2839#issuecomment-302058227).
### Removed


Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## Understanding the basics
We welcome contributions to JabRef and encourage to create a fork, clone, **create a new branch** (such as `fix-for-issue-121`), **work on the new branch — not master**, and create a pull request.
Be sure to create a **separate branch** for each improvement you implement.
Take a look at GitHub's excellent [help documentation] for a detailed explanation.
Take a look at GitHub's excellent [help documentation] for a detailed explanation and the explanation of [Feature Branch Workflow](https://de.atlassian.com/git/tutorials/comparing-workflows#feature-branch-workflow) for the idea behind this kind of development.

We also have [code howtos](https://github.com/JabRef/jabref/wiki/Code-Howtos) and [guidelines for setting up a local workspace](https://github.com/JabRef/jabref/wiki/Guidelines-for-setting-up-a-local-workspace).

Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ tasks.withType(Test) {
}

task jacocoMerge(type: JacocoMerge) {
executionData test, fetcherTest, databaseTest
executionData test, databaseTest
}

jacocoTestReport {
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/jabref/gui/DefaultInjector.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import org.jabref.gui.keyboard.KeyBindingRepository;
import org.jabref.gui.util.TaskExecutor;
import org.jabref.logic.journals.JournalAbbreviationLoader;
import org.jabref.preferences.PreferencesService;
import org.jabref.logic.sharelatex.ShareLatexManager;
import org.jabref.preferences.JabRefPreferences;

import com.airhacks.afterburner.injection.Injector;
import com.airhacks.afterburner.injection.PresenterFactory;
Expand All @@ -28,7 +28,7 @@ private static Object createDependency(Class<?> clazz) {
return new FXDialogService();
} else if (clazz == TaskExecutor.class) {
return Globals.taskExecutor;
} else if (clazz == JabRefPreferences.class) {
} else if (clazz == PreferencesService.class) {
return Globals.prefs;
} else if (clazz == KeyBindingRepository.class) {
return Globals.getKeyPrefs();
Expand Down
74 changes: 18 additions & 56 deletions src/main/java/org/jabref/logic/pdf/PdfAnnotationImporter.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.jabref.logic.pdf;

import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
Expand All @@ -18,13 +17,10 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSFloat;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
import org.apache.pdfbox.util.PDFTextStripperByArea;

public class PdfAnnotationImporter implements AnnotationImporter {

Expand Down Expand Up @@ -53,8 +49,8 @@ public List<FileAnnotation> importAnnotations(final Path path) {
if (!isSupportedAnnotationType(annotation)) {
continue;
}
if (FileAnnotationType.UNDERLINE.toString().equals(annotation.getSubtype()) ||
FileAnnotationType.HIGHLIGHT.toString().equals(annotation.getSubtype())) {

if (FileAnnotationType.isMarkedFileAnnotationType(annotation.getSubtype())) {
annotationsList.add(createMarkedAnnotations(pageIndex, page, annotation));
} else {
FileAnnotation fileAnnotation = new FileAnnotation(annotation, pageIndex + 1);
Expand All @@ -71,6 +67,13 @@ public List<FileAnnotation> importAnnotations(final Path path) {
}

private boolean isSupportedAnnotationType(PDAnnotation annotation) {
if (annotation.getSubtype() == null) {
return false;
}
if ("Link".equals(annotation.getSubtype()) || "Widget".equals(annotation.getSubtype())) {
LOGGER.debug(annotation.getSubtype() + " is excluded from the supported file annotations");
return false;
}
try {
if (!Arrays.asList(FileAnnotationType.values()).contains(FileAnnotationType.valueOf(annotation.getSubtype()))) {
return false;
Expand All @@ -86,75 +89,34 @@ private FileAnnotation createMarkedAnnotations(int pageIndex, PDPage page, PDAnn
annotation.getDictionary().getString(COSName.T), FileAnnotation.extractModifiedTime(annotation.getModifiedDate()),
pageIndex + 1, annotation.getContents(), FileAnnotationType.valueOf(annotation.getSubtype().toUpperCase(Locale.ROOT)), Optional.empty());

try {
if (FileAnnotationType.HIGHLIGHT.toString().equals(annotation.getSubtype()) || FileAnnotationType.UNDERLINE.toString().equals(annotation.getSubtype())) {
annotation.setContents(extractMarkedText(page, annotation));
if (annotationBelongingToMarking.getAnnotationType().isLinkedFileAnnotationType()) {
try {
COSArray boundingBoxes = (COSArray) annotation.getDictionary().getDictionaryObject(COSName.getPDFName("QuadPoints"));
annotation.setContents(new TextExtractor(page, boundingBoxes).extractMarkedText());
} catch (IOException e) {
annotation.setContents("JabRef: Could not extract any marked text!");
}
} catch (IOException e) {
annotation.setContents("JabRef: Could not extract any marked text!");
}

//Marked text that has a sticky note on it should be linked to the sticky note
return new FileAnnotation(annotation, pageIndex + 1, annotationBelongingToMarking);
}

private String extractMarkedText(PDPage page, PDAnnotation annotation) throws IOException {
//highlighted or underlined text has to be extracted by the rectangle calculated from the marking
PDFTextStripperByArea stripperByArea = new PDFTextStripperByArea();
COSArray quadsArray = (COSArray) annotation.getDictionary().getDictionaryObject(COSName.getPDFName("QuadPoints"));
String markedText = "";
for (int j = 1,
k = 0;
j <= (quadsArray.size() / 8);
j++) {

COSFloat upperLeftX = (COSFloat) quadsArray.get(k);
COSFloat upperLeftY = (COSFloat) quadsArray.get(1 + k);
COSFloat upperRightX = (COSFloat) quadsArray.get(2 + k);
COSFloat upperRightY = (COSFloat) quadsArray.get(3 + k);
COSFloat lowerLeftX = (COSFloat) quadsArray.get(4 + k);
COSFloat lowerLeftY = (COSFloat) quadsArray.get(5 + k);

k += 8;

float ulx = upperLeftX.floatValue() - 1;
float uly = upperLeftY.floatValue();
float width = upperRightX.floatValue() - lowerLeftX.floatValue();
float height = upperRightY.floatValue() - lowerLeftY.floatValue();

PDRectangle pageSize = page.getMediaBox();
uly = pageSize.getHeight() - uly;

Rectangle2D.Float rectangle = new Rectangle2D.Float(ulx, uly, width, height);
stripperByArea.addRegion("markedRegion", rectangle);
stripperByArea.extractRegions(page);
String markedTextInLine = stripperByArea.getTextForRegion("markedRegion");

if (j > 1) {
markedText = markedText.concat(markedTextInLine);
} else {
markedText = markedTextInLine;
}
}

return markedText.trim();
}

private boolean validatePath(Path path) {
Objects.requireNonNull(path);

if (!path.toString().toLowerCase(Locale.ROOT).endsWith(".pdf")) {
LOGGER.warn(String.format("File %s does not end with .pdf!", path));
LOGGER.warn(String.format("File '%s' does not end with .pdf!", path));
return false;
}

if (!Files.exists(path)) {
LOGGER.warn(String.format("File %s does not exist!", path));
LOGGER.warn(String.format("File '%s' does not exist!", path));
return false;
}

if (!Files.isRegularFile(path) || !Files.isReadable(path)) {
LOGGER.warn(String.format("File %s is not readable!", path));
LOGGER.warn(String.format("File '%s' is not readable!", path));
return false;
}

Expand Down
86 changes: 86 additions & 0 deletions src/main/java/org/jabref/logic/pdf/TextExtractor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package org.jabref.logic.pdf;

import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.util.Objects;

import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSFloat;
import org.apache.pdfbox.cos.COSInteger;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.util.PDFTextStripperByArea;

/**
* Extracts the text of marked annotations using bounding boxes.
*/
public final class TextExtractor {

private final COSArray boundingBoxes;
private final PDPage page;

/**
* @param page the page the annotation is on, must not be null
* @param boundingBoxes the raw annotation, must not be null
*/
public TextExtractor(PDPage page, COSArray boundingBoxes) {
this.page = Objects.requireNonNull(page);
this.boundingBoxes = Objects.requireNonNull(boundingBoxes);
}

/**
* Extracts the text of a marked annotation such as highlights, underlines, strikeouts etc.
*
* @return The text of the annotation
* @throws IOException If the PDFTextStripperByArea fails to initialize.
*/
public String extractMarkedText() throws IOException {
// Text has to be extracted by the rectangle calculated from the marking
PDFTextStripperByArea stripperByArea = new PDFTextStripperByArea();
String markedText = "";

// Iterates over the array of segments. Each segment consists of 8 points forming a bounding box.
int totalSegments = boundingBoxes.size() / 8;
for (int currentSegment = 1, segmentPointer = 0; currentSegment <= totalSegments; currentSegment++, segmentPointer += 8) {
try {
stripperByArea.addRegion("markedRegion", calculateSegmentBoundingBox(boundingBoxes, segmentPointer));
stripperByArea.extractRegions(page);

markedText = markedText.concat(stripperByArea.getTextForRegion("markedRegion"));
} catch (IllegalArgumentException e) {
throw new IOException("Cannot read annotation coordinates!", e);
}
}

return markedText.trim();
}

private Rectangle2D calculateSegmentBoundingBox(COSArray quadsArray, int segmentPointer) {
// Extract coordinate values
float upperLeftX = toFloat(quadsArray.get(segmentPointer));
float upperLeftY = toFloat(quadsArray.get(segmentPointer + 1));
float upperRightX = toFloat(quadsArray.get(segmentPointer + 2));
float upperRightY = toFloat(quadsArray.get(segmentPointer + 3));
float lowerLeftX = toFloat(quadsArray.get(segmentPointer + 4));
float lowerLeftY = toFloat(quadsArray.get(segmentPointer + 5));

// Post-processing of the raw coordinates.
PDRectangle pageSize = page.getMediaBox();
float ulx = upperLeftX - 1; // It is magic.
float uly = pageSize.getHeight() - upperLeftY;
float width = upperRightX - lowerLeftX;
float height = upperRightY - lowerLeftY;

return new Rectangle2D.Float(ulx, uly, width, height);
}

private float toFloat(Object cosNumber) {
if (cosNumber instanceof COSFloat) {
return ((COSFloat) cosNumber).floatValue();
}
if (cosNumber instanceof COSInteger) {
return ((COSInteger) cosNumber).floatValue();
}
throw new IllegalArgumentException("The number type of the annotation is not supported!");
}
}
2 changes: 1 addition & 1 deletion src/main/java/org/jabref/model/entry/identifier/DOI.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class DOI implements Identifier {
private static final Log LOGGER = LogFactory.getLog(DOI.class);

// DOI resolver
private static final URI RESOLVER = URI.create("http://doi.org");
private static final URI RESOLVER = URI.create("https://doi.org");
// Regex
// (see http://www.doi.org/doi_handbook/2_Numbering.html)
private static final String DOI_EXP = ""
Expand Down
48 changes: 34 additions & 14 deletions src/main/java/org/jabref/model/pdf/FileAnnotationType.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,28 @@
*/

public enum FileAnnotationType {
TEXT("Text"),
HIGHLIGHT("Highlight"),
UNDERLINE("Underline"),
POLYGON("Polygon"),
POPUP("Popup"),
LINE("Line"),
CIRCLE("Circle"),
FREETEXT("FreeText"),
STRIKEOUT("Strikeout"),
LINK("Link"),
INK("Ink"),
UNKNOWN("Unknown"),
NONE("None");
TEXT("Text", false),
HIGHLIGHT("Highlight", true),
SQUIGGLY("Squiggly", true),
UNDERLINE("Underline", true),
STRIKEOUT("StrikeOut", true),
POLYGON("Polygon", false),
POPUP("Popup", false),
LINE("Line", false),
CIRCLE("Circle", false),
FREETEXT("FreeText", false),
INK("Ink", false),
UNKNOWN("Unknown", false),
NONE("None", false);

private static final Log LOGGER = LogFactory.getLog(FileAnnotationType.class);

private final String name;
private final boolean linkedFileAnnotationType;

FileAnnotationType(String name) {
FileAnnotationType(String name, boolean linkedFileAnnotationType) {
this.name = name;
this.linkedFileAnnotationType = linkedFileAnnotationType;
}

/**
Expand All @@ -50,6 +52,24 @@ public static FileAnnotationType parse(PDAnnotation annotation) {
}
}

/**
* Determines if a String is a supported marked FileAnnotation type.
*
* @param annotationType a type descriptor
* @return true if annotationType is a supported marked FileAnnotation type
*/
public static boolean isMarkedFileAnnotationType(String annotationType) {
try {
return FileAnnotationType.valueOf(annotationType.toUpperCase(Locale.ROOT)).linkedFileAnnotationType;
} catch (IllegalArgumentException e) {
return false;
}
}

public boolean isLinkedFileAnnotationType() {
return linkedFileAnnotationType;
}

public String toString() {
return this.name;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public void setUp() throws Exception {
diezSliceTheoremEntry.setField("keywords", "Mathematical Physics, Mathematics - Differential Geometry, Mathematics - Symplectic Geometry, 58B99, 58Z05, 58B25, 22E65, 58D19, 53D20, 53D42");
diezSliceTheoremEntry.setField("month", "#may#");
diezSliceTheoremEntry.setField("primaryclass", "math-ph");
diezSliceTheoremEntry.setField("url", "http://adsabs.harvard.edu/abs/2014arXiv1405.2249D");
diezSliceTheoremEntry.setField("abstract",
"A general slice theorem for the action of a Fr$\\backslash$'echet Lie group on a" + NEWLINE
+ "Fr$\\backslash$'echet manifolds is established. The Nash-Moser theorem provides the" + NEWLINE
Expand Down Expand Up @@ -79,6 +80,7 @@ public void setUp() throws Exception {
famaeyMcGaughEntry.setField("eprint", "1112.3960");
famaeyMcGaughEntry.setField("pages", "10");
famaeyMcGaughEntry.setField("keywords", "astronomical observations, Newtonian limit, equations of motion, extragalactic astronomy, cosmology, theories of gravity, fundamental physics, astrophysics");
famaeyMcGaughEntry.setField("url", "http://adsabs.harvard.edu/abs/2012LRR....15...10F");

sunWelchEntry = new BibEntry();
sunWelchEntry.setType(BiblatexEntryTypes.ARTICLE);
Expand All @@ -91,6 +93,7 @@ public void setUp() throws Exception {
sunWelchEntry.setField("title", "Solution-processed small-molecule solar cells with 6.7\\% efficiency");
sunWelchEntry.setField("volume", "11");
sunWelchEntry.setField("year", "2012");
sunWelchEntry.setField("url", "http://adsabs.harvard.edu/abs/2012NatMa..11...44S");

xiongSunEntry = new BibEntry();
xiongSunEntry.setType(BiblatexEntryTypes.ARTICLE);
Expand All @@ -103,6 +106,7 @@ public void setUp() throws Exception {
xiongSunEntry.setField("title", "Multiyear On-Orbit Calibration and Performance of Terra MODIS Reflective Solar Bands");
xiongSunEntry.setField("volume", "45");
xiongSunEntry.setField("year", "2007");
xiongSunEntry.setField("url", "http://adsabs.harvard.edu/abs/2007ITGRS..45..879X");

ingersollPollardEntry = new BibEntry();
ingersollPollardEntry.setType(BiblatexEntryTypes.ARTICLE);
Expand All @@ -116,6 +120,7 @@ public void setUp() throws Exception {
ingersollPollardEntry.setField("title", "Motion in the interiors and atmospheres of Jupiter and Saturn - Scale analysis, anelastic equations, barotropic stability criterion");
ingersollPollardEntry.setField("volume", "52");
ingersollPollardEntry.setField("year", "1982");
ingersollPollardEntry.setField("url", "http://adsabs.harvard.edu/abs/1982Icar...52...62I");

luceyPaulEntry = new BibEntry();
luceyPaulEntry.setType(BiblatexEntryTypes.ARTICLE);
Expand All @@ -128,6 +133,7 @@ public void setUp() throws Exception {
luceyPaulEntry.setField("title", "Lunar iron and titanium abundance algorithms based on final processing of Clementine ultraviolet-visible images");
luceyPaulEntry.setField("volume", "105");
luceyPaulEntry.setField("year", "2000");
luceyPaulEntry.setField("url", "http://adsabs.harvard.edu/abs/2000JGR...10520297L");
}

@Test
Expand Down
Loading

0 comments on commit f7c9c61

Please sign in to comment.