Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
5076dd1
Add controlled vocabulary
ekoi Jan 20, 2021
6960a4c
Merge pull request #41 from ekoi/external-cvoc
PaulBoon Feb 2, 2021
f1d5fb5
Merge branch 'develop' into external-cvoc
PaulBoon Feb 2, 2021
6ee5a09
Merge branch 'external-cvoc' of github.com:DANS-KNAW/dataverse into e…
janvanmansum Feb 2, 2021
56721ad
Merge pull request #44 from PaulBoon/external-cvoc
PaulBoon Feb 2, 2021
68d5aa3
Fix problem where pressing tab skips some fields.
JingMa87 Feb 17, 2021
6224e3b
Merge pull request #49 from JingMa87/external-cvoc
janvanmansum Feb 18, 2021
8e5eb3c
External cvoc (#47)
ekoi Feb 19, 2021
4cb9ca9
Have cvoc URL fields use the readonly setting
PaulBoon Feb 24, 2021
847dc65
Merge pull request #50 from PaulBoon/DD-375
janvanmansum Feb 24, 2021
aa43772
DD-377 Improving the cvoc metadata term selection input (#52)
PaulBoon Mar 3, 2021
8ef8408
Added ajax loading indicator css for the extenal cvoc autocomplete in…
PaulBoon Mar 10, 2021
c0d9c30
DD-386: Uses the vocab-uri parameter from the cvoc config (#55)
PaulBoon Mar 16, 2021
43d6631
Merge branch 'develop' into external-cvoc
PaulBoon Mar 16, 2021
e369ffe
Merge pull request #56 from PaulBoon/external-cvoc
PaulBoon Mar 16, 2021
feefe49
Added the cvoc-interface.js file to the application resources
PaulBoon Mar 23, 2021
78f3ec2
Changed the default js-url to this compiled in resource
PaulBoon Mar 23, 2021
5d78401
Merge pull request #60 from PaulBoon/FixInterfaceJs
janvanmansum Mar 23, 2021
a480b4f
Merge branch 'develop' into external-cvoc
janvanmansum Mar 23, 2021
30de328
Merged back develop in external cvoc
janvanmansum Apr 14, 2021
ec5d019
Merge pull request #71 from janvanmansum/MERGE_BACK_DEVELOP_IN_EXT_CVOC
janvanmansum Apr 14, 2021
00e5df4
Merge branch 'develop' into external-cvoc
janvanmansum Apr 23, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 182 additions & 9 deletions src/main/java/edu/harvard/iq/dataverse/DatasetPage.java
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,35 @@
import org.primefaces.PrimeFaces;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;
import org.primefaces.model.file.UploadedFile;

import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;
import javax.faces.view.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.json.*;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above, comment on globbing imports.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ekoi, fyi

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import java.io.*;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above, comment on globbing imports.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ekoi, fyi

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above, comment on globbing imports.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ekoi, fyi

import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;

import static edu.harvard.iq.dataverse.util.JsfHelper.JH;
import static edu.harvard.iq.dataverse.util.StringUtil.isEmpty;

/**
*
Expand Down Expand Up @@ -1282,7 +1311,7 @@ public boolean canUpdateDataset() {
public boolean canPublishDataverse() {
return permissionsWrapper.canIssuePublishDataverseCommand(dataset.getOwner());
}

public boolean canPublishDataset(){
return permissionsWrapper.canIssuePublishDatasetCommand(dataset);
}
Expand Down Expand Up @@ -1863,8 +1892,8 @@ private String init(boolean initFull) {
mdcLogService.logEntry(entry);
}
displayWorkflowComments();


if (initFull) {
// init the list of FileMetadatas
if (workingVersion.isDraft() && canUpdateDataset()) {
Expand Down Expand Up @@ -2727,7 +2756,7 @@ public String refresh() {
}

displayWorkflowComments();

return "";
}

Expand Down Expand Up @@ -3373,8 +3402,8 @@ public String save() {
}


// Use the Create or Update command to save the dataset:

// Use the Create or Update command to save the dataset:
Command<Dataset> cmd;
Map<Long, String> deleteStorageLocations = null;

Expand Down Expand Up @@ -3486,7 +3515,7 @@ public String save() {
} else {
JsfHelper.addWarningMessage(BundleUtil.getStringFromBundle("dataset.message.createSuccess.failedToSaveFiles"));
}
} else {
} else {
JsfHelper.addSuccessMessage(BundleUtil.getStringFromBundle("dataset.message.createSuccess").concat(" ").concat(datasetService.getReminderString(dataset, canPublishDataset())));
}
}
Expand Down Expand Up @@ -5488,12 +5517,156 @@ public void setFileAccessRequest(boolean fileAccessRequest) {
this.fileAccessRequest = fileAccessRequest;
}

// wrapper method to see if the file has been deleted (or replaced) in the current version
// wrapper method to see if the file has been deleted (or replaced) in the current version
public boolean isFileDeleted (DataFile dataFile) {
if (dataFile.getDeleted() == null) {
dataFile.setDeleted(datafileService.hasBeenDeleted(dataFile));
}

return dataFile.getDeleted();
}

public Map<String, CVoc> getCVocConf(){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is invoked by every Dataset "Edit Mode" page call, reading the saved JSON from the database, parsing it and create a map to access the configurations for the fields. It get's called from JSF via EL and saved to a var cvoc. To me this looks like a very CPU intense thing to do...

IMHO there should be a call to get the config for a specific field (still inside DatasetPage backing bean) and that is then retrieved from the DatasetFieldServiceBean. The config can be cached there in a Map<DatasetField,CVoc>, initialised either from the database, or even fancier: injected via MicroProfile Config API.

Map <String, CVoc> cvocMap = new HashMap<>();
String cvocSetting = settingsService.getValueForKey(SettingsServiceBean.Key.CVocConf);
if (cvocSetting == null || cvocSetting.isEmpty())
return cvocMap;

JsonReader jsonReader = Json.createReader(new StringReader(settingsService.getValueForKey(SettingsServiceBean.Key.CVocConf)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should either make this live inside edu.harvard.iq.dataverse.util.json.JsonParser (meh) or use proper JSON-B. Or just don't use JSON, making use of MicroProfile Config API instead (which is much easier to use in non-classic deployment scenarios).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ekoi, something to consider.

JsonArray cvocConfJsonArray = jsonReader.readArray();
jsonReader.close();
if (cvocConfJsonArray != null) {
for (JsonObject jo : cvocConfJsonArray.getValuesAs(JsonObject.class)) {
JsonArray vocabs = jo.getJsonArray("vocabs");
List<String> vocabsList = new ArrayList<>();
for (JsonString elm: vocabs.getValuesAs(JsonString.class)){
vocabsList.add(elm.getString());
}
JsonArray vocabCodes = jo.getJsonArray("vocab-codes");
List<String> vocabCodesList = new ArrayList<>();
for (JsonString elm: vocabCodes.getValuesAs(JsonString.class)){
vocabCodesList.add(elm.getString());
logger.fine("cvoc - vocab-codes: " + elm.getString());
}
String cvocLang = BundleUtil.getDefaultLocale().getLanguage();//default
if (jo.containsKey("language"))
cvocLang = jo.getString("language"); // in case of "language":"", "&lang=" will be send to the middleware
logger.fine("cvoc - language: " + cvocLang);
boolean cvocReadonly = false;
if (jo.containsKey("readonly") && jo.getString("readonly").toLowerCase().equals("true"))
cvocReadonly = true;
logger.fine("cvoc - readonly: " + cvocReadonly);
boolean cvocHideReadonlyUrls = false;
if (jo.containsKey("hideReadonlyUrls") && jo.getString("hideReadonlyUrls").toLowerCase().equals("true"))
cvocHideReadonlyUrls = true;
logger.fine("cvoc - cvocHideReadonlyUrls: " + cvocHideReadonlyUrls);
int cvocMinChars = 0;
if (jo.containsKey("minChars") && jo.getInt("minChars") >= 0)
cvocMinChars = jo.getInt("minChars");
logger.fine("cvoc - minChars: " + cvocMinChars);
String cvocProtocol = "skosmos";//default
if (jo.containsKey("protocol"))
cvocProtocol = jo.getString("protocol");
logger.fine("cvoc - protocol: " + cvocProtocol);
String cvocMapId = "uri" ;//default
if (jo.containsKey("map-id"))
cvocMapId = jo.getString("map-id");
logger.fine("cvoc - map-id: " + cvocMapId);
String cvocMapQuery = "prefLabel" ;//default
if (jo.containsKey("map-query"))
cvocMapQuery = jo.getString("map-query");
logger.fine("cvoc - map-query: " + cvocMapQuery);
String cvocJsUrl = "/resources/js/cvoc-interface.js";
if (jo.containsKey("js-url"))
cvocJsUrl = jo.getString("js-url");
logger.fine("cvoc - js-url: " + cvocJsUrl);
String cvocTermParentUri = "";
if (jo.containsKey("term-parent-uri"))
cvocTermParentUri = jo.getString("term-parent-uri");
logger.fine("cvoc - term-parent-uri: " + cvocTermParentUri);
String cvocVocabUri = "";
if (jo.containsKey("vocab-uri"))
cvocVocabUri = jo.getString("vocab-uri");
logger.fine("cvoc - vocab-uri: " + cvocVocabUri);
String cvocUrl = "http://localhost/Skosmos";
if (jo.containsKey("cvoc-url"))
cvocUrl = jo.getString("cvoc-url");
logger.fine("cvoc - cvoc-url: " + cvocUrl);
CVoc cvoc = new CVoc(cvocUrl, cvocLang, cvocProtocol, cvocVocabUri, cvocTermParentUri, cvocReadonly, cvocHideReadonlyUrls, cvocMinChars, vocabsList, vocabCodesList
, cvocJsUrl, cvocMapId, cvocMapQuery);
cvocMap.put(jo.getString("vocab-name"), cvoc);
}
}
return cvocMap;
}
public class CVoc {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we please move this outta here to a distinct package? There are likely more places this code will be used in the future... (E. g. API endpoints)

Also:

  • All of the class fields should be private final, as they cannot be changed after being initialised.
  • The class itself should be final, as it should not be inherited from it.
  • There is absolutely no Javadoc present, var names could be a bit more descriptive.
  • The class field names, constructor parameters and getters are very much unaligned with the JSON fields. It's lots of brainwork to map both.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ekoi, something to make it more reusable in the future if API endpoints will be extended with external CV support.

String cvocUrl;
String language;
String protocol;
String vocabUri;
String termParentUri;
String jsUrl;
String mapId;
String mapQuery;
boolean readonly;
boolean hideReadonlyUrls;
int minChars;
List<String> vocabs;
List<String> keys;
public CVoc(String cvocUrl, String language, String protocol, String vocabUri, String termParentUri, boolean readonly, boolean hideReadonlyUrls, int minChars,
List<String> vocabs, List<String> keys, String jsUrl, String mapId, String mapQuery){
this.cvocUrl = cvocUrl;
this.language = language;
this.protocol = protocol;
this.readonly = readonly;
this.hideReadonlyUrls = hideReadonlyUrls;
this.minChars = minChars;
this.vocabs = vocabs;
this.vocabUri = vocabUri;
this.termParentUri = termParentUri;
this.keys = keys;
this.jsUrl = jsUrl;
this.mapId = mapId;
this.mapQuery = mapQuery;
}

public String getCVocUrl() {
return cvocUrl;
}
public String getLanguage() {
return language;
}
public String getProtocol() { return protocol; }
public String getVocabUri() {
return vocabUri;
}
public String getTermParentUri() {
return termParentUri;
}
public boolean isReadonly() {
return readonly;
}
public boolean isHideReadonlyUrls() {
return hideReadonlyUrls;
}
public int getMinChars() { return minChars; }
public List<String> getVocabs() {
return vocabs;
}
public List<String> getKeys() {
return keys;
}

public String getJsUrl() {
return jsUrl;
}

public String getMapId() {
return mapId;
}

public String getMapQuery() {
return mapQuery;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
package edu.harvard.iq.dataverse.settings;

import edu.harvard.iq.dataverse.Dataset;
import edu.harvard.iq.dataverse.actionlogging.ActionLogRecord;
import edu.harvard.iq.dataverse.actionlogging.ActionLogServiceBean;
import edu.harvard.iq.dataverse.api.ApiBlockingFilter;
import edu.harvard.iq.dataverse.engine.command.DataverseRequest;
import edu.harvard.iq.dataverse.util.StringUtil;

import java.io.StringReader;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.inject.Named;
import javax.json.Json;
import javax.json.JsonObject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.io.StringReader;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Service bean accessing a persistent hash map, used as settings in the application.
Expand Down Expand Up @@ -192,12 +190,14 @@ public enum Key {
/** Optionally override http://guides.dataverse.org . */
GuidesBaseUrl,

CVocConf,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be unnecessary when using MPCONFIG. Happy to help here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, I would like to keep the current way to read config and implement MPCONFIG as another option to set configuration variables.


/**
* A link to an installation of https://github.com/IQSS/miniverse or
* some other metrics app.
*/
MetricsUrl,

/**
* Number of minutes before a metrics query can be rerun. Otherwise a cached value is returned.
* Previous month dates always return cache. Only applies to new internal caching system (not miniverse).
Expand Down Expand Up @@ -465,7 +465,7 @@ public String get( String name ) {
}

/**
* Same as {@link #get(java.lang.String)}, but with static checking.
* Same as {@link #get(String)}, but with static checking.
* @param key Enum value of the name.
* @return The setting, or {@code null}.
*/
Expand Down
Loading