[Demonstration 1]

[Buggy Method]
@Override
public void execute() throws ExecutionException {
    AnnotationSet annotationSet = document.getAnnotations(annotationSetName);
    AnnotationSet candidateAnnotationSet = annotationSet.get(candidateAnnotationType, REQUIRED_CANDIDATE_FEATURES);
    // disambiguate each context separately
    for (Annotation context : annotationSet.get(contextAnnotationType)) {
        Set<SortedSet<Location>> lookups = new HashSet<SortedSet<Location>>();
        // collect candidate locations at each lookup
        Set<Integer> addedAnnotationIDs = new HashSet<Integer>();
        AnnotationSet candidatesInContext = candidateAnnotationSet.get(context.getStartNode().getOffset(), context.getEndNode().getOffset());
        for (Annotation lookup : candidatesInContext) {
            if (addedAnnotationIDs.contains(lookup.getId()))
                continue;
            // collect candidate locations at this lookup
            SortedSet<Location> candidates = new TreeSet<Location>();
            AnnotationSet candidatesInLookup = candidatesInContext.get(lookup.getStartNode().getOffset(), lookup.getEndNode().getOffset());
            for (Annotation candidate : candidatesInLookup) {
                FeatureMap candidateFeatures = candidate.getFeatures();
                Object instFeature = candidateFeatures.get(ID_FEATURE_NAME);
                Object typeFeature = candidateFeatures.get(TYPE_FEATURE_NAME);
                Object ancestorsFeature = candidateFeatures.get(ANCESTORS_FEATURE_NAME);
                Object latitudeFeature = candidateFeatures.get(LATITUDE_FEATURE_NAME);
                Object longitudeFeature = candidateFeatures.get(LONGITUDE_FEATURE_NAME);
                Object populationFeature = candidateFeatures.get(POPULATION_FEATURE_NAME);
                // should not happen according to GATE documentation
                if (instFeature == null || typeFeature == null || ancestorsFeature == null || latitudeFeature == null || longitudeFeature == null) {
                    throw new ExecutionException("GATE sucks");
                }
                // parse ID from instance
                String url = (String) instFeature;
                int id = Integer.parseInt(url.substring(GEONAMES_ID_PREFIX.length(), url.length() - GEONAMES_ID_SUFFIX.length()));
                // parse type
                String type = (String) typeFeature;
                type = type.substring(GEONAMES_TYPE_PREFIX.length());
                // parse latitude and longitude
                double latitude = Double.parseDouble((String) ((Collection) latitudeFeature).iterator().next());
                double longitude = Double.parseDouble((String) ((Collection) longitudeFeature).iterator().next());
                // parse population if present
                long population = 0;
                if (populationFeature != null)
                    population = Long.parseLong((String) ((Collection) populationFeature).iterator().next());
                // parse the ancestor IDs
                Set<Integer> ancestors = new HashSet<Integer>();
                for (Object ancestorsFeatureItem : (Collection) ancestorsFeature) {
                    String ancestor = (String) ancestorsFeatureItem;
                    ancestors.add(Integer.valueOf(ancestor.substring(GEONAMES_ID_PREFIX.length(), ancestor.length() - GEONAMES_ID_SUFFIX.length())));
                }
                // add location to the set of candidates
                candidates.add(new Location(id, type, latitude, longitude, population, ancestors));
                addedAnnotationIDs.add(candidate.getId());
            }
            // add the set of candidates to the set of lookups
            lookups.add(candidates);
        }
        // collect the instances to keep
        SortedSet<Location> locations = Disambiguator.disambiguate(lookups, keepAncestors);
        Set<String> instancesToKeep = new HashSet<String>();
        for (Location location : locations) {
            instancesToKeep.add(GEONAMES_ID_PREFIX + location.getId() + GEONAMES_ID_SUFFIX);
        }
        // remove other instances
        for (Annotation candidate : candidatesInContext) {
            String instance = (String) candidate.getFeatures().get(ID_FEATURE_NAME);
            if (instance == null || !instancesToKeep.contains(instance))
                annotationSet.remove(candidate);
        }
        // add the coordinates of the center as features of the context annotation, because we can
        double[] centerCoordinates = calculateCenterCoordinates(locations);
        context.getFeatures().put(LATITUDE_FEATURE_NAME, centerCoordinates[0]);
        context.getFeatures().put(LONGITUDE_FEATURE_NAME, centerCoordinates[1]);
    }
}

[Buggy Hunk]
String type = (String) typeFeature;

[Patch]
String type = (String) ((Collection) typeFeature).iterator().next();

[Demonstration 2]

[Buggy Method]
@Override
public void onMessage(PFlow pf) {
    List<PFlow> list = new FastList<PFlow>();
    IndexHits<Relationship> q = Order.context(pf.getOPNode());
    try {
        Iterator<Relationship> it = q.iterator();
        while (it.hasNext()) {
            Relationship r = it.next();
            Subscribable<PFlow> onQuestion = pf.getManipulator().onQuestion(r);
            if (onQuestion != null) {
                PFlow nextPF = new PFlow(pf, pf.getVector().question(r));
                nextPF.questionChannel().subscribe(onQuestion);
                list.add(nextPF);
            } else {
                pf.sendAnswer(pf.getVector().answered(r));
            }
        }
    } finally {
        q.close();
    }
    if (list.isEmpty())
        pf.done();
    else
        pf.waitBeforeClosePipe(list.size());
    for (PFlow nextPF : list) {
        nextPF.questionChannel().publish(nextPF);
    }
}

[Buggy Hunk]
PFlow nextPF = new PFlow(pf, pf.getVector().question(r));

[Patch]
PFlow nextPF = new PFlow(pf, pf.getVector().question2(r));

[Demonstration 3]

[Buggy Method]
public static void getColRange(Data[] x, double[][] range) {
    int n = x.length;
    int p = x[0].data.length;
    for (int i = 0; i < p; i++) {
        range[i][0] = Double.NEGATIVE_INFINITY;
        range[i][1] = Double.POSITIVE_INFINITY;
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < p; j++) {
            double value = x[n].data[j];
            if (value > range[j][0])
                range[j][0] = value;
            if (value < range[j][1])
                range[j][1] = value;
        }
    }
}

[Buggy Hunk]
double value = x[n].data[j];

[Patch]
double value = x[i].data[j];