diff --git a/src/main/java/org/genesys2/server/model/impl/Crop.java b/src/main/java/org/genesys2/server/model/impl/Crop.java index 8778b54ec11b36c337e004abdd8e18e7138da589..2212eed2795ce4ae2847b32df6174783f4032e87 100644 --- a/src/main/java/org/genesys2/server/model/impl/Crop.java +++ b/src/main/java/org/genesys2/server/model/impl/Crop.java @@ -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 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 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 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 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> i18nMap = new HashMap>(); + + private synchronized Map buildVernacularMap(String field) { + getI18nJson() ; + if(! this.i18nMap.containsKey(field) && this.i18nJ.has(field)) { + this.i18nMap.put(field, new HashMap() ) ; + JsonNode fieldMap = this.i18nJ.get(field) ; + Iterator 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 with language code as the key and the vernacular string as the value. + */ + public Map getLocalNameMap() { + return buildVernacularMap("name") ; + } + + /** + * Method to return the map of available vernacular definitions of crops + * @return Map with language code as the key and the vernacular string as the value. + */ + public Map getLocalDefinitionMap() { + return buildVernacularMap("description") ; + } + + + + } diff --git a/src/main/java/org/genesys2/server/servlet/controller/rdf/CropControllerRdf.java b/src/main/java/org/genesys2/server/servlet/controller/rdf/CropControllerRdf.java index 2a623b3549dae5b4cb0fb5fc96f72ff45b173bb2..d6e12c801eb7e17b00f501aa3b78527593359a69 100644 --- a/src/main/java/org/genesys2/server/servlet/controller/rdf/CropControllerRdf.java +++ b/src/main/java/org/genesys2/server/servlet/controller/rdf/CropControllerRdf.java @@ -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 vernacularNameMap = trait.getLocalNameMap() ; + */ + Map 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 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 rules = cropService.getCropRules(crop) ; + for(CropRule cr : rules) { + String species = cr.getSpecies() ; + String genus = cr.getGenus() ; + Boolean isIncluded = cr.isIncluded() ; } - Map 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 diff --git a/src/main/java/org/genesys2/server/servlet/controller/rdf/DescriptorControllerRdf.java b/src/main/java/org/genesys2/server/servlet/controller/rdf/DescriptorControllerRdf.java index d7a91cecfe43fbbaeefab9660333729ed7532d4a..4bdd99d56dce72b29ca4dcff40fd5f511223c955 100644 --- a/src/main/java/org/genesys2/server/servlet/controller/rdf/DescriptorControllerRdf.java +++ b/src/main/java/org/genesys2/server/servlet/controller/rdf/DescriptorControllerRdf.java @@ -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 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 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 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 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 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); } diff --git a/src/main/java/org/genesys2/server/servlet/controller/rdf/RdfBaseController.java b/src/main/java/org/genesys2/server/servlet/controller/rdf/RdfBaseController.java index ab315d428592bf51227d1ef1a47a6e9485a99060..6879daec2bf2761f99fe74774d22117f721f4b53 100644 --- a/src/main/java/org/genesys2/server/servlet/controller/rdf/RdfBaseController.java +++ b/src/main/java/org/genesys2/server/servlet/controller/rdf/RdfBaseController.java @@ -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" ; - /**

The namespace of the vocabulary as a string

*/ - 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 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) ; }