@Test
  public void created_EntityWithNoUser() throws Exception {
    logger.debug("### created_EntityWithNoUser");
    String callerRef = "mk1hz";
    SystemUser su = registerSystemUser("created_EntityWithNoUser");

    Fortress fortress =
        fortressService.registerFortress(
            su.getCompany(), new FortressInputBean("created_EntityWithNoUser", true));
    EntityInputBean entityBean =
        new EntityInputBean(fortress, null, "CompanyNode", DateTime.now(), callerRef);

    // No fortress user
    ContentInputBean contentInputBean =
        new ContentInputBean(
            null, null, DateTime.now(), Helper.getSimpleMap("name", "a"), "Answer");
    entityBean.setContent(contentInputBean);
    TrackResultBean resultBean = mediationFacade.trackEntity(su.getCompany(), entityBean);

    Entity entity = entityService.findByCode(fortress, "CompanyNode", callerRef);
    Assert.assertEquals(null, entity.getCreatedBy());

    SearchChange searchChange = searchService.getSearchChange(resultBean);
    assertNotNull(searchChange);

    searchChange = searchService.rebuild(entity, resultBean.getCurrentLog());
    assertNotNull(searchChange);
  }
  @Test
  public void completion_numericCodesIgnored() throws Exception {

    // DAT-446

    String comp = "comp4";
    String fort = "fort4";
    String user = "******";
    Map<String, Object> what = Helper.getRandomMap();

    Entity entity = getEntity(comp, fort, user, fort, "AZERTY");
    deleteEsIndex(entity);

    // 2 char code as this is the minimum we will index from
    TagInputBean noName = new TagInputBean("11", "NumCode", "rlxname");
    TagInputBean numCodeWithName =
        new TagInputBean("21", "AutoComplete", "rlxname").setName("Code should not be indexed");
    TagInputBean zipCode = new TagInputBean("70612", "ZipCode");

    Collection<EntityTag> tags = new ArrayList<>();
    tags.add(Helper.getEntityTag(entity, noName, "rlxname"));
    tags.add(Helper.getEntityTag(entity, numCodeWithName, "rlxname"));
    tags.add(Helper.getEntityTag(entity, zipCode, "zip"));

    SearchChange change = new EntitySearchChange(entity, indexHelper.parseIndex(entity));
    change.setData(what);
    change.setStructuredTags(EntityService.TAG_STRUCTURE.DEFAULT, tags);

    indexMappingService.ensureIndexMapping(change);
    SearchChange searchResult = searchRepo.handle(change);

    assertNotNull(searchResult);
    Thread.sleep(2000);
    logger.info(doQuery(entity, entity.getCode(), 1));

    doCompletionQuery(entity, noName.getCode(), 1, "Should be found as there is no name");
    doCompletionQuery(entity, "code", 1, "Find by name, but Code is not indexed");
    doCompletionQuery(
        entity, numCodeWithName.getCode(), 0, "Should not be found as numeric code is ignored");
    doCompletionQuery(entity, zipCode.getCode(), 1, "Didn't find the zip code");
    doFieldQuery(
        entity,
        "tag.rlxname.autocomplete.code",
        numCodeWithName.getCode(),
        0,
        "Code should not be indexed");
    doFacetQuery(
        indexHelper.parseIndex(entity),
        entity.getType(),
        "tag.rlxname.autocomplete.name.facet",
        numCodeWithName.getName(),
        1,
        "Name should have been indexed");
  }
  @Test
  public void completion_FindTagsByCodeAndDescription() throws Exception {

    String comp = "comp2";
    String fort = "fort2";
    String user = "******";
    Map<String, Object> what = Helper.getRandomMap();

    Entity entity = getEntity(comp, fort, user, fort, "AZERTY");
    //        deleteEsIndex(entity);

    TagInputBean tagInputA = new TagInputBean("tagCode", "AutoComplete", "blah");

    TagInputBean tagInputB = new TagInputBean("myvalue", "AutoComplete", "blah");
    TagInputBean inst = new TagInputBean("Royal Marsden Free Hospital", "Institution", "inst");
    TagInputBean lead = new TagInputBean("Shepherd, JA", "Person", "lead");
    TagInputBean writer = new TagInputBean("Smith, JA", "Person", "lead");
    TagInputBean procedure =
        new TagInputBean("Surgical Procedures, Minimally Invasive", "Procedure", "involves");
    TagInputBean procedureB = new TagInputBean("Surgical Instruments", "Procedure", "involves");

    Collection<EntityTag> tags = new ArrayList<>();
    tags.add(Helper.getEntityTag(entity, tagInputA, "rlxname"));
    tags.add(Helper.getEntityTag(entity, tagInputB, "rlxname"));
    tags.add(Helper.getEntityTag(entity, inst, "abc"));
    tags.add(Helper.getEntityTag(entity, lead, "lead"));
    tags.add(Helper.getEntityTag(entity, writer, "writer"));
    tags.add(Helper.getEntityTag(entity, procedure, "proc"));
    tags.add(Helper.getEntityTag(entity, procedureB, "proc"));

    SearchChange change = new EntitySearchChange(entity, indexHelper.parseIndex(entity));
    change.setData(what);
    change.setStructuredTags(EntityService.TAG_STRUCTURE.DEFAULT, tags);

    indexMappingService.ensureIndexMapping(change);
    SearchChange searchResult = searchRepo.handle(change);

    assertNotNull(searchResult);
    Thread.sleep(2000);
    doQuery(entity, entity.getCode(), 1);

    doCompletionQuery(entity, "tag", 1, "Completion failed");
    doCompletionQuery(entity, "tagc", 1, "Completion failed");
    doCompletionQuery(entity, "tagcod", 1, "Completion failed");

    doCompletionQuery(entity, "shep", 1, "Completion failed");

    doCompletionQuery(entity, "myv", 1, "Completion failed");
    // Only supports "start with"
    //        doCompletionQuery(entity.getFortress().getIndexName(), "mars", 1, "Completion
    // failed");

  }
  @Test
  public void merge_Simple() throws Exception {
    cleanUpGraph();
    SystemUser su = registerSystemUser("merge_Simple");
    Fortress fortress =
        fortressService.registerFortress(
            su.getCompany(), new FortressInputBean("merge_Simple", true));

    TagInputBean tagInputA = new TagInputBean("TagA", "MoveTag", "rlxA");
    TagInputBean tagInputB = new TagInputBean("TagB", "MoveTag", "rlxB");

    EntityInputBean inputBean =
        new EntityInputBean(fortress, "*****@*****.**", "CompanyNode", DateTime.now(), "AAA");
    inputBean.addTag(tagInputA);
    Entity entityA = mediationFacade.trackEntity(su.getCompany(), inputBean).getEntity();
    inputBean =
        new EntityInputBean(fortress, "*****@*****.**", "CompanyNode", DateTime.now(), "BBB");
    inputBean.addTag(tagInputB);
    Entity entityB = mediationFacade.trackEntity(su.getCompany(), inputBean).getEntity();

    assertEquals(1, entityTagService.getEntityTags(entityA).size());
    assertEquals(1, entityTagService.getEntityTags(entityB).size());

    Tag tagA = tagService.findTag(su.getCompany(), null, tagInputA.getCode());
    assertNotNull(tagA);
    Tag tagB = tagService.findTag(su.getCompany(), null, tagInputB.getCode());
    assertNotNull(tagB);

    // The above is the setup. We will look to merge tagA into tagB. The end result will be that
    // entity

    Collection<Long> results = entityTagService.mergeTags(tagA.getId(), tagB.getId());
    assertEquals("One Entity should have been affected by this operation", 1, results.size());
    Long entityResult = results.iterator().next();
    assertEquals("The wrong Entity was affected by this operation", entityA.getId(), entityResult);

    entityA = entityService.getEntity(su.getCompany(), entityA.getMetaKey());
    Collection<EntityTag> tags = entityTagService.getEntityTags(entityA);
    assertEquals(1, tags.size());
    assertEquals(tagInputB.getName(), tags.iterator().next().getTag().getName());

    assertNull(
        "TagA should have been deleted",
        tagService.findTag(su.getCompany(), null, tagInputA.getCode()));
    tags = entityTagService.getEntityTags(entityB);
    assertEquals(1, tags.size());
    assertEquals(tagInputB.getName(), tags.iterator().next().getTag().getName());

    assertEquals(2, entityTagService.findEntityTags(su.getCompany(), tagInputB.getCode()).size());

    // assertEquals("rlxA", tags.iterator().next().);

  }
  @Test
  public void query_EndPoints() throws Exception {
    Map<String, Object> json = Helper.getBigJsonText(20);

    String fortress = "epFortress";
    String company = "epCompany";
    String doc = "epDocType";
    String user = "******";

    Entity entity = Helper.getEntity(company, fortress, user, doc);

    EntitySearchChange change = new EntitySearchChange(entity);
    change.setDescription("Test Description");
    change.setWhat(json);

    deleteEsIndex(entity);
    Thread.sleep(1000);

    SearchResults searchResults =
        trackService.createSearchableChange(new EntitySearchChanges(change));
    SearchResult searchResult = searchResults.getSearchResults().iterator().next();
    Thread.sleep(2000);
    assertNotNull(searchResult);
    assertNotNull(searchResult.getSearchKey());

    QueryParams qp = new QueryParams(entity.getSegment());
    qp.setCompany(company);
    qp.setSearchText("*");
    // Sanity check - there is only one document in the index
    EsSearchResult queryResult = queryServiceEs.doFdViewSearch(qp);
    assertEquals(1, queryResult.getResults().size());
    assertEquals(entity.getMetaKey(), queryResult.getResults().iterator().next().getMetaKey());
    MetaKeyResults metaResults = queryServiceEs.doMetaKeyQuery(qp);
    assertEquals(1, metaResults.getResults().size());
    assertEquals(entity.getMetaKey(), metaResults.getResults().iterator().next());

    // Find with just a fortress
    qp = new QueryParams(entity.getSegment());
    qp.setSearchText("description");
    queryResult = queryServiceEs.doFdViewSearch(qp);
    assertEquals(1, queryResult.getResults().size());
    assertEquals(entity.getMetaKey(), queryResult.getResults().iterator().next().getMetaKey());

    qp = new QueryParams().setCompany(company.toLowerCase());
    qp.setSearchText("description");
    queryResult = queryServiceEs.doFdViewSearch(qp);
    assertEquals(1, queryResult.getResults().size());
    assertEquals(entity.getMetaKey(), queryResult.getResults().iterator().next().getMetaKey());

    qp = new QueryParams(entity.getSegment());
    qp.setSearchText("-description"); // Ignore description
    queryResult = queryServiceEs.doFdViewSearch(qp);
    assertEquals(0, queryResult.getResults().size());
  }
  @Test
  public void created_UserAgainstEntityAndLog() throws Exception {
    logger.debug("### created_UserAgainstEntityAndLog");
    String callerRef = "mk1hz";
    SystemUser su = registerSystemUser("created_UserAgainstEntityAndLog");

    Fortress fortress =
        fortressService.registerFortress(
            su.getCompany(), new FortressInputBean("created_UserAgainstEntityAndLog", true));
    EntityInputBean entityBean =
        new EntityInputBean(fortress, "poppy", "CompanyNode", DateTime.now(), callerRef);

    entityBean.setContent(
        new ContentInputBean(
            "billie", null, DateTime.now(), Helper.getSimpleMap("name", "a"), "Answer"));
    mediationFacade.trackEntity(su.getCompany(), entityBean);

    Entity entity = entityService.findByCode(fortress, "CompanyNode", callerRef);
    Assert.assertEquals("poppy", entity.getCreatedBy().getCode().toLowerCase());

    Set<EntityLog> logs = entityService.getEntityLogs(su.getCompany(), entity.getMetaKey());
    assertEquals(1, logs.size());
    EntityLog log = logs.iterator().next();
    assertEquals("billie", log.getLog().getMadeBy().getCode().toLowerCase());

    entityBean.setContent(
        new ContentInputBean("nemo", DateTime.now(), Helper.getSimpleMap("name", "b")));
    mediationFacade.trackEntity(su.getCompany(), entityBean);
    assertTrue(
        "Event name incorrect", log.getLog().getEvent().getCode().equalsIgnoreCase("answer"));

    entity = entityService.findByCode(fortress, "CompanyNode", callerRef);
    Assert.assertEquals("poppy", entity.getCreatedBy().getCode().toLowerCase());

    logs = entityService.getEntityLogs(su.getCompany(), entity.getMetaKey());
    assertTrue(logs.size() == 2);
    boolean billieFound = false;
    boolean nemoFound = false;
    for (EntityLog entityLog : logs) {
      if (entityLog.getLog().getMadeBy().getCode().equals("billie")) billieFound = true;
      if (entityLog.getLog().getMadeBy().getCode().equals("nemo")) nemoFound = true;
    }
    assertTrue("Didn't find Billie & Nemo", billieFound && nemoFound);
  }
  @Test
  public void completion_ShortCodesIgnored() throws Exception {

    String comp = "comp3";
    String fort = "fort3";
    String user = "******";
    Map<String, Object> what = Helper.getRandomMap();

    Entity entity = getEntity(comp, fort, user, fort, "AZERTY");
    deleteEsIndex(entity);

    TagInputBean tagInputA =
        new TagInputBean("A", "AutoComplete")
            .setName("Finding name should not be found as the code is too short");
    TagInputBean tagInputB =
        new TagInputBean("AB", "AutoComplete").setName("Finding code and name indexed");

    Collection<EntityTag> tags = new ArrayList<>();
    tags.add(Helper.getEntityTag(entity, tagInputA, "rlxname"));
    tags.add(Helper.getEntityTag(entity, tagInputB, "rlxname"));

    SearchChange change = new EntitySearchChange(entity, indexHelper.parseIndex(entity));
    change.setData(what);
    change.setStructuredTags(EntityService.TAG_STRUCTURE.DEFAULT, tags);

    indexMappingService.ensureIndexMapping(change);
    SearchChange searchResult = searchRepo.handle(change);

    assertNotNull(searchResult);
    Thread.sleep(2000);
    logger.info(doQuery(entity, entity.getCode(), 1));

    doCompletionQuery(entity, "find", 2, "Find by tag name failed");
    doCompletionQuery(entity, "ab", 1, "Code is 2 chars and should be indexed");
    doCompletionQuery(entity, "a", 0, "Code less than 2 chars should have been ignored");
  }
  @Test
  public void fortressConcepts() throws Exception {
    try {
      logger.debug("### fortressConcepts");

      Transaction t = beginManualTransaction();
      setSecurity();
      SystemUser su = registerSystemUser("fortressConcepts", mike_admin);
      assertNotNull(su);
      engineConfig.setConceptsEnabled(true);
      engineConfig.setTestMode(true);

      Fortress fortA =
          fortressService.registerFortress(
              su.getCompany(), new FortressInputBean("fortressConcepts", true));

      DocumentType dType = conceptService.resolveByDocCode(fortA, "ABC123", true);
      commitManualTransaction(t); // Should only be only one docTypes

      assertNotNull(dType);
      Long id = dType.getId();
      dType = conceptService.resolveByDocCode(fortA, "ABC123", false);
      assertEquals(id, dType.getId());

      EntityInputBean input = new EntityInputBean(fortA, "jinks", "DocA", new DateTime());
      input.addTag(new TagInputBean("cust123", "Customer", "purchased"));
      Entity meta = mediationFacade.trackEntity(su.getCompany(), input).getEntity();

      assertNotNull(entityService.getEntity(su.getCompany(), meta.getKey()));

      input = new EntityInputBean(fortA, "jinks", "DocA", new DateTime());
      input.addTag(new TagInputBean("cust124", "Customer", "purchased").setLabel("Customer"));

      mediationFacade.trackEntity(su.getCompany(), input).getEntity();

      Collection<String> docs = new ArrayList<>();
      docs.add("DocA");
      Collection<DocumentResultBean> documentTypes =
          conceptService.findConcepts(su.getCompany(), docs, false);
      assertNotNull(documentTypes);
      assertEquals(1, documentTypes.size());

      // add a second docTypes
      input = new EntityInputBean(fortA, "jinks", "DocA", new DateTime());
      input.addTag(new TagInputBean("cust123", "Rep", "sold").setLabel("Rep"));
      mediationFacade.trackEntity(su.getCompany(), input);

      documentTypes = conceptService.getConceptsWithRelationships(su.getCompany(), docs);
      assertEquals("Only one doc type should exist", 1, documentTypes.size());

      Boolean foundCustomer = false, foundRep = false;

      for (DocumentResultBean docTypes : documentTypes) {
        for (ConceptResultBean concept : docTypes.getConcepts()) {
          if (concept.getName().equals("Customer")) {
            foundCustomer = true;
            assertEquals(1, concept.getRelationships().size());
            Assert.assertEquals(
                "purchased", concept.getRelationships().iterator().next().getName());
            assertEquals(true, concept.toString().contains(concept.getName()));
          }
          if (concept.getName().equals("Rep")) {
            foundRep = true;
            assertEquals(1, concept.getRelationships().size());
            Assert.assertEquals("sold", concept.getRelationships().iterator().next().getName());
            assertEquals(true, concept.toString().contains(concept.getName()));
          }
        }
      }
      assertTrue("Didn't find Customer concept", foundCustomer);
      assertTrue("Didn't find Rep concept", foundRep);
    } finally {
      cleanUpGraph();
    }
  }