public static Op applyCovers(
      Op parentOp, SparqlViewCache conceptMap, Map<Op, CacheResult> opToCover) {

    Op result;

    CacheResult cacheResult = opToCover.get(parentOp);
    if (cacheResult == null) {
      // Recursively descend to the children
      List<Op> subOps = OpUtils.getSubOps(parentOp);
      List<Op> newSubOps =
          subOps
              .stream()
              .map(child -> applyCovers(child, conceptMap, opToCover))
              .collect(Collectors.toList());

      result = OpUtils.copy(parentOp, newSubOps);
    } else {
      // CacheHit cacheHit = cacheHits.iterator().next();
      // CacheResult cacheResult = cacheHits;
      QuadFilterPatternCanonical qfpc = cacheResult.getReplacementPattern();

      Op o = qfpc.toOp();

      Collection<Table> tables = cacheResult.getTables();
      Op opTable = null;
      for (Table table : tables) {
        Op tmp = OpTable.create(table);

        if (opTable == null) {
          opTable = tmp;
        } else {
          opTable = OpJoin.create(opTable, tmp);
        }
      }

      // System.out.println("Table size: " + table.size());

      if (o instanceof OpNull) {
        result = opTable;
      } else {
        result = OpJoin.create(opTable, o);
      }
    }
    return result;
  }