code: public Hits<ExplainedAttribute> findAttributes(
        EntityType sourceEntityType, Set<String> queryTerms, Collection<OntologyTerm> ontologyTerms) {
      Iterable<String> attributeIdentifiers =
          semanticSearchServiceHelper.getAttributeIdentifiers(sourceEntityType);
  
      QueryRule disMaxQueryRule =
          semanticSearchServiceHelper.createDisMaxQueryRuleForAttribute(queryTerms, ontologyTerms);
  
      List<QueryRule> finalQueryRules =
          Lists.newArrayList(new QueryRule(AttributeMetadata.ID, Operator.IN, attributeIdentifiers));
  
      if (!disMaxQueryRule.getNestedRules().isEmpty()) {
        finalQueryRules.addAll(Arrays.asList(new QueryRule(Operator.AND), disMaxQueryRule));
      }
  
      Stream<Entity> attributeEntities =
          dataService.findAll(ATTRIBUTE_META_DATA, new QueryImpl<>(finalQueryRules));
  
      Map<String, String> collectExpanedQueryMap =
          semanticSearchServiceHelper.collectExpandedQueryMap(queryTerms, ontologyTerms);
  
      // Because the explain-API can be computationally expensive we limit the explanation to the top
      // 10 attributes
      List<ExplainedAttribute> attributeSearchHits = new ArrayList<>();
      AtomicInteger count = new AtomicInteger(0);
      attributeEntities.forEach(
          attributeEntity -> {
            Attribute attribute =
                sourceEntityType.getAttribute(attributeEntity.getString(AttributeMetadata.NAME));
            Set<ExplainedQueryString> explainedQueryStrings;
            boolean isHighQuality;
            if (count.get() < MAX_NUMBER_EXPLAINED_ATTRIBUTES) {
              explainedQueryStrings =
                  convertAttributeToExplainedAttribute(
                      attribute, collectExpanedQueryMap, new QueryImpl<>(finalQueryRules));
  
              isHighQuality =
                  isSingleMatchHighQuality(
                      queryTerms,
                      Sets.newHashSet(collectExpanedQueryMap.values()),
                      explainedQueryStrings);
            } else {
              explainedQueryStrings = emptySet();
              isHighQuality = false;
            }
            attributeSearchHits.add(
                ExplainedAttribute.create(attribute, explainedQueryStrings, isHighQuality));
            count.incrementAndGet();
          });
  
      return Hits.create(
          attributeSearchHits
              .stream()
              .map(explainedAttribute -> Hit.create(explainedAttribute, 1f))
              .collect(toList()));
    }
docs: public for testability