From ef3697cddf5518a63e5fb08e469071c664ae9ff6 Mon Sep 17 00:00:00 2001 From: lbownik Date: Thu, 2 Jul 2026 15:00:27 +0200 Subject: [PATCH 1/8] replaced .orElse(null) with more functional approach --- .../dataset/FieldValueDivider.java | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/dataset/FieldValueDivider.java b/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/dataset/FieldValueDivider.java index 47c0a51a70..e7c418f3e6 100644 --- a/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/dataset/FieldValueDivider.java +++ b/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/dataset/FieldValueDivider.java @@ -1,7 +1,6 @@ package edu.harvard.iq.dataverse.persistence.dataset; -import org.apache.commons.lang3.StringUtils; - +import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; import static org.apache.commons.lang3.StringUtils.isNotBlank; @@ -9,7 +8,8 @@ import java.util.Arrays; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; public class FieldValueDivider { private static final FieldValueDivider EMPTY = new FieldValueDivider(); @@ -37,39 +37,39 @@ public static FieldValueDivider create(DatasetFieldType fieldType) { } public List divide(DatasetField sourceCompound, String delimiter) { - List fields = new ArrayList<>(); - DatasetField sourceField = sourceCompound.getDatasetFieldsChildren().stream() + final List result = new ArrayList<>(); + sourceCompound.getDatasetFieldsChildren().stream() .filter(f -> sourceFieldName.equals(f.getTypeName())) - .findFirst().orElse(null); - if (sourceField == null) { - return fields; - } - List values = splitValue(sourceField, delimiter); - Map valuesToCopy = prepareValuesToCopy(sourceCompound); - for (int i = 0; i < values.size(); i++) { - fields.add(i == 0 - ? sourceCompound - : DatasetField.createNewEmptyDatasetField(sourceCompound.getDatasetFieldType(), null)); - for (DatasetField subfield : fields.get(i).getDatasetFieldsChildren()) { - String name = subfield.getTypeName(); - if (sourceFieldName.equals(name)) { - subfield.setFieldValue(values.get(i)); - } else if (valuesToCopy.containsKey(name)) { - subfield.setFieldValue(valuesToCopy.get(name)); - } - } - } - return fields; + .findFirst() + .map(sourceField -> splitValue(sourceField, delimiter)) + .ifPresent(values -> { + final Map valuesToCopy = prepareValuesToCopy(sourceCompound); + for (int i = 0; i < values.size(); i++) { + result.add(i == 0 + ? sourceCompound + : DatasetField.createNewEmptyDatasetField(sourceCompound.getDatasetFieldType(), null)); + + for (DatasetField subfield : result.get(i).getDatasetFieldsChildren()) { + String name = subfield.getTypeName(); + if (sourceFieldName.equals(name)) { + subfield.setFieldValue(values.get(i)); + } else if (valuesToCopy.containsKey(name)) { + subfield.setFieldValue(valuesToCopy.get(name)); + } + } + } + }); + return result; } // -------------------- PRIVATE -------------------- private List splitValue(DatasetField sourceField, String delimiter) { - String value = sourceField.getFieldValue().getOrElse(StringUtils.EMPTY); + final String value = sourceField.getFieldValue().getOrElse(StringUtils.EMPTY); return Arrays.stream(value.split(delimiter)) .filter(StringUtils::isNotBlank) .map(String::trim) - .collect(Collectors.toList()); + .collect(toList()); } private Map prepareValuesToCopy(DatasetField sourceCompound) { From 103898f66b65b1b943ad76effc21634f57e4ba2f Mon Sep 17 00:00:00 2001 From: lbownik Date: Thu, 2 Jul 2026 15:04:01 +0200 Subject: [PATCH 2/8] this, final, removed redundant variable & inverted condition --- .../dataset/FieldValueDivider.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/dataset/FieldValueDivider.java b/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/dataset/FieldValueDivider.java index e7c418f3e6..08c279943d 100644 --- a/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/dataset/FieldValueDivider.java +++ b/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/dataset/FieldValueDivider.java @@ -24,22 +24,22 @@ private FieldValueDivider() { } // -------------------- LOGIC -------------------- @SuppressWarnings("unchecked") - public static FieldValueDivider create(DatasetFieldType fieldType) { - boolean hasDivider = fieldType.hasMetadata("divider"); - if (!hasDivider) { - return EMPTY; - } - Map dividerData = (Map) fieldType.getMetadata("divider"); - FieldValueDivider divider = new FieldValueDivider(); - divider.sourceFieldName = (String) dividerData.get("source"); - divider.fieldsToCopyNames.addAll((List) dividerData.get("copy")); - return divider; - } + public static FieldValueDivider create(final DatasetFieldType fieldType) { + if (fieldType.hasMetadata("divider")) { + final Map dividerData = (Map) fieldType.getMetadata("divider"); + final FieldValueDivider divider = new FieldValueDivider(); + divider.sourceFieldName = (String) dividerData.get("source"); + divider.fieldsToCopyNames.addAll((List) dividerData.get("copy")); + return divider; + } else { + return EMPTY; + } + } public List divide(DatasetField sourceCompound, String delimiter) { final List result = new ArrayList<>(); sourceCompound.getDatasetFieldsChildren().stream() - .filter(f -> sourceFieldName.equals(f.getTypeName())) + .filter(f -> this.sourceFieldName.equals(f.getTypeName())) .findFirst() .map(sourceField -> splitValue(sourceField, delimiter)) .ifPresent(values -> { @@ -51,7 +51,7 @@ public List divide(DatasetField sourceCompound, String delimiter) for (DatasetField subfield : result.get(i).getDatasetFieldsChildren()) { String name = subfield.getTypeName(); - if (sourceFieldName.equals(name)) { + if (this.sourceFieldName.equals(name)) { subfield.setFieldValue(values.get(i)); } else if (valuesToCopy.containsKey(name)) { subfield.setFieldValue(valuesToCopy.get(name)); @@ -64,7 +64,7 @@ public List divide(DatasetField sourceCompound, String delimiter) // -------------------- PRIVATE -------------------- - private List splitValue(DatasetField sourceField, String delimiter) { + private List splitValue(final DatasetField sourceField, final String delimiter) { final String value = sourceField.getFieldValue().getOrElse(StringUtils.EMPTY); return Arrays.stream(value.split(delimiter)) .filter(StringUtils::isNotBlank) @@ -72,9 +72,9 @@ private List splitValue(DatasetField sourceField, String delimiter) { .collect(toList()); } - private Map prepareValuesToCopy(DatasetField sourceCompound) { + private Map prepareValuesToCopy(final DatasetField sourceCompound) { return sourceCompound.getDatasetFieldsChildren().stream() - .filter(f -> fieldsToCopyNames.contains(f.getTypeName()) + .filter(f -> this.fieldsToCopyNames.contains(f.getTypeName()) && isNotBlank(f.getFieldValue().getOrElse(StringUtils.EMPTY))) .collect(toMap(DatasetField::getTypeName, f -> f.getFieldValue().get(), (prev, next) -> next)); } From 1a812f844885d8c430c210d42c22338be214632c Mon Sep 17 00:00:00 2001 From: lbownik Date: Thu, 2 Jul 2026 15:41:18 +0200 Subject: [PATCH 3/8] renamed variables, this, final, static imports, minor style improvements --- .../citation/CitationDataExtractor.java | 340 +++++++++--------- 1 file changed, 180 insertions(+), 160 deletions(-) diff --git a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/citation/CitationDataExtractor.java b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/citation/CitationDataExtractor.java index db533559a5..378b8aa4ac 100644 --- a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/citation/CitationDataExtractor.java +++ b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/citation/CitationDataExtractor.java @@ -1,7 +1,51 @@ package edu.harvard.iq.dataverse.citation; -import edu.harvard.iq.dataverse.common.BundleUtil; -import edu.harvard.iq.dataverse.common.DatasetFieldConstant; +import static edu.harvard.iq.dataverse.common.BundleUtil.getStringFromBundleWithLocale; +import static edu.harvard.iq.dataverse.common.DatasetFieldConstant.city; +import static edu.harvard.iq.dataverse.common.DatasetFieldConstant.country; +import static edu.harvard.iq.dataverse.common.DatasetFieldConstant.dateOfCollection; +import static edu.harvard.iq.dataverse.common.DatasetFieldConstant.dateOfCollectionEnd; +import static edu.harvard.iq.dataverse.common.DatasetFieldConstant.dateOfCollectionStart; +import static edu.harvard.iq.dataverse.common.DatasetFieldConstant.distributorName; +import static edu.harvard.iq.dataverse.common.DatasetFieldConstant.geographicCoverage; +import static edu.harvard.iq.dataverse.common.DatasetFieldConstant.grantNumber; +import static edu.harvard.iq.dataverse.common.DatasetFieldConstant.grantNumberAgency; +import static edu.harvard.iq.dataverse.common.DatasetFieldConstant.kindOfData; +import static edu.harvard.iq.dataverse.common.DatasetFieldConstant.language; +import static edu.harvard.iq.dataverse.common.DatasetFieldConstant.otherGeographicCoverage; +import static edu.harvard.iq.dataverse.common.DatasetFieldConstant.otherIdValue; +import static edu.harvard.iq.dataverse.common.DatasetFieldConstant.producer; +import static edu.harvard.iq.dataverse.common.DatasetFieldConstant.producerAffiliation; +import static edu.harvard.iq.dataverse.common.DatasetFieldConstant.producerName; +import static edu.harvard.iq.dataverse.common.DatasetFieldConstant.productionDate; +import static edu.harvard.iq.dataverse.common.DatasetFieldConstant.productionPlace; +import static edu.harvard.iq.dataverse.common.DatasetFieldConstant.series; +import static edu.harvard.iq.dataverse.common.DatasetFieldConstant.seriesName; +import static edu.harvard.iq.dataverse.common.DatasetFieldConstant.state; +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; +import static java.util.stream.Collectors.joining; +import static java.util.stream.Collectors.toList; +import static org.apache.commons.lang3.StringUtils.EMPTY; +import static org.apache.commons.lang3.StringUtils.defaultString; +import static org.apache.commons.lang3.StringUtils.isNotEmpty; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.format.DateTimeParseException; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.ejb.Stateless; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import edu.harvard.iq.dataverse.common.DateUtil; import edu.harvard.iq.dataverse.persistence.DvObject; import edu.harvard.iq.dataverse.persistence.GlobalId; @@ -15,25 +59,6 @@ import edu.harvard.iq.dataverse.persistence.harvest.HarvestingClient; import io.vavr.Tuple; import io.vavr.Tuple2; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.ejb.Stateless; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.time.format.DateTimeParseException; -import java.util.Arrays; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Locale; -import java.util.Optional; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import static org.apache.commons.lang3.StringUtils.isNotEmpty; @Stateless public class CitationDataExtractor { @@ -42,247 +67,242 @@ public class CitationDataExtractor { // -------------------- LOGIC -------------------- - public CitationData create(DatasetVersion datasetVersion, Locale locale) { - CitationData data = new CitationData(); - extractAndWriteCommonValues(datasetVersion, data, locale); - - data.setDirect(false) - .setPersistentId(extractPID(datasetVersion, datasetVersion.getDataset(), false)) // Global Id: always part of citation for local datasets & some harvested - .setPidOfDataset(extractDatasetPID(datasetVersion)); - - return data; + public CitationData create(final DatasetVersion version, final Locale locale) { + final CitationData result = new CitationData(); + extractAndWriteCommonValues(version, result, locale); + result.setDirect(false) + .setPersistentId(extractPID(version, version.getDataset(), false)) // Global Id: always part of citation for local datasets & some harvested + .setPidOfDataset(extractDatasetPID(version)); + return result; } - public CitationData create(FileMetadata fileMetadata, boolean direct, Locale locale) { - CitationData data = new CitationData(); - DatasetVersion dsv = fileMetadata.getDatasetVersion(); - extractAndWriteCommonValues(dsv, data, locale); - - DataFile df = fileMetadata.getDataFile(); - - data.setDirect(direct) - .setFileTitle(fileMetadata.getLabel()) - .setPersistentId(extractPID(dsv, df, direct)) // Global Id of datafile (if published & isDirect==true) or dataset as appropriate - .setPidOfDataset(extractDatasetPID(dsv)) - .setPidOfFile(extractFilePID(dsv, df, direct)); - return data; + public CitationData create(final FileMetadata metadata, final boolean direct, + final Locale locale) { + final CitationData result = new CitationData(); + final DatasetVersion version = metadata.getDatasetVersion(); + extractAndWriteCommonValues(version, result, locale); + final DataFile dataFile = metadata.getDataFile(); + result.setDirect(direct) + .setFileTitle(metadata.getLabel()) + .setPersistentId(extractPID(version, dataFile, direct)) // Global Id of datafile (if published & isDirect==true) or dataset as appropriate + .setPidOfDataset(extractDatasetPID(version)) + .setPidOfFile(extractFilePID(version, dataFile, direct)); + return result; } // -------------------- PRIVATE -------------------- - private void extractAndWriteCommonValues(DatasetVersion dsv, CitationData data, Locale locale) { - Date dataDate = extractCitationDate(dsv); - - data.getAuthors().addAll(extractAuthors(dsv)); - data.setYear(new SimpleDateFormat("yyyy").format(dataDate)) - .setTitle(dsv.getParsedTitle()); - - if (!dsv.getDataset().isHarvested()) { - data.getProducers().addAll(extractProducers(dsv)); - data.getDistributors().addAll(getDatasetFieldValuesByTypeName(dsv, DatasetFieldConstant.distributorName)); - data.getFunders().addAll(getUniqueGrantAgencyValues(dsv)); - data.getKindsOfData().addAll(dsv.extractFieldValues(DatasetFieldConstant.kindOfData)); - data.getDatesOfCollection().addAll(getDatesOfCollection(dsv)); - data.getLanguages().addAll(dsv.extractFieldValues(DatasetFieldConstant.language)); - data.getSpatialCoverages().addAll(extractSpatialCoverages(dsv)); - data.getKeywords().addAll(dsv.getKeywords()); - data.getOtherIds().addAll(getDatasetFieldValuesByTypeName(dsv, DatasetFieldConstant.otherIdValue)); - - data.setDate(dataDate) - .setProductionPlace(extractField(dsv, DatasetFieldConstant.productionPlace)) - .setProductionDate(extractProductionDate(dsv)) - .setReleaseYear(extractReleaseYear(dsv)) - .setRootDataverseName(dsv.getRootDataverseNameForCitation()) - .setSeriesTitle(getSeriesTitle(dsv)) - .setPublisher(extractPublisher(dsv)) - .setVersion(extractVersion(dsv,locale)); + private void extractAndWriteCommonValues(final DatasetVersion version, + final CitationData citation, final Locale locale) { + final Date citationDate = extractCitationDate(version); + + citation.getAuthors().addAll(extractAuthors(version)); + citation.setYear(new SimpleDateFormat("yyyy").format(citationDate)) + .setTitle(version.getParsedTitle()); + + if (!version.getDataset().isHarvested()) { + citation.getProducers().addAll(extractProducers(version)); + citation.getDistributors().addAll(getDatasetFieldValuesByTypeName(version, distributorName)); + citation.getFunders().addAll(getUniqueGrantAgencyValues(version)); + citation.getKindsOfData().addAll(version.extractFieldValues(kindOfData)); + citation.getDatesOfCollection().addAll(getDatesOfCollection(version)); + citation.getLanguages().addAll(version.extractFieldValues(language)); + citation.getSpatialCoverages().addAll(extractSpatialCoverages(version)); + citation.getKeywords().addAll(version.getKeywords()); + citation.getOtherIds().addAll(getDatasetFieldValuesByTypeName(version, otherIdValue)); + + citation.setDate(citationDate) + .setProductionPlace(extractField(version, productionPlace)) + .setProductionDate(extractProductionDate(version)) + .setReleaseYear(extractReleaseYear(version)) + .setRootDataverseName(version.getRootDataverseNameForCitation()) + .setSeriesTitle(getSeriesTitle(version)) + .setPublisher(extractPublisher(version)) + .setVersion(extractVersion(version,locale)); } } - private List getDatasetFieldValuesByTypeName(DatasetVersion dsv, String datasetFieldTypeName) { - return dsv.streamDatasetFieldsByTypeName(datasetFieldTypeName) + private List getDatasetFieldValuesByTypeName(final DatasetVersion version, + final String datasetFieldTypeName) { + return version.streamDatasetFieldsByTypeName(datasetFieldTypeName) .map(DatasetField::getValue) - .collect(Collectors.toList()); + .collect(toList()); } - private String extractField(DatasetVersion dsv, String typeName) { - return dsv.getDatasetFieldByTypeName(typeName) + private String extractField(final DatasetVersion version, final String typeName) { + return version.getDatasetFieldByTypeName(typeName) .map(DatasetField::getValue) .orElse(null); } - private List getUniqueGrantAgencyValues(DatasetVersion version) { + private List getUniqueGrantAgencyValues(final DatasetVersion version) { // Since only grant agency names are returned, use distinct() to avoid repeats // (e.g. if there are two grants from the same agency) - return version.getCompoundChildFieldValues(DatasetFieldConstant.grantNumber, - Collections.singletonList(DatasetFieldConstant.grantNumberAgency)).stream() + return version.getCompoundChildFieldValues(grantNumber, + singletonList(grantNumberAgency)).stream() .distinct() - .collect(Collectors.toList()); + .collect(toList()); } - private List getDatesOfCollection(DatasetVersion dsv) { - return dsv.extractFieldWithSubfields(DatasetFieldConstant.dateOfCollection, - Arrays.asList(DatasetFieldConstant.dateOfCollectionStart, DatasetFieldConstant.dateOfCollectionEnd)) + private List getDatesOfCollection(final DatasetVersion version) { + return version.extractFieldWithSubfields(dateOfCollection, + asList(dateOfCollectionStart, dateOfCollectionEnd)) .stream() - .map(e -> Tuple.of(e.get(DatasetFieldConstant.dateOfCollectionStart), e.get(DatasetFieldConstant.dateOfCollectionEnd))) + .map(e -> Tuple.of(e.get(dateOfCollectionStart), e.get(dateOfCollectionEnd))) .filter(t -> t._1 != null && !t._1.isEmptyForDisplay() && t._2 != null && !t._2.isEmptyForDisplay()) .map(t -> t._1.getValue() + "/" + t._2.getValue()) - .collect(Collectors.toList()); + .collect(toList()); } - public List extractSpatialCoverages(DatasetVersion version) { - List subfields = Arrays.asList(DatasetFieldConstant.country, DatasetFieldConstant.state, - DatasetFieldConstant.city, DatasetFieldConstant.otherGeographicCoverage); - return version.extractFieldWithSubfields(DatasetFieldConstant.geographicCoverage, subfields).stream() + public List extractSpatialCoverages(final DatasetVersion version) { + final List subfields = asList(country, state, city, otherGeographicCoverage); + return version.extractFieldWithSubfields(geographicCoverage, subfields).stream() .map(s -> subfields.stream() .map(s::get) .filter(v -> v != null && !v.isEmptyForDisplay()) .map(DatasetField::getValue) - .collect(Collectors.joining(","))) + .collect(joining(","))) .filter(StringUtils::isNotEmpty) - .collect(Collectors.toList()); + .collect(toList()); } - private String extractProductionDate(DatasetVersion dsv) { - String rawDate = dsv.getDatasetFieldByTypeName(DatasetFieldConstant.productionDate) + private String extractProductionDate(final DatasetVersion version) { + return version.getDatasetFieldByTypeName(productionDate) .map(DatasetField::getValue) - .orElse(StringUtils.EMPTY); - Pattern year = Pattern.compile("\\d{4}"); - Matcher yearMatcher = year.matcher(rawDate); - if (yearMatcher.find()) { - return yearMatcher.group(); - } - return StringUtils.EMPTY; + .map(date -> { + final Matcher yearMatcher = Pattern.compile("\\d{4}").matcher(date); + return yearMatcher.find() ? yearMatcher.group(): EMPTY; + }) + .orElse(EMPTY); } - private List extractProducers(DatasetVersion dsv) { - return getProducers(dsv).stream() + private List extractProducers(final DatasetVersion version) { + return getProducers(version).stream() .map(p -> new CitationData.Producer(p._1, p._2)) - .collect(Collectors.toList()); + .collect(toList()); } - private List> getProducers(DatasetVersion dsv) { - return dsv.extractFieldWithSubfields(DatasetFieldConstant.producer, - Arrays.asList(DatasetFieldConstant.producerName, DatasetFieldConstant.producerAffiliation)) + private List> getProducers(final DatasetVersion version) { + return version.extractFieldWithSubfields(producer, asList(producerName, producerAffiliation)) .stream() .filter(e -> { - DatasetField name = e.get(DatasetFieldConstant.producerName); + final DatasetField name = e.get(producerName); return name != null && !name.isEmptyForDisplay(); }) - .map(e -> Tuple.of(e.get(DatasetFieldConstant.producerName), e.get(DatasetFieldConstant.producerAffiliation))) - .map(t -> Tuple.of(t._1.getValue(), - t._2 != null ? t._2.getValue() : StringUtils.EMPTY)) - .collect(Collectors.toList()); + .map(e -> Tuple.of(e.get(producerName), e.get(producerAffiliation))) + .map(t -> Tuple.of(t._1.getValue(), defaultString(t._2.getValue()))) + .collect(toList()); } - private String extractReleaseYear(DatasetVersion dsv) { - return dsv.getReleaseTime() != null - ? new SimpleDateFormat("yyyy").format(dsv.getReleaseTime()) - : StringUtils.EMPTY; + private String extractReleaseYear(final DatasetVersion version) { + return version.getReleaseTime() != null + ? new SimpleDateFormat("yyyy").format(version.getReleaseTime()) + : EMPTY; } - private List extractAuthors(DatasetVersion dsv) { - return dsv.getDatasetAuthors().stream() + private List extractAuthors(final DatasetVersion version) { + return version.getDatasetAuthors().stream() .filter(a -> !a.isEmpty()) .map(a -> a.getName().getDisplayValue().trim()) - .collect(Collectors.toList()); + .collect(toList()); } - private GlobalId extractPID(DatasetVersion dsv, DvObject dv, boolean direct) { - if (shouldCreateGlobalId(dsv)) { - if (!direct && isNotEmpty(dsv.getDataset().getIdentifier())) { - return new GlobalId(dsv.getDataset()); - } else if (direct && isNotEmpty(dv.getIdentifier())) { - return new GlobalId(dv); + private GlobalId extractPID(final DatasetVersion version, + final DvObject dvObject, final boolean direct) { + if (shouldCreateGlobalId(version)) { + if (!direct && isNotEmpty(version.getDataset().getIdentifier())) { + return new GlobalId(version.getDataset()); + } else if (direct && isNotEmpty(dvObject.getIdentifier())) { + return new GlobalId(dvObject); } } return null; } - private GlobalId extractDatasetPID(DatasetVersion dsv) { - return shouldCreateGlobalId(dsv) && isNotEmpty(dsv.getDataset().getIdentifier()) - ? new GlobalId(dsv.getDataset()) : null; + private GlobalId extractDatasetPID(final DatasetVersion version) { + return shouldCreateGlobalId(version) && isNotEmpty(version.getDataset().getIdentifier()) + ? new GlobalId(version.getDataset()) : null; } - private GlobalId extractFilePID(DatasetVersion dsv, DataFile datafile, boolean direct) { - return shouldCreateGlobalId(dsv) && !direct && isNotEmpty(datafile.getIdentifier()) + private GlobalId extractFilePID(final DatasetVersion version, + final DataFile datafile, final boolean direct) { + return shouldCreateGlobalId(version) && !direct && isNotEmpty(datafile.getIdentifier()) ? new GlobalId(datafile) : null; } - private boolean shouldCreateGlobalId(DatasetVersion dsv) { - HarvestStyle harvestStyle = Optional.ofNullable(dsv.getDataset().getHarvestedFrom()) + private boolean shouldCreateGlobalId(final DatasetVersion version) { + final HarvestStyle harvestStyle = Optional.ofNullable(version.getDataset().getHarvestedFrom()) .map(HarvestingClient::getHarvestStyle) .orElse(null); - return !dsv.getDataset().isHarvested() + return !version.getDataset().isHarvested() || HarvestStyle.VDC.equals(harvestStyle) || HarvestStyle.ICPSR.equals(harvestStyle) || HarvestStyle.DATAVERSE.equals(harvestStyle) || HarvestStyle.DOI.equals(harvestStyle); } - private Date extractCitationDate(DatasetVersion dsv) { + private Date extractCitationDate(final DatasetVersion version) { Date citationDate = null; - if (!dsv.getDataset().isHarvested()) { - citationDate = getCitationDate(dsv); + if (!version.getDataset().isHarvested()) { + citationDate = getCitationDate(version); if (citationDate == null) { - citationDate = dsv.getDataset().getPublicationDate() != null - ? dsv.getDataset().getPublicationDate() - : dsv.getLastUpdateTime(); // for drafts + citationDate = version.getDataset().getPublicationDate() != null + ? version.getDataset().getPublicationDate() + : version.getLastUpdateTime(); // for drafts } } else { try { - citationDate = DateUtil.parseDateTimeFormatAsDate(dsv.getProductionDate()); + citationDate = DateUtil.parseDateTimeFormatAsDate(version.getProductionDate()); if (citationDate == null) { - citationDate = dsv.getDataset().getPublicationDate(); + citationDate = version.getDataset().getPublicationDate(); } } catch (DateTimeParseException pe) { - logger.warn(String.format("Error parsing date [%s]", dsv.getProductionDate()), pe); + logger.warn(String.format("Error parsing date [%s]", version.getProductionDate()), pe); } } if (citationDate == null) { - logger.warn("Unable to find citation date for datasetversion: {}", dsv.getId()); + logger.warn("Unable to find citation date for datasetversion: {}", version.getId()); citationDate = new Date(); // As a last resort, pick the current date } return citationDate; } - private Date getCitationDate(DatasetVersion dsv) { - DatasetFieldType citationDateType = dsv.getDataset().getCitationDateDatasetFieldType(); - DatasetField citationDate = citationDateType != null - ? dsv.getDatasetFieldByTypeName(citationDateType.getName()).orElse(null) : null; + private Date getCitationDate(final DatasetVersion version) { + final DatasetFieldType citationDateType = version.getDataset().getCitationDateDatasetFieldType(); + final DatasetField citationDate = citationDateType != null + ? version.getDatasetFieldByTypeName(citationDateType.getName()).orElse(null) : null; if (citationDate != null && FieldType.DATE.equals(citationDate.getDatasetFieldType().getFieldType())) { try { return new SimpleDateFormat("yyyy").parse(citationDate.getValue()); - } catch (ParseException ex) { + } catch (final ParseException ex) { logger.warn("Date parsing exception: ", ex); } } return null; } - private String getSeriesTitle(DatasetVersion version) { - return version.getCompoundChildFieldValues(DatasetFieldConstant.series, - Collections.singletonList(DatasetFieldConstant.seriesName)) + private String getSeriesTitle(final DatasetVersion version) { + return version.getCompoundChildFieldValues(series, singletonList(seriesName)) .stream() .findFirst() .orElse(null); } - private String extractPublisher(DatasetVersion dsv) { - return dsv.getRootDataverseNameForCitation(); + private String extractPublisher(final DatasetVersion version) { + return version.getRootDataverseNameForCitation(); } - private String extractVersion(DatasetVersion dsv, Locale locale) { - String version = StringUtils.EMPTY; - if (dsv.isDraft()) { - version = BundleUtil.getStringFromBundleWithLocale("draftversion", locale); - } else if (dsv.getVersionNumber() != null) { - version = "V" + dsv.getVersionNumber() - + (dsv.isDeaccessioned() - ? ", " + BundleUtil.getStringFromBundleWithLocale("deaccessionedversion", locale) - : StringUtils.EMPTY); + private String extractVersion(final DatasetVersion version, final Locale locale) { + if (version.isDraft()) { + return getStringFromBundleWithLocale("draftversion", locale); + } else if (version.getVersionNumber() != null) { + return "V" + version.getVersionNumber() + + (version.isDeaccessioned() + ? ", " + getStringFromBundleWithLocale("deaccessionedversion", locale) + : EMPTY); + } else { + return EMPTY; } - return version; } } From 63a5f63efdb28a79b8e362294c6c5ab237af2b32 Mon Sep 17 00:00:00 2001 From: lbownik Date: Thu, 2 Jul 2026 15:45:41 +0200 Subject: [PATCH 4/8] removed redundant method, minor performance improvement --- .../iq/dataverse/citation/CitationDataExtractor.java | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/citation/CitationDataExtractor.java b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/citation/CitationDataExtractor.java index 378b8aa4ac..c7844e1ba3 100644 --- a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/citation/CitationDataExtractor.java +++ b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/citation/CitationDataExtractor.java @@ -177,20 +177,14 @@ private String extractProductionDate(final DatasetVersion version) { } private List extractProducers(final DatasetVersion version) { - return getProducers(version).stream() - .map(p -> new CitationData.Producer(p._1, p._2)) - .collect(toList()); - } - - private List> getProducers(final DatasetVersion version) { - return version.extractFieldWithSubfields(producer, asList(producerName, producerAffiliation)) + return version.extractFieldWithSubfields(producer, asList(producerName, producerAffiliation)) .stream() .filter(e -> { final DatasetField name = e.get(producerName); return name != null && !name.isEmptyForDisplay(); }) - .map(e -> Tuple.of(e.get(producerName), e.get(producerAffiliation))) - .map(t -> Tuple.of(t._1.getValue(), defaultString(t._2.getValue()))) + .map(e -> new CitationData.Producer(e.get(producerName).getValue(), + defaultString(e.get(producerAffiliation).getValue()))) .collect(toList()); } From 18b5b0d2a838ddbdca3c21be945c5d254e323675 Mon Sep 17 00:00:00 2001 From: lbownik Date: Thu, 2 Jul 2026 15:47:51 +0200 Subject: [PATCH 5/8] removed unused import --- .../edu/harvard/iq/dataverse/citation/CitationDataExtractor.java | 1 - 1 file changed, 1 deletion(-) diff --git a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/citation/CitationDataExtractor.java b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/citation/CitationDataExtractor.java index c7844e1ba3..82eb65a905 100644 --- a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/citation/CitationDataExtractor.java +++ b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/citation/CitationDataExtractor.java @@ -58,7 +58,6 @@ import edu.harvard.iq.dataverse.persistence.harvest.HarvestStyle; import edu.harvard.iq.dataverse.persistence.harvest.HarvestingClient; import io.vavr.Tuple; -import io.vavr.Tuple2; @Stateless public class CitationDataExtractor { From 59c83bd43b3f36f07c9d6f74829b723cb7ef147c Mon Sep 17 00:00:00 2001 From: lbownik Date: Fri, 3 Jul 2026 15:43:43 +0200 Subject: [PATCH 6/8] introduced DVObject repository, moved some logic there --- .../iq/dataverse/persistence/DvObject.java | 14 ---- .../persistence/DvObjectRepository.java | 45 ++++++++++ .../iq/dataverse/DataFileServiceBean.java | 14 ++-- .../edu/harvard/iq/dataverse/DvObjectDao.java | 17 ++-- .../iq/dataverse/DvObjectServiceBean.java | 78 ++++++++---------- .../edu/harvard/iq/dataverse/api/Index.java | 82 ++++++++++--------- .../permission/ManagePermissionsPage.java | 2 +- .../search/index/IndexServiceBean.java | 3 +- .../savedsearch/SavedSearchServiceBean.java | 2 +- .../users/MergeInAccountServiceIT.java | 2 +- 10 files changed, 143 insertions(+), 116 deletions(-) create mode 100644 fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/DvObjectRepository.java diff --git a/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/DvObject.java b/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/DvObject.java index a9822e1c92..fc35479abb 100644 --- a/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/DvObject.java +++ b/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/DvObject.java @@ -48,24 +48,10 @@ */ @SuppressWarnings("serial") @NamedQueries({ - @NamedQuery(name = "DvObject.findAll", - query = "SELECT o FROM DvObject o ORDER BY o.id"), - @NamedQuery(name = "DvObject.findById", - query = "SELECT o FROM DvObject o WHERE o.id=:id"), - @NamedQuery(name = "DvObject.ownedObjectsById", - query = "SELECT COUNT(obj) FROM DvObject obj WHERE obj.owner.id=:id"), @NamedQuery(name = "DvObject.findByGlobalId", query = "SELECT o FROM DvObject o WHERE o.identifier=:identifier and o.authority=:authority and o.protocol=:protocol and o.dtype=:dtype"), - @NamedQuery(name = "DvObject.findByAlternativeGlobalId", query = "SELECT o FROM DvObject o, AlternativePersistentIdentifier a WHERE o.id = a.dvObject.id and a.identifier=:identifier and a.authority=:authority and a.protocol=:protocol and o.dtype=:dtype"), - - @NamedQuery(name = "DvObject.findByProtocolIdentifierAuthority", - query = "SELECT o FROM DvObject o WHERE o.identifier=:identifier and o.authority=:authority and o.protocol=:protocol"), - @NamedQuery(name = "DvObject.findByOwnerId", - query = "SELECT o FROM DvObject o WHERE o.owner.id=:ownerId"), - @NamedQuery(name = "DvObject.findByAuthenticatedUserId", - query = "SELECT o FROM DvObject o WHERE o.creator.id=:ownerId or o.releaseUser.id=:releaseUserId") }) @Entity // Inheritance strategy "JOINED" will create 4 db tables - diff --git a/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/DvObjectRepository.java b/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/DvObjectRepository.java new file mode 100644 index 0000000000..6c78570869 --- /dev/null +++ b/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/DvObjectRepository.java @@ -0,0 +1,45 @@ +package edu.harvard.iq.dataverse.persistence; + +import java.util.List; +import java.util.Optional; + +import javax.ejb.Stateless; + +@Stateless +public class DvObjectRepository extends JpaRepository { + + public DvObjectRepository() { + super(DvObject.class); + } + + public List findByOwnerId(final Long id) { + return createQuery("SELECT o FROM DvObject o WHERE o.owner.id=:id") + .setParameter("id", id) + .getResultList(); + } + + public boolean hasData(final Long id) { + return this.em.createQuery( + "SELECT COUNT(obj) FROM DvObject obj WHERE obj.owner.id=:id", + Long.class) + .setParameter("id", id) + .getSingleResult() > 0; + } + + public List findByAuthenticatedUserId(final Long id) { + return createQuery( + "SELECT o FROM DvObject o WHERE o.creator.id=:id or o.releaseUser.id=:id") + .setParameter("id", id) + .getResultList(); + } + + public Optional findByGlobalId(final String protocol, + final String authority, final String identifier) { + return getSingleResult(createQuery( + "SELECT o FROM DvObject o " + + "WHERE o.identifier=:identifier and o.authority=:authority and o.protocol=:protocol") + .setParameter("protocol", protocol) + .setParameter("authority", authority) + .setParameter("identifier", identifier)); + } +} diff --git a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DataFileServiceBean.java b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DataFileServiceBean.java index 00aae12391..4ad9e44e8e 100644 --- a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DataFileServiceBean.java +++ b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DataFileServiceBean.java @@ -37,6 +37,7 @@ import edu.harvard.iq.dataverse.dataaccess.ImageThumbConverter; import edu.harvard.iq.dataverse.dataaccess.StorageIO; import edu.harvard.iq.dataverse.globalid.GlobalIdServiceBean; +import edu.harvard.iq.dataverse.persistence.DvObjectRepository; import edu.harvard.iq.dataverse.persistence.GlobalId; import edu.harvard.iq.dataverse.persistence.datafile.DataFile; import edu.harvard.iq.dataverse.persistence.datafile.DataFileRepository; @@ -73,6 +74,8 @@ public class DataFileServiceBean implements Serializable { private DataFileRepository fileRepo; @Inject private FileMetadataRepository fileMetadataRepo; + @Inject + private DvObjectRepository dvObjectRepository; @PersistenceContext(unitName = "VDCNet-ejbPU") private EntityManager em; @@ -432,7 +435,8 @@ public String generateDataFileIdentifier(DataFile datafile, GlobalIdServiceBean * * @return {@code true} iff the global identifier is unique. */ - public boolean isGlobalIdUnique(String userIdentifier, DataFile datafile, GlobalIdServiceBean idServiceBean) { + public boolean isGlobalIdUnique(String userIdentifier, DataFile datafile, + GlobalIdServiceBean idServiceBean) { String testAuthority = datafile.getAuthority() != null ? datafile.getAuthority() : settingsService.getValueForKey(Authority); @@ -440,12 +444,8 @@ public boolean isGlobalIdUnique(String userIdentifier, DataFile datafile, Global ? datafile.getProtocol() : settingsService.getValueForKey(Protocol); - boolean unique = em.createNamedQuery("DvObject.findByProtocolIdentifierAuthority") - .setParameter("protocol", testProtocol) - .setParameter("authority", testAuthority) - .setParameter("identifier", userIdentifier) - .getResultList().isEmpty(); - + boolean unique = ! this.dvObjectRepository. + findByGlobalId(testProtocol, testAuthority, userIdentifier).isPresent(); try { if (idServiceBean.alreadyExists(new GlobalId(testProtocol, testAuthority, userIdentifier))) { diff --git a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DvObjectDao.java b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DvObjectDao.java index 1c6114e791..3ad15cecde 100644 --- a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DvObjectDao.java +++ b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DvObjectDao.java @@ -9,6 +9,7 @@ import edu.harvard.iq.dataverse.dataset.DatasetService; import edu.harvard.iq.dataverse.persistence.DvObject; +import edu.harvard.iq.dataverse.persistence.DvObjectRepository; import edu.harvard.iq.dataverse.persistence.dataset.Dataset; import edu.harvard.iq.dataverse.persistence.dataverse.Dataverse; @@ -17,11 +18,15 @@ public class DvObjectDao { private DataverseDao dataverseDao; private DatasetService datasetService; + private DvObjectRepository dvObjectRepository; @Inject - public DvObjectDao(DataverseDao dataverseDao, DatasetService datasetService) { + public DvObjectDao(final DataverseDao dataverseDao, + final DatasetService datasetService, + final DvObjectRepository dvObjectRepository) { this.dataverseDao = dataverseDao; this.datasetService = datasetService; + this.dvObjectRepository = dvObjectRepository; } public DvObjectDao() { @@ -40,16 +45,10 @@ public DvObjectDao() { */ public DvObject findDvo(String id) { if (isNumeric(id)) { - return this.findDvo(Long.valueOf(id)); + return this.dvObjectRepository.getById(Long.valueOf(id)); } else { - Dataverse d = dataverseDao.findByAlias(id); + final Dataverse d = dataverseDao.findByAlias(id); return (d != null) ? d : datasetService.findByGlobalId(id); } } - - private DvObject findDvo(Long id) { - return em.createNamedQuery("DvObject.findById", DvObject.class) - .setParameter("id", id) - .getSingleResult(); - } } diff --git a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java index 28ba271a07..105ee08935 100644 --- a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java +++ b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java @@ -1,19 +1,11 @@ package edu.harvard.iq.dataverse; -import edu.harvard.iq.dataverse.persistence.DvObject; -import edu.harvard.iq.dataverse.persistence.DvObjectContainer; -import edu.harvard.iq.dataverse.persistence.GlobalId; -import edu.harvard.iq.dataverse.persistence.dataverse.Dataverse; -import edu.harvard.iq.dataverse.persistence.user.AuthenticatedUser; -import org.ocpsoft.common.util.Strings; +import static java.util.Collections.emptyList; +import static java.util.logging.Level.FINE; +import static java.util.logging.Logger.getLogger; +import static javax.ejb.TransactionAttributeType.REQUIRES_NEW; +import static org.apache.commons.lang3.StringUtils.join; -import javax.ejb.Stateless; -import javax.ejb.TransactionAttribute; -import javax.persistence.EntityManager; -import javax.persistence.NoResultException; -import javax.persistence.NonUniqueResultException; -import javax.persistence.PersistenceContext; -import javax.persistence.Query; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Collection; @@ -21,14 +13,25 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.logging.Logger; -import static java.util.Collections.emptyList; -import static java.util.logging.Level.FINE; -import static java.util.logging.Logger.getLogger; -import static javax.ejb.TransactionAttributeType.REQUIRES_NEW; -import static org.apache.commons.lang3.StringUtils.join; +import javax.ejb.Stateless; +import javax.ejb.TransactionAttribute; +import javax.inject.Inject; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; + +import org.ocpsoft.common.util.Strings; + +import edu.harvard.iq.dataverse.persistence.DvObject; +import edu.harvard.iq.dataverse.persistence.DvObjectContainer; +import edu.harvard.iq.dataverse.persistence.DvObjectRepository; +import edu.harvard.iq.dataverse.persistence.GlobalId; +import edu.harvard.iq.dataverse.persistence.dataverse.Dataverse; +import edu.harvard.iq.dataverse.persistence.user.AuthenticatedUser; /** * Your goto bean for everything {@link DvObject}, that's not tied to any @@ -42,6 +45,9 @@ public class DvObjectServiceBean implements java.io.Serializable { @PersistenceContext(unitName = "VDCNet-ejbPU") private EntityManager em; + + @Inject + private DvObjectRepository repository; private static final Logger logger = getLogger(DvObjectServiceBean.class.getCanonicalName()); @@ -51,30 +57,22 @@ public class DvObjectServiceBean implements java.io.Serializable { * {@link DvObject}. */ public boolean hasData(DvObjectContainer dvoc) { - return em.createNamedQuery("DvObject.ownedObjectsById", Long.class) - .setParameter("id", dvoc.getId()) - .getSingleResult() > 0; + return this.repository.hasData(dvoc.getId()); + } + public DvObject getDvObject(final Long id) { + return this.repository.getById(id); } - public DvObject findDvObject(Long id) { - try { - return em.createNamedQuery("DvObject.findById", DvObject.class) - .setParameter("id", id) - .getSingleResult(); - } catch (NoResultException | NonUniqueResultException ex) { - return null; - } + public Optional findDvObject(final Long id) { + return this.repository.findById(id); } public List findAll() { - return em.createNamedQuery("DvObject.findAll", DvObject.class).getResultList(); + return this.repository.findAll(); } - - public List findByOwnerId(Long ownerId) { - return em.createNamedQuery("DvObject.findByOwnerId", DvObject.class) - .setParameter("ownerId", ownerId) - .getResultList(); + public List findByOwnerId(final Long id) { + return this.repository.findByOwnerId(id); } // FIXME This type-by-string has to go, in favor of passing a class parameter. @@ -119,12 +117,8 @@ public DvObject findByGlobalId(String globalIdString, String typeString, Boolean } } - public List findByAuthenticatedUserId(AuthenticatedUser user) { - return em.createNamedQuery("DvObject.findByAuthenticatedUserId", - DvObject.class) - .setParameter("ownerId", user.getId()) - .setParameter("releaseUserId", user.getId()) - .getResultList(); + public List findByAuthenticatedUserId(final AuthenticatedUser user) { + return this.repository.findByAuthenticatedUserId(user.getId()); } public DvObject updateContentIndexTime(DvObject dvObject) { @@ -133,7 +127,7 @@ public DvObject updateContentIndexTime(DvObject dvObject) { * dvObject before we try to setIndexTime? See * https://github.com/IQSS/dataverse/commit/6ad0ebb272c8cb46368cb76784b55dbf33eea947 */ - DvObject dvObjectToModify = findDvObject(dvObject.getId()); + DvObject dvObjectToModify = findDvObject(dvObject.getId()).get(); dvObjectToModify.setIndexTime(new Timestamp(new Date().getTime())); DvObject savedDvObject = em.merge(dvObjectToModify); return savedDvObject; diff --git a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/api/Index.java b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/api/Index.java index 9baf49731f..704cdecfa9 100644 --- a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/api/Index.java +++ b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/api/Index.java @@ -1,5 +1,37 @@ package edu.harvard.iq.dataverse.api; +import static edu.harvard.iq.dataverse.common.NullSafeJsonBuilder.jsonObjectBuilder; +import static javax.ws.rs.core.Response.Status.BAD_REQUEST; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.ejb.EJB; +import javax.ejb.EJBException; +import javax.inject.Inject; +import javax.json.Json; +import javax.json.JsonArrayBuilder; +import javax.json.JsonObject; +import javax.json.JsonObjectBuilder; +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.apache.solr.client.solrj.SolrServerException; + import edu.harvard.iq.dataverse.DataFileServiceBean; import edu.harvard.iq.dataverse.DatasetFieldServiceBean; import edu.harvard.iq.dataverse.DataverseDao; @@ -46,34 +78,6 @@ import edu.harvard.iq.dataverse.search.response.SolrQueryResponse; import edu.harvard.iq.dataverse.search.response.SolrSearchResult; import edu.harvard.iq.dataverse.util.FileSortFieldAndOrder; -import org.apache.solr.client.solrj.SolrServerException; - -import javax.ejb.EJB; -import javax.ejb.EJBException; -import javax.inject.Inject; -import javax.json.Json; -import javax.json.JsonArrayBuilder; -import javax.json.JsonObject; -import javax.json.JsonObjectBuilder; -import javax.validation.ConstraintViolation; -import javax.validation.ConstraintViolationException; -import javax.ws.rs.DELETE; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; - -import static edu.harvard.iq.dataverse.common.NullSafeJsonBuilder.jsonObjectBuilder; @Path("admin/index") public class Index extends AbstractApiBean { @@ -358,14 +362,14 @@ public Response indexAllPermissions() { @GET @Path("perms/{id}") - public Response indexPermissions(@PathParam("id") Long id) { - DvObject dvObject = dvObjectService.findDvObject(id); - if (dvObject == null) { - return error(Status.BAD_REQUEST, "Could not find DvObject based on id " + id); + public Response indexPermissions(@PathParam("id") Long id) { + final Optional dvObject = dvObjectService.findDvObject(id); + if(dvObject.isPresent()) { + return ok(this.solrIndexService.indexPermissionsForOneDvObject(dvObject.get()).getMessage()); } else { - IndexResponse indexResponse = solrIndexService.indexPermissionsForOneDvObject(dvObject); - return ok(indexResponse.getMessage()); + return error(BAD_REQUEST, "Could not find DvObject based on id " + id); } + } @GET @@ -609,11 +613,11 @@ public Response searchPermsDebug( return error(Response.Status.UNAUTHORIZED, "Invalid apikey"); } - DvObject dvObjectToLookUp = dvObjectService.findDvObject(dvObjectId); - if (dvObjectToLookUp == null) { - return error(Status.BAD_REQUEST, "Could not find DvObject based on id " + dvObjectId); + final Optional dvObjectToLookUp = dvObjectService.findDvObject(dvObjectId); + if (!dvObjectToLookUp.isPresent()) { + return error(BAD_REQUEST, "Could not find DvObject based on id " + dvObjectId); } - List solrDocs = solrDocFactory.determinePermissionsDocsOnSelfOnly(dvObjectToLookUp); + List solrDocs = solrDocFactory.determinePermissionsDocsOnSelfOnly(dvObjectToLookUp.get()); JsonObjectBuilder data = Json.createObjectBuilder(); @@ -633,7 +637,7 @@ public Response searchPermsDebug( } data.add("perms", permissionsData); - DvObject dvObject = dvObjectService.findDvObject(dvObjectId); + DvObject dvObject = dvObjectService.getDvObject(dvObjectId); NullSafeJsonBuilder timestamps = jsonObjectBuilder(); timestamps.add(contentChanged, SearchUtil.getTimestampOrNull(dvObject.getModificationTime())); timestamps.add(contentIndexed, SearchUtil.getTimestampOrNull(dvObject.getIndexTime())); diff --git a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/permission/ManagePermissionsPage.java b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/permission/ManagePermissionsPage.java index 48229937e1..6ddc8370a5 100644 --- a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/permission/ManagePermissionsPage.java +++ b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/permission/ManagePermissionsPage.java @@ -101,7 +101,7 @@ public void setId(Long id) { public String init() { if (id != null) { - dvObject = dvObjectService.findDvObject(id); + dvObject = dvObjectService.findDvObject(id).orElse(null); } else { return permissionsWrapper.notFound(); } diff --git a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/search/index/IndexServiceBean.java b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/search/index/IndexServiceBean.java index 4f274da30b..32b079e76a 100644 --- a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/search/index/IndexServiceBean.java +++ b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/search/index/IndexServiceBean.java @@ -1393,8 +1393,7 @@ private List findDvObjectInSolrOnly(String type) throws SearchException { if (idObject != null) { try { long id = (Long) idObject; - DvObject dvobject = dvObjectService.findDvObject(id); - if (dvobject == null) { + if (!this.dvObjectService.findDvObject(id).isPresent()) { dvObjectInSolrOnly.add(id); } } catch (ClassCastException ex) { diff --git a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/search/savedsearch/SavedSearchServiceBean.java b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/search/savedsearch/SavedSearchServiceBean.java index 48c8de46f3..bd5c7c9340 100644 --- a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/search/savedsearch/SavedSearchServiceBean.java +++ b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/search/savedsearch/SavedSearchServiceBean.java @@ -165,7 +165,7 @@ public JsonObjectBuilder makeLinksForSingleSavedSearch(DataverseRequest dvReq, S hitInfo.add("name", solrSearchResult.getNameSort()); hitInfo.add("dvObjectId", solrSearchResult.getEntityId()); - DvObject dvObjectThatDefinitionPointWillLinkTo = dvObjectService.findDvObject(solrSearchResult.getEntityId()); + DvObject dvObjectThatDefinitionPointWillLinkTo = dvObjectService.findDvObject(solrSearchResult.getEntityId()).orElse(null); if (dvObjectThatDefinitionPointWillLinkTo == null) { hitInfo.add(resultString, "Could not find DvObject with id " + solrSearchResult.getEntityId()); infoPerHit.add(hitInfo); diff --git a/fairchive-webapp/src/test/java/edu/harvard/iq/dataverse/users/MergeInAccountServiceIT.java b/fairchive-webapp/src/test/java/edu/harvard/iq/dataverse/users/MergeInAccountServiceIT.java index 0093d82288..20336ab10b 100644 --- a/fairchive-webapp/src/test/java/edu/harvard/iq/dataverse/users/MergeInAccountServiceIT.java +++ b/fairchive-webapp/src/test/java/edu/harvard/iq/dataverse/users/MergeInAccountServiceIT.java @@ -229,7 +229,7 @@ private void addObjectsToUser(AuthenticatedUser authenticatedUser) { guestbookResponse.setAuthenticatedUser(authenticatedUser); entityManager.merge(guestbookResponse); - DvObject dvObject = dvObjectService.findDvObject(67L); + DvObject dvObject = dvObjectService.getDvObject(67L); dvObject.setCreator(authenticatedUser); dvObject.setReleaseUser(authenticatedUser); entityManager.merge(dvObject); From e235d86db5adce30daad8caf842e30f6adac1222 Mon Sep 17 00:00:00 2001 From: lbownik Date: Fri, 3 Jul 2026 15:49:07 +0200 Subject: [PATCH 7/8] removed unused method --- .../edu/harvard/iq/dataverse/DvObjectServiceBean.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java index 105ee08935..8bdb69f4c0 100644 --- a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java +++ b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java @@ -238,17 +238,6 @@ public List getDvObjectInfoByParentIdForMyData(List dvObjectPare } - /** - * Used to exclude Harvested Data from the Mydata page - * - * @return - */ - @SuppressWarnings("unchecked") - public List getAllHarvestedDataverseIds() { - return em.createNativeQuery("SELECT h.dataverse_id FROM harvestingclient h;") - .getResultList(); - } - /** * Used to calculate the dvObject tree paths for the search results on the * dataverse page. (In order to determine if "linked" or not). From ccaa14de6ee00992ef3fc63f8088aa3096f7c734 Mon Sep 17 00:00:00 2001 From: lbownik Date: Fri, 3 Jul 2026 17:37:22 +0200 Subject: [PATCH 8/8] more of the same stuff --- .../iq/dataverse/persistence/DvObject.java | 53 +++++++------------ .../persistence/DvObjectRepository.java | 25 +++++++++ .../iq/dataverse/DataFileServiceBean.java | 2 +- .../iq/dataverse/DvObjectServiceBean.java | 52 +++++------------- .../iq/dataverse/dataset/DatasetService.java | 12 +++-- 5 files changed, 66 insertions(+), 78 deletions(-) diff --git a/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/DvObject.java b/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/DvObject.java index fc35479abb..c352ad5845 100644 --- a/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/DvObject.java +++ b/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/DvObject.java @@ -1,26 +1,5 @@ package edu.harvard.iq.dataverse.persistence; -import edu.harvard.iq.dataverse.persistence.datafile.DataFile; -import edu.harvard.iq.dataverse.persistence.dataset.Dataset; -import edu.harvard.iq.dataverse.persistence.dataverse.Dataverse; -import edu.harvard.iq.dataverse.persistence.user.AuthenticatedUser; -import edu.harvard.iq.dataverse.persistence.user.RoleAssignment; - -import javax.persistence.Column; -import javax.persistence.DiscriminatorColumn; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.Index; -import javax.persistence.Inheritance; -import javax.persistence.ManyToOne; -import javax.persistence.NamedQueries; -import javax.persistence.NamedQuery; -import javax.persistence.OneToMany; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.UniqueConstraint; - import static javax.persistence.CascadeType.ALL; import static javax.persistence.CascadeType.MERGE; import static javax.persistence.CascadeType.PERSIST; @@ -32,6 +11,7 @@ import static org.apache.commons.lang3.StringUtils.SPACE; import static org.apache.commons.lang3.StringUtils.isNotEmpty; +import java.io.Serializable; import java.sql.Timestamp; import java.text.SimpleDateFormat; import java.util.Arrays; @@ -39,20 +19,27 @@ import java.util.List; import java.util.Objects; import java.util.Set; -import java.io.Serializable; -/** - * Base of the object hierarchy for "anything that can be inside a dataverse". - * - * @author michael - */ +import javax.persistence.Column; +import javax.persistence.DiscriminatorColumn; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Index; +import javax.persistence.Inheritance; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.UniqueConstraint; + +import edu.harvard.iq.dataverse.persistence.datafile.DataFile; +import edu.harvard.iq.dataverse.persistence.dataset.Dataset; +import edu.harvard.iq.dataverse.persistence.dataverse.Dataverse; +import edu.harvard.iq.dataverse.persistence.user.AuthenticatedUser; +import edu.harvard.iq.dataverse.persistence.user.RoleAssignment; + @SuppressWarnings("serial") -@NamedQueries({ - @NamedQuery(name = "DvObject.findByGlobalId", - query = "SELECT o FROM DvObject o WHERE o.identifier=:identifier and o.authority=:authority and o.protocol=:protocol and o.dtype=:dtype"), - @NamedQuery(name = "DvObject.findByAlternativeGlobalId", - query = "SELECT o FROM DvObject o, AlternativePersistentIdentifier a WHERE o.id = a.dvObject.id and a.identifier=:identifier and a.authority=:authority and a.protocol=:protocol and o.dtype=:dtype"), -}) @Entity // Inheritance strategy "JOINED" will create 4 db tables - // the top-level dvobject, with the common columns, and the 3 child classes - diff --git a/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/DvObjectRepository.java b/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/DvObjectRepository.java index 6c78570869..d6bc1f628c 100644 --- a/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/DvObjectRepository.java +++ b/fairchive-persistence/src/main/java/edu/harvard/iq/dataverse/persistence/DvObjectRepository.java @@ -42,4 +42,29 @@ public Optional findByGlobalId(final String protocol, .setParameter("authority", authority) .setParameter("identifier", identifier)); } + + public Optional findByGlobalId(final String protocol, + final String authority, final String identifier, final String type) { + return getSingleResult(createQuery( + "SELECT o FROM DvObject o " + + "WHERE o.identifier=:identifier and o.authority=:authority " + + "and o.protocol=:protocol and o.dtype=:type") + .setParameter("protocol", protocol) + .setParameter("authority", authority) + .setParameter("identifier", identifier) + .setParameter("type", type)); + } + + public Optional findByAlternativeGlobalId(final String protocol, + final String authority, final String identifier, final String type) { + return getSingleResult(createQuery( + "SELECT o FROM DvObject o, AlternativePersistentIdentifier a " + + " WHERE o.id = a.dvObject.id and a.identifier=:identifier " + + " and a.authority=:authority and a.protocol=:protocol " + + " and o.dtype=:type") + .setParameter("protocol", protocol) + .setParameter("authority", authority) + .setParameter("identifier", identifier) + .setParameter("type", type)); + } } diff --git a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DataFileServiceBean.java b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DataFileServiceBean.java index 4ad9e44e8e..0a538665f6 100644 --- a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DataFileServiceBean.java +++ b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DataFileServiceBean.java @@ -90,7 +90,7 @@ public Optional find(final Long id) { public DataFile findByGlobalId(final String globalId) { return (DataFile) this.dvObjectService.findByGlobalId(globalId, - DataFile.DATAFILE_DTYPE_STRING); + DataFile.DATAFILE_DTYPE_STRING).orElse(null); } public Optional findReplacementFile(final Long previousFileId) { diff --git a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java index 8bdb69f4c0..4377b88630 100644 --- a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java +++ b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/DvObjectServiceBean.java @@ -75,46 +75,20 @@ public List findByOwnerId(final Long id) { return this.repository.findByOwnerId(id); } - // FIXME This type-by-string has to go, in favor of passing a class parameter. - public DvObject findByGlobalId(String globalIdString, String typeString) { - return findByGlobalId(globalIdString, typeString, false); + public Optional findByGlobalId(final String globalIdString, + final String type) { + + final GlobalId gid = new GlobalId(globalIdString); + return this.repository.findByGlobalId(gid.getProtocol(), + gid.getAuthority(), gid.getIdentifier(), type); } - - // FIXME This type-by-string has to go, in favor of passing a class parameter. - public DvObject findByGlobalId(String globalIdString, String typeString, Boolean altId) { - - try { - GlobalId gid = new GlobalId(globalIdString); - - DvObject foundDvObject = null; - try { - Query query; - if (altId) { - query = em.createNamedQuery("DvObject.findByAlternativeGlobalId"); - } else { - query = em.createNamedQuery("DvObject.findByGlobalId"); - } - query.setParameter("identifier", gid.getIdentifier()); - query.setParameter("protocol", gid.getProtocol()); - query.setParameter("authority", gid.getAuthority()); - query.setParameter("dtype", typeString); - foundDvObject = (DvObject) query.getSingleResult(); - } catch (javax.persistence.NoResultException e) { - // (set to .info, this can fill the log file with thousands of - // these messages during a large harvest run) - logger.fine("no dvObject found: " + globalIdString); - // DO nothing, just return null. - return null; - } catch (Exception ex) { - logger.info("Exception caught in findByGlobalId: " + ex.getLocalizedMessage()); - return null; - } - return foundDvObject; - - } catch (IllegalArgumentException iae) { - logger.info("Invalid identifier: " + globalIdString); - return null; - } + + public Optional findByAlternativeGlobalId(final String globalIdString, + final String type) { + + final GlobalId gid = new GlobalId(globalIdString); + return this.repository.findByAlternativeGlobalId(gid.getProtocol(), + gid.getAuthority(), gid.getIdentifier(), type); } public List findByAuthenticatedUserId(final AuthenticatedUser user) { diff --git a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/dataset/DatasetService.java b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/dataset/DatasetService.java index ec91f2775f..cd4f944775 100644 --- a/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/dataset/DatasetService.java +++ b/fairchive-webapp/src/main/java/edu/harvard/iq/dataverse/dataset/DatasetService.java @@ -10,6 +10,7 @@ import java.io.InputStream; import java.util.Date; import java.util.List; +import java.util.Optional; import java.util.logging.Level; import java.util.logging.Logger; @@ -134,12 +135,13 @@ public List findStaleOrMissingDatasets() { } public Dataset findByGlobalId(final String globalId) { - final Dataset retVal = (Dataset) this.dvObjectService.findByGlobalId(globalId, "Dataset"); - if (retVal != null) { - return retVal; + + final Optional result = this.dvObjectService.findByGlobalId(globalId, "Dataset"); + if(result.isPresent()) { + return (Dataset) result.get(); } else { - //try to find with alternative PID - return (Dataset) this.dvObjectService.findByGlobalId(globalId, "Dataset", true); + return (Dataset) this.dvObjectService.findByAlternativeGlobalId(globalId, "Dataset") + .orElse(null); } }