AnswerServerController { @RequestMapping(value = "entity-facts", method = RequestMethod.GET) public List<SourcedFact> getEntityFacts( @RequestParam(ENTITY_PARAM) final String entity, @RequestParam(value = MAX_RESULTS_PARAM, required = false) final Integer maxResults, @RequestParam(INDEXES_PARAM) final Collection<String> databases ) { final AciParameters params = new AciParameters(AnswerServerActions.Report.name()); params.add(ReportParams.Entity.name(), entity); if (maxResults != null) { params.add(ReportParams.MaxResults.name(), maxResults); } final ReportResponsedata entityInfo = aciService.executeAction( configService.getConfig().getAnswerServer().toAciServerDetails(), params, reportProcessor); final List<ReportFact> reportFacts; if (entityInfo.getReport() != null) { reportFacts = entityInfo.getReport().getItem().stream() .flatMap(item -> item.getMetadata().getFact().stream()) .limit(maxResults == null ? DEFAULT_MAX_FACTS : maxResults) .collect(Collectors.toList()); } else { reportFacts = Collections.emptyList(); } final Map<String, SourcedFact> sourcedFacts = new HashMap<>(); if (!reportFacts.isEmpty()) { final FieldText fieldText = new MATCH( "*/" + FACT_ID_FIELD, reportFacts.stream().map(ReportFact::getSource).collect(Collectors.toList())); final IdolQueryRestrictions queryRestrictions = queryRestrictionsBuilderFactory.getObject() .fieldText(fieldText.toString()) .databases(databases) .build(); final IdolQueryRequest queryRequest = queryRequestBuilderFactory.getObject() .queryRestrictions(queryRestrictions) .maxResults(reportFacts.size() * 100) .queryType(QueryRequest.QueryType.RAW) .print(PrintParam.Fields.name()) .printField(FACT_ID_FIELD) .printField(FACT_SENTENCE_FIELD) .build(); final Documents<IdolSearchResult> docs = documentsService.queryTextIndex(queryRequest); final Map<String, List<DocumentFact>> docsByFactId = new HashMap<>(); for (final IdolSearchResult doc : docs.getDocuments()) { for (final FieldValue<?> factsField : doc.getFieldMap().get("facts").getValues()) { for (final Serializable factField : ((Map<String, List<Serializable>>) factsField.getValue()) .get("fact_extract_") ) { final List<String> factIds = ((Map<String, List<String>>) factField) .getOrDefault("id", Collections.emptyList()); final String sentence = ((Map<String, List<String>>) factField).get("sentence").get(0); for (final String factId : factIds) { if (!docsByFactId.containsKey(factId)) { docsByFactId.put(factId, new ArrayList<>()); } docsByFactId.get(factId).add( new DocumentFact(doc.getIndex(), doc.getReference(), sentence)); } } } } for (final ReportFact reportFact : reportFacts) { if (docsByFactId.containsKey(reportFact.getSource())) { sourcedFacts.put(reportFact.getSource(), new SourcedFact(reportFact, docsByFactId.get(reportFact.getSource()))); } } } return new ArrayList<>(sourcedFacts.values()); } @Autowired  AnswerServerController(
        final AciService aciService,
        final AskAnswerServerService askAnswerServerService,
        final ObjectFactory<AskAnswerServerRequestBuilder> requestBuilderFactory,
        final ConfigService<IdolFindConfig> configService,
        final ProcessorFactory processorFactory,
        final DocumentsService<IdolQueryRequest, ?, ?, IdolQueryRestrictions, IdolSearchResult, AciErrorException> documentsService,
        final org.springframework.beans.factory.ObjectFactory<? extends QueryRestrictionsBuilder<IdolQueryRestrictions, String, ?>> queryRestrictionsBuilderFactory,
        final ObjectFactory<? extends QueryRequestBuilder<IdolQueryRequest, IdolQueryRestrictions, ?>> queryRequestBuilderFactory
    ); @RequestMapping(value = ASK_PATH, method = RequestMethod.GET) List<AskAnswer> ask(@RequestParam(TEXT_PARAM)
                               final String text,
                               @RequestParam(value = FIELDTEXT_PARAM, required = false)
                               final String fieldText,
                               @RequestParam(value = MAX_RESULTS_PARAM, required = false)
                               final Integer maxResults); @RequestMapping(value = "entity-facts", method = RequestMethod.GET) List<SourcedFact> getEntityFacts(
        @RequestParam(ENTITY_PARAM) final String entity,
        @RequestParam(value = MAX_RESULTS_PARAM, required = false) final Integer maxResults,
        @RequestParam(INDEXES_PARAM) final Collection<String> databases
    );  }
@Test public void getEntityFacts_singleResult() { mockQueryResponse(Collections.singletonList( createDoc("doc 1", Collections.singletonList( createFactField("first fact", Collections.singletonList("1")) )) )); final List<SourcedFact> response = controller.getEntityFacts("space", 7, Collections.singletonList("db")); final ArgumentCaptor<AciParameters> paramsCaptor = ArgumentCaptor.forClass(AciParameters.class); Mockito.verify(aciService).executeAction(any(), paramsCaptor.capture(), any()); Assert.assertEquals("should send report action to answerserver", Report.name(), paramsCaptor.getValue().get(AciConstants.PARAM_ACTION)); Assert.assertEquals("should send entity to answerserver", "space", paramsCaptor.getValue().get(ReportParams.Entity.name())); Assert.assertEquals("should send max results to answerserver", "7", paramsCaptor.getValue().get(ReportParams.MaxResults.name())); Assert.assertNull("should not send timeout to answerserver when not configured", paramsCaptor.getValue().get(ReportParams.Timeout.name())); Assert.assertEquals("should return matching fact", 1, response.size()); Assert.assertEquals("should return first fact", "1", response.get(0).fact.getSource()); Assert.assertEquals("fact should include matching document", 1, response.get(0).documents.size()); final DocumentFact doc = response.get(0).documents.get(0); Assert.assertEquals("should return document index", "db", doc.index); Assert.assertEquals("should return document ref", "doc 1", doc.reference); Assert.assertEquals("should return document sentence", "first fact", doc.sentence); }
@Test public void getEntityFacts_docWithMultipleSentences() { mockQueryResponse(Collections.singletonList( createDoc("doc 1", Arrays.asList( createFactField("first fact", Collections.singletonList("1")), createFactField("second fact", Collections.singletonList("2")) )) )); final List<SourcedFact> response = controller.getEntityFacts("space", 7, Collections.singletonList("db")); Assert.assertEquals("should return both facts", 2, response.size()); Assert.assertEquals("should return first fact", "1", response.get(0).fact.getSource()); Assert.assertEquals("first fact should include document", 1, response.get(0).documents.size()); Assert.assertEquals("first fact document should be correct", "doc 1", response.get(0).documents.get(0).reference); Assert.assertEquals("should return second fact", "2", response.get(1).fact.getSource()); Assert.assertEquals("second fact should include document", 1, response.get(1).documents.size()); Assert.assertEquals("second fact document should be correct", "doc 1", response.get(1).documents.get(0).reference); }
@Test public void getEntityFacts_sentenceWithMultipleFacts() { mockQueryResponse(Collections.singletonList( createDoc("doc 1", Collections.singletonList( createFactField("first fact", Arrays.asList("1", "2")) )) )); final List<SourcedFact> response = controller.getEntityFacts("space", 7, Collections.singletonList("db")); Assert.assertEquals("should return both facts", 2, response.size()); Assert.assertEquals("should return first fact", "1", response.get(0).fact.getSource()); Assert.assertEquals("first fact should include document", 1, response.get(0).documents.size()); Assert.assertEquals("should return second fact", "2", response.get(1).fact.getSource()); Assert.assertEquals("second fact should include document", 1, response.get(1).documents.size()); }
@Test public void getEntityFacts_docWithSameFactTwice() { mockQueryResponse(Collections.singletonList( createDoc("doc 1", Arrays.asList( createFactField("first fact", Collections.singletonList("1")), createFactField("first fact again", Collections.singletonList("1")) )) )); final List<SourcedFact> response = controller.getEntityFacts("space", 7, Collections.singletonList("db")); Assert.assertEquals("should return the fact", 1, response.size()); Assert.assertEquals("fact should include the document twice", 2, response.get(0).documents.size()); Assert.assertEquals("first reference should be correct", "doc 1", response.get(0).documents.get(0).reference); Assert.assertEquals("first sentence should be correct", "first fact", response.get(0).documents.get(0).sentence); Assert.assertEquals("second reference should be correct", "doc 1", response.get(0).documents.get(1).reference); Assert.assertEquals("second sentence should be correct", "first fact again", response.get(0).documents.get(1).sentence); }
@Test public void getEntityFacts_multipleDocs() { mockQueryResponse(Arrays.asList( createDoc("doc 1", Collections.singletonList( createFactField("first fact", Collections.singletonList("1")) )), createDoc("doc 2", Collections.singletonList( createFactField("second fact", Collections.singletonList("2")) )) )); final List<SourcedFact> response = controller.getEntityFacts("space", 7, Collections.singletonList("db")); Assert.assertEquals("should return both facts", 2, response.size()); Assert.assertEquals("should return first fact", "1", response.get(0).fact.getSource()); Assert.assertEquals("first fact should include document", 1, response.get(0).documents.size()); Assert.assertEquals("first fact document should be correct", "doc 1", response.get(0).documents.get(0).reference); Assert.assertEquals("should return second fact", "2", response.get(1).fact.getSource()); Assert.assertEquals("second fact should include document", 1, response.get(1).documents.size()); Assert.assertEquals("second fact document should be correct", "doc 2", response.get(1).documents.get(0).reference); }
@Test public void getEntityFacts_multipleDocsWithSameFact() { mockQueryResponse(Arrays.asList( createDoc("doc 1", Collections.singletonList( createFactField("first fact", Collections.singletonList("1")) )), createDoc("doc 2", Collections.singletonList( createFactField("first fact again", Collections.singletonList("1")) )) )); final List<SourcedFact> response = controller.getEntityFacts("space", 7, Collections.singletonList("db")); Assert.assertEquals("should return the fact", 1, response.size()); Assert.assertEquals("fact should include both documents", 2, response.get(0).documents.size()); Assert.assertEquals("first document should be correct", "doc 1", response.get(0).documents.get(0).reference); Assert.assertEquals("second document should be correct", "doc 2", response.get(0).documents.get(1).reference); }
@Test public void getEntityFacts_multipleReports() { mockReportResponse(Arrays.asList( createReport(Collections.singletonList(createFact("1"))), createReport(Collections.singletonList(createFact("2"))) )); mockQueryResponse(Collections.singletonList( createDoc("doc 1", Arrays.asList( createFactField("first fact", Collections.singletonList("1")), createFactField("second fact", Collections.singletonList("2")) )) )); final List<SourcedFact> response = controller.getEntityFacts("space", 7, Collections.singletonList("db")); Assert.assertEquals("should return both facts", 2, response.size()); Assert.assertEquals("should return first fact", "1", response.get(0).fact.getSource()); Assert.assertEquals("should return second fact", "2", response.get(1).fact.getSource()); }
@Test public void getEntityFacts_duplicateReports() { mockReportResponse(Arrays.asList( createReport(Collections.singletonList(createFact("1"))), createReport(Collections.singletonList(createFact("1"))) )); mockQueryResponse(Collections.singletonList( createDoc("doc 1", Collections.singletonList( createFactField("first fact", Collections.singletonList("1")) )) )); final List<SourcedFact> response = controller.getEntityFacts("space", 7, Collections.singletonList("db")); Assert.assertEquals("should return the fact only once", 1, response.size()); Assert.assertEquals("should return first fact", "1", response.get(0).fact.getSource()); }
@Test public void getEntityFacts_noFacts() { when(aciService.executeAction(any(), any(), any())).thenReturn(new ReportResponsedata()); final List<SourcedFact> response = controller.getEntityFacts("space", 7, Collections.singletonList("db")); Assert.assertEquals("should return empty list", Collections.emptyList(), response); }
@Test public void getEntityFacts_noMaxResults() { final List<SourcedFact> response = controller.getEntityFacts("space", null, Collections.singletonList("db")); final ArgumentCaptor<AciParameters> paramsCaptor = ArgumentCaptor.forClass(AciParameters.class); Mockito.verify(aciService).executeAction(any(), paramsCaptor.capture(), any()); Assert.assertNull("should not send max results to answerserver", paramsCaptor.getValue().get(ReportParams.MaxResults.name())); Assert.assertEquals("should not limit results", 3, response.size()); }
@Test public void getEntityFacts_lowMaxResults() { final List<SourcedFact> response = controller.getEntityFacts("space", 2, Collections.singletonList("db")); Assert.assertEquals("should limit results", 2, response.size()); Assert.assertEquals("should return first fact", "1", response.get(0).fact.getSource()); Assert.assertEquals("should return second fact", "2", response.get(1).fact.getSource()); }