Commit 9d910c9c authored by Richard Bruskiewich's avatar Richard Bruskiewich Committed by Matija Obreza

Trait & Method ontology RDF generation use case in GENESYS - first iteration

parent 3aa65c2b
......@@ -486,6 +486,20 @@
<artifactId>hazelcast-hibernate4</artifactId>
<version>3.1.5</version>
</dependency>
<dependency>
<groupId>org.apache.jena</groupId>
<artifactId>apache-jena-libs</artifactId>
<type>pom</type>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>org.bioversityinternational</groupId>
<artifactId>org.bioversityinternational.ontology</artifactId>
<version>0.0.5</version>
</dependency>
</dependencies>
<build>
......
......@@ -17,7 +17,10 @@
package org.genesys2.server.model.genesys;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import javax.persistence.Column;
......@@ -31,7 +34,6 @@ import javax.persistence.Transient;
import org.genesys2.server.model.AclAwareModel;
import org.genesys2.server.model.GlobalVersionedAuditedModel;
import org.genesys2.server.model.impl.Crop;
import com.fasterxml.jackson.databind.JsonNode;
......@@ -97,12 +99,11 @@ public class Parameter extends GlobalVersionedAuditedModel implements AclAwareMo
public void setTitle(final String title) {
this.title = title;
}
public String getTitle(Locale locale) {
return getTitleLocal(locale);
}
private synchronized String getTitleLocal(Locale locale) {
public void setI18n(String i18n) {
this.i18n = i18n;
}
private synchronized void parseTitleLocal() {
if (this.titleJ == null && this.i18n != null) {
ObjectMapper mapper = new ObjectMapper();
try {
......@@ -110,15 +111,40 @@ public class Parameter extends GlobalVersionedAuditedModel implements AclAwareMo
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Transient
private Map<String,String> titleMap = new HashMap<String,String>();
/**
* Method to return the map of available languages keys
* @return Map<String,String> with language code as the key and the vernacular string as the value.
*/
public Map<String,String> getLocalTitleMap() {
return buildLocalTitleMap() ;
}
private synchronized Map<String,String> buildLocalTitleMap() {
if (this.titleMap.isEmpty() && this.i18n != null) {
parseTitleLocal() ;
Iterator<String> languages = this.titleJ.fieldNames() ;
while(languages.hasNext()) {
String language = languages.next() ;
titleMap.put(language, this.titleJ.get(language).textValue()) ;
}
}
return this.titleJ != null &&
this.titleJ.has(locale.getLanguage())
? this.titleJ.get(locale.getLanguage()).textValue()
: this.title;
return titleMap ;
}
public void setI18n(String i18n) {
this.i18n = i18n;
public String getTitle(Locale locale) {
return getTitleLocal(locale);
}
private synchronized String getTitleLocal(Locale locale) {
parseTitleLocal() ;
return this.titleJ != null && this.titleJ.has(locale.getLanguage()) ? this.titleJ.get(locale.getLanguage()).textValue() : this.title;
}
// @Override
......
......@@ -14,7 +14,7 @@
* limitations under the License.
**/
package org.genesys2.server.servlet.controller;
package org.genesys2.server.servlet.controller.rdf;
import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.service.CropService;
......
/**
* Copyright 2014 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
package org.genesys2.server.servlet.controller.rdf;
import java.util.List;
import java.util.Map;
import org.genesys2.server.model.genesys.Method;
import org.genesys2.server.model.genesys.Parameter;
import org.genesys2.server.model.genesys.ParameterCategory;
import org.genesys2.server.model.genesys.TraitCode;
import org.genesys2.server.model.impl.Crop;
import org.genesys2.server.service.TraitService;
import org.genesys2.spring.ResourceNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.vocabulary.RDF;
import com.hp.hpl.jena.vocabulary.RDFS;
import org.bioversityinternational.model.rdf.skos.SKOS;
import org.bioversityinternational.model.germplasm.CCO;
/**
* Controller which simply handles RDF Turtle meta-data requests
*/
@Controller
@RequestMapping(value = "/descriptors", method = RequestMethod.GET, headers = "accept=text/turtle", produces = RdfBaseController.RDF_MEDIATYPE_TURTLE)
public class DescriptorControllerRdf extends RdfBaseController {
@Autowired
private TraitService traitService;
/**
* Method to publish ParameterCategory meta-data as RDF
* @param model
* @return RDF formatted list of categories
*
* Exemplar:
*
* cco:MorphologyTrait rdfs:subClassOf cco:TraitCategory ;
* skos:broader cco:TraitCategory ;
* skos:prefLabel "Morphology" @en;
* skos:definition "Category of trait pertaining to the anatomy and form of a plant"@en;
* skos:prefLabel "Morfología" @es;
* skos:prefLabel "Mорфология" @ru;
* skos:prefLabel "形态学" @zh;
* skos:inScheme cco:PlantTraitCategoryVocabulary ;
* dc:hasVersion "Revision: 0.1" ;
* dc:creator "Global Crop Diversity Trust";
*/
@RequestMapping(value = "/categories")
public @ResponseBody
String viewCategories() {
Model model = startModel() ;
List<ParameterCategory> categories = traitService.listCategories() ;
for(ParameterCategory category:categories) {
// Insert category record into RDF model
Resource subject = createSubject(model, CCO.getURI()+category.getName()) ;
subject.addProperty(SKOS.inScheme,CCO.PlantTraitCategoryVocabulary) ;
subject.addProperty(SKOS.broader, CCO.TraitCategory) ;
Map<String,String> vernacularNameMap = category.getLocalNameMap() ;
for(String language:vernacularNameMap.keySet()) {
Literal vernacularNameLiteral =
model.createLiteral(vernacularNameMap.get(language), language) ;
subject.addProperty(SKOS.prefLabel, vernacularNameLiteral) ;
}
}
return endModel(model) ;
}
@RequestMapping()
public @ResponseBody
Object index(ModelMap model, @RequestParam(value = "page", required = false, defaultValue = "1") int page) {
model.addAttribute("pagedData", traitService.listTraits(new PageRequest(page - 1, 50, new Sort("title"))));
return "/descr/index";
}
/**
* Method to publish crop trait property ("Parameter") meta-data as multi-lingual RDF
*
* @param model
* @return RDF formatted list of categories
*
* Exemplar:
*
* cco:MusaTrait a skos:Concept;
* cco:category cco:GeneralTrait ;
* skos:prefLabel "Musa taxonomic traits"@en;
* skos:definition "Nomenclature for Characterization traits for species in the Musa taxa."@en;
* skos:prefLabel "Rasgos taxonómicos de Musa."@es;
* skos:definition "Nomenclatura de los rasgos de caracterización de las especies en el taxón Musa."@es;
* skos:prefLabel "Муса таксономические черты"@ru;
* skos:definition "Номенклатура для характеристики признаков для видов в таксонов Муса."@ru;
* skos:prefLabel "穆萨分类学特征"@zh;
* skos:definition "命名为表征特性的物种的穆萨类群"@zh;
* skos:inScheme cco:MusaTraitVocabulary;
* dc:creator "Bioversity International";
*/
@RequestMapping("/{traitId}")
public @ResponseBody
Object view(@PathVariable long traitId) {
Parameter trait = traitService.getTrait(traitId);
if (trait == null) {
throw new ResourceNotFoundException();
}
Model model = startModel() ;
Resource subject = createSubject(model, GENESYS_BASEURI+"/descriptors/"+traitId ) ;
subject.addProperty(RDF.type, SKOS.Concept) ;
String seeAlso = trait.getRdfUri() ;
if(seeAlso!=null)
subject.addProperty(
RDFS.seeAlso,
model.createResource(seeAlso)
) ;
Crop crop = trait.getCrop() ;
CCO.Vocabulary.set(model, subject, CCO.Vocabulary.TRAIT, crop.getShortName()) ;
ParameterCategory category = trait.getCategory() ;
subject.addProperty(CCO.category, model.createResource(category.getRdfUri())) ;
//model.addAttribute("traitMethods", traitService.getTraitMethods(trait));
Map<String,String> vernacularTitleMap = trait.getLocalTitleMap() ;
for( String language : vernacularTitleMap.keySet() ) {
Literal vernacularNameLiteral =
model.createLiteral(vernacularTitleMap.get(language), language) ;
subject.addProperty(SKOS.prefLabel,vernacularNameLiteral) ;
}
/*
TODO - The Parameter table doesn't yet appear to track trait descriptions...
Map<String,String> vernacularTitleMap = trait.getLocalTitleMap() ;
for( String language : vernacularDefinitionMap.keySet() ) {
Literal vernacularNameLiteral =
model.createLiteral(vernacularTitleMap.get(language), language) ;
subject.addProperty(SKOS.prefLabel,vernacularNameLiteral) ;
}
*/
return endModel(model);
}
@RequestMapping("/{traitId}/{methodId}")
public @ResponseBody
Object view(ModelMap model, @PathVariable long traitId, @PathVariable long methodId) {
Parameter trait = traitService.getTrait(traitId);
if (trait == null) {
throw new ResourceNotFoundException();
}
Method method = traitService.getMethod(methodId);
if (method == null) {
throw new ResourceNotFoundException();
}
if (!method.getParameter().getId().equals(trait.getId())) {
_logger.warn("Method does not belong to Param");
}
model.addAttribute("trait", trait);
model.addAttribute("method", method);
model.addAttribute("metadatas", traitService.listMetadataByMethod(method));
if (method.isCoded()) {
Map<String, String> codeMap = TraitCode.parseCodeMap(method.getOptions());
model.addAttribute("codeMap", codeMap);
model.addAttribute("codeStatistics", traitService.getMethodStatistics(method));
}
return "/descr/method";
}
}
/**
* Copyright 2014 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
package org.genesys2.server.servlet.controller.rdf;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import org.bioversityinternational.model.germplasm.CCO;
import org.bioversityinternational.model.rdf.dc.DublinCore;
import org.bioversityinternational.model.rdf.skos.SKOS;
import org.genesys2.server.servlet.controller.BaseController;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.vocabulary.RDF;
import com.hp.hpl.jena.vocabulary.RDFS;
/**
* Controller which simply handles RDF requests
*/
public abstract class RdfBaseController extends BaseController {
/**
* A String equivalent of {@link RdfBaseController#RDF_MEDIATYPE_XML}.
*/
public final static String RDF_MEDIATYPE_XML = "application/rdf+xml";
/**
* A String equivalent of {@link RdfBaseController#RDF_MEDIATYPE_TURTLE}.
*/
public final static String RDF_MEDIATYPE_TURTLE = "text/turtle";
protected static final String GCDT = "Global Crop Diversity Trust" ;
protected static final String RDF_MODEL_VERSION = "Revision: 0.1" ;
/** <p>The namespace of the vocabulary as a string</p> */
public static final String GENESYS_BASEURI = "http://www.genesys-pgr.org" ;
protected static String modelVersion() {
return RDF_MODEL_VERSION ;
}
/*
* Method to set up the RDF model with basic global annotation.
*/
protected Model startModel() {
Model model = ModelFactory.createDefaultModel();
model.setNsPrefix("rdf", RDF.getURI() );
model.setNsPrefix("rdfs", RDFS.getURI() );
model.setNsPrefix("dc", DublinCore.getURI() );
model.setNsPrefix("skos", SKOS.getURI() );
model.setNsPrefix("cco", CCO.getURI() );
return model ;
}
/*
* Method to create a Subject reousrce initialized with common core annotation.
*/
protected Resource createSubject(Model model, String uri) {
Resource subject = model.createResource(uri) ;
subject.addProperty(DublinCore.hasVersion,modelVersion()) ;
subject.addProperty(DublinCore.creator,GCDT) ;
return subject ;
}
protected void seeAlso(Model model, Resource subject, String seeAlso) {
if(seeAlso!=null)
subject.addProperty(RDFS.seeAlso,model.createResource(seeAlso)) ;
}
/*
* Method to write out the model as a Turtle RDF string
* (TODO: maybe convert this to an HTTP Converter which can
* handle other RDF formats?)
*/
protected String endModel(Model model) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(os);
//model.write(ps, "RDF/XML-ABBREV") ;
model.write(ps, "TURTLE") ;
String output = "" ;
try {
output = os.toString("UTF8");
} catch (UnsupportedEncodingException e) {
_logger.debug("Failed while to write out parameter categories as Turtle RDF", e);
}
_logger.info("Returning: "+output);
return output ;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment