Commit 2e915b07 authored by Richard Bruskiewich's avatar Richard Bruskiewich Committed by Matija Obreza

Elaborating export of RDF for Crop records in GENESYS (crop table).

parent d28c5959
......@@ -18,8 +18,12 @@ package org.genesys2.server.model.impl;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
//import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.persistence.Column;
import javax.persistence.Entity;
......@@ -32,7 +36,6 @@ import javax.persistence.Transient;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.Store;
......@@ -127,10 +130,10 @@ public class Crop extends GlobalVersionedAuditedModel {
}
@Transient
private JsonNode i18nJO ;
private JsonNode i18nJO;
@Transient
private JsonNode i18nJU ;
private JsonNode i18nJU;
/*
* This is meant to be a complex language tag merge operation... is there an easier way?
......@@ -146,35 +149,28 @@ public class Crop extends GlobalVersionedAuditedModel {
System.err.println("I18n = " + i18n);
e.printStackTrace();
}
if(this.i18nJU != null) {
Iterator<String> jui = this.i18nJU.fieldNames() ;
while(jui.hasNext()) {
String uField = jui.next() ;
if(this.i18nJO.has(uField)) {
JsonNode juf = this.i18nJU.get(uField) ;
JsonNode jof = this.i18nJO.get(uField) ;
Iterator<String> ulocales = juf.fieldNames() ;
while(ulocales.hasNext()) {
String locale = ulocales.next() ;
// TODO - append/overwrite jof.ufield.locale with juf.ufield.locale
}
if (this.i18nJU != null) {
Iterator<String> jui = this.i18nJU.fieldNames();
while (jui.hasNext()) {
String uField = jui.next();
if (this.i18nJO.has(uField)) {
JsonNode juf = this.i18nJU.get(uField);
JsonNode jof = this.i18nJO.get(uField);
Iterator<String> ulocales = juf.fieldNames();
while (ulocales.hasNext()) {
String locale = ulocales.next();
// TODO - append/overwrite jof.ufield.locale with
// juf.ufield.locale
}
}
}
this.i18n = this.i18nJO.asText() ;
this.i18n = this.i18nJO.asText();
}
*/
}
public String getName(Locale locale) {
return StringUtils.defaultIfBlank(translate("name", locale), this.name);
}
public String getDescription(Locale locale) {
return StringUtils.defaultIfBlank(translate("description", locale), this.name);
}
private synchronized String translate(String field, Locale locale) {
if (this.i18nJ == null && !StringUtils.isBlank(this.i18n)) {
private synchronized void getI18nJson() {
if (this.i18nJ == null && ! StringUtils.isBlank(this.i18n)) {
ObjectMapper mapper = new ObjectMapper();
try {
this.i18nJ = mapper.readTree(this.i18n);
......@@ -183,7 +179,58 @@ public class Crop extends GlobalVersionedAuditedModel {
e.printStackTrace();
}
}
}
private synchronized String translate(String field, Locale locale) {
getI18nJson() ;
return this.i18nJ != null && this.i18nJ.has(field) && this.i18nJ.get(field).has(locale.getLanguage()) ? this.i18nJ.get(field).get(locale.getLanguage())
.textValue() : null;
}
@Transient
private Map<String,Map<String,String>> i18nMap = new HashMap<String,Map<String,String>>();
private synchronized Map<String,String> buildVernacularMap(String field) {
getI18nJson() ;
if(! this.i18nMap.containsKey(field) && this.i18nJ.has(field)) {
this.i18nMap.put(field, new HashMap<String,String>() ) ;
JsonNode fieldMap = this.i18nJ.get(field) ;
Iterator<String> languages = fieldMap.fieldNames() ;
while(languages.hasNext()) {
String language = languages.next() ;
String vernacular = fieldMap.get(language).textValue() ;
this.i18nMap.get(field).put(language, vernacular) ;
}
}
return i18nMap.get(field) ;
}
public String getName(Locale locale) {
return StringUtils.defaultIfBlank(translate("name", locale), this.name);
}
public String getDescription(Locale locale) {
return StringUtils.defaultIfBlank(translate("description", locale), this.name);
}
/**
* Method to return the map of available vernacular names of crops
* @return Map<String,String> with language code as the key and the vernacular string as the value.
*/
public Map<String,String> getLocalNameMap() {
return buildVernacularMap("name") ;
}
/**
* Method to return the map of available vernacular definitions of crops
* @return Map<String,String> with language code as the key and the vernacular string as the value.
*/
public Map<String,String> getLocalDefinitionMap() {
return buildVernacularMap("description") ;
}
}
......@@ -17,6 +17,7 @@
package org.genesys2.server.servlet.controller.rdf;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
......@@ -25,11 +26,14 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
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.DC;
import com.hp.hpl.jena.vocabulary.RDFS;
import org.genesys2.server.model.impl.Crop;
import org.genesys2.server.model.impl.CropRule;
import org.genesys2.server.service.CropService;
import org.genesys2.spring.ResourceNotFoundException;
import org.bioversityinternational.model.germplasm.CCO;
......@@ -75,7 +79,7 @@ public class CropControllerRdf extends RdfBaseController {
private void wrapCrop(Model model, Crop crop) {
Resource subject = createSubject(model, crop, CCO.getURI(), crop.getShortName()+" Taxon") ;
Resource subject = createSubject(model, crop, CCO.getURI()+crop.getId(), crop.getShortName()+" Taxon") ;
subject.addProperty(DarwinCore.scientificName, crop.getShortName()) ;
String seeAlso = crop.getRdfUri() ;
......@@ -87,29 +91,37 @@ public class CropControllerRdf extends RdfBaseController {
/*
* vernacular names & descriptions in i18n
*
Map<String,String> vernacularNameMap = trait.getLocalNameMap() ;
*/
Map<String,String> vernacularNameMap = crop.getLocalNameMap() ;
if(vernacularNameMap!=null)
for( String language : vernacularNameMap.keySet() ) {
Literal vernacularNameLiteral =
model.createLiteral(vernacularNameMap.get(language), language) ;
subject.addLiteral(DarwinCore.vernacularName,vernacularNameLiteral) ;
}
else
this._logger.warn("Empty vernacular crop name map for crop "+crop.getShortName());
Map<String,String> vernacularDefinitionMap = crop.getLocalDefinitionMap() ;
for( String language : vernacularNameMap.keySet() ) {
Literal vernacularNameLiteral =
model.createLiteral(vernacularNameMap.get(language), language) ;
traitSubject.addLiteral(DarwinCore.vernacularName,vernacularNameLiteral) ;
if(vernacularDefinitionMap!=null)
for( String language : vernacularDefinitionMap.keySet() ) {
Literal vernacularDefinitionLiteral =
model.createLiteral(vernacularDefinitionMap.get(language), language) ;
subject.addLiteral(DC.description,vernacularDefinitionLiteral) ;
}
else
this._logger.warn("Empty vernacular crop description map for crop "+crop.getShortName());
List<CropRule> rules = cropService.getCropRules(crop) ;
for(CropRule cr : rules) {
String species = cr.getSpecies() ;
String genus = cr.getGenus() ;
Boolean isIncluded = cr.isIncluded() ;
}
Map<String,String> vernacularDefinitionMap = trait.getLocalDefinitionMap() ;
for( String language : vernacularDefinitionMap.keySet() ) {
Literal vernacularDefinitionLiteral =
model.createLiteral(vernacularDefinitionMap.get(language), language) ;
traitSubject.addLiteral(DC.description,vernacularDefinitionLiteral) ;
}
*/
/*
model.addAttribute("cropTaxonomies", cropService.getCropTaxonomies(crop, new PageRequest(0, 20, new Sort("taxonomy.genus", "taxonomy.species"))));
*/
}
@RequestMapping
......
......@@ -19,6 +19,8 @@ package org.genesys2.server.servlet.controller.rdf;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.Resource;
......@@ -30,7 +32,6 @@ 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.ResponseBody;
import org.genesys2.server.model.genesys.Method;
import org.genesys2.server.model.genesys.Parameter;
import org.genesys2.server.model.genesys.ParameterCategory;
......@@ -50,30 +51,66 @@ import org.bioversityinternational.model.rdf.skos.SKOS;
@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/" ;
public static final String DESCRIPTOR_NS = getBaseUri()+"/descriptors/";;
public static final String CATEGORY_NS = DESCRIPTOR_NS+"categories/" ;
public static final String TRAIT_NS = DESCRIPTOR_NS+"trait/" ;
public static final String METHOD_NS = DESCRIPTOR_NS+"method/" ;
public static final 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 ;
/**
* Method to retrieve list of all descriptor meta-data
* recorded in the database, formatted as Turtle RDF.
*
* @return List of RDF Turtle formatted trait properties
*/
@RequestMapping
public @ResponseBody
Object dumpAll() {
Model model = startModel() ;
wrapCategories(model) ;
for(Parameter trait : traitService.listTraits())
wrapTrait(model, trait) ;
for(Method method : traitService.listMethods()) {
Parameter trait = method.getParameter() ;
wrapMethod(model, trait, method) ;
}
return endModel(model) ;
}
/*
* Creates and annotates a Method subject
*/
private Resource categorySubject(Model model, ParameterCategory category) {
return createSubject(model, category, CATEGORY_NS, category.getName() ) ;
return createSubject(model, category, CATEGORY_NS+category.getId(), category.getName() ) ;
}
/*
* Method generates RDF for one trait category record as RDF.
*/
private void wrapCategories(Model model) {
List<ParameterCategory> categories = traitService.listCategories() ;
for(ParameterCategory category:categories) {
// Insert category record into RDF model
Resource subject = categorySubject(model, category) ;
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.addLiteral(SKOS.prefLabel, vernacularNameLiteral) ;
}
}
}
/**
......@@ -100,22 +137,8 @@ public class DescriptorControllerRdf extends RdfBaseController {
Model model = startModel() ;
List<ParameterCategory> categories = traitService.listCategories() ;
for(ParameterCategory category:categories) {
// Insert category record into RDF model
Resource subject = createSubject(model, category, CCO.getURI(), category.getName()) ;
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.addLiteral(SKOS.prefLabel, vernacularNameLiteral) ;
}
}
wrapCategories(model) ;
return endModel(model) ;
}
......@@ -140,7 +163,7 @@ public class DescriptorControllerRdf extends RdfBaseController {
* Creates and annotates a Method subject
*/
private Resource traitSubject(Model model, Parameter trait) {
return createProperty(model, trait, TRAIT_NS, trait.getTitle() ) ;
return createProperty(model, trait, DESCRIPTOR_NS+trait.getId(), trait.getTitle() ) ;
}
/*
......@@ -209,7 +232,7 @@ public class DescriptorControllerRdf extends RdfBaseController {
*/
@RequestMapping("/{traitId}")
public @ResponseBody
Object dumpTrait(@PathVariable long traitId) {
Object dumpTrait(@PathVariable long traitId, HttpServletResponse response) {
Parameter trait = traitService.getTrait(traitId);
......@@ -221,6 +244,8 @@ public class DescriptorControllerRdf extends RdfBaseController {
wrapTrait(model, trait) ;
response.setDateHeader("Last-Modified", trait.getLastModifiedDate().getTime());
return endModel(model);
}
......@@ -313,8 +338,19 @@ public class DescriptorControllerRdf extends RdfBaseController {
private Resource[] traitAndMethodSubjects(Model model, Parameter trait, Method method) {
Resource[] subjects = new Resource[3] ;
subjects[0] = traitSubject(model, trait) ;
subjects[1] = createProperty(model, method, METHOD_NS, trait.getTitle()+" Method" ) ;
subjects[2] = createProperty(model, method, SCALE_NS, trait.getTitle()+" Scale" ) ;
subjects[1] = createProperty(
model,
method,
DESCRIPTOR_NS+trait.getId()+"/"+method.getId(),
trait.getTitle()+" Method"
) ;
subjects[2] = createProperty(
model,
method,
/* not sure if this is a complete enough specification for a Scale URI...*/
SCALE_NS+trait.getId()+"/"+method.getId(),
trait.getTitle()+" Scale"
) ;
return subjects ;
}
......@@ -441,7 +477,14 @@ public class DescriptorControllerRdf extends RdfBaseController {
Resource scaleSubj, Resource scaleVocabulary, String units
) {
Resource scaleValuesSubj = createProperty(model, method, SCALE_NS, trait.getTitle()+" Scale Values", true) ;
Resource scaleValuesSubj =
createProperty(
model,
method,
SCALE_NS+trait.getId()+"/"+method.getId(),
trait.getTitle()+" Scale Values",
true // is a SKOS Collection...
) ;
scaleSubj.addProperty( CCO.scaleType, "Nominal" ) ;
scaleSubj.addProperty( CCO.scaleUnit, scaleValuesSubj ) ;
scaleValuesSubj.addProperty(SKOS.inScheme, scaleVocabulary ) ;
......@@ -452,7 +495,13 @@ public class DescriptorControllerRdf extends RdfBaseController {
Map<String, String> codeMap = TraitCode.parseCodeMap(options);
int n = 1 ;
for(String code : codeMap.keySet()) {
Resource valueSubj = createProperty(model, method, SCALE_NS, trait.getTitle()+" Scale Value"+n) ;
Resource valueSubj =
createProperty(
model,
method,
SCALE_NS+trait.getId()+"/"+method.getId()+"/"+n,
trait.getTitle()+" Scale Value"+n
) ;
scaleValuesSubj.addProperty( SKOS.member, valueSubj ) ;
valueSubj.addProperty( SKOS.broader, scaleSubj ) ;
valueSubj.addProperty(SKOS.inScheme, scaleVocabulary ) ;
......@@ -483,7 +532,6 @@ public class DescriptorControllerRdf extends RdfBaseController {
Parameter trait = method.getParameter() ;
wrapMethod(model, trait, method) ;
}
return endModel(model) ;
}
......@@ -497,7 +545,7 @@ public class DescriptorControllerRdf extends RdfBaseController {
*/
@RequestMapping("/{traitId}/{methodId}")
public @ResponseBody
Object dumpMethod( @PathVariable long traitId, @PathVariable long methodId) {
Object dumpMethod( @PathVariable long traitId, @PathVariable long methodId, HttpServletResponse response) {
Parameter trait = traitService.getTrait(traitId);
......@@ -520,6 +568,8 @@ public class DescriptorControllerRdf extends RdfBaseController {
wrapTrait(model, trait) ;
wrapMethod(model, trait, method) ;
response.setDateHeader("Last-Modified", method.getLastModifiedDate().getTime());
return endModel(model);
}
......
......@@ -22,6 +22,7 @@ import java.io.UnsupportedEncodingException;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
......@@ -35,6 +36,7 @@ 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.dwc.DarwinCore;
......@@ -61,8 +63,16 @@ public abstract class RdfBaseController extends BaseController {
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" ;
// TODO: the @Value initialization with the Spring set Property base.url
// here doesn't seem to work (even if I set the variable to a non-static private
@Value("${base.url}")
private static String baseUrl = "http://genesys-pgr.org" ;
protected static String getBaseUri() {
if(baseUrl==null)
throw new NullPointerException("Base URI not set in RdfBaseController?") ;
return baseUrl ;
}
protected static String modelVersion() {
return RDF_MODEL_VERSION ;
......@@ -80,7 +90,7 @@ public abstract class RdfBaseController extends BaseController {
model.setNsPrefix("dwc", DarwinCore.getURI() );
model.setNsPrefix("skos", SKOS.getURI() );
model.setNsPrefix("cco", CCO.getURI() );
model.setNsPrefix("genesys", GENESYS_BASEURI+"/" );
model.setNsPrefix("genesys", getBaseUri()+"/" );
return model ;
}
......@@ -115,10 +125,10 @@ public abstract class RdfBaseController extends BaseController {
Model model,
VersionedAuditedModel entity,
String uri,
String id,
String tag,
Boolean isProperty
) {
return createResource( model, entity, uri, id, isProperty, false ) ;
return createResource( model, entity, uri, tag, isProperty, false ) ;
}
// This version checks a flag for SKOS:Collection status
......@@ -126,17 +136,10 @@ public abstract class RdfBaseController extends BaseController {
Model model,
VersionedAuditedModel entity,
String uri,
String id,
String tag,
Boolean isProperty,
Boolean isCollection // SKOS type - true if isa SKOS:Collection
) {
if(isProperty)
id= TitleCase(id,false) ;
else
id = TitleCase(id,true) ;
uri += id ;
Resource subject = model.createResource(uri) ;
......@@ -145,6 +148,12 @@ public abstract class RdfBaseController extends BaseController {
subject.addProperty(RDF.type, SKOS.Collection) ;
else
subject.addProperty(RDF.type, SKOS.Concept) ;
if(isProperty)
tag= TitleCase(tag,false) ;
else
tag = TitleCase(tag,true) ;
subject.addProperty(SKOS.hiddenLabel,tag) ;
// dc:creator <user>
long userId = entity.getCreatedBy() ;
......@@ -172,16 +181,16 @@ public abstract class RdfBaseController extends BaseController {
/**
* Method to create a Subject Resource initialized with common core annotation.
*/
protected Resource createSubject(Model model, VersionedAuditedModel entity, String uri, String id) {
return createResource(model, entity, uri, id, false) ;
protected Resource createSubject(Model model, VersionedAuditedModel entity, String uri, String tag) {
return createResource(model, entity, uri, tag, false) ;
}
/**
* Method to create a Property Resource initialized with common core annotation.
*/
protected Resource createProperty(Model model, VersionedAuditedModel entity, String uri, String id) {
return createResource(model, entity, uri, id, true) ;
protected Resource createProperty(Model model, VersionedAuditedModel entity, String uri, String tag) {
return createResource(model, entity, uri, tag, true) ;
}
......@@ -189,16 +198,16 @@ public abstract class RdfBaseController extends BaseController {
* Method to create a Property Resource initialized with common core annotation.
* This version checks if the Resource is meant to be a SKOS Collection
*/
protected Resource createProperty(Model model, VersionedAuditedModel entity, String uri, String id, Boolean isCollection) {
return createResource(model, entity, uri, id, true, isCollection) ;
protected Resource createProperty(Model model, VersionedAuditedModel entity, String uri, String tag, Boolean isCollection) {
return createResource(model, entity, uri, tag, true, isCollection) ;
}
/*
* Method to create an Object Resource initialized with common core annotation.
*/
protected Resource createObject(Model model, VersionedAuditedModel entity, String uri, String id) {
return createResource(model, entity, uri, id, false) ;
protected Resource createObject(Model model, VersionedAuditedModel entity, String uri, String tag) {
return createResource(model, entity, uri, tag, false) ;
}
......