dhp-schemas/src/main/java/eu/dnetlib/dhp/schema/oaf/Result.java

899 lines
20 KiB
Java

package eu.dnetlib.dhp.schema.oaf;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import eu.dnetlib.dhp.schema.common.AccessRightComparator;
import eu.dnetlib.dhp.schema.common.ModelConstants;
import eu.dnetlib.dhp.schema.oaf.utils.CleaningFunctions;
/**
* The type Result.
*/
public class Result extends OafEntity implements Serializable {
/**
* ( article | book ) processing charges.
*/
private Field<String> processingchargeamount;
/**
* currency - alphabetic code describe in ISO-4217.
*/
private Field<String> processingchargecurrency;
/**
* The Measures.
*/
private List<Measure> measures;
/**
* The Author.
*/
private List<Author> author;
/**
* The Resulttype.
*/
// resulttype allows subclassing results into publications | datasets | software
private Qualifier resulttype;
/**
* The Language.
*/
// common fields
private Qualifier language;
/**
* The Country.
*/
private List<Country> country;
/**
* The Subject.
*/
private List<StructuredProperty> subject;
/**
* The Title.
*/
private List<StructuredProperty> title;
/**
* The Relevantdate.
*/
private List<StructuredProperty> relevantdate;
/**
* The Description.
*/
private List<Field<String>> description;
/**
* The Dateofacceptance.
*/
private Field<String> dateofacceptance;
/**
* The Publisher.
*/
private Field<String> publisher;
/**
* The Embargoenddate.
*/
private Field<String> embargoenddate;
/**
* The Source.
*/
private List<Field<String>> source;
/**
* The Fulltext.
*/
private List<Field<String>> fulltext; // remove candidate
/**
* The Format.
*/
private List<Field<String>> format;
/**
* The Contributor.
*/
private List<Field<String>> contributor;
/**
* The Resourcetype.
*/
private Qualifier resourcetype;
/**
* The Coverage.
*/
private List<Field<String>> coverage;
/**
* The Bestaccessright.
*/
private Qualifier bestaccessright;
/**
* The Context.
*/
private List<Context> context;
/**
* The External reference.
*/
private List<ExternalReference> externalReference;
/**
* The Instance.
*/
private List<Instance> instance;
/**
* EOSC Interoperability Framework Guidelines
*/
private List<EoscIfGuidelines> eoscifguidelines;
/**
* Gets measures.
*
* @return the measures
*/
public List<Measure> getMeasures() {
return measures;
}
/**
* Sets measures.
*
* @param measures the measures
*/
public void setMeasures(List<Measure> measures) {
this.measures = measures;
}
public Field<String> getProcessingchargeamount() {
return processingchargeamount;
}
public void setProcessingchargeamount(Field<String> processingchargeamount) {
this.processingchargeamount = processingchargeamount;
}
public Field<String> getProcessingchargecurrency() {
return processingchargecurrency;
}
public void setProcessingchargecurrency(Field<String> processingchargecurrency) {
this.processingchargecurrency = processingchargecurrency;
}
/**
* Gets author.
*
* @return the author
*/
public List<Author> getAuthor() {
return author;
}
/**
* Sets author.
*
* @param author the author
*/
public void setAuthor(List<Author> author) {
this.author = author;
}
/**
* Gets resulttype.
*
* @return the resulttype
*/
public Qualifier getResulttype() {
return resulttype;
}
/**
* Sets resulttype.
*
* @param resulttype the resulttype
*/
public void setResulttype(Qualifier resulttype) {
this.resulttype = resulttype;
}
/**
* Gets language.
*
* @return the language
*/
public Qualifier getLanguage() {
return language;
}
/**
* Sets language.
*
* @param language the language
*/
public void setLanguage(Qualifier language) {
this.language = language;
}
/**
* Gets country.
*
* @return the country
*/
public List<Country> getCountry() {
return country;
}
/**
* Sets country.
*
* @param country the country
*/
public void setCountry(List<Country> country) {
this.country = country;
}
/**
* Gets subject.
*
* @return the subject
*/
public List<StructuredProperty> getSubject() {
return subject;
}
/**
* Sets subject.
*
* @param subject the subject
*/
public void setSubject(List<StructuredProperty> subject) {
this.subject = subject;
}
/**
* Gets title.
*
* @return the title
*/
public List<StructuredProperty> getTitle() {
return title;
}
/**
* Sets title.
*
* @param title the title
*/
public void setTitle(List<StructuredProperty> title) {
this.title = title;
}
/**
* Gets relevantdate.
*
* @return the relevantdate
*/
public List<StructuredProperty> getRelevantdate() {
return relevantdate;
}
/**
* Sets relevantdate.
*
* @param relevantdate the relevantdate
*/
public void setRelevantdate(List<StructuredProperty> relevantdate) {
this.relevantdate = relevantdate;
}
/**
* Gets description.
*
* @return the description
*/
public List<Field<String>> getDescription() {
return description;
}
/**
* Sets description.
*
* @param description the description
*/
public void setDescription(List<Field<String>> description) {
this.description = description;
}
/**
* Gets dateofacceptance.
*
* @return the dateofacceptance
*/
public Field<String> getDateofacceptance() {
return dateofacceptance;
}
/**
* Sets dateofacceptance.
*
* @param dateofacceptance the dateofacceptance
*/
public void setDateofacceptance(Field<String> dateofacceptance) {
this.dateofacceptance = dateofacceptance;
}
/**
* Gets publisher.
*
* @return the publisher
*/
public Field<String> getPublisher() {
return publisher;
}
/**
* Sets publisher.
*
* @param publisher the publisher
*/
public void setPublisher(Field<String> publisher) {
this.publisher = publisher;
}
/**
* Gets embargoenddate.
*
* @return the embargoenddate
*/
public Field<String> getEmbargoenddate() {
return embargoenddate;
}
/**
* Sets embargoenddate.
*
* @param embargoenddate the embargoenddate
*/
public void setEmbargoenddate(Field<String> embargoenddate) {
this.embargoenddate = embargoenddate;
}
/**
* Gets source.
*
* @return the source
*/
public List<Field<String>> getSource() {
return source;
}
/**
* Sets source.
*
* @param source the source
*/
public void setSource(List<Field<String>> source) {
this.source = source;
}
/**
* Gets fulltext.
*
* @return the fulltext
*/
public List<Field<String>> getFulltext() {
return fulltext;
}
/**
* Sets fulltext.
*
* @param fulltext the fulltext
*/
public void setFulltext(List<Field<String>> fulltext) {
this.fulltext = fulltext;
}
/**
* Gets format.
*
* @return the format
*/
public List<Field<String>> getFormat() {
return format;
}
/**
* Sets format.
*
* @param format the format
*/
public void setFormat(List<Field<String>> format) {
this.format = format;
}
/**
* Gets contributor.
*
* @return the contributor
*/
public List<Field<String>> getContributor() {
return contributor;
}
/**
* Sets contributor.
*
* @param contributor the contributor
*/
public void setContributor(List<Field<String>> contributor) {
this.contributor = contributor;
}
/**
* Gets resourcetype.
*
* @return the resourcetype
*/
public Qualifier getResourcetype() {
return resourcetype;
}
/**
* Sets resourcetype.
*
* @param resourcetype the resourcetype
*/
public void setResourcetype(Qualifier resourcetype) {
this.resourcetype = resourcetype;
}
/**
* Gets coverage.
*
* @return the coverage
*/
public List<Field<String>> getCoverage() {
return coverage;
}
/**
* Sets coverage.
*
* @param coverage the coverage
*/
public void setCoverage(List<Field<String>> coverage) {
this.coverage = coverage;
}
/**
* Gets bestaccessright.
*
* @return the bestaccessright
*/
public Qualifier getBestaccessright() {
return bestaccessright;
}
/**
* Sets bestaccessright.
*
* @param bestaccessright the bestaccessright
*/
public void setBestaccessright(Qualifier bestaccessright) {
this.bestaccessright = bestaccessright;
}
/**
* Gets context.
*
* @return the context
*/
public List<Context> getContext() {
return context;
}
/**
* Sets context.
*
* @param context the context
*/
public void setContext(List<Context> context) {
this.context = context;
}
/**
* Gets external reference.
*
* @return the external reference
*/
public List<ExternalReference> getExternalReference() {
return externalReference;
}
/**
* Sets external reference.
*
* @param externalReference the external reference
*/
public void setExternalReference(List<ExternalReference> externalReference) {
this.externalReference = externalReference;
}
/**
* Gets instance.
*
* @return the instance
*/
public List<Instance> getInstance() {
return instance;
}
/**
* Sets instance.
*
* @param instance the instance
*/
public void setInstance(List<Instance> instance) {
this.instance = instance;
}
public List<EoscIfGuidelines> getEoscifguidelines() {
return eoscifguidelines;
}
public void setEoscifguidelines(List<EoscIfGuidelines> eoscifguidelines) {
this.eoscifguidelines = eoscifguidelines;
}
/**
* Is an enrichment boolean.
*
* @param e the e
* @return the boolean
*/
public static boolean isAnEnrichment(OafEntity e) {
return e.getDataInfo()!= null &&
e.getDataInfo().getProvenanceaction()!= null
&& ModelConstants.PROVENANCE_ENRICH.equalsIgnoreCase(e.getDataInfo().getProvenanceaction().getClassid());
}
/**
* Normalize pid string.
*
* @param pid the pid
* @return the string
*/
private static String extractKeyFromPid(final StructuredProperty pid) {
if (pid == null)
return null;
final StructuredProperty normalizedPid = CleaningFunctions.normalizePidValue(pid);
return String.format("%s::%s", normalizedPid.getQualifier().getClassid(), normalizedPid.getValue());
}
/**
* Valid pid boolean.
*
* @param p the p
* @return the boolean
*/
private static boolean validPid(final StructuredProperty p) {
return p.getValue()!= null && p.getQualifier()!= null && p.getQualifier().getClassid()!=null;
}
/**
* This method converts the list of instance enrichments
* into a Map where the key is the normalized identifier
* and the value is the instance itself
*
* @param ri the list of enrichment instances
* @return the result map
*/
public static Map<String, Instance> toInstanceMap(final List<Instance> ri) {
return ri
.stream()
.filter(i -> i.getPid() != null || i.getAlternateIdentifier() != null)
.flatMap(i -> {
final List<Pair<String, Instance>> result = new ArrayList<>();
if (i.getPid() != null)
i.getPid().stream().filter(Result::validPid).forEach(p -> result.add(new ImmutablePair<>(extractKeyFromPid(p), i)));
if (i.getAlternateIdentifier() != null)
i.getAlternateIdentifier().stream().filter(Result::validPid).forEach(p -> result.add(new ImmutablePair<>(extractKeyFromPid(p), i)));
return result.stream();
}).collect(Collectors.toMap(
Pair::getLeft,
Pair::getRight,
(a, b) -> a
));
}
/**
* This utility method finds the list of enrichment instances
* that match one or more PIDs in the input list
*
* @param pids the list of PIDs
* @param enrichments the List of enrichment instances having the same pid
* @return the list
*/
private static List<Instance> findEnrichmentsByPID(final List<StructuredProperty> pids, final Map<String,Instance> enrichments) {
if (pids == null || enrichments == null)
return null;
return pids
.stream()
.map(Result::extractKeyFromPid)
.map(enrichments::get)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
/**
* This method apply enrichment on a single instance
* The enrichment consists of replacing values on
* single attribute only if in the current instance is missing
* The only repeatable field enriched is measures
*
* @param currentInstance the current instance
* @param enrichment the enrichment instance
*/
private static void applyEnrichment(final Instance currentInstance, final Instance enrichment) {
if (currentInstance == null || enrichment == null)
return;
//ENRICH accessright
if (enrichment.getAccessright()!=null && currentInstance.getAccessright() == null)
currentInstance.setAccessright(enrichment.getAccessright());
//ENRICH license
if (enrichment.getLicense()!=null && currentInstance.getLicense() == null)
currentInstance.setLicense(enrichment.getLicense());
//ENRICH instanceType
if (enrichment.getInstancetype()!=null && currentInstance.getInstancetype() == null)
currentInstance.setInstancetype(enrichment.getInstancetype());
//ENRICH hostedby
if (enrichment.getHostedby()!=null && currentInstance.getHostedby() == null)
currentInstance.setHostedby(enrichment.getHostedby());
//ENRICH distributionlocation
if (enrichment.getDistributionlocation()!=null && currentInstance.getDistributionlocation() == null)
currentInstance.setDistributionlocation(enrichment.getDistributionlocation());
//ENRICH collectedfrom
if (enrichment.getCollectedfrom()!=null && currentInstance.getCollectedfrom() == null)
currentInstance.setCollectedfrom(enrichment.getCollectedfrom());
//ENRICH dateofacceptance
if (enrichment.getDateofacceptance()!=null && currentInstance.getDateofacceptance() == null)
currentInstance.setDateofacceptance(enrichment.getDateofacceptance());
//ENRICH processingchargeamount
if (enrichment.getProcessingchargeamount()!=null && currentInstance.getProcessingchargeamount() == null)
currentInstance.setProcessingchargeamount(enrichment.getProcessingchargeamount());
//ENRICH refereed
if (enrichment.getRefereed()!=null && currentInstance.getRefereed() == null)
currentInstance.setRefereed(enrichment.getRefereed());
//ENRICH measures
if (enrichment.getMeasures()!=null)
if (currentInstance.getMeasures() == null)
currentInstance.setMeasures(enrichment.getMeasures());
else
enrichment.getMeasures().forEach(currentInstance.getMeasures()::add);
}
/**
* This main method apply the enrichment of the instances
*
* @param toEnrichInstances the instances that could be enriched
* @param enrichmentInstances the enrichment instances
* @return list of instances possibly enriched
*/
private static List<Instance> enrichInstances(final List<Instance> toEnrichInstances,final List<Instance> enrichmentInstances) {
final List<Instance> enrichmentResult = new ArrayList<>();
if (toEnrichInstances == null) {
return enrichmentResult;
}
if (enrichmentInstances == null) {
return enrichmentResult;
}
Map<String, Instance> ri = toInstanceMap(enrichmentInstances);
toEnrichInstances.forEach(i -> {
final List<Instance> e = findEnrichmentsByPID(i.getPid(), ri);
if (e!= null && e.size()> 0) {
e.forEach(enr -> applyEnrichment(i, enr));
} else {
final List<Instance> a = findEnrichmentsByPID(i.getAlternateIdentifier(), ri);
if (a!= null && a.size()> 0) {
a.forEach(enr -> applyEnrichment(i, enr));
}
}
enrichmentResult.add(i);
});
return enrichmentResult;
}
@Override
public void mergeFrom(OafEntity e) {
super.mergeFrom(e);
if (!Result.class.isAssignableFrom(e.getClass())) {
return;
}
Result r = (Result) e;
if(processingchargeamount == null || StringUtils.isBlank(processingchargeamount.getValue() )){
processingchargeamount = r.getProcessingchargeamount();
processingchargecurrency = r.getProcessingchargecurrency();
}
measures = mergeLists(measures, r.getMeasures());
eoscifguidelines = mergeLists(eoscifguidelines, r.getEoscifguidelines());
if( !isAnEnrichment(this) && !isAnEnrichment(e))
instance = mergeLists(instance, r.getInstance());
else {
final List<Instance> enrichmentInstances = isAnEnrichment(this) ? instance : r.getInstance();
final List<Instance> enrichedInstances= isAnEnrichment(this) ? r.getInstance(): instance;
if (isAnEnrichment(this))
setDataInfo(e.getDataInfo());
instance = enrichInstances(enrichedInstances,enrichmentInstances);
}
if (r.getBestaccessright() != null
&& new AccessRightComparator().compare(r.getBestaccessright(), bestaccessright) < 0)
bestaccessright = r.getBestaccessright();
if (r.getResulttype() != null && compareTrust(this, r) < 0)
resulttype = r.getResulttype();
if (r.getLanguage() != null && compareTrust(this, r) < 0)
language = r.getLanguage();
if (Objects.nonNull(r.getDateofacceptance())) {
if (Objects.isNull(getDateofacceptance())) {
dateofacceptance = r.getDateofacceptance();
} else if (compareTrust(this, r) < 0) {
dateofacceptance = r.getDateofacceptance();
}
}
country = mergeLists(country, r.getCountry());
subject = mergeLists(subject, r.getSubject());
// merge title lists: main title with higher trust and distinct between the others
StructuredProperty baseMainTitle = null;
if (title != null) {
baseMainTitle = getMainTitle(title);
if (baseMainTitle != null) {
final StructuredProperty p = baseMainTitle;
title = title.stream().filter(t -> t != p).collect(Collectors.toList());
}
}
StructuredProperty newMainTitle = null;
if (r.getTitle() != null) {
newMainTitle = getMainTitle(r.getTitle());
if (newMainTitle != null) {
final StructuredProperty p = newMainTitle;
r.setTitle(r.getTitle().stream().filter(t -> t != p).collect(Collectors.toList()));
}
}
if (newMainTitle != null && compareTrust(this, r) < 0) {
baseMainTitle = newMainTitle;
}
title = mergeLists(title, r.getTitle());
if (title != null && baseMainTitle != null) {
title.add(baseMainTitle);
}
relevantdate = mergeLists(relevantdate, r.getRelevantdate());
description = longestLists(description, r.getDescription());
if (r.getPublisher() != null && compareTrust(this, r) < 0)
publisher = r.getPublisher();
if (r.getEmbargoenddate() != null && compareTrust(this, r) < 0)
embargoenddate = r.getEmbargoenddate();
source = mergeLists(source, r.getSource());
fulltext = mergeLists(fulltext, r.getFulltext());
format = mergeLists(format, r.getFormat());
contributor = mergeLists(contributor, r.getContributor());
if (r.getResourcetype() != null)
resourcetype = r.getResourcetype();
coverage = mergeLists(coverage, r.getCoverage());
context = mergeLists(context, r.getContext());
externalReference = mergeLists(externalReference, r.getExternalReference());
}
/**
* Longest lists list.
*
* @param a the a
* @param b the b
* @return the list
*/
private List<Field<String>> longestLists(List<Field<String>> a, List<Field<String>> b) {
if (a == null || b == null)
return a == null ? b : a;
if (a.size() == b.size()) {
int msa = a
.stream()
.filter(i -> i != null && i.getValue() != null)
.map(i -> i.getValue().length())
.max(Comparator.naturalOrder())
.orElse(0);
int msb = b
.stream()
.filter(i -> i != null && i.getValue() != null)
.map(i -> i.getValue().length())
.max(Comparator.naturalOrder())
.orElse(0);
return msa > msb ? a : b;
}
return a.size() > b.size() ? a : b;
}
/**
* Gets main title.
*
* @param titles the titles
* @return the main title
*/
private StructuredProperty getMainTitle(List<StructuredProperty> titles) {
// need to check if the list of titles contains more than 1 main title? (in that case, we should chose which
// main title select in the list)
for (StructuredProperty t : titles) {
if (t.getQualifier() != null && t.getQualifier().getClassid() != null)
if (t.getQualifier().getClassid().equals("main title"))
return t;
}
return null;
}
}