Skip to content

Commit 2f3d169

Browse files
committed
support all versions/all pids, styling fix
1 parent 68e44a8 commit 2f3d169

File tree

7 files changed

+103
-44
lines changed

7 files changed

+103
-44
lines changed

src/main/java/edu/harvard/iq/dataverse/DataCitation.java

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package edu.harvard.iq.dataverse;
77

88
import edu.harvard.iq.dataverse.branding.BrandingUtil;
9+
import edu.harvard.iq.dataverse.dataset.DatasetType;
910
import edu.harvard.iq.dataverse.harvest.client.HarvestingClient;
1011
import edu.harvard.iq.dataverse.pidproviders.AbstractPidProvider;
1112

@@ -29,19 +30,29 @@
2930
import java.util.stream.Collectors;
3031

3132
import jakarta.ejb.EJBException;
33+
import jakarta.json.JsonObject;
34+
3235
import javax.xml.stream.XMLOutputFactory;
3336
import javax.xml.stream.XMLStreamException;
3437
import javax.xml.stream.XMLStreamWriter;
3538

3639
import edu.harvard.iq.dataverse.util.BundleUtil;
3740
import edu.harvard.iq.dataverse.util.DateUtil;
41+
import edu.harvard.iq.dataverse.util.PersonOrOrgUtil;
42+
import edu.harvard.iq.dataverse.util.SystemConfig;
43+
import edu.harvard.iq.dataverse.util.json.JsonUtil;
44+
3845
import org.apache.commons.text.StringEscapeUtils;
3946

4047
import de.undercouch.citeproc.CSL;
48+
import de.undercouch.citeproc.csl.CSLDate;
4149
import de.undercouch.citeproc.csl.CSLItemData;
4250
import de.undercouch.citeproc.csl.CSLItemDataBuilder;
51+
import de.undercouch.citeproc.csl.CSLName;
4352
import de.undercouch.citeproc.csl.CSLNameBuilder;
4453
import de.undercouch.citeproc.csl.CSLType;
54+
import de.undercouch.citeproc.helper.json.JsonBuilder;
55+
import de.undercouch.citeproc.helper.json.StringJsonBuilderFactory;
4556

4657
import org.apache.commons.lang3.StringUtils;
4758

@@ -54,6 +65,7 @@ public class DataCitation {
5465
private static final Logger logger = Logger.getLogger(DataCitation.class.getCanonicalName());
5566

5667
private List<String> authors = new ArrayList<String>();
68+
private List<CSLName> cslAuthors = new ArrayList<CSLName>();
5769
private List<String> producers = new ArrayList<String>();
5870
private String title;
5971
private String fileTitle = null;
@@ -74,7 +86,9 @@ public class DataCitation {
7486
private List<String> spatialCoverages;
7587

7688
private List<DatasetField> optionalValues = new ArrayList<>();
77-
private int optionalURLcount = 0;
89+
private int optionalURLcount = 0;
90+
91+
private DatasetType type;
7892

7993
public DataCitation(DatasetVersion dsv) {
8094
this(dsv, false);
@@ -149,8 +163,14 @@ private void getCommonValuesFrom(DatasetVersion dsv) {
149163
spatialCoverages = dsv.getSpatialCoverages();
150164
publisher = getPublisherFrom(dsv);
151165
version = getVersionFrom(dsv);
166+
type = getTypeFrom(dsv);
152167
}
153168

169+
private DatasetType getTypeFrom(DatasetVersion dsv) {
170+
return dsv.getDataset().getDatasetType();
171+
}
172+
173+
154174
public String getAuthorsString() {
155175
return String.join("; ", authors);
156176
}
@@ -659,17 +679,25 @@ public Map<String, String> getDataCiteMetadata() {
659679
return metadata;
660680
}
661681

662-
String getCSLFormat(String style) throws IOException {
663-
CSLItemData item = new CSLItemDataBuilder().type(CSLType.ARTICLE_JOURNAL)
664-
.title("Protein measurement with the Folin phenol reagent")
665-
.author(new CSLNameBuilder().given("Oliver H.").family("Lowry").build(),
666-
new CSLNameBuilder().given("Nira J.").family("Rosebrough").build(),
667-
new CSLNameBuilder().given("A. Lewis").family("Farr").build(),
668-
new CSLNameBuilder().given("Rose J.").family("Randall").build())
669-
.issued(1951).containerTitle("The Journal of biological chemistry").volume(193).issue(1).page(265, 275)
670-
.build();
671-
672-
return CSL.makeAdhocBibliography("apa", item).makeString();
682+
public JsonObject getCSLJsonFormat() {
683+
CSLItemDataBuilder itemBuilder = new CSLItemDataBuilder();
684+
if (type.equals(DatasetType.DATASET_TYPE_SOFTWARE)) {
685+
itemBuilder.type(CSLType.SOFTWARE);
686+
} else {
687+
itemBuilder.type(CSLType.DATASET);
688+
}
689+
itemBuilder.title(title).author((CSLName[]) cslAuthors.toArray(new CSLName[0])).issued(Integer.parseInt(year));
690+
if (seriesTitles != null) {
691+
itemBuilder.containerTitle(seriesTitles.get(0));
692+
}
693+
itemBuilder.version(version).DOI(persistentId.asString());
694+
if (keywords != null) {
695+
itemBuilder.categories(keywords.toArray(new String[0]));
696+
}
697+
itemBuilder.abstrct(description).publisher(publisher)
698+
.URL(SystemConfig.getDataverseSiteUrlStatic() + "/citation?persistentId=" + persistentId.asString());
699+
JsonBuilder b = (new StringJsonBuilderFactory()).createJsonBuilder();
700+
return JsonUtil.getJsonObject((String) itemBuilder.build().toJson(b));
673701
}
674702

675703
// helper methods
@@ -778,6 +806,20 @@ private void getAuthorsAndProducersFrom(DatasetVersion dsv) {
778806
if (!author.isEmpty()) {
779807
String an = author.getName().getDisplayValue().trim();
780808
authors.add(an);
809+
boolean isOrg = "ROR".equals(author.getIdType());
810+
JsonObject authorJson = PersonOrOrgUtil.getPersonOrOrganization(an, false, !isOrg);
811+
if (!authorJson.getBoolean("isPerson")) {
812+
cslAuthors.add(new CSLNameBuilder().literal(authorJson.getString("fullName")).isInstitution(true).build());
813+
} else {
814+
if (authorJson.containsKey("givenName") && authorJson.containsKey("familyName")) {
815+
String givenName = authorJson.getString("givenName");
816+
String familyName = authorJson.getString("familyName");
817+
cslAuthors.add(new CSLNameBuilder().given(givenName).family(familyName).isInstitution(false).build());
818+
} else {
819+
cslAuthors.add(
820+
new CSLNameBuilder().literal(authorJson.getString("fullName")).isInstitution(false).build());
821+
}
822+
}
781823
}
782824
});
783825
producers = dsv.getDatasetProducerNames();

src/main/java/edu/harvard/iq/dataverse/api/Pids.java

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package edu.harvard.iq.dataverse.api;
22

33
import edu.harvard.iq.dataverse.Dataset;
4+
import edu.harvard.iq.dataverse.DatasetVersion;
5+
import edu.harvard.iq.dataverse.DvObject.DType;
46
import edu.harvard.iq.dataverse.GlobalId;
57
import edu.harvard.iq.dataverse.api.auth.AuthRequired;
68
import edu.harvard.iq.dataverse.authorization.users.User;
@@ -173,36 +175,44 @@ public Response getPidProviderId(@Context ContainerRequestContext crc, @PathPara
173175
}
174176
}
175177

178+
/**
179+
* Get the JSON CSL format for a given PID
180+
* @param persistentId, e.g. doi:10.5072/FK2ABCDEF
181+
* @return THe CSL JSON object, or a 404 if the PID is not recognized or managed by a known provider, or the CSL is not available.
182+
* @throws WrappedResponse
183+
*/
176184
@GET
177-
@AuthRequired
178185
// The :.+ suffix allows PIDs with a / char to be entered w/o escaping
179186
@Path("{persistentId:.+}/csl")
180187
@Produces(MediaType.APPLICATION_JSON)
181-
public Response getCSLJson(@Context ContainerRequestContext crc, @PathParam("persistentId") String persistentId)
182-
throws WrappedResponse {
183-
try {
184-
getRequestAuthenticatedUserOrDie(crc);
185-
} catch (WrappedResponse ex) {
186-
return ex.getResponse();
187-
}
188+
public Response getCSLJson(@PathParam("persistentId") String persistentId) throws WrappedResponse {
188189
GlobalId globalId = PidUtil.parseAsGlobalID(persistentId);
189190
if (globalId == null) {
190191
return error(Response.Status.NOT_FOUND, "No provider found for PID");
191192
} else {
192193
PidProvider provider = PidUtil.getPidProvider(globalId.getProviderId());
193-
try {
194-
JsonObject csl = provider.getCSLJson(globalId);
195-
if (csl != null) {
196-
return ok(csl);
197-
} else {
198-
return error(Response.Status.NOT_FOUND, "No CSL JSON found for PID");
194+
if (provider.canManagePID()) {
195+
try {
196+
Dataset dataset = (Dataset) dvObjectSvc.findByGlobalId(globalId,DType.Dataset);
197+
DatasetVersion dsv = dataset.getLatestVersionForCopy();
198+
if (dsv.isReleased()) {
199+
JsonObject csl = provider.getCSLJson(dsv);
200+
if (csl != null) {
201+
return ok(csl);
202+
} else {
203+
return error(Response.Status.NOT_FOUND, "No CSL JSON found for PID");
204+
}
205+
} else {
206+
return error(Response.Status.NOT_FOUND, "No released dataset version for PID");
207+
}
208+
} catch (Exception e) {
209+
logger.warning("Unable to return CSL JSON for PID: " + e.getMessage());
210+
e.printStackTrace();
211+
return error(Response.Status.NOT_FOUND, "Unable to return CSL JSON for PID");
199212
}
200-
} catch (Exception e) {
201-
logger.warning("Unable to return CSL JSON for PID: " + e.getMessage());
202-
e.printStackTrace();
203-
return error(Response.Status.NOT_FOUND, "Unable to return CSL JSON for PID");
213+
} else {
214+
return error(Response.Status.NOT_FOUND, "Not a managed PID");
204215
}
205216
}
206217
}
207-
208218
}

src/main/java/edu/harvard/iq/dataverse/pidproviders/AbstractPidProvider.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package edu.harvard.iq.dataverse.pidproviders;
22

3+
import edu.harvard.iq.dataverse.DataCitation;
34
import edu.harvard.iq.dataverse.DataFile;
45
import edu.harvard.iq.dataverse.Dataset;
56
import edu.harvard.iq.dataverse.DatasetField;
7+
import edu.harvard.iq.dataverse.DatasetVersion;
68
import edu.harvard.iq.dataverse.DvObject;
79
import edu.harvard.iq.dataverse.GlobalId;
810
import edu.harvard.iq.dataverse.util.SystemConfig;
@@ -566,7 +568,7 @@ public boolean updateIdentifier(DvObject dvObject) {
566568

567569
/** By default, this is not implemented */
568570
@Override
569-
public JsonObject getCSLJson(GlobalId pid) {
570-
throw new NotImplementedException();
571+
public JsonObject getCSLJson(DatasetVersion datasetVersion) {
572+
return new DataCitation(datasetVersion).getCSLJsonFormat();
571573
}
572574
}

src/main/java/edu/harvard/iq/dataverse/pidproviders/PidProvider.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
package edu.harvard.iq.dataverse.pidproviders;
22

3+
import edu.harvard.iq.dataverse.DatasetVersion;
34
import edu.harvard.iq.dataverse.DvObject;
45
import edu.harvard.iq.dataverse.GlobalId;
56
import jakarta.json.JsonObject;
6-
import jakarta.json.JsonValue;
7-
87
import java.util.*;
98
import java.util.logging.Logger;
109

@@ -193,9 +192,9 @@ static boolean checkDOIAuthority(String doiAuthority){
193192
* For some providers, this could be a call to the service API. For others, it
194193
* may involve generating a local copy.
195194
*
196-
* @param pid
195+
* @param datasetVersion
197196
* @return - the CSL Json for the PID
198197
*/
199-
public JsonObject getCSLJson(GlobalId pid);
198+
public JsonObject getCSLJson(DatasetVersion datasetVersion);
200199

201200
}

src/main/java/edu/harvard/iq/dataverse/pidproviders/doi/datacite/DataCiteDOIProvider.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.util.logging.Level;
1717
import java.util.logging.Logger;
1818

19+
import edu.harvard.iq.dataverse.DataCitation;
1920
import edu.harvard.iq.dataverse.DataFile;
2021
import edu.harvard.iq.dataverse.Dataset;
2122
import edu.harvard.iq.dataverse.DatasetVersion;
@@ -358,10 +359,11 @@ public boolean updateIdentifier(DvObject dvObject) {
358359
*
359360
*/
360361
@Override
361-
public JsonObject getCSLJson(GlobalId doi) {
362-
362+
public JsonObject getCSLJson(DatasetVersion dsv) {
363+
if(dsv.isLatestVersion() && dsv.isReleased()) {
364+
String doi = dsv.getDataset().getGlobalId().asRawIdentifier();
363365
try {
364-
URL url = new URI(getApiUrl() + "/dois/" + doi.getAuthority() + "/" + doi.getIdentifier()).toURL();
366+
URL url = new URI(getApiUrl() + "/dois/" + doi).toURL();
365367

366368
HttpURLConnection connection = null;
367369
connection = (HttpURLConnection) url.openConnection();
@@ -376,7 +378,7 @@ public JsonObject getCSLJson(GlobalId doi) {
376378
"Incorrect Response Status from DataCite: " + status + " : " + connection.getResponseMessage());
377379
throw new HttpException("Status: " + status);
378380
}
379-
logger.fine("getCSLJson status for " + doi.asString() + ": " + status);
381+
logger.fine("getCSLJson status for " + doi + ": " + status);
380382
BufferedReader in = new BufferedReader(
381383
new InputStreamReader((InputStream) connection.getContent()));
382384
String cslString="";
@@ -388,8 +390,11 @@ public JsonObject getCSLJson(GlobalId doi) {
388390
JsonObject csl = JsonUtil.getJsonObject(cslString);
389391
return csl;
390392
} catch (IOException | URISyntaxException e) {
391-
logger.log(Level.INFO, "Unable to get CSL JSON for " + doi.toString(), e);
393+
logger.log(Level.WARNING, "Unable to get CSL JSON for " + doi, e);
392394
return null;
395+
}}
396+
else {
397+
return super.getCSLJson(dsv);
393398
}
394399
}
395400
}

src/main/webapp/dataset.xhtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2064,7 +2064,7 @@
20642064
<script>
20652065
Cite.CSL.register.addTemplate("#{DatasetPage.requestedCSL}",
20662066
"#{CSLUtil:getCitationFormat((DatasetPage.requestedCSL == '') ? 'apa' : DatasetPage.requestedCSL)}");
2067-
fetch("http://ec2-3-238-245-253.compute-1.amazonaws.com/api/pids/doi:10.33564/FK2MIYN9Q/csl")
2067+
fetch("#{DatasetPage.dataverseSiteUrl}/api/pids/#{DatasetPage.globalId}/csl")
20682068
.then(response => response.json())
20692069
.then(json =>
20702070
{

src/main/webapp/resources/css/structure.css

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1223,14 +1223,15 @@ span.label-default { background-color: #757575 }
12231223
display:block;
12241224
}
12251225

1226-
#datasetForm\:cslOutput, .csl-bib-body {
1226+
#datasetForm\:cslOutput, .csl-bib-body, .csl-right-inline {
12271227
display:inline;
12281228
}
12291229

12301230
#datasetForm\:cslCitation .glyphicon-copy{
12311231
font-size: x-large;
12321232
display: inline;
12331233
vertical-align: bottom;
1234+
margin-left: 5px;
12341235
}
12351236

12361237
/* Suppress the number in some styles indication this references ordinal position in a larger bibliography (which is always 1 in our dialog)*/

0 commit comments

Comments
 (0)