-
Notifications
You must be signed in to change notification settings - Fork 535
Externally controlled vocabulary support #7712
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5076dd1
6960a4c
f1d5fb5
6ee5a09
56721ad
68d5aa3
6224e3b
8e5eb3c
4cb9ca9
847dc65
aa43772
8ef8408
c0d9c30
43d6631
e369ffe
feefe49
78f3ec2
5d78401
a480b4f
30de328
ec5d019
00e5df4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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.*; | ||
| import javax.servlet.ServletOutputStream; | ||
| import javax.servlet.http.HttpServletResponse; | ||
| import javax.validation.ConstraintViolation; | ||
| import java.io.*; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See above, comment on globbing imports.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.*; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See above, comment on globbing imports.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; | ||
|
|
||
| /** | ||
| * | ||
|
|
@@ -1282,7 +1311,7 @@ public boolean canUpdateDataset() { | |
| public boolean canPublishDataverse() { | ||
| return permissionsWrapper.canIssuePublishDataverseCommand(dataset.getOwner()); | ||
| } | ||
|
|
||
| public boolean canPublishDataset(){ | ||
| return permissionsWrapper.canIssuePublishDatasetCommand(dataset); | ||
| } | ||
|
|
@@ -1863,8 +1892,8 @@ private String init(boolean initFull) { | |
| mdcLogService.logEntry(entry); | ||
| } | ||
| displayWorkflowComments(); | ||
|
|
||
|
|
||
| if (initFull) { | ||
| // init the list of FileMetadatas | ||
| if (workingVersion.isDraft() && canUpdateDataset()) { | ||
|
|
@@ -2727,7 +2756,7 @@ public String refresh() { | |
| } | ||
|
|
||
| displayWorkflowComments(); | ||
|
|
||
| return ""; | ||
| } | ||
|
|
||
|
|
@@ -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; | ||
|
|
||
|
|
@@ -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()))); | ||
| } | ||
| } | ||
|
|
@@ -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(){ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 IMHO there should be a call to get the config for a specific field (still inside |
||
| 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))); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should either make this live inside
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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:
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. | ||
|
|
@@ -192,12 +190,14 @@ public enum Key { | |
| /** Optionally override http://guides.dataverse.org . */ | ||
| GuidesBaseUrl, | ||
|
|
||
| CVocConf, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will be unnecessary when using MPCONFIG. Happy to help here.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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). | ||
|
|
@@ -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}. | ||
| */ | ||
|
|
||
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ekoi, fyi