Skip to content

Commit

Permalink
JabRef#8491 : Refactor Date Fix using Date.parse
Browse files Browse the repository at this point in the history
  • Loading branch information
addak committed Feb 27, 2022
1 parent 24f2aa3 commit e2e4b82
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 98 deletions.
98 changes: 24 additions & 74 deletions src/main/java/org/jabref/logic/xmp/DublinCoreExtractor.java
Original file line number Diff line number Diff line change
@@ -1,38 +1,31 @@
package org.jabref.logic.xmp;

import java.io.IOException;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Consumer;
import java.util.function.Predicate;

import org.apache.commons.lang3.LocaleUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.jabref.logic.TypedBibEntry;
import org.jabref.model.database.BibDatabaseMode;
import org.jabref.model.entry.Author;
import org.jabref.model.entry.AuthorList;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.Date;
import org.jabref.model.entry.Month;
import org.jabref.model.entry.field.Field;
import org.jabref.model.entry.field.FieldFactory;
import org.jabref.model.entry.field.StandardField;
import org.jabref.model.entry.field.UnknownField;
import org.jabref.model.entry.types.EntryTypeFactory;
import org.jabref.model.schema.DublinCoreSchemaCustom;
import org.jabref.model.strings.StringUtil;

import org.apache.xmpbox.DateConverter;
import org.apache.xmpbox.schema.DublinCoreSchema;
import org.apache.xmpbox.type.BadFieldValueException;
import org.slf4j.Logger;
Expand Down Expand Up @@ -90,45 +83,20 @@ private void extractAuthor() {
* property filled with jan will override this behavior and no data is lost. In the cases, where xmp is written by
* another service, the assumption is, that the 1st January is not a publication date at all.
*/
private void extractYearAndMonth() {
private void extractDate() {
List<String> dates = dcSchema.getUnqualifiedSequenceValueList("date");
if ((dates != null) && !dates.isEmpty()) {

String dateString = dates.get(0).trim();
var dateFormat = ((DublinCoreSchemaCustom) dcSchema).getDateAttributeFormatQualifier();

Calendar calender = null;
String date = dates.get(0).trim();
try {
calender = DateConverter.toCalendar(dateString);
} catch (IOException ignored) {
// Ignored
}

if (Objects.nonNull(calender)) {
if (StringUtils.isNotEmpty(dateFormat)) {
LocalDate date = LocalDate.ofInstant(calender.toInstant(), ZoneId.systemDefault());
switch (dateFormat) {
case "YYYY-MM-DD":
bibEntry.setField(StandardField.DAY, Integer.toString(date.getDayOfMonth()));
case "YYYY-MM":
Month.getMonthByNumber(date.getMonthValue())
.ifPresent(month -> bibEntry.setMonth(month));
case "YYYY":
bibEntry.setField(StandardField.YEAR, String.valueOf(date.getYear()));
break;
default:

}

} else {
bibEntry.setField(StandardField.YEAR, String.valueOf(calender.get(Calendar.YEAR)));
int monthNumber = calender.get(Calendar.MONTH) + 1;
// not the 1st of January
if (!((monthNumber == 1) && (calender.get(Calendar.DAY_OF_MONTH) == 1))) {
Month.getMonthByNumber(monthNumber)
.ifPresent(month -> bibEntry.setMonth(month));
}
}
Date.parse(date)
.ifPresent(dateValue -> {
dateValue.getDay().ifPresent(day -> bibEntry.setField(StandardField.DAY, Integer.toString(day)));
dateValue.getMonth().ifPresent(bibEntry::setMonth);
dateValue.getYear().ifPresent(year -> bibEntry.setField(StandardField.YEAR, Integer.toString(year)));
});
} catch (RuntimeException e) {
LOGGER.error("Failed To Parse Date\n {}", ExceptionUtils.getStackTrace(e));
}
}
}
Expand Down Expand Up @@ -267,20 +235,26 @@ private void extractType() {
}
}

/**
* No Equivalent in BibTex. Will create an Unknown "Coverage" Field
*/
private void extractCoverage() {
String coverage = dcSchema.getCoverage();
if (!StringUtils.isEmpty(coverage)) {
bibEntry.setField(FieldFactory.parseField(DC_COVERAGE), coverage);
}
}

/**
* Language is equivalent in both formats (BibTex and DublinCore)
*/
private void extractLanguages() {
StringBuilder builder = new StringBuilder();

List<String> languages = dcSchema.getLanguages();
if (languages != null && !languages.isEmpty()) {
languages.forEach(language -> builder.append(",").append(language));
bibEntry.setField(StandardField.LANGUAGE, builder.substring(1).toString());
bibEntry.setField(StandardField.LANGUAGE, builder.substring(1));
}
}

Expand All @@ -302,7 +276,7 @@ public Optional<BibEntry> extractBibtexEntry() {
// then extract all "standard" dublin core entries
this.extractEditor();
this.extractAuthor();
this.extractYearAndMonth();
this.extractDate();
this.extractAbstract();
this.extractDOI();
this.extractPublisher();
Expand Down Expand Up @@ -351,19 +325,7 @@ private void fillCreator(String creators) {
*/
private void fillDate() {
bibEntry.getFieldOrAlias(StandardField.DATE)
.ifPresent(publicationDate -> {
dcSchema.addUnqualifiedSequenceValue("date", publicationDate);
String[] f = publicationDate.split("-");
String format;
if (f.length == 3) {
format = "YYYY-MM-DD";
} else if (f.length == 2) {
format = "YYYY-MM";
} else {
format = "YYYY";
}
((DublinCoreSchemaCustom) dcSchema).setDateAttributeFormatQualifier(format);
});
.ifPresent(publicationDate -> dcSchema.addUnqualifiedSequenceValue("date", publicationDate));
}

/**
Expand Down Expand Up @@ -415,7 +377,7 @@ private void fillTitle(String title) {
}

/**
* BibTex : Coverage (Custom Field); DC Field : Coverage
* BibTex : Coverage (Custom Field); DC Field : Coverage
*
* @param coverage
*/
Expand All @@ -430,17 +392,7 @@ private void fillCoverage(String coverage) {
*/
private void fillLanguages(String languages) {
Arrays.stream(languages.split(","))
.forEach(
language -> {
try {
Locale locale = LocaleUtils.toLocale(language);
language = locale.getLanguage();
} catch (IllegalArgumentException e) {
LOGGER.warn("Not in ISO 639 standard. Use value as is");
}
dcSchema.addLanguage(language);
}
);
.forEach(dcSchema::addLanguage);
}

/**
Expand Down Expand Up @@ -477,15 +429,13 @@ public void fillDublinCoreSchema() {

Set<Entry<Field, String>> fieldValues = new TreeSet<>(Comparator.comparing(fieldStringEntry -> fieldStringEntry.getKey().getName()));
fieldValues.addAll(bibEntry.getFieldMap().entrySet());

boolean hasStandardYearField = fieldValues.stream().anyMatch(field -> StandardField.YEAR.equals(field.getKey()));
for (Entry<Field, String> field : fieldValues) {
if (useXmpPrivacyFilter && xmpPreferences.getXmpPrivacyFilter().contains(field.getKey())) {
continue;
}

Field fieldEntry = field.getKey();

if (fieldEntry instanceof StandardField) {
switch ((StandardField) fieldEntry) {
case EDITOR:
Expand Down Expand Up @@ -515,8 +465,8 @@ public void fillDublinCoreSchema() {
case LANGUAGE:
this.fillLanguages(field.getValue());
break;
case MONTH:
case DAY:
case MONTH:
if (hasStandardYearField) {
break;
}
Expand Down
39 changes: 17 additions & 22 deletions src/main/java/org/jabref/model/schema/DublinCoreSchemaCustom.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package org.jabref.model.schema;

import java.util.List;
import java.util.Objects;
import javax.xml.XMLConstants;
import java.util.stream.Collectors;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.xmpbox.XMPMetadata;
import org.apache.xmpbox.schema.DublinCoreSchema;
import org.apache.xmpbox.type.AbstractField;
import org.apache.xmpbox.type.ArrayProperty;
import org.apache.xmpbox.type.Attribute;
import org.apache.xmpbox.type.DateType;
import org.apache.xmpbox.type.StructuredType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -41,27 +42,21 @@ public static DublinCoreSchemaCustom copyDublinCoreSchema(DublinCoreSchema dcSch
return dublinCoreSchemaCustom;
}

public String getDateAttributeFormatQualifier() {
AbstractField abstractProperty = getAbstractProperty("date");

if (abstractProperty instanceof ArrayProperty) {
return ((ArrayProperty) abstractProperty)
.getContainer()
.getAllProperties()
.get(0).getAttribute("format").getValue();
@Override
public List<String> getUnqualifiedSequenceValueList(String seqName) {
AbstractField abstractProperty = getAbstractProperty(seqName);
if (abstractProperty instanceof ArrayProperty)
{
if("date".equals(seqName)){
return ((ArrayProperty) abstractProperty).getContainer()
.getAllProperties()
.stream()
.map( field -> (String)((DateType)field).getRawValue())
.collect(Collectors.toList());
}

return ((ArrayProperty) abstractProperty).getElementsAsString();
}

return null;
}

public void setDateAttributeFormatQualifier(String value) {
AbstractField abstractProperty = getAbstractProperty("date");

if (abstractProperty instanceof ArrayProperty) {
var properties = ((ArrayProperty) abstractProperty)
.getContainer()
.getAllProperties();
properties.get(properties.size() - 1).setAttribute(new Attribute(XMLConstants.XML_NS_URI, "format", value));
}
}
}
4 changes: 2 additions & 2 deletions src/test/java/org/jabref/logic/xmp/XmpUtilWriterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ private void initBibEntries() {
vapnik2000.setField(StandardField.AUTHOR, "Vladimir N. Vapnik");
vapnik2000.setField(StandardField.DOI, "10.1007/978-1-4757-3264-1");
vapnik2000.setField(StandardField.OWNER, "Ich");
vapnik2000.setField(StandardField.LANGUAGE, "English, Japanese");
vapnik2000.setDate(new Date(2314, 11, 1));
vapnik2000.setField(StandardField.LANGUAGE,"English, Japanese");
vapnik2000.setDate(new Date(2000, 5));

vapnik2000.setField(new UnknownField(DC_COVERAGE), "coverageField");
vapnik2000.setField(new UnknownField((DC_SOURCE)), "JabRef");
Expand Down

0 comments on commit e2e4b82

Please sign in to comment.