private void addLink(
     Study study,
     Map<Integer, Term> stageForNode,
     Map<Integer, String> taxonForNode,
     LabeledCSVParser links,
     Location location)
     throws StudyImporterException, NodeFactoryException {
   Integer consumerNodeID = Integer.parseInt(links.getValueByLabel("ConsumerNodeID"));
   Integer resourceNodeID = Integer.parseInt(links.getValueByLabel("ResourceNodeID"));
   String linkType = links.getValueByLabel("LinkType");
   InteractType interactType =
       interactionMapping.get(StringUtils.trim(StringUtils.lowerCase(linkType)));
   if (interactType == null) {
     throw new StudyImporterException(
         "failed to map interaction type ["
             + linkType
             + "] in line ["
             + links.lastLineNumber()
             + "]");
   }
   Specimen consumer = nodeFactory.createSpecimen(study, taxonForNode.get(consumerNodeID));
   consumer.setLifeStage(stageForNode.get(consumerNodeID));
   consumer.setExternalId(getNamespace() + ":NodeID:" + consumerNodeID);
   consumer.caughtIn(location);
   String resourceName = taxonForNode.get(resourceNodeID);
   Specimen resource = nodeFactory.createSpecimen(study, resourceName);
   resource.setLifeStage(stageForNode.get(resourceNodeID));
   resource.setExternalId(getNamespace() + ":NodeID:" + resourceNodeID);
   resource.caughtIn(location);
   consumer.interactsWith(resource, interactType);
 }
  @Test
  public void writeSiteMapWithNames() throws StudyImporterException, IOException {
    final PropertyEnricher taxonEnricher =
        new PropertyEnricher() {
          @Override
          public Map<String, String> enrich(Map<String, String> properties) {
            Taxon taxon = new TaxonImpl();
            TaxonUtil.mapToTaxon(properties, taxon);
            if ("H**o sapiens".equals(taxon.getName())) {
              taxon.setExternalId("homoSapiensId");
              taxon.setPath("one two three");
            } else if ("Canis lupus".equals(taxon.getName())) {
              taxon.setExternalId("canisLupusId");
              taxon.setPath("four five six");
            }
            return TaxonUtil.taxonToMap(taxon);
          }

          @Override
          public void shutdown() {}
        };
    taxonIndex = ExportTestUtil.taxonIndexWithEnricher(taxonEnricher, getGraphDb());
    Study study = nodeFactory.getOrCreateStudy("title", "source", "citation 123");
    final Specimen human = nodeFactory.createSpecimen(study, "H**o sapiens");
    final Specimen dog = nodeFactory.createSpecimen(study, "Canis familiaris");
    human.ate(dog);
    resolveNames();

    final File baseDirNames = createBaseDir("target/sitemap/names");

    final GraphExporter siteMapForNames = new ExporterSiteMapForNames();
    siteMapForNames.export(getGraphDb(), baseDirNames.getAbsolutePath());
    assertSiteMap(
        baseDirNames,
        "http://www.globalbioticinteractions.org/?interactionType=interactsWith&sourceTaxon=H**o%20sapiens",
        "https://globi.s3.amazonaws.com/snapshot/target/data/sitemap/names/sitemap.xml.gz");
  }
  public void resolveNames(Long batchSize) {
    StopWatch watchForEntireRun = new StopWatch();
    watchForEntireRun.start();
    StopWatch watchForBatch = new StopWatch();
    watchForBatch.start();
    Long count = 0L;

    Index<Node> studyIndex = graphService.index().forNodes("studies");
    IndexHits<Node> studies = studyIndex.query("title", "*");
    for (Node studyNode : studies) {
      final Study study1 = new Study(studyNode);
      final Iterable<Relationship> specimens = study1.getSpecimens();
      for (Relationship collected : specimens) {
        Specimen specimen = new Specimen(collected.getEndNode());
        final Relationship classifiedAs =
            specimen
                .getUnderlyingNode()
                .getSingleRelationship(RelTypes.CLASSIFIED_AS, Direction.OUTGOING);
        if (classifiedAs == null) {
          final Relationship describedAs =
              specimen
                  .getUnderlyingNode()
                  .getSingleRelationship(RelTypes.ORIGINALLY_DESCRIBED_AS, Direction.OUTGOING);
          final TaxonNode describedAsTaxon = new TaxonNode(describedAs.getEndNode());
          try {
            if (taxonFilter.shouldInclude(describedAsTaxon)) {
              TaxonNode resolvedTaxon = taxonIndex.getOrCreateTaxon(describedAsTaxon);
              if (resolvedTaxon != null) {
                specimen.classifyAs(resolvedTaxon);
              }
            }
          } catch (NodeFactoryException e) {
            LOG.warn(
                "failed to create taxon with name ["
                    + describedAsTaxon.getName()
                    + "] and id ["
                    + describedAsTaxon.getExternalId()
                    + "]",
                e);
          } finally {
            count++;
            if (count % batchSize == 0) {
              watchForBatch.stop();
              final long duration = watchForBatch.getTime();
              if (duration > 0) {
                LOG.info(
                    "resolved batch of ["
                        + batchSize
                        + "] names in "
                        + getProgressMsg(batchSize, duration));
              }
              watchForBatch.reset();
              watchForBatch.start();
            }
          }
        }
      }
    }
    studies.close();
    watchForEntireRun.stop();
    LOG.info(
        "resolved [" + count + "] names in " + getProgressMsg(count, watchForEntireRun.getTime()));
  }