private QueryCriteria queryCriteriaCase(
        AttributeQueryCriteria criteria, List<AttributeReference.Key> arg) {
      final AttributeReference basicAttRef;
      if (arg.isEmpty()) {
        basicAttRef = criteria.getAttributeReference();
      } else {
        basicAttRef = criteria.getAttributeReference().prepend(arg);
      }

      DisjunctionBuilder disjunctionBuilder = new DisjunctionBuilder();

      disjunctionBuilder.add(criteria);

      for (int i = 0; i < basicAttRef.getKeys().size(); i++) {
        AttributeReference existsAttRef = basicAttRef.subReference(0, i + 1);

        List<AttributeReference.Key> newArg =
            basicAttRef.getKeys().subList(i + 1, basicAttRef.getKeys().size());

        QueryCriteria plainNewBody = criteria.accept(QUERY_CRITERIA_FACTORY, newArg);

        QueryCriteria newBody =
            plainNewBody.accept(this, Collections.<AttributeReference.Key>emptyList());

        disjunctionBuilder.add(new ExistsQueryCriteria(existsAttRef, newBody));
      }

      return disjunctionBuilder.build();
    }
    @Override
    public QueryCriteria visit(ExistsQueryCriteria criteria, Void arg) {
      Set<AttributeReference> combinedAttRefs =
          combineAttributeReferences(criteria.getAttributeReference());

      QueryCriteria subQuery = criteria.getBody().accept(this, null);

      DisjunctionBuilder disjunctionBuilder = new DisjunctionBuilder();
      for (AttributeReference combinedAttRef : combinedAttRefs) {
        disjunctionBuilder.add(new ExistsQueryCriteria(combinedAttRef, subQuery));
      }

      return disjunctionBuilder.build();
    }
    @Override
    public QueryCriteria visit(TypeIsQueryCriteria criteria, Void arg) {
      Set<AttributeReference> combinedAttRefs =
          combineAttributeReferences(criteria.getAttributeReference());
      if (combinedAttRefs.size() == 1) {
        return criteria;
      }

      DisjunctionBuilder disjunctionBuilder = new DisjunctionBuilder();
      for (AttributeReference combinedAttRef : combinedAttRefs) {
        disjunctionBuilder.add(new TypeIsQueryCriteria(combinedAttRef, criteria.getExpectedType()));
      }

      return disjunctionBuilder.build();
    }
    @Override
    public QueryCriteria visit(ContainsAttributesQueryCriteria criteria, Void arg) {
      Set<AttributeReference> combinedAttRefs =
          combineAttributeReferences(criteria.getAttributeReference());
      if (combinedAttRefs.size() == 1) {
        return criteria;
      }

      DisjunctionBuilder disjunctionBuilder = new DisjunctionBuilder();
      for (AttributeReference combinedAttRef : combinedAttRefs) {
        disjunctionBuilder.add(
            new ContainsAttributesQueryCriteria(
                combinedAttRef, criteria.getAttributes(), criteria.isExclusive()));
      }

      return disjunctionBuilder.build();
    }