public static void collect(Set<FeatureStructure> aFSes, FeatureStructure aFS) { if (aFS != null && !aFSes.contains(aFS)) { aFSes.add(aFS); for (Feature f : aFS.getType().getFeatures()) { if (!f.getRange().isPrimitive() && !CAS.FEATURE_BASE_NAME_SOFA.equals(f.getShortName())) { collect(aFSes, aFS.getFeatureValue(f)); } } } }
public static Set<FeatureStructure> getNonIndexedFSes(CAS aCas) { TypeSystem ts = aCas.getTypeSystem(); Set<FeatureStructure> allIndexedFS = collectIndexed(aCas); Set<FeatureStructure> allReachableFS = collectReachable(aCas); // Remove all that are indexed allReachableFS.removeAll(allIndexedFS); // Remove all that are not annotations allReachableFS.removeIf(fs -> !ts.subsumes(aCas.getAnnotationType(), fs.getType())); // All that is left are non-index annotations return allReachableFS; }
@Override public boolean check(Project aProject, CAS aCas, List<LogMessage> aMessages) { Map<FeatureStructure, FeatureStructure> nonIndexed = getNonIndexedFSesWithOwner(aCas); if (!nonIndexed.isEmpty()) { aMessages.add(new LogMessage(this, LogLevel.ERROR, "Unindexed feature structures: %d", nonIndexed.size())); for (Entry<FeatureStructure, FeatureStructure> e : nonIndexed.entrySet()) { aMessages.add(new LogMessage(this, LogLevel.ERROR, "Non-indexed feature structure [%s] reachable through [%s]", e.getKey(), e.getValue())); } } // else { // aMessages.add(String.format("[%s] OK", getClass().getSimpleName())); // } return nonIndexed.isEmpty(); } }
public static Map<FeatureStructure, FeatureStructure> getNonIndexedFSesWithOwner(CAS aCas) { TypeSystem ts = aCas.getTypeSystem(); LowLevelCAS llcas = aCas.getLowLevelCAS(); Set<FeatureStructure> allIndexedFS = collectIndexed(aCas); Map<FeatureStructure, FeatureStructure> allReachableFS = new TreeMap<>( Comparator.comparingInt(llcas::ll_getFSRef)); FSIterator<FeatureStructure> i = aCas.getIndexRepository().getAllIndexedFS( aCas.getTypeSystem().getTopType()); i.forEachRemaining(fs -> collect(allReachableFS, allIndexedFS, fs, fs)); // Remove all that are not annotations allReachableFS.entrySet().removeIf(e -> !ts.subsumes(aCas.getAnnotationType(), e.getKey().getType())); // Remove all that are indexed allReachableFS.entrySet().removeIf(e -> e.getKey() == e.getValue()); // All that is left are non-index annotations return allReachableFS; } }
@Override public void repair(Project aProject, CAS aCas, List<LogMessage> aMessages) Set<FeatureStructure> nonIndexed = getNonIndexedFSes(aCas);
/** * Recursively collect referenced FSes and also record for each the last indexed FS that refers * the them. */ public static void collect(Map<FeatureStructure, FeatureStructure> aFSes, Set<FeatureStructure> aIndexed, FeatureStructure aFS, FeatureStructure aLastIndexed) { if (aFS != null && !aFSes.containsKey(aFS)) { // We might find an annotation indirectly. In that case make sure we consider it as // an indexed annotation instead of wrongly recording it as non-indexed if (aIndexed.contains(aFS)) { aFSes.put(aFS, aFS); } else { aFSes.put(aFS, aLastIndexed); } for (Feature f : aFS.getType().getFeatures()) { if (!f.getRange().isPrimitive() && !CAS.FEATURE_BASE_NAME_SOFA.equals(f.getShortName())) { collect(aFSes, aIndexed, aFS.getFeatureValue(f), aIndexed.contains(aFS) ? aFS : aLastIndexed); } } } }
@Override public void repair(Project aProject, CAS aCas, List<LogMessage> aMessages) Map<FeatureStructure, FeatureStructure> nonIndexed = getNonIndexedFSesWithOwner(aCas);
public static Set<FeatureStructure> collectReachable(CAS aCas) { LowLevelCAS llcas = aCas.getLowLevelCAS(); Set<FeatureStructure> fses = new TreeSet<>(Comparator.comparingInt(llcas::ll_getFSRef)); FSIterator<FeatureStructure> i = aCas.getIndexRepository().getAllIndexedFS( aCas.getTypeSystem().getTopType()); i.forEachRemaining(fs -> collect(fses, fs)); return fses; }