Commit eda753ce authored by Richard Bruskiewich's avatar Richard Bruskiewich Committed by Matija Obreza
Browse files

Turtle RDF publication of Trait and Methods is evolving... latest iteration.

parent 9d910c9c
......@@ -497,7 +497,7 @@
<dependency>
<groupId>org.bioversityinternational</groupId>
<artifactId>org.bioversityinternational.ontology</artifactId>
<version>0.0.5</version>
<version>0.0.6</version>
</dependency>
</dependencies>
......
......@@ -36,6 +36,8 @@ public interface TraitService {
Parameter getTrait(long traitId);
List<Parameter> listTraits();
List<Method> getTraitMethods(Parameter trait);
Method getMethod(long traitId);
......
......@@ -134,15 +134,15 @@ public class GenesysServiceImpl implements GenesysService, TraitService, Dataset
@Autowired
private CropTaxonomyRepository cropTaxonomyRepository;
@Autowired
private MethodRepository methodRepository;
@Autowired
private ParameterCategoryRepository parameterCategoryRepository;
@Autowired
private ParameterRepository parameterRepository;
@Autowired
private MethodRepository methodRepository;
@Autowired
private OrganizationRepository organizationRepository;
......@@ -401,6 +401,15 @@ public class GenesysServiceImpl implements GenesysService, TraitService, Dataset
return accessionRepository.findByInstitute(members, pageable);
}
@Override
public List<ParameterCategory> listCategories() {
return parameterCategoryRepository.findAll(new Sort(new Order(Direction.ASC, "id")));
}
@Override
public List<Parameter> listTraits() {
return parameterRepository.findAll(new Sort(new Order(Direction.ASC, "id")));
}
@Override
public Page<Parameter> listTraits(Pageable pageable) {
return parameterRepository.findAll(pageable);
......@@ -1283,11 +1292,6 @@ public class GenesysServiceImpl implements GenesysService, TraitService, Dataset
return null;
}
@Override
public List<ParameterCategory> listCategories() {
return parameterCategoryRepository.findAll(new Sort(new Order(Direction.ASC, "id")));
}
@Override
public Map<ParameterCategory, List<Parameter>> mapTraits(Crop crop, List<ParameterCategory> parameterCategories) {
if (parameterCategories == null || parameterCategories.size() == 0)
......@@ -1318,4 +1322,5 @@ public class GenesysServiceImpl implements GenesysService, TraitService, Dataset
return paramMethods;
}
}
......@@ -19,6 +19,9 @@ package org.genesys2.server.servlet.controller.rdf;
import java.util.List;
import java.util.Map;
import org.bioversityinternational.model.germplasm.CCO;
import org.bioversityinternational.model.rdf.skos.SKOS;
import org.genesys2.server.model.genesys.Metadata;
import org.genesys2.server.model.genesys.Method;
import org.genesys2.server.model.genesys.Parameter;
import org.genesys2.server.model.genesys.ParameterCategory;
......@@ -27,25 +30,17 @@ 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
*/
......@@ -53,9 +48,31 @@ import org.bioversityinternational.model.germplasm.CCO;
@RequestMapping(value = "/descriptors", method = RequestMethod.GET, headers = "accept=text/turtle", produces = RdfBaseController.RDF_MEDIATYPE_TURTLE)
public class DescriptorControllerRdf extends RdfBaseController {
public final static String DESCRIPTOR_NS = GENESYS_BASEURI+"/descriptors/";
public final static String CATEGORY_NS = DESCRIPTOR_NS+"categories/" ;
public final static String TRAIT_NS = DESCRIPTOR_NS+"trait/" ;
public final static String METHOD_NS = DESCRIPTOR_NS+"method/" ;
public final static String SCALE_NS = DESCRIPTOR_NS+"scale/" ;
@Autowired
private TraitService traitService;
@Override
protected Model startModel() {
Model model = super.startModel();
model.setNsPrefix("cat", CATEGORY_NS );
model.setNsPrefix("trait", TRAIT_NS );
model.setNsPrefix("method",METHOD_NS );
model.setNsPrefix("scale", SCALE_NS );
return model ;
}
/*
* Creates and annotates a Method subject
*/
private Resource categorySubject(Model model, ParameterCategory category) {
return createSubject(model, category, CATEGORY_NS, category.getName() ) ;
}
/**
* Method to publish ParameterCategory meta-data as RDF
......@@ -77,45 +94,31 @@ public class DescriptorControllerRdf extends RdfBaseController {
*/
@RequestMapping(value = "/categories")
public @ResponseBody
String viewCategories() {
String dumpCategories() {
Model model = startModel() ;
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()) ;
Resource subject = createSubject(model, category, CCO.getURI(), category.getName()) ;
subject.addProperty(SKOS.inScheme,CCO.PlantTraitCategoryVocabulary) ;
CCO.Vocabulary.set(model, subject, CCO.Vocabulary.CATEGORY, "Plant") ;
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) ;
subject.addLiteral(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:
/**
* Trait Turtle RDF format Exemplar:
*
* cco:MusaTrait a skos:Concept;
* cco:category cco:GeneralTrait ;
......@@ -130,33 +133,34 @@ public class DescriptorControllerRdf extends RdfBaseController {
* 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() ;
/*
* Creates and annotates a Method subject
*/
private Resource traitSubject(Model model, Parameter trait) {
return createProperty(model, trait, TRAIT_NS, trait.getTitle() ) ;
}
/*
* Method generates RDF for one trait record as RDF.
*/
private void wrapTrait(Model model, Parameter trait) {
Resource subject = createSubject(model, GENESYS_BASEURI+"/descriptors/"+traitId ) ;
subject.addProperty(RDF.type, SKOS.Concept) ;
Resource traitSubject = traitSubject(model, trait) ;
String seeAlso = trait.getRdfUri() ;
if(seeAlso!=null)
subject.addProperty(
traitSubject.addProperty(
RDFS.seeAlso,
model.createResource(seeAlso)
) ;
Crop crop = trait.getCrop() ;
CCO.Vocabulary.set(model, subject, CCO.Vocabulary.TRAIT, crop.getShortName()) ;
CCO.Vocabulary.set(model, traitSubject, CCO.Vocabulary.TRAIT, crop.getShortName()) ;
ParameterCategory category = trait.getCategory() ;
subject.addProperty(CCO.category, model.createResource(category.getRdfUri())) ;
Resource categorySubject = categorySubject(model, category) ;
traitSubject.addProperty(CCO.category, categorySubject) ;
//model.addAttribute("traitMethods", traitService.getTraitMethods(trait));
Map<String,String> vernacularTitleMap = trait.getLocalTitleMap() ;
......@@ -164,7 +168,7 @@ public class DescriptorControllerRdf extends RdfBaseController {
for( String language : vernacularTitleMap.keySet() ) {
Literal vernacularNameLiteral =
model.createLiteral(vernacularTitleMap.get(language), language) ;
subject.addProperty(SKOS.prefLabel,vernacularNameLiteral) ;
traitSubject.addLiteral(SKOS.prefLabel,vernacularNameLiteral) ;
}
/*
......@@ -175,38 +179,228 @@ public class DescriptorControllerRdf extends RdfBaseController {
for( String language : vernacularDefinitionMap.keySet() ) {
Literal vernacularNameLiteral =
model.createLiteral(vernacularTitleMap.get(language), language) ;
subject.addProperty(SKOS.prefLabel,vernacularNameLiteral) ;
subject.addLiteral(SKOS.prefLabel,vernacularNameLiteral) ;
}
*/
}
/**
* Method to retrieve list of all trait properties in the database, formatted as Turtle RDF
* @return List of RDF Turtle formatted trait properties
*/
@RequestMapping()
public @ResponseBody
Object dumpTraits() {
Model model = startModel() ;
for(Parameter trait : traitService.listTraits()) wrapTrait(model, trait) ;
return endModel(model) ;
}
/**
* Method to publish crop trait property ("Parameter") meta-data as multi-lingual RDF
*
* @param PathVariable long traitId
* @return RDF formatted list of categories
*/
@RequestMapping("/{traitId}")
public @ResponseBody
Object dumpTrait(@PathVariable long traitId) {
Parameter trait = traitService.getTrait(traitId);
if (trait == null) {
throw new ResourceNotFoundException();
}
Model model = startModel() ;
wrapTrait(model, trait) ;
return endModel(model);
}
/**
* Trait Method RDF Exemplar (from the Bioversity model...
* some properties may not be generated from the GENESYS database)
*
* cco:fruitLengthMethod a skos:Concept;
* skos:broader cco:MusaTraitMethod;
* skos:related cco:fruitLength ;
* cco:trait cco:fruitLength ;
* dcterms:created "2014/01/14 12:00:00";
* dcterms:modified "2014/01/14 12:00:00";
* skos:prefLabel "Fruit length method"@en;
* skos:definition "Measured length of the fruit, without pedicel."@en;
* skos:prefLabel "Método para Longitud de los frutos [cm]"@es;
* skos:definition "Medir el longitud del fruto, sin el pedicelo."@es;
* skos:prefLabel "Фрукты метод длина"@ru;
* skos:definition "Измеряется длина плода, без плодоножки."@ru;
* skos:prefLabel "果长法"@zh;
* skos:definition "测得的果实长度,无花梗"@zh;
* skos:inScheme cco:MusaTraitMethodVocabulary
* .
*
* cco:fruitLengthMethod2 a skos:Concept;
* skos:broader cco:MusaTraitMethod;
* skos:related cco:fruitLength ;
* cco:trait cco:fruitLength ;
* dcterms:created "2014/01/14 12:00:00";
* dcterms:modified "2014/01/14 12:00:00";
* skos:prefLabel "Alternative fruit length method"@en;
* skos:definition "Measured length of the fruit, with the pedicel."@en;
* skos:prefLabel "Método alternativo para longitud de los frutos [cm]"@es;
* skos:definition "Medir el longitud del fruto, con el pedicelo."@es;
* skos:prefLabel "Альтернативный метод длина фрукты"@ru;
* skos:definition "Измеряется длина плода, с плодоножки."@ru;
* skos:prefLabel "另类水果长度的方法"@zh;
* skos:definition "测得的果实长度,与花梗"@zh;
* skos:inScheme cco:MusaTraitMethodVocabulary
* .
*
* cco:fruitLengthScale a skos:Concept;
* skos:broader cco:MusaTraitScale ;
* skos:related cco:fruitLengthMethod, cco:fruitLengthMethod2 ;
* cco:method cco:fruitLengthMethod, cco:fruitLengthMethod2 ;
* skos:prefLabel "Fruit length scale"@en;
* skos:prefLabel "Escala Longitud de los frutos [cm] "@es;
* dcterms:created "2014/01/14 12:00:00";
* dcterms:modified "2014/01/14 12:00:00";
* skos:inScheme cco:MusaTraitScaleVocabulary ;
* skos:definition "1 =<15 cm, 2 16- 20 cm, 3 21- 25 cm, 4 26- 30 cm, 5 >=31 cm"@en;
* skos:definition "1 =< 15 cm, 2 16-20 cm, 3 21-25 cm, 4 26-30 cm, 5 > =31 cm"@es;
* cco:scaleType "Nominal";
* cco:scaleUnit cco:fruitLengthScaleValues
* .
*
* cco:fruitLengthScaleValues a skos:Collection;
* skos:prefLabel "Fruit length scale values"@en ;
* skos:prefLabel "Valores para Longitud de los frutos [cm]"@es ;
* dcterms:created "2014/01/14 12:00:00";
* dcterms:modified "2014/01/14 12:00:00";
* skos:definition "Controlled list of values for Fruit length"@en;
* skos:definition "Lista controlada de valores para Longitud de los frutos [cm]"@es;
* skos:member cco:fruitLengthScaleValue1, cco:fruitLengthScaleValue2, cco:fruitLengthScaleValue3, cco:fruitLengthScaleValue4, cco:fruitLengthScaleValue5
* .
*
* cco:fruitLengthScaleValue1
* a cco:IntegerValueRange ;
* cco:integerMinValue "0"^^xsd:integer ;
* cco:integerMaxValue "15"^^xsd:integer ;
* cco:scaleUnit "cm" ;
* skos:broader cco:fruitLengthScale;
* dcterms:created "2014/01/14 12:00:00";
* dcterms:modified "2014/01/14 12:00:00";
* skos:prefLabel "=<15 cm"@en ;
* skos:prefLabel "=<15 cm"@es ;
* skos:altLabel "1" ;
* skos:definition "=<15 cm"@en ;
* skos:definition "=<15 cm"@es ;
* skos:inScheme cco:MusaTraitScaleVocabulary
* .
*
*/
/*
* Creates and annotates a Method subject
*/
private Resource[] traitAndMethodSubjects(Model model, Parameter trait, Method method) {
Resource[] subjects = new Resource[2] ;
subjects[0] = traitSubject(model, trait) ;
subjects[1] = createProperty(model, method, METHOD_NS, trait.getTitle()+" Method" ) ;
return subjects ;
}
/*
* Method generates RDF for one trait method.
*/
private void wrapMethod(Model model, Parameter trait, Method method) {
int TRAIT = 0 , METHOD = 1 ;
Resource[] subjects = traitAndMethodSubjects(model,trait,method) ;
Resource traitSubj = subjects[0] ;
Resource methodSubj = subjects[1] ;
String seeAlso = method.getRdfUri() ;
if(seeAlso!=null)
methodSubj.addProperty(
RDFS.seeAlso,
model.createResource(seeAlso)
) ;
Crop crop = trait.getCrop() ;
CCO.Vocabulary.set(model, methodSubj, CCO.Vocabulary.METHOD, crop.getShortName()) ;
methodSubj.addProperty( SKOS.related, traitSubj ) ;
methodSubj.addProperty( CCO.trait, traitSubj ) ;
/*
//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) ;
methodSubject.addLiteral(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.addLiteral(SKOS.prefLabel,vernacularNameLiteral) ;
}
List<Metadata> metadata = traitService.listMetadataByMethod(method);
if (method.isCoded()) {
Map<String, String> codeMap = TraitCode.parseCodeMap(method.getOptions());
//model.addAttribute("codeMap", codeMap);
//model.addAttribute("codeStatistics", traitService.getMethodStatistics(method));
}
*/
}
/**
* Method to publish a single crop trait method and associated scale meta-data, as multi-lingual RDF
*
* @param traitId
* @param methodId
* @return RDF formatted list of categories
*/
@RequestMapping("/{traitId}/{methodId}")
public @ResponseBody
Object view(ModelMap model, @PathVariable long traitId, @PathVariable long methodId) {
Object dumpMethod( @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";
Model model = startModel() ;
wrapMethod(model, trait, method) ;
return endModel(model);
}
}
......@@ -19,23 +19,35 @@ package org.genesys2.server.servlet.controller.rdf;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.Date;
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 org.springframework.beans.factory.annotation.Autowired;
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.DC;
import com.hp.hpl.jena.vocabulary.RDF;
import com.hp.hpl.jena.vocabulary.RDFS;
import org.genesys2.server.exception.UserException;
import org.genesys2.server.model.VersionedAuditedModel;
import org.genesys2.server.model.impl.User;
import org.genesys2.server.service.UserService;
import org.genesys2.server.servlet.controller.BaseController;
import org.bioversityinternational.model.germplasm.CCO;
import org.bioversityinternational.model.rdf.dc.DublinCore;
import org.bioversityinternational.model.rdf.skos.SKOS;
/**
* Controller which simply handles RDF requests
*/
public abstract class RdfBaseController extends BaseController {
@Autowired
private UserService userService;
/**
* A String equivalent of {@link RdfBaseController#RDF_MEDIATYPE_XML}.
*/
......@@ -63,49 +75,143 @@ public abstract class RdfBaseController extends BaseController {
Model model = ModelFactory.createDefaultModel();
model.setNsPrefix("rdf", RDF.getURI() );
model.setNsPrefix("rdfs", RDFS.getURI() );
model.setNsPrefix("dc", DublinCore.getURI() );
model.setNsPrefix("dc", DC.getURI() );
model.setNsPrefix("dcterms", DublinCore.getURI() );
model.setNsPrefix("skos", SKOS.getURI() );
model.setNsPrefix("cco", CCO.getURI() );
model.setNsPrefix("genesys", GENESYS_BASEURI+"/" );
return model ;
}
/**
* Generates a Camel cased identifier from its imput string
*
* @param s
* @return
*/
private static String TitleCase(String s, Boolean capitalizeFirst) {
String[] words = s.split("\\s") ;
s = "" ;
for(String word: words) {
if(!capitalizeFirst) {
// only run once in the loop if false (reset to true...)
s += word.toLowerCase() ;
capitalizeFirst = true ;
} else {
s += word.substring(0,1).toUpperCase() ;
s += word.substring(1).toLowerCase() ;
}
}
return s ;
}
/*
* Method to create a Subject reousrce initialized with common core annotation.
* Method to create a subject Resource initialized with common core annotation.
*/
protected Resource createSubject(Model model, String uri) {
private Resource createResource(Model model, VersionedAuditedModel entity, String uri, String id, Boolean isProperty) {
if(isProperty)
id= TitleCase(id,false) ;
else
id = TitleCase(id,true) ;
uri += id ;