Example usage for com.fasterxml.jackson.databind ObjectMapper convertValue

List of usage examples for com.fasterxml.jackson.databind ObjectMapper convertValue

Introduction

In this page you can find the example usage for com.fasterxml.jackson.databind ObjectMapper convertValue.

Prototype

@SuppressWarnings("unchecked")
    public <T> T convertValue(Object fromValue, JavaType toValueType) throws IllegalArgumentException 

Source Link

Usage

From source file:org.bedework.notifier.outbound.email.EmailAdaptor.java

private List<TemplateResult> applyTemplates(final Action action) throws NoteException {
    final Note note = action.getNote();
    final NotificationType nt = note.getNotification();
    final EmailSubscription sub = EmailSubscription.rewrap(action.getSub());

    List<TemplateResult> results = new ArrayList<TemplateResult>();
    try {//  w w  w.  j  ava2  s  .c  om
        String prefix = nt.getParsed().getDocumentElement().getPrefix();

        if (prefix == null) {
            prefix = "default";
        }

        final String abstractPath = Util.buildPath(false, Note.DeliveryMethod.email.toString(), "/", prefix,
                "/", nt.getNotification().getElementName().getLocalPart());

        File templateDir = new File(Util.buildPath(false, globalConfig.getTemplatesPath(), "/", abstractPath));
        if (templateDir.isDirectory()) {

            Map<String, Object> root = new HashMap<String, Object>();
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true);
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(new InputSource(new StringReader(nt.toXml(true))));
            Element el = doc.getDocumentElement();
            NodeModel.simplify(el);
            NodeModel.useJaxenXPathSupport();
            root.put("notification", el);

            HashSet<String> recipients = new HashSet<String>();
            for (String email : sub.getEmails()) {
                recipients.add(MAILTO + email);
            }
            root.put("recipients", recipients);

            if (globalConfig.getCardDAVHost() != null && globalConfig.getCardDAVPort() != 0
                    && globalConfig.getCardDAVContextPath() != null) {
                HashMap<String, Object> vcards = new HashMap<String, Object>();
                BasicHttpClient client;
                try {
                    ArrayList<Header> hdrs = new ArrayList<Header>();
                    BasicHeader h = new BasicHeader(HEADER_ACCEPT, globalConfig.getVCardContentType());
                    hdrs.add(h);

                    client = new BasicHttpClient(globalConfig.getCardDAVHost(), globalConfig.getCardDAVPort(),
                            null, 15 * 1000);

                    XPathExpression exp = xPath.compile("//*[local-name() = 'href']");
                    NodeList nl = (NodeList) exp.evaluate(doc, XPathConstants.NODESET);

                    HashSet<String> vcardLookups = new HashSet<String>();
                    for (int i = 0; i < nl.getLength(); i++) {
                        Node n = nl.item(i);
                        String text = n.getTextContent();

                        text = pMailto.matcher(text).replaceFirst(MAILTO);
                        if (text.startsWith(MAILTO)
                                || text.startsWith(globalConfig.getCardDAVPrincipalsPath())) {
                            vcardLookups.add(text);
                        }
                    }

                    // Get vCards for recipients too. They may not be referenced in the notification.
                    vcardLookups.addAll(recipients);

                    for (String lookup : vcardLookups) {
                        String path = Util.buildPath(false,
                                globalConfig.getCardDAVContextPath() + "/" + lookup.replace(':', '/'));

                        final InputStream is = client.get(path + VCARD_SUFFIX, "application/text", hdrs);
                        if (is != null) {
                            ObjectMapper om = new ObjectMapper();
                            @SuppressWarnings("unchecked")
                            ArrayList<Object> hm = om.readValue(is, ArrayList.class);
                            vcards.put(lookup, hm);
                        }
                    }
                    root.put("vcards", vcards);
                } catch (final Throwable t) {
                    error(t);
                }
            }

            if (nt.getNotification() instanceof ResourceChangeType) {
                ResourceChangeType chg = (ResourceChangeType) nt.getNotification();
                BedeworkConnectorConfig cfg = ((BedeworkConnector) action.getConn()).getConnectorConfig();
                BasicHttpClient cl = getClient(cfg);
                List<Header> hdrs = getHeaders(cfg, new BedeworkSubscription(action.getSub()));

                String href = null;
                if (chg.getCreated() != null) {
                    href = chg.getCreated().getHref();
                } else if (chg.getDeleted() != null) {
                    href = chg.getDeleted().getHref();
                } else if (chg.getUpdated() != null && chg.getUpdated().size() > 0) {
                    href = chg.getUpdated().get(0).getHref();
                }

                if (href != null) {
                    if (chg.getDeleted() == null) {
                        // We only have an event for the templates on a create or update, not on delete.
                        ObjectMapper om = new ObjectMapper();
                        final InputStream is = cl.get(cfg.getSystemUrl() + href, null, hdrs);
                        JsonNode a = om.readValue(is, JsonNode.class);

                        // Check for a recurrence ID on this notification.
                        XPathExpression exp = xPath.compile("//*[local-name() = 'recurrenceid']/text()");
                        String rid = exp.evaluate(doc);
                        if (rid != null && !rid.isEmpty()) {
                            Calendar rcal = Calendar.getInstance();
                            recurIdFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
                            rcal.setTime(recurIdFormat.parse(rid));

                            // Find the matching recurrence ID in the JSON, and make that the only vevent object.
                            Calendar c = Calendar.getInstance();
                            ArrayNode vevents = (ArrayNode) a.get(2);
                            for (JsonNode vevent : vevents) {
                                if (vevent.size() > 1 && vevent.get(1).size() > 1) {
                                    JsonNode n = vevent.get(1).get(0);
                                    if (n.get(0).asText().equals("recurrence-id")) {
                                        if (n.get(1).size() > 0 && n.get(1).get("tzid") != null) {
                                            jsonIdFormatTZ.setTimeZone(
                                                    TimeZone.getTimeZone(n.get(1).get("tzid").asText()));
                                            c.setTime(jsonIdFormatTZ.parse(n.get(3).asText()));
                                        } else {
                                            jsonIdFormatUTC.setTimeZone(TimeZone.getTimeZone("UTC"));
                                            c.setTime(jsonIdFormatUTC.parse(n.get(3).asText()));
                                        }
                                        if (rcal.compareTo(c) == 0) {
                                            vevents.removeAll();
                                            vevents.add(vevent);
                                            break;
                                        }
                                    }
                                }
                            }
                        }

                        root.put("vevent", (ArrayList<Object>) om.convertValue(a, ArrayList.class));
                    }

                    // TODO: Provide some calendar information to the templates. This is currently the publisher's
                    // calendar, but needs to be fixed to be the subscriber's calendar.
                    String chref = href.substring(0, href.lastIndexOf("/"));
                    hdrs.add(new BasicHeader(HEADER_DEPTH, "0"));
                    int rc = cl.sendRequest("PROPFIND", cfg.getSystemUrl() + chref, hdrs, "text/xml",
                            CALENDAR_PROPFIND.length(), CALENDAR_PROPFIND.getBytes());
                    if (rc == HttpServletResponse.SC_OK || rc == SC_MULTISTATUS) {
                        Document d = builder.parse(new InputSource(cl.getResponseBodyAsStream()));
                        HashMap<String, String> hm = new HashMap<String, String>();
                        XPathExpression exp = xPath.compile("//*[local-name() = 'href']/text()");
                        hm.put("href", exp.evaluate(d));
                        exp = xPath.compile("//*[local-name() = 'displayname']/text()");
                        hm.put("name", (String) exp.evaluate(d));
                        exp = xPath.compile("//*[local-name() = 'calendar-description']/text()");
                        hm.put("description", (String) exp.evaluate(d));
                        root.put("calendar", hm);
                    }
                }
            }

            if (note.getExtraValues() != null) {
                root.putAll(note.getExtraValues());
            }

            DefaultObjectWrapper wrapper = new DefaultObjectWrapperBuilder(
                    Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS).build();
            root.put("timezone", (TemplateHashModel) wrapper.getStaticModels().get("java.util.TimeZone"));

            // Sort files so the user can control the order of content types/body parts of the email by template file name.
            File[] templates = templateDir.listFiles(templateFilter);
            Arrays.sort(templates);
            for (File f : templates) {
                Template template = fmConfig.getTemplate(Util.buildPath(false, abstractPath, "/", f.getName()));
                Writer out = new StringWriter();
                Environment env = template.createProcessingEnvironment(root, out);
                env.process();

                TemplateResult r = new TemplateResult(f.getName(), out.toString(), env);
                if (!r.getBooleanVariable("skip")) {
                    results.add(new TemplateResult(f.getName(), out.toString(), env));
                }
            }
        }
    } catch (final Throwable t) {
        throw new NoteException(t);
    }
    return results;
}

From source file:com.ikanow.aleph2.graph.titan.utils.TestTitanGraphBuildingUtils.java

@SuppressWarnings("unchecked")
@Test/*w  w w. j av  a  2  s. c o m*/
public void test_invokeUserMergeCode() {
    // (Also tests addGraphSON2Graph)
    // (Also tests insertProperties)
    // (Also tests denestProperties)

    // This has a massive set of params, here we go:
    final TitanGraph titan = getSimpleTitanGraph();
    TitanManagement mgmt = titan.openManagement();
    mgmt.makePropertyKey(GraphAnnotationBean.a2_p).dataType(String.class).cardinality(Cardinality.SET).make();
    mgmt.commit();
    final TitanTransaction tx = titan.buildTransaction().start();
    final Vertex v1 = tx.addVertex("existing_1");
    v1.property("existing", true);
    final Vertex v2 = tx.addVertex("existing_2");
    v2.property("existing", true);
    final Edge e1 = v1.addEdge("existing_1_2", v2);
    e1.property("existing", true);
    final Edge e2 = v2.addEdge("existing_2_1", v1);
    e2.property("existing", true);
    // Graph schema
    final GraphSchemaBean graph_schema = BeanTemplateUtils.build(GraphSchemaBean.class)
            .with(GraphSchemaBean::deduplication_fields,
                    Arrays.asList(GraphAnnotationBean.name, GraphAnnotationBean.type))
            .with(GraphSchemaBean::custom_finalize_all_objects, false).done().get();
    // Security service
    final MockSecurityService mock_security = new MockSecurityService();
    final String user = "nobody";
    mock_security.setGlobalMockRole("nobody:DataBucketBean:read,write:test:security:*", true);
    // Simple merger
    final IEnrichmentModuleContext delegate_context = Mockito.mock(IEnrichmentModuleContext.class);
    Mockito.when(delegate_context.getNextUnusedId()).thenReturn(0L);
    final Optional<Tuple2<IEnrichmentBatchModule, GraphMergeEnrichmentContext>> maybe_merger = Optional
            .of(Tuples._2T((IEnrichmentBatchModule) new SimpleGraphMergeService(),
                    new GraphMergeEnrichmentContext(delegate_context, graph_schema)));
    maybe_merger.ifPresent(t2 -> t2._1().onStageInitialize(t2._2(), null, null, null, null));
    // special titan mapper
    final org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper titan_mapper = titan.io(IoCore.graphson())
            .mapper().create().createMapper();
    // Bucket
    final String bucket_path = "/test/security";
    // Key
    final ObjectNode vertex_key_1 = _mapper.createObjectNode().put(GraphAnnotationBean.name, "alex")
            .put(GraphAnnotationBean.type, "person");
    final ObjectNode vertex_key_2 = _mapper.createObjectNode().put(GraphAnnotationBean.name, "caleb")
            .put(GraphAnnotationBean.type, "person");
    final ObjectNode edge_key = (ObjectNode) ((ObjectNode) _mapper.createObjectNode()
            .put(GraphAnnotationBean.label, "test_label").set(GraphAnnotationBean.inV, vertex_key_1))
                    .set(GraphAnnotationBean.outV, vertex_key_2);
    // New elements (note can mess about with different keys because they are checked higher up in the stack, here things are just "pre-grouped" lists)
    final List<ObjectNode> new_vertices = Arrays.asList(
            (ObjectNode) ((ObjectNode) _mapper.createObjectNode().put(GraphAnnotationBean.type, "vertex")
                    .put(GraphAnnotationBean.label, "test_v_1").set(GraphAnnotationBean.id, vertex_key_1))
                            // (set some properties)
                            .set(GraphAnnotationBean.properties,
                                    ((ObjectNode) _mapper.createObjectNode().put("props_str", "str").set(
                                            "props_array",
                                            _mapper.convertValue(Arrays.asList("a", "r", "r"), JsonNode.class)))
                                                    .set("props_obj",
                                                            _mapper.createObjectNode().put(
                                                                    GraphAnnotationBean.value, "obj_str"))),
            (ObjectNode) ((ObjectNode) _mapper.createObjectNode().put(GraphAnnotationBean.type, "vertex")
                    .put(GraphAnnotationBean.label, "test_v_2").set(GraphAnnotationBean.id, vertex_key_2)));
    final List<ObjectNode> new_edges = Arrays.asList(
            (ObjectNode) ((ObjectNode) ((ObjectNode) _mapper.createObjectNode()
                    .put(GraphAnnotationBean.type, "edge").put(GraphAnnotationBean.label, "test_e_1")
                    .set(GraphAnnotationBean.inV, vertex_key_1)).set(GraphAnnotationBean.outV, vertex_key_2))
                            // (set some properties)
                            .set(GraphAnnotationBean.properties,
                                    (ObjectNode) _mapper.createObjectNode().put("props_long", 5L).set(
                                            "props_obj",
                                            _mapper.createObjectNode().set(GraphAnnotationBean.value,
                                                    _mapper.convertValue(Arrays.asList("a", "r", "r"),
                                                            JsonNode.class)))),
            (ObjectNode) ((ObjectNode) _mapper.createObjectNode().put(GraphAnnotationBean.type, "edge")
                    .put(GraphAnnotationBean.label, "test_e_2").set(GraphAnnotationBean.inV, vertex_key_1))
                            .set(GraphAnnotationBean.outV, vertex_key_2));
    // Existing elements
    final List<Vertex> existing_vertices = Arrays.asList(v1);
    final List<Edge> existing_edges = Arrays.asList(e1);
    // State
    final Map<ObjectNode, Vertex> mutable_existing_vertex_store = new HashMap<>();
    mutable_existing_vertex_store.put(vertex_key_1, v1);
    mutable_existing_vertex_store.put(vertex_key_2, v2);
    final MutableStatsBean mutable_stats = new MutableStatsBean();

    // Vertices, no existing elements
    {
        mutable_stats.reset();

        List<Vertex> ret_val = TitanGraphBuildingUtils.invokeUserMergeCode(tx, graph_schema,
                Tuples._2T(user, mock_security), Optional.empty(), maybe_merger, titan_mapper, mutable_stats,
                Vertex.class, bucket_path, vertex_key_1, Arrays.asList(new_vertices.get(0)),
                Collections.emptyList(), Collections.emptyMap());

        assertEquals(1, ret_val.size());
        assertEquals(
                Optionals.streamOf(tx.query().hasNot("existing").vertices(), false)
                        .map(v -> titan_mapper
                                .convertValue(v, org.apache.tinkerpop.shaded.jackson.databind.JsonNode.class)
                                .toString())
                        .collect(Collectors.toList()),
                ret_val.stream()
                        .map(v -> titan_mapper
                                .convertValue(v, org.apache.tinkerpop.shaded.jackson.databind.JsonNode.class)
                                .toString())
                        .collect(Collectors.toList()));

        ret_val.stream()
                .forEach(v -> assertEquals(Arrays.asList(bucket_path),
                        Optionals.streamOf(v.properties(GraphAnnotationBean.a2_p), false)
                                .map(p -> p.value().toString()).collect(Collectors.toList())));

        // Stats
        assertEquals(0L, mutable_stats.edge_errors);
        assertEquals(0L, mutable_stats.edge_matches_found);
        assertEquals(0L, mutable_stats.edges_created);
        assertEquals(0L, mutable_stats.edges_emitted);
        assertEquals(0L, mutable_stats.edges_updated);
        assertEquals(0L, mutable_stats.vertex_errors);
        assertEquals(0L, mutable_stats.edge_matches_found);
        assertEquals(1L, mutable_stats.vertices_created);
        assertEquals(0L, mutable_stats.vertices_emitted);
        assertEquals(0L, mutable_stats.vertices_updated);

        // Check the properties situation:
        assertEquals(1, Optionals.streamOf(tx.query().has("props_str", "str").vertices(), false).count());
        assertEquals(1,
                Optionals.streamOf(
                        tx.query().has("props_array", Arrays.asList("a", "r", "r").toArray()).vertices(), false)
                        .count());
        assertEquals(1, Optionals.streamOf(tx.query().has("props_obj", "obj_str").vertices(), false).count());

        // Check that we did actually add another vertex:
        assertEquals(3, Optionals.streamOf(tx.query().vertices(), false).count());
        // Time
        assertEquals(1,
                Optionals.streamOf(tx.query().has(GraphAnnotationBean.a2_tc).vertices(), false).count()); // (added/updated time)
        assertEquals(1,
                Optionals.streamOf(tx.query().has(GraphAnnotationBean.a2_tm).vertices(), false).count()); // (added/updated time)

        // (clear the graph ready for the next test)
        tx.query().hasNot("existing").vertices().forEach(v -> ((Vertex) v).remove());
    }
    // Vertices, existing elements, multiple new elements
    {
        mutable_stats.reset();

        List<Vertex> ret_val = TitanGraphBuildingUtils.invokeUserMergeCode(tx, graph_schema,
                Tuples._2T(user, mock_security), Optional.empty(), maybe_merger, titan_mapper, mutable_stats,
                Vertex.class, bucket_path, vertex_key_1, new_vertices, existing_vertices,
                Collections.emptyMap());

        assertEquals(1, ret_val.size());
        assertEquals(0, Optionals.streamOf(tx.query().hasNot("existing").vertices(), false).count()); // (since i've overwritten an existing one...)
        assertEquals(
                Optionals.streamOf(tx.query().has(GraphAnnotationBean.a2_p).vertices(), false)
                        .map(v -> titan_mapper
                                .convertValue(v, org.apache.tinkerpop.shaded.jackson.databind.JsonNode.class)
                                .toString())
                        .collect(Collectors.toList()),
                ret_val.stream()
                        .map(v -> titan_mapper
                                .convertValue(v, org.apache.tinkerpop.shaded.jackson.databind.JsonNode.class)
                                .toString())
                        .collect(Collectors.toList()));

        ret_val.stream()
                .forEach(v -> assertEquals(Arrays.asList(bucket_path),
                        Optionals.streamOf(v.properties(GraphAnnotationBean.a2_p), false)
                                .map(p -> p.value().toString()).collect(Collectors.toList())));

        // Stats
        assertEquals(0L, mutable_stats.edge_errors);
        assertEquals(0L, mutable_stats.edge_matches_found);
        assertEquals(0L, mutable_stats.edges_created);
        assertEquals(0L, mutable_stats.edges_emitted);
        assertEquals(0L, mutable_stats.edges_updated);
        assertEquals(0L, mutable_stats.vertex_errors);
        assertEquals(0L, mutable_stats.edge_matches_found);
        assertEquals(0L, mutable_stats.vertices_created);
        assertEquals(0L, mutable_stats.vertices_emitted);
        assertEquals(1L, mutable_stats.vertices_updated);

        // Check that we didn't actually add another vertex:
        assertEquals(2, Optionals.streamOf(tx.query().vertices(), false).count());
        // Time
        assertEquals(1,
                Optionals.streamOf(tx.query().has(GraphAnnotationBean.a2_tc).vertices(), false).count()); // (added/updated time)
        assertEquals(1,
                Optionals.streamOf(tx.query().has(GraphAnnotationBean.a2_tm).vertices(), false).count()); // (added/updated time)

        // (clear the graph ready for the next test)
        tx.query().hasNot("existing").vertices().forEach(v -> ((Vertex) v).remove());
        tx.query().has(GraphAnnotationBean.a2_p).vertices().forEach(
                v -> ((Vertex) v).properties(GraphAnnotationBean.a2_p).forEachRemaining(p -> p.remove()));
        tx.query().has(GraphAnnotationBean.a2_tc).vertices().forEach(
                v -> ((Vertex) v).properties(GraphAnnotationBean.a2_tc).forEachRemaining(p -> p.remove()));
        tx.query().has(GraphAnnotationBean.a2_tm).vertices().forEach(
                v -> ((Vertex) v).properties(GraphAnnotationBean.a2_tm).forEachRemaining(p -> p.remove()));
    }
    // Vertices, existing elements, single element
    {
        mutable_stats.reset();

        List<Vertex> ret_val = TitanGraphBuildingUtils.invokeUserMergeCode(tx, graph_schema,
                Tuples._2T(user, mock_security), Optional.empty(), maybe_merger, titan_mapper, mutable_stats,
                Vertex.class, bucket_path, vertex_key_1, new_vertices, existing_vertices,
                Collections.emptyMap());

        assertEquals(1, ret_val.size());
        assertEquals(0, Optionals.streamOf(tx.query().hasNot("existing").vertices(), false).count()); // (since i've overwritten an existing one...)
        assertEquals(
                Optionals.streamOf(tx.query().has(GraphAnnotationBean.a2_p).vertices(), false)
                        .map(v -> titan_mapper
                                .convertValue(v, org.apache.tinkerpop.shaded.jackson.databind.JsonNode.class)
                                .toString())
                        .collect(Collectors.toList()),
                ret_val.stream()
                        .map(v -> titan_mapper
                                .convertValue(v, org.apache.tinkerpop.shaded.jackson.databind.JsonNode.class)
                                .toString())
                        .collect(Collectors.toList()));

        ret_val.stream()
                .forEach(v -> assertEquals(Arrays.asList(bucket_path),
                        Optionals.streamOf(v.properties(GraphAnnotationBean.a2_p), false)
                                .map(p -> p.value().toString()).collect(Collectors.toList())));

        // Stats
        assertEquals(0L, mutable_stats.edge_errors);
        assertEquals(0L, mutable_stats.edge_matches_found);
        assertEquals(0L, mutable_stats.edges_created);
        assertEquals(0L, mutable_stats.edges_emitted);
        assertEquals(0L, mutable_stats.edges_updated);
        assertEquals(0L, mutable_stats.vertex_errors);
        assertEquals(0L, mutable_stats.edge_matches_found);
        assertEquals(0L, mutable_stats.vertices_created);
        assertEquals(0L, mutable_stats.vertices_emitted);
        assertEquals(1L, mutable_stats.vertices_updated);

        // Check that we didn't actually add another vertex:
        assertEquals(2, Optionals.streamOf(tx.query().vertices(), false).count());
        // Time
        assertEquals(1,
                Optionals.streamOf(tx.query().has(GraphAnnotationBean.a2_tc).vertices(), false).count()); // (added/updated time)
        assertEquals(1,
                Optionals.streamOf(tx.query().has(GraphAnnotationBean.a2_tm).vertices(), false).count()); // (added/updated time)

        // (clear the graph ready for the next test)
        tx.query().hasNot("existing").vertices().forEach(v -> ((Vertex) v).remove());
        tx.query().has(GraphAnnotationBean.a2_p).vertices().forEach(
                v -> ((Vertex) v).properties(GraphAnnotationBean.a2_p).forEachRemaining(p -> p.remove()));
    }
    // Edges, no existing elements, single new element
    {
        mutable_stats.reset();
        final List<Edge> ret_val = TitanGraphBuildingUtils.invokeUserMergeCode(tx, graph_schema,
                Tuples._2T(user, mock_security), Optional.empty(), maybe_merger, titan_mapper, mutable_stats,
                Edge.class, bucket_path, edge_key, Arrays.asList(new_edges.get(0)), Collections.emptyList(),
                mutable_existing_vertex_store);

        assertEquals(1, ret_val.size());
        assertEquals(
                Optionals.streamOf(tx.query().hasNot("existing").edges(), false)
                        .map(v -> titan_mapper
                                .convertValue(v, org.apache.tinkerpop.shaded.jackson.databind.JsonNode.class)
                                .toString())
                        .collect(Collectors.toList()),
                ret_val.stream()
                        .map(v -> titan_mapper
                                .convertValue(v, org.apache.tinkerpop.shaded.jackson.databind.JsonNode.class)
                                .toString())
                        .collect(Collectors.toList()));

        ret_val.stream()
                .forEach(v -> assertEquals(Arrays.asList(bucket_path),
                        Optionals.streamOf(v.properties(GraphAnnotationBean.a2_p), false)
                                .map(p -> p.value().toString()).collect(Collectors.toList())));

        // Stats
        assertEquals(0L, mutable_stats.edge_errors);
        assertEquals(0L, mutable_stats.edge_matches_found);
        assertEquals(1L, mutable_stats.edges_created);
        assertEquals(0L, mutable_stats.edges_emitted);
        assertEquals(0L, mutable_stats.edges_updated);
        assertEquals(0L, mutable_stats.vertex_errors);
        assertEquals(0L, mutable_stats.edge_matches_found);
        assertEquals(0L, mutable_stats.vertices_created);
        assertEquals(0L, mutable_stats.vertices_emitted);
        assertEquals(0L, mutable_stats.vertices_updated);

        // Check the properties situation:
        assertEquals(1, Optionals.streamOf(tx.query().has("props_long", 5L).edges(), false).count());
        assertEquals(1, Optionals
                .streamOf(tx.query().has("props_obj", Arrays.asList("a", "r", "r").toArray()).edges(), false)
                .count());

        // Check that we did actually add another edge:
        assertEquals(3, Optionals.streamOf(tx.query().edges(), false).count());
        // Time
        assertEquals(1, Optionals.streamOf(tx.query().has(GraphAnnotationBean.a2_tc).edges(), false).count()); // (added/updated time)
        assertEquals(1, Optionals.streamOf(tx.query().has(GraphAnnotationBean.a2_tm).edges(), false).count()); // (added/updated time)

        // (clear the graph ready for the next test)
        tx.query().hasNot("existing").edges().forEach(v -> ((Edge) v).remove());
    }
    // Edges, no existing elements, multiple new elements
    {
        mutable_stats.reset();

        List<Edge> ret_val = TitanGraphBuildingUtils.invokeUserMergeCode(tx, graph_schema,
                Tuples._2T(user, mock_security), Optional.empty(), maybe_merger, titan_mapper, mutable_stats,
                Edge.class, bucket_path, edge_key, new_edges, Collections.emptyList(),
                mutable_existing_vertex_store);

        assertEquals(1, ret_val.size());
        assertEquals(
                Optionals.streamOf(tx.query().hasNot("existing").edges(), false)
                        .map(v -> titan_mapper
                                .convertValue(v, org.apache.tinkerpop.shaded.jackson.databind.JsonNode.class)
                                .toString())
                        .collect(Collectors.toList()),
                ret_val.stream()
                        .map(v -> titan_mapper
                                .convertValue(v, org.apache.tinkerpop.shaded.jackson.databind.JsonNode.class)
                                .toString())
                        .collect(Collectors.toList()));

        ret_val.stream()
                .forEach(v -> assertEquals(Arrays.asList(bucket_path),
                        Optionals.streamOf(v.properties(GraphAnnotationBean.a2_p), false)
                                .map(p -> p.value().toString()).collect(Collectors.toList())));

        // Stats
        assertEquals(0L, mutable_stats.edge_errors);
        assertEquals(0L, mutable_stats.edge_matches_found);
        assertEquals(1L, mutable_stats.edges_created);
        assertEquals(0L, mutable_stats.edges_emitted);
        assertEquals(0L, mutable_stats.edges_updated);
        assertEquals(0L, mutable_stats.vertex_errors);
        assertEquals(0L, mutable_stats.edge_matches_found);
        assertEquals(0L, mutable_stats.vertices_created);
        assertEquals(0L, mutable_stats.vertices_emitted);
        assertEquals(0L, mutable_stats.vertices_updated);

        // Check that we did actually add another edge:
        assertEquals(3, Optionals.streamOf(tx.query().edges(), false).count());
        // Time
        assertEquals(1, Optionals.streamOf(tx.query().has(GraphAnnotationBean.a2_tc).edges(), false).count()); // (added/updated time)
        assertEquals(1, Optionals.streamOf(tx.query().has(GraphAnnotationBean.a2_tm).edges(), false).count()); // (added/updated time)

        // (clear the graph ready for the next test)
        tx.query().hasNot("existing").edges().forEach(v -> ((Edge) v).remove());
    }
    // Edges, existing elements, multiple elements (unlike single one)
    {
        mutable_stats.reset();

        List<Edge> ret_val = TitanGraphBuildingUtils.invokeUserMergeCode(tx, graph_schema,
                Tuples._2T(user, mock_security), Optional.empty(), maybe_merger, titan_mapper, mutable_stats,
                Edge.class, bucket_path, edge_key, new_edges, existing_edges, mutable_existing_vertex_store);

        assertEquals(1, ret_val.size());
        assertEquals(0, Optionals.streamOf(tx.query().hasNot("existing").edges(), false).count()); // (since i've overwritten an existing one...)
        assertEquals(
                Optionals.streamOf(tx.query().has(GraphAnnotationBean.a2_p).edges(), false)
                        .map(v -> titan_mapper
                                .convertValue(v, org.apache.tinkerpop.shaded.jackson.databind.JsonNode.class)
                                .toString())
                        .collect(Collectors.toList()),
                ret_val.stream()
                        .map(v -> titan_mapper
                                .convertValue(v, org.apache.tinkerpop.shaded.jackson.databind.JsonNode.class)
                                .toString())
                        .collect(Collectors.toList()));

        ret_val.stream()
                .forEach(v -> assertEquals(Arrays.asList(bucket_path),
                        Optionals.streamOf(v.properties(GraphAnnotationBean.a2_p), false)
                                .map(p -> p.value().toString()).collect(Collectors.toList())));

        // Stats
        assertEquals(0L, mutable_stats.edge_errors);
        assertEquals(0L, mutable_stats.edge_matches_found);
        assertEquals(0L, mutable_stats.edges_created);
        assertEquals(0L, mutable_stats.edges_emitted);
        assertEquals(1L, mutable_stats.edges_updated);
        assertEquals(0L, mutable_stats.vertex_errors);
        assertEquals(0L, mutable_stats.edge_matches_found);
        assertEquals(0L, mutable_stats.vertices_created);
        assertEquals(0L, mutable_stats.vertices_emitted);
        assertEquals(0L, mutable_stats.vertices_updated);

        // Check that we didn't actually add another edge:
        assertEquals(2, Optionals.streamOf(tx.query().edges(), false).count());
        // Time
        assertEquals(1, Optionals.streamOf(tx.query().has(GraphAnnotationBean.a2_tc).edges(), false).count()); // (added/updated time)
        assertEquals(1, Optionals.streamOf(tx.query().has(GraphAnnotationBean.a2_tm).edges(), false).count()); // (added/updated time)

        // (clear the graph ready for the next test)
        tx.query().hasNot("existing").edges().forEach(v -> ((Edge) v).remove());
        tx.query().has(GraphAnnotationBean.a2_p).edges().forEach(
                v -> ((Edge) v).properties(GraphAnnotationBean.a2_p).forEachRemaining(p -> p.remove()));
        tx.query().has(GraphAnnotationBean.a2_tc).edges().forEach(
                v -> ((Edge) v).properties(GraphAnnotationBean.a2_tc).forEachRemaining(p -> p.remove()));
        tx.query().has(GraphAnnotationBean.a2_tm).edges().forEach(
                v -> ((Edge) v).properties(GraphAnnotationBean.a2_tm).forEachRemaining(p -> p.remove()));
    }
    // Some error cases:
    // 1) Demonstrate a failure, just remove the label
    {
        mutable_stats.reset();

        new_vertices.get(0).remove(GraphAnnotationBean.label);

        List<Vertex> ret_val = TitanGraphBuildingUtils.invokeUserMergeCode(tx, graph_schema,
                Tuples._2T(user, mock_security), Optional.empty(), maybe_merger, titan_mapper, mutable_stats,
                Vertex.class, bucket_path, vertex_key_1, Arrays.asList(new_vertices.get(0)),
                Collections.emptyList(), Collections.emptyMap());

        // Stats
        assertEquals(0L, mutable_stats.edge_errors);
        assertEquals(0L, mutable_stats.edge_matches_found);
        assertEquals(0L, mutable_stats.edges_created);
        assertEquals(0L, mutable_stats.edges_emitted);
        assertEquals(0L, mutable_stats.edges_updated);
        assertEquals(1L, mutable_stats.vertex_errors);
        assertEquals(0L, mutable_stats.edge_matches_found);
        assertEquals(0L, mutable_stats.vertices_created);
        assertEquals(0L, mutable_stats.vertices_emitted);
        assertEquals(0L, mutable_stats.vertices_updated);

        // Time
        assertEquals(0, Optionals.streamOf(tx.query().has(GraphAnnotationBean.a2_tc).edges(), false).count()); // (added/updated time)
        assertEquals(0, Optionals.streamOf(tx.query().has(GraphAnnotationBean.a2_tm).edges(), false).count()); // (added/updated time)

        assertEquals(0, ret_val.size());
    }
    // 2) Shouldn't happen, but just check the case where no vertex can be found
    {
        mutable_stats.reset();

        List<Edge> ret_val = TitanGraphBuildingUtils.invokeUserMergeCode(tx, graph_schema,
                Tuples._2T(user, mock_security), Optional.empty(), maybe_merger, titan_mapper, mutable_stats,
                Edge.class, bucket_path, edge_key, new_edges, Collections.emptyList(), Collections.emptyMap());

        // Stats
        assertEquals(1L, mutable_stats.edge_errors);
        assertEquals(0L, mutable_stats.edge_matches_found);
        assertEquals(0L, mutable_stats.edges_created);
        assertEquals(0L, mutable_stats.edges_emitted);
        assertEquals(0L, mutable_stats.edges_updated);
        assertEquals(0L, mutable_stats.vertex_errors);
        assertEquals(0L, mutable_stats.edge_matches_found);
        assertEquals(0L, mutable_stats.vertices_created);
        assertEquals(0L, mutable_stats.vertices_emitted);
        assertEquals(0L, mutable_stats.vertices_updated);

        // Time
        assertEquals(0, Optionals.streamOf(tx.query().has(GraphAnnotationBean.a2_tc).edges(), false).count()); // (added/updated time)
        assertEquals(0, Optionals.streamOf(tx.query().has(GraphAnnotationBean.a2_tm).edges(), false).count()); // (added/updated time)

        assertEquals(0, ret_val.size());
    }

    tx.commit();

    //Quick test coverage of the simple merger, should avoid me having to do any unit testing for that module elsewhere...
    maybe_merger.ifPresent(t2 -> t2._1().onStageComplete(true));
}

From source file:com.ikanow.aleph2.graph.titan.utils.TestTitanGraphBuildingUtils.java

@SuppressWarnings("unchecked")
@Test/*  www. j a  v  a2 s . c o  m*/
public void test_buildGraph_handleMerge() {
    // Titan
    final TitanGraph titan = getSimpleTitanGraph();
    final org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper titan_mapper = titan.io(IoCore.graphson())
            .mapper().create().createMapper();
    TitanManagement mgmt = titan.openManagement();
    mgmt.makePropertyKey(GraphAnnotationBean.a2_p).dataType(String.class).cardinality(Cardinality.SET).make();
    mgmt.commit();
    // Graph schema
    final GraphSchemaBean graph_schema = BeanTemplateUtils.build(GraphSchemaBean.class)
            .with(GraphSchemaBean::deduplication_fields,
                    Arrays.asList(GraphAnnotationBean.name, GraphAnnotationBean.type))
            .with(GraphSchemaBean::custom_finalize_all_objects, false).done().get();
    // Security service
    final MockSecurityService mock_security = new MockSecurityService();
    final String user = "nobody";
    mock_security.setGlobalMockRole("nobody:DataBucketBean:read,write:test:security:*", true);
    mock_security.setGlobalMockRole(
            "nobody:DataBucketBean:read,write:aleph2_testing:other_user:test:security:*", true); // (equivalent for test bucket)
    // Bucket
    final DataBucketBean bucket = BeanTemplateUtils.build(DataBucketBean.class)
            .with(DataBucketBean::full_name, "/test/security").done().get();
    // Simple merger
    final IEnrichmentModuleContext delegate_context = Mockito.mock(IEnrichmentModuleContext.class);
    Mockito.when(delegate_context.getNextUnusedId()).thenReturn(0L);
    final Optional<Tuple2<IEnrichmentBatchModule, GraphMergeEnrichmentContext>> maybe_merger = Optional
            .of(Tuples._2T((IEnrichmentBatchModule) new SimpleGraphMergeService(),
                    new GraphMergeEnrichmentContext(delegate_context, graph_schema)));
    maybe_merger.ifPresent(t2 -> t2._1().onStageInitialize(t2._2(), null, null, null, null));
    // Stream of incoming objects

    // State:
    final LinkedList<ObjectNode> mutable_new_element_keys = new LinkedList<>();
    final MutableStatsBean mutable_stats = new MutableStatsBean();

    // Call merge with empty graph
    {
        final List<ObjectNode> vertices_and_edges = test_buildGraph_getUserGeneratedAssets_run();

        final TitanTransaction tx = titan.buildTransaction().start();

        // (tested in test_buildGraph_collectUserGeneratedAssets, assumed to work here)
        final Stream<Tuple4<ObjectNode, List<ObjectNode>, List<ObjectNode>, List<Vertex>>> ret_val_s = TitanGraphBuildingUtils
                .buildGraph_collectUserGeneratedAssets(tx, graph_schema, Tuples._2T(user, mock_security),
                        Optional.empty(), bucket, mutable_stats, vertices_and_edges.stream());

        TitanGraphBuildingUtils.buildGraph_handleMerge(tx, graph_schema, Tuples._2T(user, mock_security),
                Optional.empty(), mutable_stats, mutable_new_element_keys, maybe_merger, bucket, ret_val_s);

        // Check graph
        assertEquals(2, StreamUtils.stream(tx.query().has(GraphAnnotationBean.type, "ip").vertices()).count());
        assertEquals(3,
                StreamUtils.stream(tx.query().has(GraphAnnotationBean.type, "host").vertices()).count());
        assertEquals(5, StreamUtils.stream(tx.query().edges()).count());

        // Check stats
        assertEquals(5L, mutable_stats.vertices_created);
        assertEquals(0L, mutable_stats.vertices_updated);
        assertEquals(5L, mutable_stats.vertices_emitted);
        assertEquals(0L, mutable_stats.vertex_matches_found);
        assertEquals(0L, mutable_stats.vertex_errors);
        assertEquals(5L, mutable_stats.edges_created);
        assertEquals(0L, mutable_stats.edges_updated);
        assertEquals(6L, mutable_stats.edges_emitted);
        assertEquals(0L, mutable_stats.edge_matches_found);
        assertEquals(0L, mutable_stats.edge_errors);

        //(delete everything read for next test)
        mutable_stats.reset();
        tx.vertices().forEachRemaining(v -> v.remove());
        tx.edges().forEachRemaining(v -> v.remove());
        tx.commit();
    }
    // With some existing edges and vertices
    {
        final List<ObjectNode> vertices_and_edges = test_buildGraph_getUserGeneratedAssets_run();

        final TitanTransaction tx = titan.buildTransaction().start();
        rebuildSimpleGraph(tx, bucket.full_name());

        // (tested in test_buildGraph_collectUserGeneratedAssets, assumed to work here)
        final Stream<Tuple4<ObjectNode, List<ObjectNode>, List<ObjectNode>, List<Vertex>>> ret_val_s = TitanGraphBuildingUtils
                .buildGraph_collectUserGeneratedAssets(tx, graph_schema, Tuples._2T(user, mock_security),
                        Optional.empty(), bucket, mutable_stats, vertices_and_edges.stream());

        TitanGraphBuildingUtils.buildGraph_handleMerge(tx, graph_schema, Tuples._2T(user, mock_security),
                Optional.empty(), mutable_stats, mutable_new_element_keys, maybe_merger, bucket, ret_val_s);

        // Check graph
        assertEquals(2, StreamUtils.stream(tx.query().has(GraphAnnotationBean.type, "ip").vertices()).count());
        assertEquals(3,
                StreamUtils.stream(tx.query().has(GraphAnnotationBean.type, "host").vertices()).count());
        assertEquals(
                "Should have the right number of edges: " + StreamUtils.stream(tx.query().edges())
                        .map(e -> titan_mapper
                                .convertValue(e, org.apache.tinkerpop.shaded.jackson.databind.JsonNode.class)
                                .toString())
                        .collect(Collectors.joining("\n")),
                6, StreamUtils.stream(tx.query().edges()).count()); //(+1 for the extra "wrong type" one i added)

        // Check stats
        assertEquals(3L, mutable_stats.vertices_created);
        assertEquals(2L, mutable_stats.vertices_updated);
        assertEquals(5L, mutable_stats.vertices_emitted);
        assertEquals(2L, mutable_stats.vertex_matches_found);
        assertEquals(0L, mutable_stats.vertex_errors);
        assertEquals(4L, mutable_stats.edges_created);
        assertEquals(1L, mutable_stats.edges_updated);
        assertEquals(6L, mutable_stats.edges_emitted);
        assertEquals(1L, mutable_stats.edge_matches_found);
        assertEquals(0L, mutable_stats.edge_errors);

        //(delete everything read for next test)
        mutable_stats.reset();
        tx.vertices().forEachRemaining(v -> v.remove());
        tx.edges().forEachRemaining(v -> v.remove());
        tx.commit();
    }
    // Existing elements, but will be ignored because in test mode
    {
        final DataBucketBean test_bucket = BucketUtils.convertDataBucketBeanToTest(
                BeanTemplateUtils.clone(bucket).with(DataBucketBean::full_name, "/something/else").done(), // (needs different name) 
                "nobody");

        final List<ObjectNode> vertices_and_edges = test_buildGraph_getUserGeneratedAssets_run();

        final TitanTransaction tx = titan.buildTransaction().start();
        rebuildSimpleGraph(tx, bucket.full_name());

        // (tested in test_buildGraph_collectUserGeneratedAssets, assumed to work here)
        final Stream<Tuple4<ObjectNode, List<ObjectNode>, List<ObjectNode>, List<Vertex>>> ret_val_s = TitanGraphBuildingUtils
                .buildGraph_collectUserGeneratedAssets(tx, graph_schema, Tuples._2T(user, mock_security),
                        Optional.empty(), test_bucket, mutable_stats, vertices_and_edges.stream());

        TitanGraphBuildingUtils.buildGraph_handleMerge(tx, graph_schema, Tuples._2T(user, mock_security),
                Optional.empty(), mutable_stats, mutable_new_element_keys, maybe_merger, bucket, ret_val_s);

        // Check graph
        assertEquals(3, StreamUtils.stream(tx.query().has(GraphAnnotationBean.type, "ip").vertices()).count()); //(+1 for the existing node that _doesn't_ get merged because of the test mode)
        assertEquals(4,
                StreamUtils.stream(tx.query().has(GraphAnnotationBean.type, "host").vertices()).count()); //(+1 for the existing node that _doesn't_ get merged because of the test mode)
        assertEquals(
                "Should have the right number of edges: " + StreamUtils.stream(tx.query().edges())
                        .map(e -> titan_mapper
                                .convertValue(e, org.apache.tinkerpop.shaded.jackson.databind.JsonNode.class)
                                .toString())
                        .collect(Collectors.joining("\n")),
                7, StreamUtils.stream(tx.query().edges()).count()); //(+1 for the extra "wrong type" one i added, +1 for the existing edge that _doesn't_ get merged because of the test mode)

        // Check stats
        assertEquals(5L, mutable_stats.vertices_created);
        assertEquals(0L, mutable_stats.vertices_updated);
        assertEquals(5L, mutable_stats.vertices_emitted);
        assertEquals(0L, mutable_stats.vertex_matches_found);
        assertEquals(0L, mutable_stats.vertex_errors);
        assertEquals(5L, mutable_stats.edges_created);
        assertEquals(0L, mutable_stats.edges_updated);
        assertEquals(6L, mutable_stats.edges_emitted);
        assertEquals(0L, mutable_stats.edge_matches_found);
        assertEquals(0L, mutable_stats.edge_errors);

        //(delete everything read for next test)
        mutable_stats.reset();
        tx.vertices().forEachRemaining(v -> v.remove());
        tx.edges().forEachRemaining(v -> v.remove());
        tx.commit();
    }
    // Existing elents, but will be ignored because _they_ are from a test mode... 
    {

        final List<ObjectNode> vertices_and_edges = test_buildGraph_getUserGeneratedAssets_run();

        final TitanTransaction tx = titan.buildTransaction().start();
        {
            //(just make sure i don't accidentally run with test_bucket)
            final DataBucketBean test_bucket = BucketUtils.convertDataBucketBeanToTest(bucket, "other_user");
            rebuildSimpleGraph(tx, test_bucket.full_name());
        }

        // (tested in test_buildGraph_collectUserGeneratedAssets, assumed to work here)
        final Stream<Tuple4<ObjectNode, List<ObjectNode>, List<ObjectNode>, List<Vertex>>> ret_val_s = TitanGraphBuildingUtils
                .buildGraph_collectUserGeneratedAssets(tx, graph_schema, Tuples._2T(user, mock_security),
                        Optional.empty(), bucket, mutable_stats, vertices_and_edges.stream());

        TitanGraphBuildingUtils.buildGraph_handleMerge(tx, graph_schema, Tuples._2T(user, mock_security),
                Optional.empty(), mutable_stats, mutable_new_element_keys, maybe_merger, bucket, ret_val_s);

        // Check graph
        assertEquals(3, StreamUtils.stream(tx.query().has(GraphAnnotationBean.type, "ip").vertices()).count()); //(+1 for the existing node that _doesn't_ get merged because of the test mode)
        assertEquals(4,
                StreamUtils.stream(tx.query().has(GraphAnnotationBean.type, "host").vertices()).count()); //(+1 for the existing node that _doesn't_ get merged because of the test mode)
        assertEquals(
                "Should have the right number of edges: " + StreamUtils.stream(tx.query().edges())
                        .map(e -> titan_mapper
                                .convertValue(e, org.apache.tinkerpop.shaded.jackson.databind.JsonNode.class)
                                .toString())
                        .collect(Collectors.joining("\n")),
                7, StreamUtils.stream(tx.query().edges()).count()); //(+1 for the extra "wrong type" one i added, +1 for the existing edge that _doesn't_ get merged because of the test mode)

        // Check stats
        assertEquals(5L, mutable_stats.vertices_created);
        assertEquals(0L, mutable_stats.vertices_updated);
        assertEquals(5L, mutable_stats.vertices_emitted);
        assertEquals(0L, mutable_stats.vertex_matches_found);
        assertEquals(0L, mutable_stats.vertex_errors);
        assertEquals(5L, mutable_stats.edges_created);
        assertEquals(0L, mutable_stats.edges_updated);
        assertEquals(6L, mutable_stats.edges_emitted);
        assertEquals(0L, mutable_stats.edge_matches_found);
        assertEquals(0L, mutable_stats.edge_errors);

        //(delete everything read for next test)
        mutable_stats.reset();
        tx.vertices().forEachRemaining(v -> v.remove());
        tx.edges().forEachRemaining(v -> v.remove());
        tx.commit();
    }
    // Existing elements, but will be ignored because security is turned off
    {
        mock_security.setGlobalMockRole("nobody:DataBucketBean:read,write:test:security:*", false);

        final List<ObjectNode> vertices_and_edges = test_buildGraph_getUserGeneratedAssets_run();

        final TitanTransaction tx = titan.buildTransaction().start();
        rebuildSimpleGraph(tx, bucket.full_name());

        // (tested in test_buildGraph_collectUserGeneratedAssets, assumed to work here)
        final Stream<Tuple4<ObjectNode, List<ObjectNode>, List<ObjectNode>, List<Vertex>>> ret_val_s = TitanGraphBuildingUtils
                .buildGraph_collectUserGeneratedAssets(tx, graph_schema, Tuples._2T(user, mock_security),
                        Optional.empty(), bucket, mutable_stats, vertices_and_edges.stream());

        TitanGraphBuildingUtils.buildGraph_handleMerge(tx, graph_schema, Tuples._2T(user, mock_security),
                Optional.empty(), mutable_stats, mutable_new_element_keys, maybe_merger, bucket, ret_val_s);

        // Check graph
        assertEquals(3, StreamUtils.stream(tx.query().has(GraphAnnotationBean.type, "ip").vertices()).count()); //(+1 for the existing node that _doesn't_ get merged because of the test mode)
        assertEquals(4,
                StreamUtils.stream(tx.query().has(GraphAnnotationBean.type, "host").vertices()).count()); //(+1 for the existing node that _doesn't_ get merged because of the test mode)
        assertEquals(
                "Should have the right number of edges: " + StreamUtils.stream(tx.query().edges())
                        .map(e -> titan_mapper
                                .convertValue(e, org.apache.tinkerpop.shaded.jackson.databind.JsonNode.class)
                                .toString())
                        .collect(Collectors.joining("\n")),
                7, StreamUtils.stream(tx.query().edges()).count()); //(+1 for the extra "wrong type" one i added, +1 for the existing edge that _doesn't_ get merged because of the test mode)

        // Check stats
        assertEquals(5L, mutable_stats.vertices_created);
        assertEquals(0L, mutable_stats.vertices_updated);
        assertEquals(5L, mutable_stats.vertices_emitted);
        assertEquals(0L, mutable_stats.vertex_matches_found);
        assertEquals(0L, mutable_stats.vertex_errors);
        assertEquals(5L, mutable_stats.edges_created);
        assertEquals(0L, mutable_stats.edges_updated);
        assertEquals(6L, mutable_stats.edges_emitted);
        assertEquals(0L, mutable_stats.edge_matches_found);
        assertEquals(0L, mutable_stats.edge_errors);

        //(delete everything read for next test)
        mutable_stats.reset();
        tx.vertices().forEachRemaining(v -> v.remove());
        tx.edges().forEachRemaining(v -> v.remove());
        tx.commit();
    }
}