Skip to content

Commit

Permalink
Merge pull request #242 from geneontology/issue-212-validation-explan…
Browse files Browse the repository at this point in the history
…ations-1

Added explanations for core shape failures
  • Loading branch information
goodb authored Sep 7, 2019
2 parents ceedace + 2cf8e26 commit 63babe7
Show file tree
Hide file tree
Showing 14 changed files with 414 additions and 149 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@

import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.geneontology.minerva.server.validation.ModelValidationReport;
import org.geneontology.minerva.server.validation.ValidationResultSet;

public interface InferenceProvider {

public boolean isConsistent();

public Set<OWLClass> getTypes(OWLNamedIndividual i);

public Set<ModelValidationReport> getValidation_reports();
public ValidationResultSet getValidation_results();

Set<OWLClass> getAllTypes(OWLNamedIndividual i);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.geneontology.minerva.server.validation;

public interface ValidationResultSet {

}
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ public static Server startUp(final MinervaStartUpConfig conf)
// set pre and post file handlers
models.addPostLoadOntologyFilter(ModelReaderHelper.INSTANCE);
conf.shex.tbox_reasoner = models.getTbox_reasoner();
conf.shex.curieHandler = conf.curieHandler;
// start server
Server server = startUp(models, conf);
return server;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.geneontology.minerva.server.handler.M3BatchHandler.M3BatchResponse.ResponseData;
import org.geneontology.minerva.server.inferences.InferenceProviderCreator;
import org.geneontology.minerva.server.validation.ModelValidationReport;
import org.geneontology.minerva.server.validation.ValidationResultSet;
import org.glassfish.jersey.server.JSONP;
import org.semanticweb.owlapi.model.OWLObjectProperty;

Expand Down Expand Up @@ -206,15 +207,9 @@ else if (Entity.meta == entity) {
inferenceProvider = inferenceProviderCreator.create(values.model);
isConsistent = inferenceProvider.isConsistent();
response.setReasoned(true);
values.renderBulk = true; // to ensure that all indivuduals are in the response
//TODO @goodb fill in explanations for shape and owl validation
for(ModelValidationReport report : inferenceProvider.getValidation_reports()) {
//if any of the validation tests come back noncomformant, set nonconformant ("something is wrong") flag
if(!report.isConformant()) {
isConformant = false;
break;
}
}
values.renderBulk = true; // to ensure that all individuals are in the response
ValidationResultSet validations = inferenceProvider.getValidation_results();
isConformant = validations.allConformant();
}

// create response.data
Expand Down Expand Up @@ -244,8 +239,7 @@ else if (Entity.meta == entity) {
response.data.inconsistentFlag = Boolean.TRUE;
}
if(!isConformant) {
response.data.nonconformantFlag = Boolean.TRUE;
response.data.validation_results = inferenceProvider.getValidation_reports();
response.data.validation_results = inferenceProvider.getValidation_results();
}
response.data.modifiedFlag = Boolean.valueOf(values.model.isModified());
// These are required for an "okay" response.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.google.gson.annotations.SerializedName;
import org.geneontology.minerva.json.*;
import org.geneontology.minerva.server.validation.ModelValidationReport;
import org.geneontology.minerva.server.validation.ValidationResultSet;

import javax.ws.rs.*;
import java.util.List;
Expand Down Expand Up @@ -121,12 +122,9 @@ public static class ResponseData extends JsonModel {

@SerializedName("sparql-result")
public JsonObject sparqlResult;

@SerializedName("noncomformant-p")
public Boolean nonconformantFlag;

@SerializedName("validation-results")
public Set<ModelValidationReport> validation_results;
public ValidationResultSet validation_results;

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class MapInferenceProvider implements InferenceProvider {
private final Map<OWLNamedIndividual, Set<OWLClass>> inferredTypes;
private final Map<OWLNamedIndividual, Set<OWLClass>> inferredTypesWithIndirects;
//for shex and other validation
private Set<ModelValidationReport> validation_reports;
private ValidationResultSet validation_results;

public static InferenceProvider create(OWLReasoner r, OWLOntology ont, ShexValidator shex) {
Map<OWLNamedIndividual, Set<OWLClass>> inferredTypes = new HashMap<>();
Expand Down Expand Up @@ -50,40 +50,36 @@ public static InferenceProvider create(OWLReasoner r, OWLOntology ont, ShexValid
inferredTypesWithIndirects.put(individual, all_inferred);
}
}
//Aim to support multiple validation regimes - e.g. reasoner, shex, gorules
Set<ModelValidationReport> all_validation_results = new HashSet<ModelValidationReport>();
//reasoner
ModelValidationReport reasoner_validation_report = new OWLValidationReport();
reasoner_validation_report.setConformant(isConsistent);
OWLValidationReport reasoner_validation = new OWLValidationReport();
reasoner_validation.setConformant(isConsistent);
if(!isConsistent) {
Violation i_v = new Violation("id of inconsistent node");
i_v.setCommentary("comment about why");
reasoner_validation_report.addViolation(i_v);
reasoner_validation.addViolation(i_v);
}
all_validation_results.add(reasoner_validation_report);

//shex
//generate an RDF model
Model model = JenaOwlTool.getJenaModel(ont);
//add superclasses to types used in model
model = shex.enrichSuperClasses(model);
ModelValidationReport validation_report = null;
ShexValidationReport shex_validation = null;
try {
validation_report = shex.createValidationReport(model);
if(validation_report!=null) {
all_validation_results.add(validation_report);
}
boolean stream_output_for_debug = true;
shex_validation = shex.runShapeMapValidation(model, stream_output_for_debug);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return new MapInferenceProvider(isConsistent, inferredTypes, inferredTypesWithIndirects, all_validation_results);
ValidationResultSet all_validations = new ValidationResultSet(reasoner_validation, shex_validation);
return new MapInferenceProvider(isConsistent, inferredTypes, inferredTypesWithIndirects, all_validations);
}

MapInferenceProvider(boolean isConsistent, Map<OWLNamedIndividual, Set<OWLClass>> inferredTypes, Map<OWLNamedIndividual, Set<OWLClass>> inferredTypesWithIndirects, Set<ModelValidationReport> validation_reports) {
MapInferenceProvider(boolean isConsistent, Map<OWLNamedIndividual, Set<OWLClass>> inferredTypes, Map<OWLNamedIndividual, Set<OWLClass>> inferredTypesWithIndirects, ValidationResultSet validation_reports) {
this.isConsistent = isConsistent;
this.inferredTypes = inferredTypes;
this.inferredTypesWithIndirects = inferredTypesWithIndirects;
this.validation_reports = validation_reports;
this.validation_results = validation_reports;
}

@Override
Expand Down Expand Up @@ -114,7 +110,9 @@ public Set<OWLClass> getAllTypes(OWLNamedIndividual i) {
return result;
}

public Set<ModelValidationReport> getValidation_reports() {
return validation_reports;
public ValidationResultSet getValidation_results() {
return validation_results;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,20 @@
import java.util.HashSet;
import java.util.Set;

import com.google.gson.annotations.SerializedName;

/**
* @author bgood
*
*/
public class ModelValidationReport {
final String id;

@SerializedName("is-conformant")
boolean conformant;
final String tracker;

@SerializedName("rule-file")
final String rulefile;
Set<Violation> violations;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,53 @@
*/
package org.geneontology.minerva.server.validation;

import java.util.Set;

import com.google.gson.annotations.SerializedName;

/**
* @author bgood
*
*/
public class ShexConstraint {
String property_id;
String propery_range;
String object;
String property;

@SerializedName("intended-range-shapes")
Set<String> intended_range_shapes;
/**
*
*/
public ShexConstraint(String property_id, String propery_range) {
this.property_id = property_id;
this.propery_range = propery_range;


public ShexConstraint(String object, String property, Set<String> intended_range_shapes) {
super();
this.object = object;
this.property = property;
this.intended_range_shapes = intended_range_shapes;
}

public Set<String> getIntended_range_shapes() {
return intended_range_shapes;
}
public void setIntended_range_shapes(Set<String> intended_range_shapes) {
this.intended_range_shapes = intended_range_shapes;
}

public String getProperty_id() {
return property_id;
public String getObject() {
return object;
}
public void setProperty_id(String property_id) {
this.property_id = property_id;

public void setObject(String object) {
this.object = object;
}
public String getPropery_range() {
return propery_range;

public String getProperty() {
return property;
}
public void setPropery_range(String propery_range) {
this.propery_range = propery_range;

public void setProperty(String property) {
this.property = property;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,19 @@
*
*/
public class ShexExplanation {
String shape_id;
String shape;
Set<ShexConstraint> constraints;
/**
*
*/
public ShexExplanation() {
constraints = new HashSet<ShexConstraint>();
}
public String getShape_id() {
return shape_id;
public String getShape() {
return shape;
}
public void setShape_id(String shape_id) {
this.shape_id = shape_id;
public void setShape(String shape) {
this.shape = shape;
}
public Set<ShexConstraint> getConstraints() {
return constraints;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,44 +15,51 @@
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.Resource;

import com.google.gson.annotations.SerializedName;


/**
* @author bgood
*
*/

public class ShexValidationReport extends ModelValidationReport{
@SerializedName("report-type")
public static final String report_type_id = "SHEX_CORE_SCHEMA";
public static final String tracker = "https://github.com/geneontology/go-shapes/issues";

@SerializedName("rule-file")
public static final String rulefile = "https://github.com/geneontology/go-shapes/blob/master/shapes/go-cam-shapes.shex";

public boolean model_is_valid;
@SerializedName("node-matched-shapes")
public Map<String, Set<String>> node_matched_shapes = new HashMap<String, Set<String>>();
public Map<String, Set<String>> node_unmatched_shapes = new HashMap<String, Set<String>>();
public Map<String, String> node_report = new HashMap<String, String>();
public Map<String, Boolean> node_is_valid = new HashMap<String, Boolean>();
public String model_report = "";
public String model_title = "";
/**
*
*/
public ShexValidationReport(String id, Model model) {
super(id, tracker, rulefile);
String q = "select ?cam ?title where {"
+ "?cam <http://purl.org/dc/elements/1.1/title> ?title }";
// + "?cam <"+DC.description.getURI()+"> ?title }";
QueryExecution qe = QueryExecutionFactory.create(q, model);
ResultSet results = qe.execSelect();
if (results.hasNext()) {
QuerySolution qs = results.next();
Resource model_id_resource = qs.getResource("cam");
Literal title = qs.getLiteral("title");
if(id==null) {
id = model_id_resource.getURI();
}
model_title = title.getString();
}

public String getAsText() {
String report = "report type id = "+report_type_id+"\nrulefile = "+rulefile+"\ntracker = "+tracker+"\n";
if(conformant) {
report+="No errors detected";
return report;
}
report+=getViolations().size()+" noncomformant nodes detected:\n";
for(Violation violation : getViolations()) {
report+="node: "+violation.getNode()+" ";
ShexViolation sv = (ShexViolation) violation;
for(ShexExplanation e : sv.getExplanations()) {
report+="was expected to match shape: "+e.shape;
report+=" but did not fit the following constraints:";
for(ShexConstraint c : e.getConstraints()) {
report+="\n\tthe objects of assertions made with "+c.getProperty()+" should be nodes that fit the one of these shapes: ";
report+="\n\t\t"+c.getIntended_range_shapes();
report+="\n\t\tbut, sadly, the object "+c.getObject()+" of one such assertion emanating from the failing node here did not.\n";
}
}
}
qe.close();
model_report = "shape id\tnode uri\tvalidation status\n";
return report;
}

}
Loading

0 comments on commit 63babe7

Please sign in to comment.