/** @author Jeremy Debattista */ public class DigitalSignatureUsage implements QualityMetric { private static final Resource ENDORSEMENT = ModelFactory.createDefaultModel().createResource("http://xmlns.com/wot/0.1/Endorsement"); private static final Property ASSURANCE = ModelFactory.createDefaultModel().createProperty("http://xmlns.com/wot/0.1/assurance"); private static final Property ENDORSER = ModelFactory.createDefaultModel().createProperty("http://xmlns.com/wot/0.1/endorser"); private HTreeMap<String, DigitalSignature> docs = MapDbFactory.createFilesystemDB().createHashMap("dig-sig-docs").make(); private HTreeMap<String, DigitalSignature> endorsements = MapDbFactory.createFilesystemDB().createHashMap("endorcements-docs").make(); private static Logger logger = LoggerFactory.getLogger(DigitalSignatureUsage.class); @Override public void compute(Quad quad) { logger.debug("Computing : {} ", quad.asTriple().toString()); Node subject = quad.getSubject(); Node object = quad.getObject(); if (quad.getObject().equals(FOAF.Document.asNode())) { docs.putIfAbsent(subject.toString(), new DigitalSignature()); } if (quad.getPredicate().equals(ASSURANCE.asNode())) { DigitalSignature ds; if (endorsements.containsKey(object.getURI())) { ds = endorsements.get(object.getURI()); } else { ds = new DigitalSignature(); ds.endorcement = object.getURI(); } ds.assurance = subject.getURI(); docs.put(subject.toString(), ds); endorsements.put(object.getURI(), ds); } if (quad.getPredicate().equals(ENDORSER.asNode())) { DigitalSignature ds; if (endorsements.containsKey(object.getURI())) { ds = endorsements.get(object.getURI()); } else { ds = new DigitalSignature(); ds.endorcement = subject.getURI(); } ds.endorcer = object.getURI(); } if (quad.getObject().equals(ENDORSEMENT.asNode())) { DigitalSignature ds = new DigitalSignature(); ds.endorcement = subject.getURI(); endorsements.putIfAbsent(subject.getURI(), ds); } } @Override public double metricValue() { double noDocs = this.docs.size(); double noDocsWithoutEndorcement = 0.0; for (DigitalSignature ds : this.docs.values()) noDocsWithoutEndorcement += (ds.fullEndorcement()) ? 1 : 0; statsLogger.info( "DigitalSignatureUsage. Dataset: {} - Total # Documents : {}; # Documents without Endorcement : {};", EnvironmentProperties.getInstance().getDatasetURI(), noDocs, noDocsWithoutEndorcement); return (noDocsWithoutEndorcement / noDocs); } @Override public Resource getMetricURI() { return DQM.DigitalSignatureUsage; } @Override public ProblemList<?> getQualityProblems() { return null; } @Override public boolean isEstimate() { return false; } @Override public Resource getAgentURI() { return DQM.LuzzuProvenanceAgent; } private class DigitalSignature implements Serializable { /** */ private static final long serialVersionUID = -2185956592313988605L; private String endorcement = null; private String endorcer = null; private String assurance = null; public boolean fullEndorcement() { if ((endorcement == null) || (endorcer == null) || (assurance == null)) return false; return true; } @Override public int hashCode() { return endorcement.hashCode(); } @Override public boolean equals(Object obj) { if (obj instanceof DigitalSignature) { DigitalSignature other = (DigitalSignature) obj; return this.endorcement.equals(other.endorcement); } return false; } } }
/** * This metric is based on the metric defined by Hogan et al. Weaving the Pedantic Web. This metric * checks if the assessed dataset has a defined classed placed in the triple's predicate and defined * property in the object position. If an undefined class or property is used, then it is ignored * * <p>Best Case : 1 Worst Case : 0 * * @author Jeremy Debattista */ public class MisplacedClassesOrProperties implements QualityMetric { private final Resource METRIC_URI = DQM.MisplacedClassesOrPropertiesMetric; private static Logger logger = LoggerFactory.getLogger(MisplacedClassesOrProperties.class); private HTreeMap<String, Boolean> seenProperties = MapDbFactory.createFilesystemDB() .createHashMap("misplaced-classes-seenProperties") .makeOrGet(); private HTreeMap<String, Boolean> seenClasses = MapDbFactory.createFilesystemDB().createHashMap("misplaced-classes-seenClasses").makeOrGet(); private double misplacedClassesCount = 0.0; private double totalClassesCount = 0.0; private double misplacedPropertiesCount = 0.0; private double totalPropertiesCount = 0.0; private List<Model> problemList = new ArrayList<Model>(); public void compute(Quad quad) { // logger.debug("Assessing {}", quad.asTriple().toString()); Node predicate = quad.getPredicate(); // retrieve predicate Node object = quad.getObject(); // retrieve object // checking if classes are found in the property position // logger.info("Is the used predicate {} actually a class?", predicate.getURI()); this.totalPropertiesCount++; if (seenProperties.containsKey(predicate.toString())) { if (!(seenProperties.get(predicate.toString()))) { this.misplacedPropertiesCount++; this.createProblemModel(quad.getSubject(), predicate, DQM.MisplacedClass); } } else { if ((VocabularyLoader.isClass(predicate)) && (VocabularyLoader.checkTerm(predicate))) { this.misplacedPropertiesCount++; this.createProblemModel(quad.getSubject(), predicate, DQM.MisplacedClass); seenProperties.put(predicate.toString(), false); } seenProperties.put(predicate.toString(), true); } // checking if properties are found in the object position if ((object.isURI()) && (predicate.getURI().equals(RDF.type.getURI())) && (VocabularyLoader.checkTerm(object))) { // logger.info("Checking {} for misplaced class", object.getURI()); this.totalClassesCount++; if (seenClasses.containsKey(object.toString())) { if (!(seenClasses.get(object.toString()))) { this.misplacedClassesCount++; this.createProblemModel(quad.getSubject(), object, DQM.MisplacedProperty); } } else { if (VocabularyLoader.isProperty(object)) { this.misplacedClassesCount++; this.createProblemModel(quad.getSubject(), object, DQM.MisplacedProperty); seenClasses.put(object.toString(), false); } seenClasses.put(object.toString(), true); } } } private void createProblemModel(Node resource, Node classOrProperty, Resource type) { Model m = ModelFactory.createDefaultModel(); Resource subject = m.createResource(resource.toString()); m.add(new StatementImpl(subject, QPRO.exceptionDescription, type)); if (type.equals(DQM.MisplacedClass)) m.add(new StatementImpl(subject, DQM.hasMisplacedClass, m.asRDFNode(classOrProperty))); else m.add(new StatementImpl(subject, DQM.hasMisplacedProperty, m.asRDFNode(classOrProperty))); this.problemList.add(m); } /** * This method computes metric value for the object of this class. * * @return (total number of undefined classes or properties) / (total number of classes or * properties) */ public double metricValue() { logger.info("Number of Misplaced Classes: {}", this.misplacedClassesCount); logger.info("Number of Misplaced Properties: {}", this.misplacedPropertiesCount); double metricValue = 1.0; double misplaced = this.misplacedPropertiesCount + this.misplacedPropertiesCount; if (misplaced > 0.0) metricValue = 1.0 - (misplaced / (this.totalPropertiesCount + this.totalClassesCount)); logger.info("Metric Value: {}", metricValue); return metricValue; } /** * Returns Metric URI * * @return metric URI */ public Resource getMetricURI() { return this.METRIC_URI; } /** * Returns list of problematic Quads * * @return list of problematic quads */ public ProblemList<?> getQualityProblems() { ProblemList<Model> tmpProblemList = null; try { if (this.problemList != null && this.problemList.size() > 0) { tmpProblemList = new ProblemList<Model>(this.problemList); } else { tmpProblemList = new ProblemList<Model>(); } } catch (ProblemListInitialisationException problemListInitialisationException) { logger.error(problemListInitialisationException.getMessage()); } return tmpProblemList; } /* (non-Javadoc) * @see de.unibonn.iai.eis.luzzu.assessment.QualityMetric#isEstimate() */ @Override public boolean isEstimate() { return false; } /* (non-Javadoc) * @see de.unibonn.iai.eis.luzzu.assessment.QualityMetric#getAgentURI() */ @Override public Resource getAgentURI() { return DQM.LuzzuProvenanceAgent; } }