updates for concept search service, adding LCSH search capability
This commit is contained in:
parent
e032ceeca4
commit
ba1c6c7075
10 changed files with 1009 additions and 135 deletions
|
@ -1,6 +1,6 @@
|
||||||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
<#import "lib-vivo-form.ftl" as lvf>
|
<#import "lib-vivo-form.ftl" as lvf>
|
||||||
|
<#include "addAssociatedConceptVocabSpecificDisplay.ftl" >
|
||||||
<#assign existingConcepts = editConfiguration.pageData.existingConcepts/>
|
<#assign existingConcepts = editConfiguration.pageData.existingConcepts/>
|
||||||
<#assign userDefinedConceptUrl = editConfiguration.pageData.userDefinedConceptUrl/>
|
<#assign userDefinedConceptUrl = editConfiguration.pageData.userDefinedConceptUrl/>
|
||||||
<#assign sources = editConfiguration.pageData.searchServices/>
|
<#assign sources = editConfiguration.pageData.searchServices/>
|
||||||
|
@ -35,29 +35,44 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<ul id="existingConcepts" >
|
<ul id="existingConcepts">
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var existingConceptsData = [];
|
var existingConceptsData = [];
|
||||||
</script>
|
</script>
|
||||||
|
<#if (existingConcepts?size > 0)>
|
||||||
|
<li class="conceptHeadings conceptsListContainer">
|
||||||
|
<div class="row">
|
||||||
|
<div class="column conceptLabelInfo">
|
||||||
|
<h4>Concept (Type)</h4>
|
||||||
|
</div>
|
||||||
|
<div class="column conceptVocabSource">
|
||||||
|
<h4>Vocabulary Source</h4>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</#if>
|
||||||
|
|
||||||
<#list existingConcepts as existingConcept>
|
<#list existingConcepts as existingConcept>
|
||||||
<li class="existingConcept">
|
<li class="existingConcept conceptsListContainer">
|
||||||
|
<div class="row">
|
||||||
<span class="concept">
|
<div class="column conceptLabelInfo"> ${existingConcept.conceptLabel}
|
||||||
|
|
||||||
<span class="conceptWrapper">
|
|
||||||
<span class="conceptLabel"> ${existingConcept.conceptLabel}
|
|
||||||
<#if existingConcept.vocabURI?has_content && existingConcept.vocabLabel?has_content>
|
|
||||||
(${existingConcept.vocabLabel})
|
|
||||||
</#if>
|
|
||||||
<#if existingConcept.conceptSemanticTypeLabel?has_content>
|
<#if existingConcept.conceptSemanticTypeLabel?has_content>
|
||||||
${existingConcept.conceptSemanticTypeLabel}
|
(${existingConcept.conceptSemanticTypeLabel})
|
||||||
</#if>
|
</#if>
|
||||||
</span>
|
</div>
|
||||||
</span>
|
<div class="column conceptVocabSource">
|
||||||
<a href="${urls.base}/edit/primitiveRdfEdit" class="remove" title="${i18n().remove_capitalized}">${i18n().remove_capitalized}</a>
|
<#if existingConcept.vocabURI?has_content && existingConcept.vocabLabel?has_content>
|
||||||
</span>
|
${existingConcept.vocabLabel}
|
||||||
|
</#if>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<a href="${urls.base}/edit/primitiveRdfEdit" class="remove" title="${i18n().remove_capitalized}">${i18n().remove_capitalized}</a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
@ -86,7 +101,7 @@
|
||||||
<form id="addConceptForm" class="customForm" action="${submitUrl}">
|
<form id="addConceptForm" class="customForm" action="${submitUrl}">
|
||||||
<#assign checkedSource = false />
|
<#assign checkedSource = false />
|
||||||
<h4 class="services">${i18n().external_vocabulary_services}</h4>
|
<h4 class="services">${i18n().external_vocabulary_services}</h4>
|
||||||
<#list sources?keys as sourceUri>
|
<#list sources?keys?sort as sourceUri>
|
||||||
<#assign thisSource = sources[sourceUri]/>
|
<#assign thisSource = sources[sourceUri]/>
|
||||||
<input type="radio" name="source" value="${sourceUri}" role="radio" <#if checkedSource = false><#assign checkedSource = true/>checked="checked"</#if>>
|
<input type="radio" name="source" value="${sourceUri}" role="radio" <#if checkedSource = false><#assign checkedSource = true/>checked="checked"</#if>>
|
||||||
<label class="inline" for="${thisSource.label}"> <a href="${thisSource.url}">${thisSource.label}</a> (${thisSource.description})</label>
|
<label class="inline" for="${thisSource.label}"> <a href="${thisSource.url}">${thisSource.label}</a> (${thisSource.description})</label>
|
||||||
|
@ -101,12 +116,21 @@
|
||||||
<input type="hidden" id="conceptSource" name="conceptSource" value="" /> <!-- Field value populated by JavaScript -->
|
<input type="hidden" id="conceptSource" name="conceptSource" value="" /> <!-- Field value populated by JavaScript -->
|
||||||
<input type="hidden" id="conceptSemanticTypeURI" name="conceptSemanticTypeURI" value="" /> <!-- Field value populated by JavaScript -->
|
<input type="hidden" id="conceptSemanticTypeURI" name="conceptSemanticTypeURI" value="" /> <!-- Field value populated by JavaScript -->
|
||||||
<input type="hidden" id="conceptSemanticTypeLabel" name="conceptSemanticTypeLabel" value="" /> <!-- Field value populated by JavaScript -->
|
<input type="hidden" id="conceptSemanticTypeLabel" name="conceptSemanticTypeLabel" value="" /> <!-- Field value populated by JavaScript -->
|
||||||
|
<input type="hidden" id="conceptBroaderURI" name="conceptBroaderURI" value=""/><!-- Field value populated by JavaScript -->
|
||||||
|
<input type="hidden" id="conceptNarrowerURI" name="conceptNarrowerURI" value=""/><!-- Field value populated by JavaScript -->
|
||||||
|
<div id="indicator" class="hidden">
|
||||||
|
<img id="loadingIndicator" class="indicator" src="${urls.base}/images/indicatorWhite.gif" alt="${i18n().processing_indicator}"/>
|
||||||
|
</div>
|
||||||
<div id="selectedConcept" name="selectedConcept" class="acSelection">
|
<div id="selectedConcept" name="selectedConcept" class="acSelection">
|
||||||
<p class="inline">
|
<p class="inline">
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<!-- Search results populated by JavaScript -->
|
<!-- Search results populated by JavaScript -->
|
||||||
</div>
|
</div>
|
||||||
|
<div id="showHideResults" name="showHideResults">
|
||||||
|
<a href="#" id="showHideLink">Results</a>
|
||||||
|
</div>
|
||||||
<div id="errors" name="errors"></div>
|
<div id="errors" name="errors"></div>
|
||||||
|
|
||||||
<input type="hidden" name="editKey" id="editKey" value="${editKey}"/>
|
<input type="hidden" name="editKey" id="editKey" value="${editKey}"/>
|
||||||
|
@ -133,16 +157,21 @@ var customFormData = {
|
||||||
predicateUri: '${editConfiguration.predicateUri}',
|
predicateUri: '${editConfiguration.predicateUri}',
|
||||||
inversePredicateUri: '${inversePredicate}'
|
inversePredicateUri: '${inversePredicate}'
|
||||||
};
|
};
|
||||||
|
var vocabSpecificDisplay = {};
|
||||||
|
<#list vocabSpecificDisplay?keys as vocab>
|
||||||
|
vocabSpecificDisplay["${vocab}"] = "${vocabSpecificDisplay[vocab]}";
|
||||||
|
</#list>
|
||||||
var i18nStrings = {
|
var i18nStrings = {
|
||||||
vocServiceUnavailable: '${i18n().vocabulary_service_unavailable}',
|
vocServiceUnavailable: '${i18n().vocabulary_service_unavailable}',
|
||||||
noResultsFound: '${i18n().no_serch_results_found}',
|
noResultsFound: '${i18n().no_serch_results_found}',
|
||||||
labelTypeString: '${i18n().label_type}',
|
defaultLabelTypeString: '${i18n().label_type}',
|
||||||
definitionString: '${i18n().definition_capitalized}',
|
definitionString: '${i18n().definition_capitalized}',
|
||||||
bestMatchString: '${i18n().best_match}',
|
bestMatchString: '${i18n().best_match}',
|
||||||
selectTermFromResults: '${i18n().select_term_from_results}',
|
selectTermFromResults: '${i18n().select_term_from_results}',
|
||||||
selectVocSource: '${i18n().select_vocabulary_source_to_search}',
|
selectVocSource: '${i18n().select_vocabulary_source_to_search}',
|
||||||
confirmTermDelete: '${i18n().confirm_term_deletion}',
|
confirmTermDelete: '${i18n().confirm_term_deletion}',
|
||||||
errorTernNotRemoved: '${i18n().error_term_not_deleted}'
|
errorTernNotRemoved: '${i18n().error_term_not_deleted}',
|
||||||
|
vocabSpecificLabels: vocabSpecificDisplay
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
|
|
||||||
|
<#--The original concept javascript is service independent, i.e. all vocabulary service information is returned from the servlet
|
||||||
|
and the template itself generates the same display for all the services. Right now we would like to show a different label
|
||||||
|
in the search results based on the service. I am storing that information here and later we can consider how the display
|
||||||
|
can return to being independent of vocabulary service-specific display options.
|
||||||
|
These values will be passed to the javascript-->
|
||||||
|
|
||||||
|
<#assign vocabSpecificDisplay = {
|
||||||
|
"http://link.informatics.stonybrook.edu/umls":"${i18n().label_type}",
|
||||||
|
"http://aims.fao.org/aos/agrovoc/agrovocScheme":"${i18n().label_altLabels}",
|
||||||
|
"http://www.eionet.europa.eu/gemet/gemetThesaurus":"${i18n().label_type}",
|
||||||
|
"http://id.loc.gov/authorities/subjects":"${i18n().label_altLabels}"
|
||||||
|
}/>
|
|
@ -1,5 +1,9 @@
|
||||||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
.conceptsListContainer {
|
||||||
|
overflow:hidden;
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
.concepts .column {
|
.concepts .column {
|
||||||
float:left;
|
float:left;
|
||||||
padding-right:3px;
|
padding-right:3px;
|
||||||
|
@ -45,3 +49,28 @@ form#addConceptForm span#createOwnOne{
|
||||||
float:left;
|
float:left;
|
||||||
margin-top:24px
|
margin-top:24px
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*For existing concepts, display will also be tabular with columns*/
|
||||||
|
|
||||||
|
.existingConcept .row, .conceptHeadings .row {
|
||||||
|
clear:both;
|
||||||
|
float:left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.existingConcept .column , .conceptHeadings .column {
|
||||||
|
float:left;
|
||||||
|
padding-right:3px;
|
||||||
|
clear:none !important; /*Overriding customFor div's clearing*/
|
||||||
|
}
|
||||||
|
/*label and semantic type if it exists*/
|
||||||
|
.existingConcept .conceptLabelInfo, .conceptHeadings .conceptLabelInfo {
|
||||||
|
width:220px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.existingConcept .conceptVocabSource, .conceptHeadings .conceptVocabSource {
|
||||||
|
width:220px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conceptHeadings .row {
|
||||||
|
border-bottom: 1px solid #5F6464;
|
||||||
|
}
|
|
@ -55,12 +55,19 @@ var addConceptForm = {
|
||||||
this.externalConceptLabel = $('#conceptLabel');
|
this.externalConceptLabel = $('#conceptLabel');
|
||||||
this.externalConceptSource = $('#conceptSource');
|
this.externalConceptSource = $('#conceptSource');
|
||||||
this.externalConceptSemanticTypeLabel = $("#conceptSemanticTypeLabel");
|
this.externalConceptSemanticTypeLabel = $("#conceptSemanticTypeLabel");
|
||||||
|
this.externalConceptBroaderUris = $("#conceptBroaderURI");
|
||||||
|
this.externalConceptNarrowerUris = $("#conceptNarrowerURI");
|
||||||
//remove links
|
//remove links
|
||||||
this.removeConceptLinks = $('a.remove');
|
this.removeConceptLinks = $('a.remove');
|
||||||
this.errors = $('#errors');
|
this.errors = $('#errors');
|
||||||
this.createOwn1 = $('#createOwnOne');
|
this.createOwn1 = $('#createOwnOne');
|
||||||
this.createOwn2 = $('#createOwnTwo');
|
this.createOwn2 = $('#createOwnTwo');
|
||||||
this.orSpan = $('span.or')
|
this.orSpan = $('span.or')
|
||||||
|
this.loadingIndicator = $("#indicator");
|
||||||
|
this.showHideSearchResults = $("#showHideResults");
|
||||||
|
//Value we are setting to cut off length of alternate labels string
|
||||||
|
this.maxNumberAlternateLabels = 4;
|
||||||
|
this.numberOfMaxInitialSearchResults = 7;
|
||||||
},
|
},
|
||||||
|
|
||||||
initPage: function() {
|
initPage: function() {
|
||||||
|
@ -87,6 +94,10 @@ var addConceptForm = {
|
||||||
addConceptForm.removeExistingConcept(this);
|
addConceptForm.removeExistingConcept(this);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
this.showHideSearchResults.find("a#showHideLink").click(function() {
|
||||||
|
addConceptForm.showHideMultipleSearchResults(this);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
initForm: function() {
|
initForm: function() {
|
||||||
// Hide the button that shows the form
|
// Hide the button that shows the form
|
||||||
|
@ -99,7 +110,9 @@ var addConceptForm = {
|
||||||
//Also clear the search input
|
//Also clear the search input
|
||||||
this.searchTerm.val("");
|
this.searchTerm.val("");
|
||||||
this.cancel.unbind('click');
|
this.cancel.unbind('click');
|
||||||
|
//make sure results loading indicator is hidden
|
||||||
|
this.loadingIndicator.addClass("hidden");
|
||||||
|
this.showHideSearchResults.hide();
|
||||||
// Show the form
|
// Show the form
|
||||||
this.form.show();
|
this.form.show();
|
||||||
},
|
},
|
||||||
|
@ -114,6 +127,8 @@ var addConceptForm = {
|
||||||
},
|
},
|
||||||
clearSearchResults:function() {
|
clearSearchResults:function() {
|
||||||
$('#selectedConcept').empty();
|
$('#selectedConcept').empty();
|
||||||
|
//Hide the indicator icon if still there
|
||||||
|
$("#indicator").addClass("hidden");
|
||||||
},
|
},
|
||||||
clearErrors:function() {
|
clearErrors:function() {
|
||||||
addConceptForm.errors.empty();
|
addConceptForm.errors.empty();
|
||||||
|
@ -134,6 +149,25 @@ var addConceptForm = {
|
||||||
this.hideForm();
|
this.hideForm();
|
||||||
this.showFormButtonWrapper.show();
|
this.showFormButtonWrapper.show();
|
||||||
},
|
},
|
||||||
|
showHideMultipleSearchResults: function(link) {
|
||||||
|
if($(link).hasClass("showmore")) {
|
||||||
|
//if clicking and already says show more then need to show the rest of the results
|
||||||
|
$("li.concepts").show(); //show everything
|
||||||
|
$(link).html("Show fewer results");
|
||||||
|
$(link).removeClass("showmore");
|
||||||
|
} else {
|
||||||
|
//if clicking and does not say show more than need to show less
|
||||||
|
$("li.concepts").slice(addConceptForm.numberOfMaxInitialSearchResults).hide();
|
||||||
|
$(link).html("Show more results");
|
||||||
|
$(link).addClass("showmore");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//reset this to default, which is hidden with show more link
|
||||||
|
resetShowHideMultipleSearchResults: function() {
|
||||||
|
addConceptForm.showHideSearchResults.hide();
|
||||||
|
addConceptForm.showHideSearchResults.find("a#showHideLink").html("Show more results");
|
||||||
|
addConceptForm.showHideSearchResults.find("a#showHideLink").addClass("showmore");
|
||||||
|
},
|
||||||
submitSearchTerm: function() {
|
submitSearchTerm: function() {
|
||||||
//Get value of search term
|
//Get value of search term
|
||||||
var searchValue = this.searchTerm.val();
|
var searchValue = this.searchTerm.val();
|
||||||
|
@ -145,7 +179,11 @@ var addConceptForm = {
|
||||||
}
|
}
|
||||||
var vocabSourceValue = checkedVocabSource.val();
|
var vocabSourceValue = checkedVocabSource.val();
|
||||||
var dataServiceUrl = addConceptForm.dataServiceUrl + "?searchTerm=" + encodeURIComponent(searchValue) + "&source=" + encodeURIComponent(vocabSourceValue);
|
var dataServiceUrl = addConceptForm.dataServiceUrl + "?searchTerm=" + encodeURIComponent(searchValue) + "&source=" + encodeURIComponent(vocabSourceValue);
|
||||||
//This should return an object including the concept list or any errors if there are any
|
//Show the loading icon until the results appear
|
||||||
|
addConceptForm.loadingIndicator.removeClass("hidden");
|
||||||
|
//Hide and reset the show more button
|
||||||
|
addConceptForm.resetShowHideMultipleSearchResults();
|
||||||
|
//This should return an object including the concept list or any errors if there are any
|
||||||
$.getJSON(dataServiceUrl, function(results) {
|
$.getJSON(dataServiceUrl, function(results) {
|
||||||
var htmlAdd = "";
|
var htmlAdd = "";
|
||||||
var vocabUnavailable = "<p>" + addConceptForm.vocServiceUnavailable + "</p>";
|
var vocabUnavailable = "<p>" + addConceptForm.vocServiceUnavailable + "</p>";
|
||||||
|
@ -166,7 +204,7 @@ var addConceptForm = {
|
||||||
//For each result, display
|
//For each result, display
|
||||||
if(numberTotalMatches > 0) {
|
if(numberTotalMatches > 0) {
|
||||||
htmlAdd = "<ul class='dd' id='concepts' name='concepts'>";
|
htmlAdd = "<ul class='dd' id='concepts' name='concepts'>";
|
||||||
htmlAdd+= addConceptForm.addResultsHeader();
|
htmlAdd+= addConceptForm.addResultsHeader(vocabSourceValue);
|
||||||
//Show best matches first
|
//Show best matches first
|
||||||
for(i = 0; i < numberBestMatches; i++) {
|
for(i = 0; i < numberBestMatches; i++) {
|
||||||
var conceptResult = bestMatchResults[i];
|
var conceptResult = bestMatchResults[i];
|
||||||
|
@ -184,6 +222,8 @@ var addConceptForm = {
|
||||||
|
|
||||||
}
|
}
|
||||||
if(htmlAdd.length) {
|
if(htmlAdd.length) {
|
||||||
|
//hide the loading icon again
|
||||||
|
addConceptForm.loadingIndicator.addClass("hidden");
|
||||||
$('#selectedConcept').html(htmlAdd);
|
$('#selectedConcept').html(htmlAdd);
|
||||||
if (htmlAdd.indexOf("No search results") >= 0) {
|
if (htmlAdd.indexOf("No search results") >= 0) {
|
||||||
addConceptForm.showHiddenElements(hasResults);
|
addConceptForm.showHiddenElements(hasResults);
|
||||||
|
@ -191,6 +231,8 @@ var addConceptForm = {
|
||||||
else {
|
else {
|
||||||
hasResults = true;
|
hasResults = true;
|
||||||
addConceptForm.showHiddenElements(hasResults);
|
addConceptForm.showHiddenElements(hasResults);
|
||||||
|
//Here, tweak the display based on the number of results
|
||||||
|
addConceptForm.displayUptoMaxResults();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -203,9 +245,12 @@ var addConceptForm = {
|
||||||
var definedBy = conceptResult.definedBy;
|
var definedBy = conceptResult.definedBy;
|
||||||
var type = conceptResult.type;
|
var type = conceptResult.type;
|
||||||
var uri = conceptResult.uri;
|
var uri = conceptResult.uri;
|
||||||
|
//also adding broader and narrower uris wherever they exist
|
||||||
|
var broaderUris = conceptResult.broaderURIList;
|
||||||
|
var narrowerUris = conceptResult.narrowerURIList;
|
||||||
//this will be null if there are no alternate labels
|
//this will be null if there are no alternate labels
|
||||||
var altLabels = conceptResult.altLabelList;
|
var altLabels = conceptResult.altLabelList;
|
||||||
return addConceptForm.generateIndividualConceptDisplay(uri, label, altLabels, definition, type, definedBy, isBestMatch);
|
return addConceptForm.generateIndividualConceptDisplay(uri, label, altLabels, definition, type, definedBy, isBestMatch, broaderUris, narrowerUris);
|
||||||
},
|
},
|
||||||
//This should now return all best matches in one array and other results in another
|
//This should now return all best matches in one array and other results in another
|
||||||
parseResults:function(resultsArray) {
|
parseResults:function(resultsArray) {
|
||||||
|
@ -225,10 +270,19 @@ var addConceptForm = {
|
||||||
}
|
}
|
||||||
return {"bestMatch":bestMatchResults, "alternate":alternateResults};
|
return {"bestMatch":bestMatchResults, "alternate":alternateResults};
|
||||||
},
|
},
|
||||||
addResultsHeader:function() {
|
addResultsHeader:function(vocabSourceValue) {
|
||||||
var htmlAdd = "<li class='concepts'><div class='row'><span class='column conceptLabel'>" + addConceptForm.labelTypeString + " </span><span class='column conceptDefinition'>" + addConceptForm.definitionString + "</span><span class='column'>" + addConceptForm.bestMatchString + "</span></div></li>";
|
var htmlAdd = "<li class='concepts'><div class='row'><span class='column conceptLabel'>" +
|
||||||
|
addConceptForm.getVocabSpecificColumnLabel(vocabSourceValue) + " </span><span class='column conceptDefinition'>" + addConceptForm.definitionString + "</span><span class='column'>" + addConceptForm.bestMatchString + "</span></div></li>";
|
||||||
return htmlAdd;
|
return htmlAdd;
|
||||||
},
|
},
|
||||||
|
//currently just the first column label depends on which service has been utilized
|
||||||
|
getVocabSpecificColumnLabel: function(vocabSourceValue) {
|
||||||
|
var columnLabel = addConceptForm.vocabSpecificLabels[vocabSourceValue];
|
||||||
|
if(columnLabel == undefined) {
|
||||||
|
columnLabel = addConceptForm.defaultLabelTypeString;
|
||||||
|
}
|
||||||
|
return columnLabel;
|
||||||
|
},
|
||||||
hideSearchResults:function() {
|
hideSearchResults:function() {
|
||||||
this.selectedConcept.hide();
|
this.selectedConcept.hide();
|
||||||
},
|
},
|
||||||
|
@ -239,11 +293,14 @@ var addConceptForm = {
|
||||||
}
|
}
|
||||||
var i;
|
var i;
|
||||||
var len = checkedElements.length;
|
var len = checkedElements.length;
|
||||||
var checkedConcept, checkedConceptElement, conceptLabel, conceptSource, conceptSemanticType;
|
var checkedConcept, checkedConceptElement, conceptLabel, conceptSource, conceptSemanticType,
|
||||||
|
conceptBroaderUri, conceptNarrowerUri;
|
||||||
var conceptNodes = [];
|
var conceptNodes = [];
|
||||||
var conceptLabels = [];
|
var conceptLabels = [];
|
||||||
var conceptSources = [];
|
var conceptSources = [];
|
||||||
var conceptSemanticTypes = [];
|
var conceptSemanticTypes = [];
|
||||||
|
var conceptBroaderUris = []; //each array element can be a string which is comma delimited for multiple uris
|
||||||
|
var conceptNarrowerUris = [];//same as above
|
||||||
|
|
||||||
checkedElements.each(function() {
|
checkedElements.each(function() {
|
||||||
checkedConceptElement = $(this);
|
checkedConceptElement = $(this);
|
||||||
|
@ -251,22 +308,29 @@ var addConceptForm = {
|
||||||
conceptLabel = checkedConceptElement.attr("label");
|
conceptLabel = checkedConceptElement.attr("label");
|
||||||
conceptSource = checkedConceptElement.attr("conceptDefinedBy");
|
conceptSource = checkedConceptElement.attr("conceptDefinedBy");
|
||||||
conceptSemanticType = checkedConceptElement.attr("conceptType");
|
conceptSemanticType = checkedConceptElement.attr("conceptType");
|
||||||
|
conceptBroaderUri = checkedConceptElement.attr("broaderUris");
|
||||||
|
conceptNarrowerUri = checkedConceptElement.attr("narrowerUris");
|
||||||
conceptNodes.push(checkedConcept);
|
conceptNodes.push(checkedConcept);
|
||||||
conceptLabels.push(conceptLabel);
|
conceptLabels.push(conceptLabel);
|
||||||
conceptSources.push(conceptSource);
|
conceptSources.push(conceptSource);
|
||||||
conceptSemanticTypes.push(conceptSemanticType);
|
conceptSemanticTypes.push(conceptSemanticType);
|
||||||
|
conceptBroaderUris.push(conceptBroaderUri);
|
||||||
|
conceptNarrowerUris.push(conceptNarrowerUri);
|
||||||
});
|
});
|
||||||
this.externalConceptURI.val(conceptNodes);
|
this.externalConceptURI.val(conceptNodes);
|
||||||
this.externalConceptLabel.val(conceptLabels);
|
this.externalConceptLabel.val(conceptLabels);
|
||||||
this.externalConceptSource.val(conceptSources);
|
this.externalConceptSource.val(conceptSources);
|
||||||
this.externalConceptSemanticTypeLabel.val(conceptSemanticTypes);
|
this.externalConceptSemanticTypeLabel.val(conceptSemanticTypes);
|
||||||
|
this.externalConceptBroaderUris.val(conceptBroaderUris);
|
||||||
|
this.externalConceptNarrowerUris.val(conceptNarrowerUris);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
generateIndividualConceptDisplay: function(cuiURI, label, altLabels, definition, type, definedBy, isBestMatch) {
|
generateIndividualConceptDisplay: function(cuiURI, label, altLabels, definition, type, definedBy, isBestMatch, broaderUris, narrowerUris) {
|
||||||
var htmlAdd = "<li class='concepts'>" +
|
var htmlAdd = "<li class='concepts'>" +
|
||||||
"<div class='row'>" +
|
"<div class='row'>" +
|
||||||
"<div class='column conceptLabel'>" +
|
"<div class='column conceptLabel'>" +
|
||||||
addConceptForm.generateIndividualCUIInput(cuiURI, label, type, definedBy) +
|
addConceptForm.generateIndividualCUIInput(cuiURI, label, type, definedBy, broaderUris, narrowerUris) +
|
||||||
addConceptForm.generateIndividualLabelsDisplay(label, altLabels) + addConceptForm.generateIndividualTypeDisplay(type) + "</div>" +
|
addConceptForm.generateIndividualLabelsDisplay(label, altLabels) + addConceptForm.generateIndividualTypeDisplay(type) + "</div>" +
|
||||||
addConceptForm.generateIndividualDefinitionDisplay(definition) +
|
addConceptForm.generateIndividualDefinitionDisplay(definition) +
|
||||||
addConceptForm.generateBestOrAlternate(isBestMatch) +
|
addConceptForm.generateBestOrAlternate(isBestMatch) +
|
||||||
|
@ -274,14 +338,23 @@ var addConceptForm = {
|
||||||
"</li>";
|
"</li>";
|
||||||
return htmlAdd;
|
return htmlAdd;
|
||||||
},
|
},
|
||||||
generateIndividualCUIInput:function(cuiURI, label, type, definedBy) {
|
generateIndividualCUIInput:function(cuiURI, label, type, definedBy, broaderUris, narrowerUris) {
|
||||||
return "<input type='checkbox' name='CUI' value='" + cuiURI + "' label='" + label + "' conceptType='" + type + "' conceptDefinedBy='" + definedBy + "'/>";
|
return "<input type='checkbox' name='CUI' value='" + cuiURI + "' label='" +
|
||||||
|
label + "' conceptType='" + type + "' conceptDefinedBy='" + definedBy + "' " +
|
||||||
|
"broaderUris='" + broaderUris + "' narrowerUris='" + narrowerUris + "'/>";
|
||||||
},
|
},
|
||||||
//In case there are multiple labels display those
|
//In case there are multiple labels display those
|
||||||
generateIndividualLabelsDisplay:function(label, altLabels) {
|
generateIndividualLabelsDisplay:function(label, altLabels) {
|
||||||
var labelDisplay = label;
|
var labelDisplay = label;
|
||||||
|
var displayAltLabels = altLabels;
|
||||||
if(altLabels != null && altLabels.length > 0) {
|
if(altLabels != null && altLabels.length > 0) {
|
||||||
labelDisplay += "<br> [" + altLabels + "]";
|
//Certain vocabulary services might return a long list of alternate labels, in which case we will show fewer
|
||||||
|
//display only upto a certain number of alternate labels and use an ellipsis to signify there
|
||||||
|
//are additional terms
|
||||||
|
if(altLabels.length > addConceptForm.maxNumberAlternateLabels) {
|
||||||
|
displayAltLabels = altLabels.slice(0, addConceptForm.maxNumberAlternateLabels) + ",...";
|
||||||
|
}
|
||||||
|
labelDisplay += "<br> (" + displayAltLabels + ")";
|
||||||
}
|
}
|
||||||
return labelDisplay;
|
return labelDisplay;
|
||||||
},
|
},
|
||||||
|
@ -307,6 +380,18 @@ var addConceptForm = {
|
||||||
}
|
}
|
||||||
return "<div class='column'><div class='" + className + "'> </div></div>";
|
return "<div class='column'><div class='" + className + "'> </div></div>";
|
||||||
},
|
},
|
||||||
|
//Certain vocabulary services return a great number of results, we would like the ability to show more or less of those results
|
||||||
|
displayUptoMaxResults:function() {
|
||||||
|
var numberConcepts = $("li.concepts").length;
|
||||||
|
if(numberConcepts > addConceptForm.numberOfMaxInitialSearchResults) {
|
||||||
|
$("li.concepts").slice(addConceptForm.numberOfMaxInitialSearchResults).hide();
|
||||||
|
//Hide the link for showing/hiding search results
|
||||||
|
addConceptForm.showHideSearchResults.show();
|
||||||
|
addConceptForm.showHideSearchResults.find("a#showHideLink").html("Show more results");
|
||||||
|
addConceptForm.showHideSearchResults.find("a#showHideLink").addClass("showmore");
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
validateConceptSelection:function(checkedElements) {
|
validateConceptSelection:function(checkedElements) {
|
||||||
var numberElements = checkedElements.length;
|
var numberElements = checkedElements.length;
|
||||||
if(numberElements < 1) {
|
if(numberElements < 1) {
|
||||||
|
|
|
@ -4,3 +4,5 @@
|
||||||
<http://link.informatics.stonybrook.edu/umls> <http://www.w3.org/2000/01/rdf-schema#label> "UMLS"^^<http://www.w3.org/2001/XMLSchema#string> .
|
<http://link.informatics.stonybrook.edu/umls> <http://www.w3.org/2000/01/rdf-schema#label> "UMLS"^^<http://www.w3.org/2001/XMLSchema#string> .
|
||||||
<http://aims.fao.org/aos/agrovoc/agrovocScheme> <http://www.w3.org/2000/01/rdf-schema#label> "AGROVOC"^^<http://www.w3.org/2001/XMLSchema#string> .
|
<http://aims.fao.org/aos/agrovoc/agrovocScheme> <http://www.w3.org/2000/01/rdf-schema#label> "AGROVOC"^^<http://www.w3.org/2001/XMLSchema#string> .
|
||||||
<http://www.eionet.europa.eu/gemet/gemetThesaurus> <http://www.w3.org/2000/01/rdf-schema#label> "GEMET"^^<http://www.w3.org/2001/XMLSchema#string> .
|
<http://www.eionet.europa.eu/gemet/gemetThesaurus> <http://www.w3.org/2000/01/rdf-schema#label> "GEMET"^^<http://www.w3.org/2001/XMLSchema#string> .
|
||||||
|
<http://id.loc.gov/authorities/subjects> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Thing> .
|
||||||
|
<http://id.loc.gov/authorities/subjects> <http://www.w3.org/2000/01/rdf-schema#label> "LCSH"^^<http://www.w3.org/2001/XMLSchema#string> .
|
||||||
|
|
|
@ -0,0 +1,510 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.semservices.service.impl;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.rmi.RemoteException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import javax.xml.rpc.ServiceException;
|
||||||
|
|
||||||
|
import net.sf.json.JSONArray;
|
||||||
|
import net.sf.json.JSONObject;
|
||||||
|
import net.sf.json.JSONSerializer;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.fao.www.webservices.AgrovocWS.ACSWWebService;
|
||||||
|
import org.fao.www.webservices.AgrovocWS.ACSWWebServiceServiceLocator;
|
||||||
|
import org.semanticweb.skos.SKOSAnnotation;
|
||||||
|
import org.semanticweb.skos.SKOSConcept;
|
||||||
|
import org.semanticweb.skos.SKOSDataFactory;
|
||||||
|
import org.semanticweb.skos.SKOSDataProperty;
|
||||||
|
import org.semanticweb.skos.SKOSDataRelationAssertion;
|
||||||
|
import org.semanticweb.skos.SKOSDataset;
|
||||||
|
import org.semanticweb.skos.SKOSEntity;
|
||||||
|
import org.semanticweb.skos.SKOSLiteral;
|
||||||
|
import org.semanticweb.skos.SKOSObjectRelationAssertion;
|
||||||
|
import org.semanticweb.skos.SKOSUntypedLiteral;
|
||||||
|
import org.semanticweb.skos.properties.*;
|
||||||
|
import org.semanticweb.skosapibinding.SKOSManager;
|
||||||
|
import org.w3c.dom.Attr;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.NamedNodeMap;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
import com.hp.hpl.jena.query.Query;
|
||||||
|
import com.hp.hpl.jena.query.QueryExecution;
|
||||||
|
import com.hp.hpl.jena.query.QueryExecutionFactory;
|
||||||
|
import com.hp.hpl.jena.query.QueryFactory;
|
||||||
|
import com.hp.hpl.jena.query.QuerySolution;
|
||||||
|
import com.hp.hpl.jena.query.ResultSet;
|
||||||
|
import com.hp.hpl.jena.rdf.model.Literal;
|
||||||
|
import com.hp.hpl.jena.rdf.model.RDFNode;
|
||||||
|
import com.hp.hpl.jena.rdf.model.Resource;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.semservices.bo.Concept;
|
||||||
|
import edu.cornell.mannlib.semservices.exceptions.ConceptsNotFoundException;
|
||||||
|
import edu.cornell.mannlib.semservices.service.ExternalConceptService;
|
||||||
|
import edu.cornell.mannlib.semservices.util.XMLUtils;
|
||||||
|
|
||||||
|
public class LCSHService implements ExternalConceptService {
|
||||||
|
|
||||||
|
protected final Log log = LogFactory.getLog(getClass());
|
||||||
|
private final String skosSuffix = ".skos.rdf";
|
||||||
|
private final String hostUri = "http://id.loc.gov";
|
||||||
|
private java.lang.String LCSHWS_address = hostUri + "/authorities/subjects";
|
||||||
|
private final String schemeUri = hostUri + "/authorities/subjects";
|
||||||
|
private final String baseUri = hostUri + "/search/";
|
||||||
|
private final String ontologyName = "LCSH";
|
||||||
|
private final String format = "SKOS";
|
||||||
|
private final String lang = "en";
|
||||||
|
private final String codeName = "hasCodeAgrovoc";
|
||||||
|
private final String searchMode = "Exact Match";
|
||||||
|
protected final String dbpedia_endpoint = " http://dbpedia.org/sparql";
|
||||||
|
//Property uris used for SKOS
|
||||||
|
protected final String SKOSNotePropertyURI = "http://www.w3.org/2004/02/skos/core#note";
|
||||||
|
protected final String SKOSPrefLabelURI = "http://www.w3.org/2004/02/skos/core#prefLabel";
|
||||||
|
protected final String SKOSAltLabelURI = "http://www.w3.org/2008/05/skos-xl#altLabel";
|
||||||
|
protected final String SKOSBroaderURI = "http://www.w3.org/2004/02/skos/core#broader";
|
||||||
|
protected final String SKOSNarrowerURI = "http://www.w3.org/2004/02/skos/core#narrower";
|
||||||
|
protected final String SKOSExactMatchURI = "http://www.w3.org/2004/02/skos/core#exactMatch";
|
||||||
|
protected final String SKOSCloseMatchURI = "http://www.w3.org/2004/02/skos/core#closeMatch";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Concept> getConcepts(String term) throws Exception {
|
||||||
|
List<Concept> conceptList = new ArrayList<Concept>();
|
||||||
|
String results = null;
|
||||||
|
String dataUrl = baseUri + "?q=" + URLEncoder.encode(term, "UTF-8")
|
||||||
|
+ "&q=cs%3Ahttp%3A%2F%2Fid.loc.gov%2Fauthorities%2Fsubjects"
|
||||||
|
+ "&format=XML";
|
||||||
|
log.debug("dataURL " + dataUrl);
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
URL rss = new URL(dataUrl);
|
||||||
|
|
||||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(
|
||||||
|
rss.openStream()));
|
||||||
|
String inputLine;
|
||||||
|
while ((inputLine = in.readLine()) != null) {
|
||||||
|
sw.write(inputLine);
|
||||||
|
}
|
||||||
|
in.close();
|
||||||
|
|
||||||
|
results = sw.toString();
|
||||||
|
log.debug(results);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.error("error occurred in servlet", ex);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(results)) {
|
||||||
|
return conceptList;
|
||||||
|
}
|
||||||
|
|
||||||
|
conceptList = processOutput(results);
|
||||||
|
|
||||||
|
return conceptList;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Results are in json format (atom) - atom entries need to be extracted
|
||||||
|
// retrieve the URIs and get the SKOS version of the entry, getting broader
|
||||||
|
// and narrower terms as applicable as well as any description (skos:note)
|
||||||
|
// that might exist
|
||||||
|
private List<Concept> processOutput(String results) throws Exception {
|
||||||
|
List<Concept> conceptList = new ArrayList<Concept>();
|
||||||
|
SKOSManager manager = new SKOSManager();
|
||||||
|
// Get uris from the results
|
||||||
|
// Properties we will be querying for
|
||||||
|
SKOSDataFactory sdf = manager.getSKOSDataFactory();
|
||||||
|
|
||||||
|
|
||||||
|
List<String> uris = getConceptURIFromXML(results);
|
||||||
|
String bestMatch = "true";
|
||||||
|
int i = 0;
|
||||||
|
for (String uri : uris) {
|
||||||
|
if(i > 0) {
|
||||||
|
bestMatch = "false";
|
||||||
|
}
|
||||||
|
log.debug("-" + uri + "-");
|
||||||
|
String conceptUriString = getSKOSURI(uri);
|
||||||
|
URI conceptURI = null;
|
||||||
|
try {
|
||||||
|
conceptURI = new URI(conceptUriString);
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
log.error("URI syntax exception in trying to get concept uri " + conceptUriString, e);
|
||||||
|
return conceptList;
|
||||||
|
}
|
||||||
|
log.debug("loading concept uri " + conceptUriString);
|
||||||
|
SKOSDataset dataset = manager.loadDataset(conceptURI);
|
||||||
|
Set<SKOSConcept> skosConcepts = dataset.getSKOSConcepts();
|
||||||
|
log.debug("Number of skos concepts " + skosConcepts.size());
|
||||||
|
|
||||||
|
for (SKOSConcept skosConcept : skosConcepts) {
|
||||||
|
|
||||||
|
Concept c = this.createConcept(sdf, bestMatch, skosConcept, dataset);
|
||||||
|
if(c != null) {
|
||||||
|
conceptList.add(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
|
||||||
|
}
|
||||||
|
return conceptList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//Will use skos if does not encounter error from skos api, otherwise will use regular XML parsing techniques
|
||||||
|
public Concept createConcept(SKOSDataFactory skosDataFactory, String bestMatch, SKOSConcept skosConcept, SKOSDataset dataset) {
|
||||||
|
|
||||||
|
Concept concept = new Concept();
|
||||||
|
String skosConceptURI = skosConcept.getURI().toString();
|
||||||
|
log.debug("SKOSConceptURI is " + skosConceptURI);
|
||||||
|
// get skos version of uri
|
||||||
|
|
||||||
|
concept.setUri(skosConceptURI);
|
||||||
|
concept.setConceptId(stripConceptId(skosConceptURI));
|
||||||
|
concept.setBestMatch(bestMatch);
|
||||||
|
concept.setDefinedBy(schemeUri);
|
||||||
|
concept.setSchemeURI(schemeUri);
|
||||||
|
concept.setType("");
|
||||||
|
|
||||||
|
//Get the skos annotations first to see if there is an error triggered, if so try and see if we can instead utilize XML
|
||||||
|
//For some of the SKOS concepts, a null pointer exception occurs while XML processing still works
|
||||||
|
//I do not yet know the reasons, hjk54
|
||||||
|
try {
|
||||||
|
Set<SKOSAnnotation> skosAnnots = skosConcept
|
||||||
|
.getSKOSAnnotations(dataset);
|
||||||
|
} catch(NullPointerException ex) {
|
||||||
|
concept = createConceptUsingXML(concept, bestMatch, skosConcept);
|
||||||
|
return concept;
|
||||||
|
} catch(Exception ex) {
|
||||||
|
log.debug("Error occurred for annotation retrieval for skos concept " + skosConceptURI, ex);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
concept = this.createConceptUsingSKOS(skosDataFactory, concept, skosConcept, dataset);
|
||||||
|
return concept;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Concept createConceptUsingSKOS(SKOSDataFactory skosDataFactory, Concept concept, SKOSConcept skosConcept, SKOSDataset dataset) {
|
||||||
|
|
||||||
|
SKOSPrefLabelProperty prefLabelProperty = skosDataFactory.getSKOSPrefLabelProperty();
|
||||||
|
SKOSAltLabelProperty altLabelProperty = skosDataFactory.getSKOSAltLabelProperty();
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<String> labelLiterals = this.getSKOSLiteralValues(skosConcept
|
||||||
|
.getSKOSRelatedConstantByProperty(dataset,
|
||||||
|
prefLabelProperty));
|
||||||
|
if(labelLiterals.size() > 0) {
|
||||||
|
concept.setLabel(labelLiterals.get(0));
|
||||||
|
} else {
|
||||||
|
//This is an error because there should be at least one label returned
|
||||||
|
log.debug("The number of preferred labels is not greater than zero");
|
||||||
|
}
|
||||||
|
|
||||||
|
// get altLabels
|
||||||
|
List<String> altLabelList = this.getSKOSLiteralValues(skosConcept
|
||||||
|
.getSKOSRelatedConstantByProperty(dataset, altLabelProperty));
|
||||||
|
concept.setAltLabelList(altLabelList);
|
||||||
|
|
||||||
|
// See if we can get a description as well
|
||||||
|
List<String> notes = this.getSKOSAnnotationValues(skosConcept
|
||||||
|
.getSKOSAnnotationsByURI(dataset, new URI(this.SKOSNotePropertyURI)));
|
||||||
|
|
||||||
|
concept.setDefinition(StringUtils.join(notes, ","));
|
||||||
|
|
||||||
|
// get the broader property URI
|
||||||
|
List<String> broaderURIList = this.getSKOSAnnotationValues(skosConcept
|
||||||
|
.getSKOSAnnotationsByURI(dataset, new URI(this.SKOSBroaderURI)));
|
||||||
|
concept.setBroaderURIList(broaderURIList);
|
||||||
|
|
||||||
|
// get the narrower property URI
|
||||||
|
List<String> narrowerURIList = this.getSKOSAnnotationValues(skosConcept
|
||||||
|
.getSKOSAnnotationsByURI(dataset, new URI(this.SKOSNarrowerURI)));
|
||||||
|
concept.setNarrowerURIList(narrowerURIList);
|
||||||
|
|
||||||
|
// exact match
|
||||||
|
List<String> exactMatchURIList = this.getSKOSAnnotationValues(skosConcept
|
||||||
|
.getSKOSAnnotationsByURI(dataset,
|
||||||
|
new URI(this.SKOSExactMatchURI)));
|
||||||
|
concept.setExactMatchURIList(exactMatchURIList);
|
||||||
|
|
||||||
|
// close match
|
||||||
|
List<String> closeMatchURIList = this.getSKOSAnnotationValues(skosConcept
|
||||||
|
.getSKOSAnnotationsByURI(dataset,
|
||||||
|
new URI(this.SKOSCloseMatchURI)));
|
||||||
|
concept.setCloseMatchURIList(closeMatchURIList);
|
||||||
|
log.debug("add concept to list");
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.debug("Exception occurred for -" + skosConcept.getURI()
|
||||||
|
+ "- " + ex.getMessage(), ex);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return concept;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private List<String> getSKOSLiteralValues(Set<SKOSLiteral> skosLiterals) {
|
||||||
|
String lang = "";
|
||||||
|
List<String> literalValues = new ArrayList<String>();
|
||||||
|
for (SKOSLiteral literal : skosLiterals) {
|
||||||
|
if (!literal.isTyped()) {
|
||||||
|
// if it has language
|
||||||
|
SKOSUntypedLiteral untypedLiteral = literal
|
||||||
|
.getAsSKOSUntypedLiteral();
|
||||||
|
if (untypedLiteral.hasLang()) {
|
||||||
|
lang = untypedLiteral.getLang();
|
||||||
|
} else {
|
||||||
|
lang = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// log.debug("literal: "+ literal.getLiteral());
|
||||||
|
if (lang.equals("en")) {
|
||||||
|
log.debug("literal value: " + literal.getLiteral());
|
||||||
|
literalValues.add(literal.getLiteral());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return literalValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
//For a given set of annotations (for example, for a specific property)
|
||||||
|
private List<String> getSKOSAnnotationValues(Set<SKOSAnnotation> skosAnnotations) {
|
||||||
|
List<String> valuesList = new ArrayList<String>();
|
||||||
|
for (SKOSAnnotation annotation : skosAnnotations) {
|
||||||
|
String value = this.getSKOSAnnotationStringValue(annotation);
|
||||||
|
valuesList.add(value);
|
||||||
|
}
|
||||||
|
return valuesList;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get string value for annotation
|
||||||
|
private String getSKOSAnnotationStringValue(SKOSAnnotation annotation) {
|
||||||
|
String value = new String();
|
||||||
|
if (annotation.isAnnotationByConstant()) {
|
||||||
|
SKOSLiteral literal = annotation
|
||||||
|
.getAnnotationValueAsConstant();
|
||||||
|
value = literal.getLiteral();
|
||||||
|
log.debug("broder uri: " + value);
|
||||||
|
} else {
|
||||||
|
// annotation is some resource
|
||||||
|
SKOSEntity entity = annotation.getAnnotationValue();
|
||||||
|
value = entity.getURI().toString();
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//this method relies on the XML of the single SKOS rdf concept in case the SKOS api throws a null pointer exception
|
||||||
|
private Concept createConceptUsingXML(Concept concept, String bestMatch,
|
||||||
|
SKOSConcept skosConcept) {
|
||||||
|
String conceptUriString = skosConcept.getURI().toString() + this.skosSuffix;;
|
||||||
|
|
||||||
|
URL conceptURL = null;
|
||||||
|
try {
|
||||||
|
conceptURL = new URL(conceptUriString);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Exception occurred in instantiating URL for " + conceptUriString, e);
|
||||||
|
//If the url is having trouble, just return null for the concept
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
log.debug("loading concept uri " + conceptUriString);
|
||||||
|
|
||||||
|
|
||||||
|
String results = null;
|
||||||
|
try {
|
||||||
|
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
|
||||||
|
|
||||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(
|
||||||
|
conceptURL.openStream()));
|
||||||
|
String inputLine;
|
||||||
|
while ((inputLine = in.readLine()) != null) {
|
||||||
|
sw.write(inputLine);
|
||||||
|
}
|
||||||
|
in.close();
|
||||||
|
|
||||||
|
results = sw.toString();
|
||||||
|
log.debug(results);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.error("Error occurred in getting concept from the URL " + conceptUriString, ex);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
Document doc = XMLUtils.parse(results);
|
||||||
|
List<String> labelLiterals = this.getValuesFromXMLNodes(doc, "skos:prefLabel", null);
|
||||||
|
if(labelLiterals.size() > 0) {
|
||||||
|
concept.setLabel(labelLiterals.get(0));
|
||||||
|
} else {
|
||||||
|
//This is an error because there should be at least one label returned
|
||||||
|
log.debug("The number of preferred labels is not greater than zero");
|
||||||
|
}
|
||||||
|
List<String> altLabelList = this.getValuesFromXMLNodes(doc, "skos:altLabel", null);
|
||||||
|
concept.setAltLabelList(altLabelList);
|
||||||
|
|
||||||
|
List<String> broaderURIList = this.getValuesFromXMLNodes(doc, "skos:broader", "rdf:resource");
|
||||||
|
concept.setBroaderURIList(broaderURIList);
|
||||||
|
List<String> narrowerURIList = this.getValuesFromXMLNodes(doc, "skos:narrower", "rdf:resource");
|
||||||
|
concept.setNarrowerURIList(narrowerURIList);
|
||||||
|
|
||||||
|
List<String> exactMatchURIList = this.getValuesFromXMLNodes(doc, "skos:exactMatch", "rdf:resource");
|
||||||
|
concept.setExactMatchURIList(exactMatchURIList);
|
||||||
|
List<String> closeMatchURIList = this.getValuesFromXMLNodes(doc, "skos:closeMatch", "rdf:resource");
|
||||||
|
concept.setCloseMatchURIList(closeMatchURIList);
|
||||||
|
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("error occurred in parsing " + results, e);
|
||||||
|
} catch (SAXException e) {
|
||||||
|
log.error("error occurred in parsing " + results, e);
|
||||||
|
} catch (ParserConfigurationException e) {
|
||||||
|
log.error("error occurred in parsing " + results, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return concept;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getSKOSURI(String uri) {
|
||||||
|
// Strip .xml at the end and replace with .skos.rdf
|
||||||
|
String skosURI = uri;
|
||||||
|
if (uri.endsWith(".xml")) {
|
||||||
|
skosURI = uri.substring(0, uri.length() - 4);
|
||||||
|
skosURI += skosSuffix;
|
||||||
|
}
|
||||||
|
return hostUri + skosURI;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getConceptURISFromJSON(String results) {
|
||||||
|
List<String> uris = new ArrayList<String>();
|
||||||
|
try {
|
||||||
|
JSONObject json = (JSONObject) JSONSerializer.toJSON(results);
|
||||||
|
log.debug(json.toString());
|
||||||
|
// Get atom entry elements
|
||||||
|
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.error("Could not get concepts", ex);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
return uris;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<String> getConceptURIFromXML(String rdf) {
|
||||||
|
List<String> uris = new ArrayList<String>();
|
||||||
|
String conceptUri = new String();
|
||||||
|
try {
|
||||||
|
Document doc = XMLUtils.parse(rdf);
|
||||||
|
NodeList nodes = doc.getElementsByTagName("search:result");
|
||||||
|
int len = nodes.getLength();
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
Node node = nodes.item(i);
|
||||||
|
NamedNodeMap attrs = node.getAttributes();
|
||||||
|
Attr idAttr = (Attr) attrs.getNamedItem("uri");
|
||||||
|
conceptUri = idAttr.getTextContent();
|
||||||
|
log.debug("concept uri is " + conceptUri);
|
||||||
|
uris.add(conceptUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("error occurred in parsing " +rdf, e);
|
||||||
|
} catch (SAXException e) {
|
||||||
|
log.error("error occurred in parsing " +rdf, e);
|
||||||
|
} catch (ParserConfigurationException e) {
|
||||||
|
log.error("error occurred in parsing " +rdf, e);
|
||||||
|
|
||||||
|
}
|
||||||
|
return uris;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Concept> processResults(String term) throws Exception {
|
||||||
|
return getConcepts(term);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param uri
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected String stripConceptId(String uri) {
|
||||||
|
String conceptId = new String();
|
||||||
|
int lastslash = uri.lastIndexOf('/');
|
||||||
|
conceptId = uri.substring(lastslash + 1, uri.length());
|
||||||
|
return conceptId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param str
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected String extractConceptId(String str) {
|
||||||
|
try {
|
||||||
|
return str.substring(1, str.length() - 1);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.error("Exception occurred in extracting concept id for " + str, ex);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Concept> getConceptsByURIWithSparql(String uri)
|
||||||
|
throws Exception {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public List<String> getValuesFromXMLNodes(Document doc, String tagName, String attributeName) {
|
||||||
|
NodeList nodes = doc.getElementsByTagName(tagName);
|
||||||
|
|
||||||
|
return getValuesFromXML(nodes, attributeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Returns list of values based on nodes and whether or not a specific attribute name should be used or just the text content
|
||||||
|
public List<String> getValuesFromXML(NodeList nodes, String attributeName) {
|
||||||
|
int len = nodes.getLength();
|
||||||
|
int i;
|
||||||
|
List<String> values = new ArrayList<String>();
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
Node node = nodes.item(i);
|
||||||
|
if(attributeName != null && !attributeName.isEmpty()) {
|
||||||
|
NamedNodeMap attrs = node.getAttributes();
|
||||||
|
Attr a = (Attr)attrs.getNamedItem(attributeName);
|
||||||
|
if(a != null) {
|
||||||
|
values.add(a.getTextContent());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
values.add(node.getTextContent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -59,6 +59,8 @@ public class AddAssociatedConceptGenerator extends VivoBaseGenerator implements
|
||||||
//TODO: Set this to a dynamic mechanism
|
//TODO: Set this to a dynamic mechanism
|
||||||
private static String VIVOCore = "http://vivoweb.org/ontology/core#";
|
private static String VIVOCore = "http://vivoweb.org/ontology/core#";
|
||||||
private static String SKOSConceptType = "http://www.w3.org/2004/02/skos/core#Concept";
|
private static String SKOSConceptType = "http://www.w3.org/2004/02/skos/core#Concept";
|
||||||
|
private static String SKOSBroaderURI = "http://www.w3.org/2004/02/skos/core#broader";
|
||||||
|
private static String SKOSNarrowerURI = "http://www.w3.org/2004/02/skos/core#narrower";
|
||||||
@Override
|
@Override
|
||||||
public EditConfigurationVTwo getEditConfiguration(VitroRequest vreq, HttpSession session) {
|
public EditConfigurationVTwo getEditConfiguration(VitroRequest vreq, HttpSession session) {
|
||||||
EditConfigurationVTwo editConfiguration = new EditConfigurationVTwo();
|
EditConfigurationVTwo editConfiguration = new EditConfigurationVTwo();
|
||||||
|
@ -97,7 +99,8 @@ public class AddAssociatedConceptGenerator extends VivoBaseGenerator implements
|
||||||
// Add preprocessors
|
// Add preprocessors
|
||||||
addPreprocessors(editConfiguration,
|
addPreprocessors(editConfiguration,
|
||||||
ModelAccess.on(vreq).getJenaOntModel(),
|
ModelAccess.on(vreq).getJenaOntModel(),
|
||||||
ModelAccess.on(vreq).getOntModelSelector().getTBoxModel());
|
ModelAccess.on(vreq).getOntModelSelector().getTBoxModel(),
|
||||||
|
vreq.getWebappDaoFactory());
|
||||||
// Adding additional data, specifically edit mode
|
// Adding additional data, specifically edit mode
|
||||||
addFormSpecificData(editConfiguration, vreq);
|
addFormSpecificData(editConfiguration, vreq);
|
||||||
// One override for basic functionality, changing url pattern
|
// One override for basic functionality, changing url pattern
|
||||||
|
@ -189,7 +192,11 @@ public class AddAssociatedConceptGenerator extends VivoBaseGenerator implements
|
||||||
"?conceptNode <" + RDFS.isDefinedBy.getURI() + "> ?conceptSource .",
|
"?conceptNode <" + RDFS.isDefinedBy.getURI() + "> ?conceptSource .",
|
||||||
"?conceptNode <" + RDF.type + "> ?conceptSemanticTypeURI ." +
|
"?conceptNode <" + RDF.type + "> ?conceptSemanticTypeURI ." +
|
||||||
"?conceptSemanticTypeURI <" + RDFS.label.getURI() + "> ?conceptSemanticTypeLabel ." +
|
"?conceptSemanticTypeURI <" + RDFS.label.getURI() + "> ?conceptSemanticTypeLabel ." +
|
||||||
"?conceptSemanticTypeURI <" + RDFS.subClassOf + "> <" + SKOSConceptType + "> ."
|
"?conceptSemanticTypeURI <" + RDFS.subClassOf + "> <" + SKOSConceptType + "> .",
|
||||||
|
"?conceptNode <" + this.SKOSNarrowerURI + "> ?conceptNarrowerURI ." +
|
||||||
|
"?conceptNarrowerURI <" + this.SKOSBroaderURI + "> ?conceptNode .",
|
||||||
|
"?conceptNode <" + this.SKOSBroaderURI + "> ?conceptBroaderURI ." +
|
||||||
|
"?conceptBroaderURI <" + this.SKOSNarrowerURI + "> ?conceptNode ."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,6 +261,8 @@ public class AddAssociatedConceptGenerator extends VivoBaseGenerator implements
|
||||||
urisOnForm.add("conceptNode");
|
urisOnForm.add("conceptNode");
|
||||||
urisOnForm.add("conceptSource");
|
urisOnForm.add("conceptSource");
|
||||||
urisOnForm.add("conceptSemanticTypeURI");
|
urisOnForm.add("conceptSemanticTypeURI");
|
||||||
|
urisOnForm.add("conceptBroaderURI");
|
||||||
|
urisOnForm.add("conceptNarrowerURI");
|
||||||
editConfiguration.setUrisOnform(urisOnForm);
|
editConfiguration.setUrisOnform(urisOnForm);
|
||||||
//Also need to add the label of the concept
|
//Also need to add the label of the concept
|
||||||
literalsOnForm.add("conceptLabel");
|
literalsOnForm.add("conceptLabel");
|
||||||
|
@ -288,8 +297,23 @@ public class AddAssociatedConceptGenerator extends VivoBaseGenerator implements
|
||||||
setVocabURIField(editConfiguration, vreq);
|
setVocabURIField(editConfiguration, vreq);
|
||||||
setConceptSemanticTypeURIField(editConfiguration,vreq);
|
setConceptSemanticTypeURIField(editConfiguration,vreq);
|
||||||
setConceptSemanticTypeLabelField(editConfiguration,vreq);
|
setConceptSemanticTypeLabelField(editConfiguration,vreq);
|
||||||
|
setConceptBroaderURIField(editConfiguration, vreq);
|
||||||
|
setConceptNarrowerURIField(editConfiguration, vreq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setConceptNarrowerURIField(
|
||||||
|
EditConfigurationVTwo editConfiguration, VitroRequest vreq) {
|
||||||
|
editConfiguration.addField(new FieldVTwo().
|
||||||
|
setName("conceptNarrowerURI"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setConceptBroaderURIField(
|
||||||
|
EditConfigurationVTwo editConfiguration, VitroRequest vreq) {
|
||||||
|
editConfiguration.addField(new FieldVTwo().
|
||||||
|
setName("conceptBroaderURI"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//this field will be hidden and include the concept node URI
|
//this field will be hidden and include the concept node URI
|
||||||
private void setConceptNodeField(EditConfigurationVTwo editConfiguration,
|
private void setConceptNodeField(EditConfigurationVTwo editConfiguration,
|
||||||
VitroRequest vreq) {
|
VitroRequest vreq) {
|
||||||
|
@ -335,14 +359,17 @@ public class AddAssociatedConceptGenerator extends VivoBaseGenerator implements
|
||||||
|
|
||||||
//Add preprocessor
|
//Add preprocessor
|
||||||
|
|
||||||
private void addPreprocessors(EditConfigurationVTwo editConfiguration, OntModel ontModel, OntModel modelChangeModel) {
|
private void addPreprocessors(EditConfigurationVTwo editConfiguration,
|
||||||
|
OntModel ontModel,
|
||||||
|
OntModel modelChangeModel,
|
||||||
|
WebappDaoFactory wdf) {
|
||||||
//An Edit submission preprocessor for enabling addition of multiple terms for a single search
|
//An Edit submission preprocessor for enabling addition of multiple terms for a single search
|
||||||
//TODO: Check if this is the appropriate way of getting model
|
//TODO: Check if this is the appropriate way of getting model
|
||||||
|
|
||||||
//Passing model to check for any URIs that are present
|
//Passing model to check for any URIs that are present
|
||||||
|
|
||||||
editConfiguration.addEditSubmissionPreprocessor(
|
editConfiguration.addEditSubmissionPreprocessor(
|
||||||
new AddAssociatedConceptsPreprocessor(editConfiguration, ontModel));
|
new AddAssociatedConceptsPreprocessor(editConfiguration, ontModel, wdf));
|
||||||
editConfiguration.addModelChangePreprocessor(new ConceptSemanticTypesPreprocessor(
|
editConfiguration.addModelChangePreprocessor(new ConceptSemanticTypesPreprocessor(
|
||||||
modelChangeModel));
|
modelChangeModel));
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
@ -27,6 +28,8 @@ import com.hp.hpl.jena.vocabulary.RDFS;
|
||||||
import com.hp.hpl.jena.vocabulary.XSD;
|
import com.hp.hpl.jena.vocabulary.XSD;
|
||||||
|
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||||
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.BaseEditSubmissionPreprocessorVTwo;
|
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.BaseEditSubmissionPreprocessorVTwo;
|
||||||
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationUtils;
|
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationUtils;
|
||||||
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
|
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo;
|
||||||
|
@ -38,8 +41,8 @@ public class AddAssociatedConceptsPreprocessor extends
|
||||||
|
|
||||||
protected static final Log log = LogFactory
|
protected static final Log log = LogFactory
|
||||||
.getLog(AddAssociatedConceptsPreprocessor.class.getName());
|
.getLog(AddAssociatedConceptsPreprocessor.class.getName());
|
||||||
//TODO: Check if better way to do this?
|
|
||||||
protected OntModel ontModel = null;
|
protected OntModel ontModel = null;
|
||||||
|
protected WebappDaoFactory wdf = null;
|
||||||
// Field names/variables names for n3 - these will have numbers added as
|
// Field names/variables names for n3 - these will have numbers added as
|
||||||
// suffix if more than one term
|
// suffix if more than one term
|
||||||
private static String conceptNodeBase = "conceptNode";
|
private static String conceptNodeBase = "conceptNode";
|
||||||
|
@ -47,6 +50,9 @@ public class AddAssociatedConceptsPreprocessor extends
|
||||||
private static String labelBase = "conceptLabel";
|
private static String labelBase = "conceptLabel";
|
||||||
private static String conceptSemanticTypeLabelBase = "conceptSemanticTypeLabel";
|
private static String conceptSemanticTypeLabelBase = "conceptSemanticTypeLabel";
|
||||||
private static String conceptSemanticTypeURIBase = "conceptSemanticTypeURI";
|
private static String conceptSemanticTypeURIBase = "conceptSemanticTypeURI";
|
||||||
|
private static String conceptBroaderURIBase = "conceptBroaderURI";
|
||||||
|
private static String conceptNarrowerURIBase = "conceptNarrowerURI";
|
||||||
|
|
||||||
//keyed off label variable, specifies which uri variable should be used, useful if same label repeated twice
|
//keyed off label variable, specifies which uri variable should be used, useful if same label repeated twice
|
||||||
private HashMap<String, String> labelVarToUriVarHash = null;
|
private HashMap<String, String> labelVarToUriVarHash = null;
|
||||||
private HashMap<String, List<String>> conceptSemanticTypeURIVarToValueMap = null;
|
private HashMap<String, List<String>> conceptSemanticTypeURIVarToValueMap = null;
|
||||||
|
@ -56,15 +62,21 @@ public class AddAssociatedConceptsPreprocessor extends
|
||||||
private static String conceptSourceValues = null;
|
private static String conceptSourceValues = null;
|
||||||
private static String conceptSemanticTypeLabelValues = null;
|
private static String conceptSemanticTypeLabelValues = null;
|
||||||
private static String conceptSemanticTypeURIValues = null;
|
private static String conceptSemanticTypeURIValues = null;
|
||||||
|
private static List<String> conceptBroaderURIValues = null;
|
||||||
|
private static List<String> conceptNarrowerURIValues = null;
|
||||||
private static MultiValueEditSubmission submission = null;
|
private static MultiValueEditSubmission submission = null;
|
||||||
|
|
||||||
|
private static String SKOSBroaderURI = "http://www.w3.org/2004/02/skos/core#broader";
|
||||||
|
private static String SKOSNarrowerURI = "http://www.w3.org/2004/02/skos/core#narrower";
|
||||||
|
|
||||||
// String datatype
|
// String datatype
|
||||||
|
|
||||||
// Will be editing the edit configuration as well as edit submission here
|
// Will be editing the edit configuration as well as edit submission here
|
||||||
|
|
||||||
public AddAssociatedConceptsPreprocessor(EditConfigurationVTwo editConfig, OntModel ontModel) {
|
public AddAssociatedConceptsPreprocessor(EditConfigurationVTwo editConfig, OntModel ontModel, WebappDaoFactory wadf) {
|
||||||
super(editConfig);
|
super(editConfig);
|
||||||
this.ontModel = ontModel;
|
this.ontModel = ontModel;
|
||||||
|
this.wdf = wadf;
|
||||||
this.labelVarToUriVarHash = new HashMap<String, String>();
|
this.labelVarToUriVarHash = new HashMap<String, String>();
|
||||||
//Saves values of concept type uris
|
//Saves values of concept type uris
|
||||||
this.conceptSemanticTypeURIVarToValueMap = new HashMap<String, List<String>>();
|
this.conceptSemanticTypeURIVarToValueMap = new HashMap<String, List<String>>();
|
||||||
|
@ -86,6 +98,7 @@ public class AddAssociatedConceptsPreprocessor extends
|
||||||
processConceptSemanticValues();
|
processConceptSemanticValues();
|
||||||
//Also need to see if any broader or narrower uris for the concepts that already exist in the system
|
//Also need to see if any broader or narrower uris for the concepts that already exist in the system
|
||||||
//and set up the appropriate relationships between this concept and the broader/narrower uri
|
//and set up the appropriate relationships between this concept and the broader/narrower uri
|
||||||
|
getExistingConceptRelationships();
|
||||||
if (numberConcepts > 1) {
|
if (numberConcepts > 1) {
|
||||||
processConceptNodes(numberConcepts);
|
processConceptNodes(numberConcepts);
|
||||||
}
|
}
|
||||||
|
@ -96,6 +109,8 @@ public class AddAssociatedConceptsPreprocessor extends
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Since we will change the uris and literals from form, we should make copies
|
//Since we will change the uris and literals from form, we should make copies
|
||||||
//of the original values and store them, this will also make iterations
|
//of the original values and store them, this will also make iterations
|
||||||
//and updates to the submission independent from accessing the values
|
//and updates to the submission independent from accessing the values
|
||||||
|
@ -103,11 +118,104 @@ public class AddAssociatedConceptsPreprocessor extends
|
||||||
conceptLabelValues = getConceptLabelValues();
|
conceptLabelValues = getConceptLabelValues();
|
||||||
conceptNodeValues = getConceptNodeValues();
|
conceptNodeValues = getConceptNodeValues();
|
||||||
conceptSourceValues = getConceptSourceValues();
|
conceptSourceValues = getConceptSourceValues();
|
||||||
|
conceptBroaderURIValues = getConceptBroaderURIValues();
|
||||||
|
conceptNarrowerURIValues = getConceptNarrowerURIValues();
|
||||||
log.debug("concept label values are " + conceptLabelValues);
|
log.debug("concept label values are " + conceptLabelValues);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
|
//For broader and narrower relationships, we will be
|
||||||
|
//linking the concept to broader and narrower terms where those terms already
|
||||||
|
//exist in the system
|
||||||
|
//This method or approach may change later in which case this method should change
|
||||||
|
private void getExistingConceptRelationships() {
|
||||||
|
List<String> existingNarrowerURIs = getExistingNarrowerURIs(conceptNarrowerURIValues);
|
||||||
|
List<String> existingBroaderURIs = getExistingBroaderURIs(conceptBroaderURIValues);
|
||||||
|
//Now set the submission values to these, overwriting the original
|
||||||
|
Map<String, List<String>> urisFromForm = submission.getUrisFromForm();
|
||||||
|
if(existingNarrowerURIs.size() > 0) {
|
||||||
|
urisFromForm.put("conceptNarrowerURI", existingNarrowerURIs);
|
||||||
|
} else {
|
||||||
|
//The original code for submission wouldn't put in a key if the values were null or size 0
|
||||||
|
urisFromForm.remove("conceptNarrowerURI");
|
||||||
|
}
|
||||||
|
if(existingBroaderURIs.size() > 0) {
|
||||||
|
urisFromForm.put("conceptBroaderURI", existingBroaderURIs);
|
||||||
|
} else {
|
||||||
|
urisFromForm.remove("conceptBroaderURI");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the broader and narrower uri values that already exist in the system from the ones returned in the search
|
||||||
|
//and use those to populate relationships between the concept and other concepts already in the system
|
||||||
|
//We should also make sure to use bidirectional n3 so the graph has both sets of relationships represented
|
||||||
|
private List<String> getConceptNarrowerURIValues() {
|
||||||
|
Map<String, List<String>> urisFromForm = submission.getUrisFromForm();
|
||||||
|
List<String> narrowerURIs = urisFromForm.get("conceptNarrowerURI");
|
||||||
|
return narrowerURIs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getConceptBroaderURIValues() {
|
||||||
|
Map<String, List<String>> urisFromForm = submission.getUrisFromForm();
|
||||||
|
List<String> broaderURIs = urisFromForm.get("conceptBroaderURI");
|
||||||
|
return broaderURIs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getExistingBroaderURIs(List<String> broaderURIs) {
|
||||||
|
if(broaderURIs == null) {
|
||||||
|
return new ArrayList<String>();
|
||||||
|
}
|
||||||
|
List<String> existingBroaderURIs = this.getExistingURIs(broaderURIs);
|
||||||
|
return existingBroaderURIs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getExistingNarrowerURIs(List<String> narrowerURIs) {
|
||||||
|
if(narrowerURIs == null)
|
||||||
|
return new ArrayList<String>();
|
||||||
|
List<String> existingNarrowerURIs = this.getExistingURIs(narrowerURIs);
|
||||||
|
return existingNarrowerURIs;
|
||||||
|
}
|
||||||
|
|
||||||
|
//We need to keep the number of elements the same if there are any entries at all in the original
|
||||||
|
//So we will use an empty string or null
|
||||||
|
private List<String> getExistingURIs(List<String> uris) {
|
||||||
|
//Important to keep the same formatting as original, because a comma delimited string as an element in the array
|
||||||
|
//refers to a list of uris appropriate for a given concept, where each element in the array corresponds to a different
|
||||||
|
//concept
|
||||||
|
List<String> existingURIs = new ArrayList<String>();
|
||||||
|
for(String uri:uris) {
|
||||||
|
if(uri.indexOf(",") != -1) {
|
||||||
|
List<String> existingURISet = new ArrayList<String>();
|
||||||
|
String[] uriSet = uri.split(",");
|
||||||
|
for(String u: uriSet) {
|
||||||
|
if(u != null && !u.isEmpty() && this.wdf.hasExistingURI(u)) {
|
||||||
|
existingURISet.add(u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Now add the comma delimited version back to the array
|
||||||
|
if(existingURISet.size() > 0) {
|
||||||
|
existingURIs.add(StringUtils.join(existingURISet, ","));
|
||||||
|
} else {
|
||||||
|
//add empty string to indicate no value here
|
||||||
|
existingURIs.add("");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(uri != null && !uri.isEmpty() && this.wdf.hasExistingURI(uri)) {
|
||||||
|
existingURIs.add(uri);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
existingURIs.add("");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return existingURIs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Process the semantic type label and URI values for the concepts
|
||||||
private void processConceptSemanticValues() {
|
private void processConceptSemanticValues() {
|
||||||
conceptSemanticTypeLabelValues = getConceptSemanticTypeLabelValues();
|
conceptSemanticTypeLabelValues = getConceptSemanticTypeLabelValues();
|
||||||
conceptSemanticTypeURIValues = getConceptSemanticTypeURIValues();
|
conceptSemanticTypeURIValues = getConceptSemanticTypeURIValues();
|
||||||
|
@ -183,10 +291,10 @@ public class AddAssociatedConceptsPreprocessor extends
|
||||||
addConceptSourceInputs(numberConcepts);
|
addConceptSourceInputs(numberConcepts);
|
||||||
addConceptLabelInputs(numberConcepts);
|
addConceptLabelInputs(numberConcepts);
|
||||||
//for concept semantic type labels and uris where they exist
|
//for concept semantic type labels and uris where they exist
|
||||||
//TODO: Make into single method as URIs depend on labels
|
|
||||||
addConceptSemanticTypeLabelAndURIInputs(numberConcepts);
|
addConceptSemanticTypeLabelAndURIInputs(numberConcepts);
|
||||||
//addConceptSemanticTypeURIInputs(numberConcepts);
|
//For broader and narrower uris where they exist (this of course is in the case of multiple broader and narrower uris
|
||||||
|
addConceptBroaderURIInputs(numberConcepts);
|
||||||
|
addConceptNarrowerURIInputs(numberConcepts);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addConceptNodeInputs(int numberConcepts) {
|
private void addConceptNodeInputs(int numberConcepts) {
|
||||||
|
@ -301,28 +409,51 @@ public class AddAssociatedConceptsPreprocessor extends
|
||||||
String[] uriValuesArray = uriVals.toArray(new String[uriVals.size()]);
|
String[] uriValuesArray = uriVals.toArray(new String[uriVals.size()]);
|
||||||
submission.addUriToForm(editConfiguration, uriInputName, uriValuesArray);
|
submission.addUriToForm(editConfiguration, uriInputName, uriValuesArray);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addConceptBroaderURIInputs(int numberConcepts) {
|
||||||
//the number of existing values may not match up, or at least existing populated ones
|
int i;
|
||||||
/*
|
//Add inputs based on if there are any broader uris to add
|
||||||
if(conceptSemanticTypeURIs != null && conceptSemanticTypeURIs.length == numberConcepts) {
|
//Can't really compare number of existing broader uris to concepts
|
||||||
int i;
|
//as each concept may or may not have a broader uri
|
||||||
|
if(this.conceptBroaderURIValues.size() > 0 && this.conceptBroaderURIValues.size() <= numberConcepts) {
|
||||||
for(i = 0; i < numberConcepts; i++) {
|
for(i = 0; i < numberConcepts; i++) {
|
||||||
int suffix = i + 1;
|
int suffix = i + 1;
|
||||||
String conceptInputName = conceptSemanticTypeURIBase + suffix;
|
String conceptBroaderURIInputName = conceptBroaderURIBase + suffix;
|
||||||
String[] uriValues = new String[1];
|
String broaderURIs = this.conceptBroaderURIValues.get(i);
|
||||||
uriValues[0] = conceptSemanticTypeURIs[i];
|
if(broaderURIs != null && !broaderURIs.isEmpty()) {
|
||||||
//Add value for uri to form
|
String[] broaderURISet = new String[1];
|
||||||
//TODO: Check if value is empty in which case don't add to submission
|
if(broaderURIs.indexOf(",") != -1) {
|
||||||
submission.addUriToForm(editConfiguration, conceptInputName, uriValues);
|
broaderURISet = broaderURIs.split(",");
|
||||||
|
} else {
|
||||||
|
broaderURISet[0] = broaderURIs;
|
||||||
|
}
|
||||||
|
//Add value for uri to form
|
||||||
|
submission.addUriToForm(editConfiguration, conceptBroaderURIInputName, broaderURISet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if(conceptSemanticTypeURIs != null && conceptSemanticTypeURIs.length != numberConcepts){
|
|
||||||
log.error("Number of concept nodes did not match the number of concepts to be added");
|
|
||||||
} else{
|
|
||||||
log.error("Concept nodes returned were null");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
}
|
||||||
|
private void addConceptNarrowerURIInputs(int numberConcepts) {
|
||||||
|
int i;
|
||||||
|
if(this.conceptNarrowerURIValues.size() > 0 && this.conceptNarrowerURIValues.size() <= numberConcepts) {
|
||||||
|
for(i = 0; i < numberConcepts; i++) {
|
||||||
|
int suffix = i + 1;
|
||||||
|
String conceptNarrowerURIInputName = conceptNarrowerURIBase + suffix;
|
||||||
|
String narrowerURIs = this.conceptNarrowerURIValues.get(i);
|
||||||
|
if(narrowerURIs != null && !narrowerURIs.isEmpty()) {
|
||||||
|
String[] narrowerURISet = new String[1];
|
||||||
|
if(narrowerURIs.indexOf(",") != -1) {
|
||||||
|
narrowerURISet = narrowerURIs.split(",");
|
||||||
|
} else {
|
||||||
|
narrowerURISet[0] = narrowerURIs;
|
||||||
|
}
|
||||||
|
//Add value for uri to form
|
||||||
|
submission.addUriToForm(editConfiguration, conceptNarrowerURIInputName, narrowerURISet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Fields
|
//Fields
|
||||||
|
@ -340,7 +471,8 @@ public class AddAssociatedConceptsPreprocessor extends
|
||||||
String source = sourceBase + suffix;
|
String source = sourceBase + suffix;
|
||||||
String conceptSemanticTypeLabel = conceptSemanticTypeLabelBase + suffix;
|
String conceptSemanticTypeLabel = conceptSemanticTypeLabelBase + suffix;
|
||||||
String conceptSemanticTypeURI = this.getConceptSemanticTypeURIFieldName(conceptSemanticTypeLabel, suffix);
|
String conceptSemanticTypeURI = this.getConceptSemanticTypeURIFieldName(conceptSemanticTypeLabel, suffix);
|
||||||
|
String conceptBroaderURI = conceptBroaderURIBase + suffix;
|
||||||
|
String conceptNarrowerURI = conceptNarrowerURIBase + suffix;
|
||||||
addConceptNodeField(conceptNode);
|
addConceptNodeField(conceptNode);
|
||||||
addLabelField(label);
|
addLabelField(label);
|
||||||
addSourceField(source);
|
addSourceField(source);
|
||||||
|
@ -351,9 +483,15 @@ public class AddAssociatedConceptsPreprocessor extends
|
||||||
conceptSemanticTypeUris.add(conceptSemanticTypeURI);
|
conceptSemanticTypeUris.add(conceptSemanticTypeURI);
|
||||||
addConceptSemanticTypeURIField(conceptSemanticTypeURI);
|
addConceptSemanticTypeURIField(conceptSemanticTypeURI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//add fields for concept broader and narrower uris
|
||||||
|
addConceptBroaderURIField(conceptBroaderURI);
|
||||||
|
addConceptNarrowerURIField(conceptNarrowerURI);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void addConceptNodeField(String conceptNode) {
|
private void addConceptNodeField(String conceptNode) {
|
||||||
List<String> validators = new ArrayList<String>();
|
List<String> validators = new ArrayList<String>();
|
||||||
validators.add("nonempty");
|
validators.add("nonempty");
|
||||||
|
@ -394,6 +532,17 @@ public class AddAssociatedConceptsPreprocessor extends
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addConceptNarrowerURIField(String conceptNarrowerURI) {
|
||||||
|
editConfiguration.addField(new FieldVTwo().
|
||||||
|
setName(conceptNarrowerURI));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addConceptBroaderURIField(String conceptBroaderURI) {
|
||||||
|
editConfiguration.addField(new FieldVTwo().
|
||||||
|
setName(conceptBroaderURI));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//original literals on form: label, uris on form: conceptNode and conceptSource
|
//original literals on form: label, uris on form: conceptNode and conceptSource
|
||||||
//This will overwrite the original values in the edit configuration
|
//This will overwrite the original values in the edit configuration
|
||||||
|
@ -412,12 +561,16 @@ public class AddAssociatedConceptsPreprocessor extends
|
||||||
String conceptSemanticTypeLabel = conceptSemanticTypeLabelBase + suffix;
|
String conceptSemanticTypeLabel = conceptSemanticTypeLabelBase + suffix;
|
||||||
//String conceptSemanticTypeURI = conceptSemanticTypeURIBase + suffix;
|
//String conceptSemanticTypeURI = conceptSemanticTypeURIBase + suffix;
|
||||||
String conceptSemanticTypeURI = this.getConceptSemanticTypeURIFieldName(conceptSemanticTypeLabel, suffix);
|
String conceptSemanticTypeURI = this.getConceptSemanticTypeURIFieldName(conceptSemanticTypeLabel, suffix);
|
||||||
|
String conceptBroaderURI = conceptBroaderURIBase + suffix;
|
||||||
|
String conceptNarrowerURI = conceptNarrowerURIBase + suffix;
|
||||||
urisOnForm.add(conceptNode);
|
urisOnForm.add(conceptNode);
|
||||||
urisOnForm.add(source);
|
urisOnForm.add(source);
|
||||||
if(!conceptSemanticTypeURIs.contains(conceptSemanticTypeURI)) {
|
if(!conceptSemanticTypeURIs.contains(conceptSemanticTypeURI)) {
|
||||||
conceptSemanticTypeURIs.add(conceptSemanticTypeURI);
|
conceptSemanticTypeURIs.add(conceptSemanticTypeURI);
|
||||||
urisOnForm.add(conceptSemanticTypeURI);
|
urisOnForm.add(conceptSemanticTypeURI);
|
||||||
}
|
}
|
||||||
|
urisOnForm.add(conceptBroaderURI);
|
||||||
|
urisOnForm.add(conceptNarrowerURI);
|
||||||
literalsOnForm.add(label);
|
literalsOnForm.add(label);
|
||||||
literalsOnForm.add(conceptSemanticTypeLabel);
|
literalsOnForm.add(conceptSemanticTypeLabel);
|
||||||
}
|
}
|
||||||
|
@ -456,10 +609,13 @@ public class AddAssociatedConceptsPreprocessor extends
|
||||||
String labelVar = "?" + labelBase;
|
String labelVar = "?" + labelBase;
|
||||||
String sourceVar = "?" + sourceBase;
|
String sourceVar = "?" + sourceBase;
|
||||||
String conceptSemanticTypeLabelVar = "?" + conceptSemanticTypeLabelBase;
|
String conceptSemanticTypeLabelVar = "?" + conceptSemanticTypeLabelBase;
|
||||||
|
String conceptBroaderURIVar = "?" + conceptBroaderURIBase;
|
||||||
|
String conceptNarrowerURIVar = "?" + conceptNarrowerURIBase;
|
||||||
String prefixStr = "@prefix core: <http://vivoweb.org/ontology/core#> .";
|
String prefixStr = "@prefix core: <http://vivoweb.org/ontology/core#> .";
|
||||||
// First one already included so add new ones here
|
// First one already included so add new ones here
|
||||||
//We already have a label var to uri var setup
|
//We already have a label var to uri var setup
|
||||||
for (index = 1; index <= numberConcepts; index++) {
|
for (index = 1; index <= numberConcepts; index++) {
|
||||||
|
//Set up the variables based on which concept node
|
||||||
int suffix = index;
|
int suffix = index;
|
||||||
String node = nodeBase + suffix;
|
String node = nodeBase + suffix;
|
||||||
String label = labelVar + suffix;
|
String label = labelVar + suffix;
|
||||||
|
@ -467,7 +623,9 @@ public class AddAssociatedConceptsPreprocessor extends
|
||||||
String conceptSemanticTypeLabel = conceptSemanticTypeLabelVar + suffix;
|
String conceptSemanticTypeLabel = conceptSemanticTypeLabelVar + suffix;
|
||||||
//get the URI appropriate for the concept semantic type label var
|
//get the URI appropriate for the concept semantic type label var
|
||||||
String conceptSemanticTypeURI = getConceptSemanticTypeURIVar(conceptSemanticTypeLabelBase + suffix, suffix);
|
String conceptSemanticTypeURI = getConceptSemanticTypeURIVar(conceptSemanticTypeLabelBase + suffix, suffix);
|
||||||
//onceptSemanticTypeURIVar + suffix;
|
String conceptBroaderURI = conceptBroaderURIVar + suffix;
|
||||||
|
String conceptNarrowerURI = conceptNarrowerURIVar + suffix;
|
||||||
|
//Set up the n3 strings
|
||||||
String n3String = prefixStr;
|
String n3String = prefixStr;
|
||||||
n3String += node + " <" + RDFS.label.getURI() + "> " + label + " .\n" +
|
n3String += node + " <" + RDFS.label.getURI() + "> " + label + " .\n" +
|
||||||
node + " <" + RDFS.isDefinedBy.getURI() + "> " + source + " .";
|
node + " <" + RDFS.isDefinedBy.getURI() + "> " + source + " .";
|
||||||
|
@ -475,10 +633,17 @@ public class AddAssociatedConceptsPreprocessor extends
|
||||||
n3ConceptTypeString += node + " <" + RDF.type.getURI() + "> " + conceptSemanticTypeURI + " ." +
|
n3ConceptTypeString += node + " <" + RDF.type.getURI() + "> " + conceptSemanticTypeURI + " ." +
|
||||||
conceptSemanticTypeURI + " <" + RDFS.label.getURI() + "> " + conceptSemanticTypeLabel + " .\n" +
|
conceptSemanticTypeURI + " <" + RDFS.label.getURI() + "> " + conceptSemanticTypeLabel + " .\n" +
|
||||||
conceptSemanticTypeURI + " <" + RDFS.subClassOf.getURI() + "> <http://www.w3.org/2004/02/skos/core#Concept> .\n" ;
|
conceptSemanticTypeURI + " <" + RDFS.subClassOf.getURI() + "> <http://www.w3.org/2004/02/skos/core#Concept> .\n" ;
|
||||||
|
//String representing the broader and narrower uri(s) for each of the concepts - these may or may not exist
|
||||||
|
String n3ConceptBroaderURI = prefixStr + node + " <" + this.SKOSNarrowerURI + "> " + conceptNarrowerURI + " ." +
|
||||||
|
conceptNarrowerURI + " <" + this.SKOSBroaderURI + "> " + node + " .";
|
||||||
|
String n3ConceptNarrowerURI = prefixStr + node + " <" + this.SKOSBroaderURI + "> " + conceptBroaderURI + " ." +
|
||||||
|
conceptBroaderURI + " <" + this.SKOSNarrowerURI + "> " + node + " .";
|
||||||
|
|
||||||
n3Optional.add(n3String);
|
n3Optional.add(n3String);
|
||||||
//adding separately so their resolution does not depend on each other
|
//adding separately so their resolution does not depend on each other
|
||||||
n3Optional.add(n3ConceptTypeString);
|
n3Optional.add(n3ConceptTypeString);
|
||||||
|
n3Optional.add(n3ConceptBroaderURI);
|
||||||
|
n3Optional.add(n3ConceptNarrowerURI);
|
||||||
|
|
||||||
}
|
}
|
||||||
//Already have n3 required so need to add to that
|
//Already have n3 required so need to add to that
|
||||||
|
@ -536,86 +701,93 @@ public class AddAssociatedConceptsPreprocessor extends
|
||||||
private String getConceptSemanticTypeLabelValues() {
|
private String getConceptSemanticTypeLabelValues() {
|
||||||
Map<String, List<Literal>> literalsFromForm = submission.getLiteralsFromForm();
|
Map<String, List<Literal>> literalsFromForm = submission.getLiteralsFromForm();
|
||||||
Map<String, List<String>> transformed = EditConfigurationUtils.transformLiteralMap(literalsFromForm);
|
Map<String, List<String>> transformed = EditConfigurationUtils.transformLiteralMap(literalsFromForm);
|
||||||
return (String) getFirstElement(transformed.get("conceptSemanticTypeLabel"));
|
String label = (String) getFirstElement(transformed.get("conceptSemanticTypeLabel"));
|
||||||
|
if(label == null) {
|
||||||
|
label = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
//This will either generate or retrieve URIs for the concept semantic type labels if they exist
|
//This will either generate or retrieve URIs for the concept semantic type labels if they exist
|
||||||
//We will then update the submission to include this
|
//We will then update the submission to include this
|
||||||
private String getConceptSemanticTypeURIValues() {
|
private String getConceptSemanticTypeURIValues() {
|
||||||
String[] conceptSemanticTypeLabels = convertDelimitedStringToArray(conceptSemanticTypeLabelValues);
|
|
||||||
//keep track of what label values already exist and to which label variables they map
|
|
||||||
HashMap<String, List<Integer>> labelValueToVarSuffix = new HashMap<String, List<Integer>>();
|
|
||||||
int numberLabels = conceptSemanticTypeLabels.length;
|
|
||||||
String pseudoInputString = "";
|
String pseudoInputString = "";
|
||||||
|
if(conceptSemanticTypeLabelValues != null && !conceptSemanticTypeLabelValues.isEmpty()) {
|
||||||
|
String[] conceptSemanticTypeLabels = convertDelimitedStringToArray(conceptSemanticTypeLabelValues);
|
||||||
|
//keep track of what label values already exist and to which label variables they map
|
||||||
|
HashMap<String, List<Integer>> labelValueToVarSuffix = new HashMap<String, List<Integer>>();
|
||||||
|
int numberLabels = conceptSemanticTypeLabels.length;
|
||||||
|
|
||||||
//The rest of this code is really only relevant for multiple values, so we could break out the old code above
|
//The rest of this code is really only relevant for multiple values, so we could break out the old code above
|
||||||
//as we don't need to set up hashes etc. if there is only one concept node being added
|
//as we don't need to set up hashes etc. if there is only one concept node being added
|
||||||
if(numberLabels == 1) {
|
if(numberLabels == 1) {
|
||||||
String label = conceptSemanticTypeLabels[0];
|
String label = conceptSemanticTypeLabels[0];
|
||||||
String uri = getURIForSemanticTypeLabel(label);
|
|
||||||
if(uri != "") {
|
|
||||||
String[] urisToAdd = new String[1];
|
|
||||||
urisToAdd[0] = uri;
|
|
||||||
pseudoInputString = uri;
|
|
||||||
log.debug("uris to add" + uri);
|
|
||||||
submission.addUriToForm(this.editConfiguration, "conceptSemanticTypeURI", urisToAdd);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
//if there is more than one concept node, we may have duplicate semantic types
|
|
||||||
//which will need to be referred to by the same semantic type uri
|
|
||||||
else if (numberLabels > 1){
|
|
||||||
|
|
||||||
for(int i = 0; i < numberLabels; i++) {
|
|
||||||
int suffix = i + 1;
|
|
||||||
String label = conceptSemanticTypeLabels[i];
|
|
||||||
String labelVar = this.conceptSemanticTypeLabelBase + suffix;
|
|
||||||
//if label has not already been encountered, create entry for label value
|
|
||||||
//and list with the label variables that would refer to it
|
|
||||||
//for unique values, the uri variable will be the same as label
|
|
||||||
Integer thisSuffix = new Integer(suffix);
|
|
||||||
if(!labelValueToVarSuffix.containsKey(label)) {
|
|
||||||
labelValueToVarSuffix.put(label, new ArrayList<Integer>());
|
|
||||||
//Add suffix to list if not already there
|
|
||||||
labelValueToVarSuffix.get(label).add(thisSuffix);
|
|
||||||
} else {
|
|
||||||
//in this case, the label already exists, get the very first element in the list
|
|
||||||
//and use that as the uri variable
|
|
||||||
List<Integer> suffixList = labelValueToVarSuffix.get(label);
|
|
||||||
if(suffixList != null && suffixList.size() > 0) {
|
|
||||||
thisSuffix = suffixList.get(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//Now add the uri var to the hash mapping label variable to uri variable
|
|
||||||
String uriVar = this.conceptSemanticTypeURIBase + thisSuffix.intValue();
|
|
||||||
this.labelVarToUriVarHash.put(labelVar, uriVar);
|
|
||||||
|
|
||||||
|
|
||||||
//Make or retrieve URI for this label
|
|
||||||
//TODO: Do we create this string with empty inputs ?
|
|
||||||
String uri = getURIForSemanticTypeLabel(label);
|
String uri = getURIForSemanticTypeLabel(label);
|
||||||
if(uri != "") {
|
if(uri != "") {
|
||||||
//uri var shouldn't be repeated?
|
String[] urisToAdd = new String[1];
|
||||||
if(!this.conceptSemanticTypeURIVarToValueMap.containsKey(uriVar)) {
|
urisToAdd[0] = uri;
|
||||||
this.conceptSemanticTypeURIVarToValueMap.put(uriVar, new ArrayList<String>());
|
pseudoInputString = uri;
|
||||||
this.conceptSemanticTypeURIVarToValueMap.get(uriVar).add(uri);
|
log.debug("uris to add" + uri);
|
||||||
}
|
submission.addUriToForm(this.editConfiguration, "conceptSemanticTypeURI", urisToAdd);
|
||||||
}
|
}
|
||||||
if(i != 0) {
|
|
||||||
pseudoInputString += ",";
|
|
||||||
}
|
|
||||||
pseudoInputString += uri;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
//if there is more than one concept node, we may have duplicate semantic types
|
||||||
|
//which will need to be referred to by the same semantic type uri
|
||||||
|
else if (numberLabels > 1){
|
||||||
|
|
||||||
//Add this string to the uris for the form
|
for(int i = 0; i < numberLabels; i++) {
|
||||||
String[] urisToAdd = new String[1];
|
int suffix = i + 1;
|
||||||
urisToAdd[0] = pseudoInputString;
|
String label = conceptSemanticTypeLabels[i];
|
||||||
log.debug("uris to add" + pseudoInputString);
|
String labelVar = this.conceptSemanticTypeLabelBase + suffix;
|
||||||
submission.addUriToForm(this.editConfiguration, "conceptSemanticTypeURI", urisToAdd);
|
//if label has not already been encountered, create entry for label value
|
||||||
|
//and list with the label variables that would refer to it
|
||||||
|
//for unique values, the uri variable will be the same as label
|
||||||
|
Integer thisSuffix = new Integer(suffix);
|
||||||
|
if(!labelValueToVarSuffix.containsKey(label)) {
|
||||||
|
labelValueToVarSuffix.put(label, new ArrayList<Integer>());
|
||||||
|
//Add suffix to list if not already there
|
||||||
|
labelValueToVarSuffix.get(label).add(thisSuffix);
|
||||||
|
} else {
|
||||||
|
//in this case, the label already exists, get the very first element in the list
|
||||||
|
//and use that as the uri variable
|
||||||
|
List<Integer> suffixList = labelValueToVarSuffix.get(label);
|
||||||
|
if(suffixList != null && suffixList.size() > 0) {
|
||||||
|
thisSuffix = suffixList.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Now add the uri var to the hash mapping label variable to uri variable
|
||||||
|
String uriVar = this.conceptSemanticTypeURIBase + thisSuffix.intValue();
|
||||||
|
this.labelVarToUriVarHash.put(labelVar, uriVar);
|
||||||
|
|
||||||
|
|
||||||
|
//Make or retrieve URI for this label
|
||||||
|
//TODO: Do we create this string with empty inputs ?
|
||||||
|
String uri = getURIForSemanticTypeLabel(label);
|
||||||
|
if(uri != "") {
|
||||||
|
//uri var shouldn't be repeated?
|
||||||
|
if(!this.conceptSemanticTypeURIVarToValueMap.containsKey(uriVar)) {
|
||||||
|
this.conceptSemanticTypeURIVarToValueMap.put(uriVar, new ArrayList<String>());
|
||||||
|
this.conceptSemanticTypeURIVarToValueMap.get(uriVar).add(uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(i != 0) {
|
||||||
|
pseudoInputString += ",";
|
||||||
|
}
|
||||||
|
pseudoInputString += uri;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add this string to the uris for the form
|
||||||
|
String[] urisToAdd = new String[1];
|
||||||
|
urisToAdd[0] = pseudoInputString;
|
||||||
|
log.debug("uris to add" + pseudoInputString);
|
||||||
|
submission.addUriToForm(this.editConfiguration, "conceptSemanticTypeURI", urisToAdd);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return pseudoInputString;
|
return pseudoInputString;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ public class ConceptSearchServiceUtils {
|
||||||
private static final String UMLSVocabSource = "http://link.informatics.stonybrook.edu/umls";
|
private static final String UMLSVocabSource = "http://link.informatics.stonybrook.edu/umls";
|
||||||
private static final String AgrovocVocabSource = "http://aims.fao.org/aos/agrovoc/agrovocScheme";
|
private static final String AgrovocVocabSource = "http://aims.fao.org/aos/agrovoc/agrovocScheme";
|
||||||
private static final String GemetVocabSource = "http://www.eionet.europa.eu/gemet/gemetThesaurus";
|
private static final String GemetVocabSource = "http://www.eionet.europa.eu/gemet/gemetThesaurus";
|
||||||
|
private static final String LCSHVocabSource = "http://id.loc.gov/authorities/subjects";
|
||||||
|
|
||||||
//Get the class that corresponds to the appropriate search
|
//Get the class that corresponds to the appropriate search
|
||||||
public static String getConceptSearchServiceClassName(String searchServiceName) {
|
public static String getConceptSearchServiceClassName(String searchServiceName) {
|
||||||
|
@ -41,6 +42,8 @@ public class ConceptSearchServiceUtils {
|
||||||
//Commenting out agrovoc for now until implementation is updated
|
//Commenting out agrovoc for now until implementation is updated
|
||||||
map.put(AgrovocVocabSource, new VocabSourceDescription("AGROVOC", AgrovocVocabSource, "http://www.fao.org/agrovoc/", "Agricultural Vocabulary"));
|
map.put(AgrovocVocabSource, new VocabSourceDescription("AGROVOC", AgrovocVocabSource, "http://www.fao.org/agrovoc/", "Agricultural Vocabulary"));
|
||||||
map.put(GemetVocabSource, new VocabSourceDescription("GEMET", GemetVocabSource, "http://www.eionet.europa.eu/gemet", "GEneral Multilingual Environmental Thesaurus"));
|
map.put(GemetVocabSource, new VocabSourceDescription("GEMET", GemetVocabSource, "http://www.eionet.europa.eu/gemet", "GEneral Multilingual Environmental Thesaurus"));
|
||||||
|
map.put(LCSHVocabSource, new VocabSourceDescription("LCSH", LCSHVocabSource, "http://id.loc.gov/authorities/subjects/", "Library of Congress Subject Headings"));
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +56,8 @@ public class ConceptSearchServiceUtils {
|
||||||
map.put(UMLSVocabSource, "edu.cornell.mannlib.semservices.service.impl.UMLSService");
|
map.put(UMLSVocabSource, "edu.cornell.mannlib.semservices.service.impl.UMLSService");
|
||||||
map.put(AgrovocVocabSource, "edu.cornell.mannlib.semservices.service.impl.AgrovocService");
|
map.put(AgrovocVocabSource, "edu.cornell.mannlib.semservices.service.impl.AgrovocService");
|
||||||
map.put(GemetVocabSource, "edu.cornell.mannlib.semservices.service.impl.GemetService");
|
map.put(GemetVocabSource, "edu.cornell.mannlib.semservices.service.impl.GemetService");
|
||||||
|
map.put(LCSHVocabSource, "edu.cornell.mannlib.semservices.service.impl.LCSHService");
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -692,6 +692,7 @@ or_add_new_one = or add a new one.
|
||||||
vocabulary_service_unavailable = The vocabulary service is unavailable. Please try again later.
|
vocabulary_service_unavailable = The vocabulary service is unavailable. Please try again later.
|
||||||
no_serch_results_found = No search results were found.
|
no_serch_results_found = No search results were found.
|
||||||
label_type = Label (Type)
|
label_type = Label (Type)
|
||||||
|
label_altLabels = Label (Alternate Labels)
|
||||||
definition_capitalized = Definition
|
definition_capitalized = Definition
|
||||||
best_match = Best Match
|
best_match = Best Match
|
||||||
select_term_from_results = Please select at least one term from the search search results.
|
select_term_from_results = Please select at least one term from the search search results.
|
||||||
|
|
Loading…
Add table
Reference in a new issue