/******************************************************************************* * Copyright (c) 2010-2013, Bergmann Gabor, Istvan Rath and Daniel Varro * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bergmann Gabor - initial API and implementation *******************************************************************************/ package hu.bme.mit.incquery.querymetrics; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.incquery.runtime.api.IncQueryEngine; import org.eclipse.incquery.runtime.base.api.NavigationHelper; import org.eclipse.incquery.runtime.exception.IncQueryException; /** * @author Bergmann Gabor * */ public class ModelOnlyMetrics { /** * #triples = #model_elements = #nodes + #edges + #attribute-assignments * Analyses of RDF Triples in Sample Datasets (COLD 2012) */ public static int calcCountTriples(IncQueryEngine engine) throws IncQueryException { return calcCountNodes(engine) + calcCountEdges(engine) + calcCountValueAssignments(engine); } /** * #nodes * Analyses of RDF Triples in Sample Datasets (COLD 2012) */ public static int calcCountNodes(IncQueryEngine engine) throws IncQueryException { final Collection<EObject> eObjects = getAllEObjects(engine); return eObjects.size(); } /** * #edges * Analyses of RDF Triples in Sample Datasets (COLD 2012) */ public static int calcCountEdges(IncQueryEngine engine) throws IncQueryException { final Collection<EObject> eObjects = getAllEObjects(engine); int countTriples = 0; for (EObject eObject : eObjects) { countTriples += countOutDegree(eObject, EdgeType.E_REFERENCE); } return countTriples; } /** * #attribute-assignments * Analyses of RDF Triples in Sample Datasets (COLD 2012) */ public static int calcCountValueAssignments(IncQueryEngine engine) throws IncQueryException { final Collection<EObject> eObjects = getAllEObjects(engine); int countTriples = 0; for (EObject eObject : eObjects) { countTriples += countOutDegree(eObject, EdgeType.E_ATTRIBUTE); } return countTriples; } private static Collection<EObject> getAllEObjects(IncQueryEngine engine) throws IncQueryException { final NavigationHelper baseIndex = engine.getBaseIndex(); final EClass eObject = EcorePackage.eINSTANCE.getEObject(); if (!baseIndex.isInWildcardMode()) baseIndex.registerEClasses(Collections.singleton(eObject)); final Collection<EObject> eObjects = baseIndex.getAllInstances(eObject); return eObjects; } /** * #node-types * Apples and Oranges */ public static int calcCountTypes(IncQueryEngine engine) throws IncQueryException { return getAllUsedEClasses(engine).size(); } private static Set<EClass> getAllUsedEClasses(IncQueryEngine engine) throws IncQueryException { Set<EClass> allEClasses = new HashSet<EClass>(); final Collection<EObject> allEObjects = getAllEObjects(engine); for (EObject eObject : allEObjects) { allEClasses.add(eObject.eClass()); } return allEClasses; } public static enum EdgeType {E_REFERENCE, E_ATTRIBUTE, E_STRUCTURAL_FEATURE} /** * kifok */ public static int countOutDegree(EObject eObject, EdgeType edgeType) { final EClass eClass = eObject.eClass(); switch (edgeType) { case E_ATTRIBUTE: return countFeatureInstances(eObject, eClass.getEAllAttributes()); case E_REFERENCE: return countFeatureInstances(eObject, eClass.getEAllReferences()); case E_STRUCTURAL_FEATURE: return countFeatureInstances(eObject, eClass.getEAllStructuralFeatures()); default: throw new IllegalArgumentException(); } } private static int countFeatureInstances(EObject eObject, final List<? extends EStructuralFeature> features) { int countTriples = 0; for (EStructuralFeature feature : features) { final Object value = eObject.eGet(feature); if (feature.isMany()) { countTriples += ((Collection)value).size(); } else { if (value!= null) countTriples++; } } return countTriples; } /** * befok */ public static int countInDegree(IncQueryEngine engine, Object value) throws IncQueryException { final NavigationHelper baseIndex = engine.getBaseIndex(); if (!baseIndex.isInWildcardMode()) throw new IllegalStateException("works only in wildcard mode"); int result = 0; if (value instanceof EObject) { result += baseIndex.getInverseReferences((EObject)value).size(); } else { result += baseIndex.findByAttributeValue(value).size(); } return result; } /** * ~In-degree, out-degree distribution * Analyses of RDF Triples in Sample Datasets (COLD 2012) */ public static int calcMaxEReferenceDegree(IncQueryEngine engine, boolean inDegree) throws IncQueryException { int maxDegree = Integer.MIN_VALUE; final Collection<EObject> allEObjects = getAllEObjects(engine); for (EObject eObject : allEObjects) { int degree = inDegree ? countInDegree(engine, eObject) : countOutDegree(eObject, EdgeType.E_REFERENCE); if (degree > maxDegree) maxDegree = degree; } return maxDegree; } /** * ~In-degree, out-degree distribution * Analyses of RDF Triples in Sample Datasets (COLD 2012) */ public static double calcAverageEReferenceDegree(IncQueryEngine engine, boolean inDegree) throws IncQueryException { int sumDegree = 0; final Collection<EObject> allEObjects = getAllEObjects(engine); for (EObject eObject : allEObjects) { int degree = inDegree ? countInDegree(engine, eObject) : countOutDegree(eObject, EdgeType.E_REFERENCE); sumDegree += degree; } return sumDegree/((double)allEObjects.size()); } }