package org.aksw.sparqlify.core.datatypes; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.aksw.sparqlify.core.TypeToken; public class XClassUtils { public static Integer getRelation(TypeDistance a, TypeDistance b) { int result; if(a.getCoercion() == null) { if(b.getCoercion() == null) { result = a.getInheritanceDepth() - b.getInheritanceDepth(); } else { result = -1; } } else { if(b.getCoercion() == null) { result = 1; } else { result = b.getInheritanceDepth() - a.getInheritanceDepth(); } } return result; } public static Integer getRelation(TypeDistance[] a, TypeDistance[] b) { boolean hasGreater = false; boolean hasLess = false; for(int i = 0; i < a.length; ++i) { TypeDistance x = a[i]; TypeDistance y = a[i]; if(x == null || y == null) { //return null; throw new NullPointerException(); // TODO Throw an exception or return null? } int d = getRelation(x, y); if (d > 0) { hasGreater = true; } else if (d < 0) { hasLess = true; } } if(hasGreater && hasLess) { return null; } else if(hasGreater) { return 1; } else if(hasLess) { return -1; } return 0; } public static TypeDistance[] getTypeDistance(XClass[] a, XClass[] b, CoercionSystemOld coercions) { int n = Math.min(a.length, b.length); TypeDistance[] result = new TypeDistance[n]; for(int i = 0; i < n; ++i) { XClass given = a[i]; // Don't try to abbreviate with (given == null) ? 0 : getDistance(given, b[i]); // It will break because getDistance may return null if(given == null) { result[i] = new TypeDistance(0, null); } else { result[i] = getTypeDistance(given, b[i], coercions); } } return result; } public static TypeDistance getTypeDistance(XClass source, XClass target, CoercionSystemOld coercions) { Integer depth = getDistance(source, target); TypeDistance result; if(depth != null) { result = new TypeDistance(depth, null); } else { result = findCoercion(source, target, coercions); } return result; } public static List<XClass> resolve(TypeSystem datatypeSystem, Collection<TypeToken> typeNames) { List<XClass> result = new ArrayList<XClass>(typeNames.size()); for(TypeToken typeName : typeNames) { XClass tmp = datatypeSystem.getByName(typeName); if(tmp == null) { throw new RuntimeException("Could not resolve: " + typeName); } result.add(tmp); } return result; } public static Integer getDistance(XClass given, XClass there) { Integer result = _getDistanceInterface(given, there, 0); return result == Integer.MAX_VALUE ? null : result; } public static TypeDistance findCoercion(XClass source, XClass target, CoercionSystemOld coercions) { List<XClass> open = new ArrayList<XClass>(); List<XClass> next = null; open.add(source); int depth = 0; while(!open.isEmpty()) { XMethod method = null; for(XClass item : open) { XMethod tmp = coercions.lookup(source, target); if(tmp != null && method != null) { throw new RuntimeException("Multiple candidates: " + tmp + ", " + item); } method = tmp; } if(method != null) { TypeDistance result = new TypeDistance(depth, method); return result; } ++depth; if(next == null) { next = new ArrayList<XClass>(); } else { next.clear(); } for(XClass item : open) { next.addAll(item.getDirectSuperClasses()); } List<XClass> swap = open; open = next; next = swap; } return null; } private static int _getDistanceInterface(XClass given, XClass there, int depth) { if(given == there) { return depth; } ++depth; int result = Integer.MAX_VALUE; for(XClass item : given.getDirectSuperClasses()) { result = Math.min(result, _getDistanceInterface(item, there, depth)); } /* Class<?> superClass = given.getSuperclass(); if(superClass != null) { result = Math.min(result, _getDistanceInterface(superClass, there, depth)); } */ return result; } public static Integer[] getDistance(XClass[] a, XClass[] b) { int n = Math.min(a.length, b.length); Integer[] result = new Integer[n]; for(int i = 0; i < n; ++i) { XClass given = a[i]; // Don't try to abbreviate with (given == null) ? 0 : getDistance(given, b[i]); // It will break because getDistance may return null if(given == null) { result[i] = 0; } else { result[i] = getDistance(given, b[i]); } } return result; } /** * Including return types * * @param ra * @param rb * @param a * @param b * @return */ public static Integer[] getDistance(XClass ra, XClass rb, XClass[] a, XClass[] b) { int n = Math.min(a.length, b.length); Integer[] result = new Integer[n + 1]; result[0] = getDistance(rb, ra); for(int i = 0; i < n; ++i) { Integer d = getDistance(a[i], b[i]); result[i + 1] = d; } return result; } }