Commit a95ee6fb authored by rwm's avatar rwm
Browse files

Enumerations and simple types via SKOS ontology value restrictions

parent 4a0f61a4
......@@ -30,7 +30,8 @@
] ;
skos:prefLabel "Enum_label_de"@de;
skos:prefLabel "Enum_label_en"@en;
skos:notation "Enum"^^:TestCS .
skos:notation "T:Enum" .
# skos:notation "Enum"^^:TestCS .
dwh:IntegerRestriction a owl:Restriction ;
owl:onProperty rdf:value ;
......
......@@ -81,18 +81,20 @@ public class ConceptImpl implements Concept {
}
@Override
public ValueRestriction getValueRestriction() throws OntologyException {
public ValueRestriction getValueRestriction(Locale locale) throws OntologyException {
try {
RepositoryResult<Statement> rs = store.getConnection().getStatements(getResource(), HIStreamOntology.DWH_RESTRICTION, null, true);
RepositoryResult<Statement> rs = store.getConnection().getStatements(getResource(), HIStreamOntology.DWH_RESTRICTION, null, false);
try{
if( !rs.hasNext() )
if( !rs.hasNext() ){
return null; // no restriction
Value o = rs.next().getObject();
// TODO: load restriction
RestrictionImpl ret = new RestrictionImpl();
}
Value obj = rs.next().getObject();
if( !(obj instanceof Resource) ){
throw new OntologyException("dwh:restriction expected to be a rdf resource");
}
ValueRestriction ret = RestrictionImpl.loadFromRDF(store.getConnection(), (Resource)obj, locale);
if( rs.hasNext() ){
throw new OntologyException("More than one dwh:restriction for "+res);
......
package de.sekmi.histream.ontology.skos;
import java.util.function.Consumer;
import org.openrdf.model.Literal;
import org.openrdf.model.Resource;
import org.openrdf.model.Statement;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;
import org.openrdf.repository.RepositoryResult;
public class RDFUtils {
public static Value getObject(RepositoryConnection connection, Resource subject, URI predicate) throws RepositoryException{
RepositoryResult<Statement> rs = connection.getStatements(subject, predicate, null, false);
try{
if( rs.hasNext() )return rs.next().getObject();
else return null;
}finally{
rs.close();
}
}
public static void forEachRDFListItem(RepositoryConnection connection, Resource rdfList, Consumer<Value> consumer) throws RepositoryException{
do{
// get value
Value obj = getObject(connection, rdfList, RDF.FIRST);
if( obj != null )consumer.accept(obj);
// get rest
obj = getObject(connection, rdfList, RDF.REST);
if( obj == null ){
// illegal termination of list
// TODO throw exception
rdfList = null;
}else if( obj.equals(RDF.NIL) ){
// end of list reached
rdfList = null;
}else if( obj instanceof Resource ){
// remaining list
rdfList = (Resource)obj;
}else{
// illegal termination of list
// TODO throw exception
rdfList = null;
}
}while( rdfList != null );
}
public static final Literal getLiteralObject(RepositoryConnection rc, Resource subject, URI predicate) throws RepositoryException {
Value v = getObject(rc, subject, predicate);
if( v instanceof Literal ){
return (Literal)v;
}else{
return null;
}
}
public static final String getLocalString(RepositoryConnection rc, Resource subject, URI predicate, String language) throws RepositoryException {
// empty language same as no language
if( language != null && language.length() == 0 )
language = null;
RepositoryResult<Statement> rs = rc.getStatements(subject, predicate, null, false);
try{
while( rs.hasNext() ){
Value v = rs.next().getObject();
if( !(v instanceof Literal) )continue;
Literal l = (Literal)v;
String lit_lang = l.getLanguage();
if( language == null && lit_lang == null ){
// neutral literal (without language)
return l.getLabel();
}else if( lit_lang != null && language != null && lit_lang.equals(language) ){
// language matched
return l.getLabel();
}
}
}finally{
rs.close();
}
return null; // no value found
}
}
package de.sekmi.histream.ontology.skos;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;
import org.openrdf.model.Literal;
import org.openrdf.model.Resource;
import org.openrdf.model.Value;
import org.openrdf.model.vocabulary.OWL;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.model.vocabulary.SKOS;
import org.openrdf.model.vocabulary.XMLSchema;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;
import de.sekmi.histream.ontology.EnumValue;
import de.sekmi.histream.ontology.OntologyException;
import de.sekmi.histream.ontology.ValueRestriction;
public class RestrictionImpl implements ValueRestriction {
Class<?> type;
EnumValue[] enumValues;
@Override
public Class<?> getType() {
// TODO Auto-generated method stub
return null;
return type;
}
@Override
public EnumValue[] getEnumeration() {
// TODO Auto-generated method stub
return null;
return enumValues;
}
@Override
......@@ -48,5 +66,55 @@ public class RestrictionImpl implements ValueRestriction {
// TODO Auto-generated method stub
return null;
}
static RestrictionImpl loadFromRDF(RepositoryConnection rdf, Resource restrictionObject, Locale locale) throws OntologyException{
RestrictionImpl ret = new RestrictionImpl();
// TODO: load restriction
try {
if( !rdf.hasStatement(restrictionObject, RDF.TYPE, OWL.RESTRICTION, false) ){
throw new OntologyException("Type owl:Restriction expected for "+restrictionObject);
}
if( !rdf.hasStatement(restrictionObject, OWL.ONPROPERTY, RDF.VALUE, false) ){
throw new OntologyException("owl:Restriction only supported owl:onProperty rdf:value");
}
// load enum
Value o = RDFUtils.getObject(rdf, restrictionObject, OWL.ONEOF);
if( o != null ){
final String language = (locale==null)?null:locale.toString();
final List<EnumValue> list = new ArrayList<>();
RDFUtils.forEachRDFListItem(rdf, (Resource)o, v -> {
try {
String label = RDFUtils.getLocalString(rdf, (Resource)v, SKOS.PREF_LABEL, language);
Literal literal = RDFUtils.getLiteralObject(rdf, (Resource)v, RDF.VALUE);
// TODO: use correct types from literal
list.add(new EnumValue(label, literal.stringValue()));
} catch (Exception e) {
// TODO log warning
}
});
ret.enumValues = list.toArray(new EnumValue[list.size()]);
}
// load type
o = RDFUtils.getObject(rdf, restrictionObject, OWL.ALLVALUESFROM);
if( o != null ){
if( o.equals(XMLSchema.INTEGER) || o.equals(XMLSchema.INT) || o.equals(XMLSchema.LONG) ){
ret.type = Integer.class;
}else if( o.equals(XMLSchema.STRING) ){
ret.type = String.class;
}else if( o.equals(XMLSchema.DECIMAL) || o.equals(XMLSchema.FLOAT) || o.equals(XMLSchema.DOUBLE) ){
ret.type = BigDecimal.class;
}else{
// TODO: check for extended / restricted types
}
}
} catch (RepositoryException e) {
throw new OntologyException(e);
}
return ret;
}
}
......@@ -7,11 +7,9 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.openrdf.model.Literal;
import org.openrdf.model.Resource;
import org.openrdf.model.Statement;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.util.Literals;
import org.openrdf.model.vocabulary.SKOS;
import org.openrdf.repository.Repository;
......@@ -177,33 +175,11 @@ public class Store implements Ontology, Plugin {
}
String getLocalString(Resource subject, URI predicate, String language) throws OntologyException {
// empty language same as no language
if( language != null && language.length() == 0 )
language = null;
try {
RepositoryResult<Statement> rs = rc.getStatements(subject, predicate, null, true);
try{
while( rs.hasNext() ){
Value v = rs.next().getObject();
if( !(v instanceof Literal) )continue;
Literal l = (Literal)v;
String lit_lang = l.getLanguage();
if( language == null && lit_lang == null ){
// neutral literal (without language)
return l.getLabel();
}else if( lit_lang != null && language != null && lit_lang.equals(language) ){
// language matched
return l.getLabel();
}
}
}finally{
rs.close();
}
return RDFUtils.getLocalString(rc, subject, predicate, language);
}catch( RepositoryException e ){
throw new OntologyException(e);
}
return null; // no value found
}
......
......@@ -10,6 +10,7 @@ import org.junit.Before;
import org.junit.Test;
import de.sekmi.histream.ontology.Concept;
import de.sekmi.histream.ontology.EnumValue;
import de.sekmi.histream.ontology.OntologyException;
import de.sekmi.histream.ontology.ValueRestriction;
import de.sekmi.histream.ontology.skos.Store;
......@@ -29,10 +30,34 @@ public class OntologyTest {
Assert.assertNotNull(c);
Assert.assertEquals(1, c.getIDs().length);
Assert.assertEquals("T:type:int", c.getIDs()[0]);
ValueRestriction rest = c.getValueRestriction();
ValueRestriction rest = c.getValueRestriction(Locale.GERMAN);
Assert.assertNotNull(rest);
}
@Test
public void enumRestrictionTest() throws OntologyException{
Concept c = store.getConceptByNotation("T:Enum");
Assert.assertNotNull(c);
// German language
ValueRestriction rest = c.getValueRestriction(Locale.GERMAN);
Assert.assertNotNull(rest);
EnumValue[] e = rest.getEnumeration();
Assert.assertNotNull(e);
Assert.assertEquals(2, e.length);
Assert.assertEquals("1", e[0].getValue());
Assert.assertEquals("1_de", e[0].getPrefLabel());
Assert.assertEquals("2", e[1].getValue());
Assert.assertEquals("2_de", e[1].getPrefLabel());
// German language
rest = c.getValueRestriction(Locale.ENGLISH);
e = rest.getEnumeration();
Assert.assertNotNull(e);
Assert.assertEquals(2, e.length);
Assert.assertEquals("1", e[0].getValue());
Assert.assertEquals("1_en", e[0].getPrefLabel());
}
@Test
public void getNarrowerTest() throws OntologyException{
Concept[] top = store.getTopConcepts();
......
......@@ -76,7 +76,9 @@ public interface Concept {
/**
* Get restrictions for the values of this concept.
* @param locale locale for labels (e.g. in enumerations)
* @return value restrictions or {@code null} if no restrictions are provided
* @throws OntologyException for ontology errors
*/
ValueRestriction getValueRestriction() throws OntologyException;
ValueRestriction getValueRestriction(Locale locale) throws OntologyException;
}
package de.sekmi.histream.ontology;
import java.util.Locale;
public class EnumValue {
private String label;
private Object value;
public interface EnumValue {
String getPrefLabel(Locale locale);
Object getValue();
public EnumValue(String label, Object value){
this.label = label;
this.value = value;
}
public String getPrefLabel(){return label;}
public Object getValue(){return value;}
}
......@@ -4,6 +4,7 @@ import java.util.regex.Pattern;
public interface ValueRestriction {
Class<?> getType();
// TODO move locale to getEnumeration
EnumValue[] getEnumeration();
Number minInclusive();
Number maxInclusive();
......
Supports Markdown
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