private String compare(Node actual, Node expected) {
    List<Node> actualChildren =
        CorePlugin.getInstance()
            .getNodeService()
            .getChildren(actual, new ServiceContext<>(CorePlugin.getInstance().getNodeService()));
    List<Node> expectedChildren =
        CorePlugin.getInstance()
            .getNodeService()
            .getChildren(expected, new ServiceContext<>(CorePlugin.getInstance().getNodeService()));

    // check number of children
    if (actualChildren.size() != expectedChildren.size()) {
      return ResourcesPlugin.getInstance()
          .getMessage(
              "regex.test.compare.result.error.childrenCount", actual.getPropertyValue(NAME));
    }

    for (int i = 0; i < actualChildren.size(); i++) {
      Node actualChild = actualChildren.get(i);
      Node expectedChild = expectedChildren.get(i);
      // compare child properties
      String propertiesCompare = compareProperties(actualChild, expectedChild);
      if (propertiesCompare != null) {
        return propertiesCompare;
      }
      // recurse
      String childrenCompare = compare(actualChild, expectedChild);
      if (childrenCompare != null) {
        return childrenCompare;
      }
    }
    return null;
  }
  private String compareProperties(Node actual, Node expected) {
    // check type
    if (!actual.getType().equals(expected.getType())) {
      return ResourcesPlugin.getInstance()
          .getMessage("regex.test.compare.result.eror.type", actual.getPropertyValue(NAME));
    }

    // check properties
    ServiceContext<NodeService> context =
        new ServiceContext<>(CorePlugin.getInstance().getNodeService());
    Map<String, Object> expectedProperties = expected.getOrPopulateProperties(context);
    Map<String, Object> actualProperties = actual.getOrPopulateProperties(context);

    // check properties size
    if (actualProperties.size() != expectedProperties.size()) {
      return ResourcesPlugin.getInstance()
          .getMessage(
              "regex.test.compare.result.error.propertiesCount", actual.getPropertyValue(NAME));
    }

    // iterate properties
    for (Entry<String, Object> entry : expectedProperties.entrySet()) {
      if (!actualProperties.containsKey(entry.getKey())) {
        return ResourcesPlugin.getInstance()
            .getMessage(
                "regex.test.compare.result.propertyNotFound",
                entry.getKey(),
                actual.getPropertyValue(NAME));
      }
      Object expectedPropertyValue = entry.getValue();
      Object actualPropertyValue = actualProperties.get(entry.getKey());
      if (!Utils.safeEquals(actualPropertyValue, expectedPropertyValue)) {
        return ResourcesPlugin.getInstance()
            .getMessage(
                "regex.test.compare.result.error.propertyValue",
                entry.getKey(),
                actual.getPropertyValue(NAME),
                expectedPropertyValue,
                actualPropertyValue);
      }
    }
    return null;
  }
 private String compareForTestFile(Node testFile) {
   String matches =
       compareForTestFile(
           testFile.getNodeUri(), REGEX_MATCHES_NODE_TYPE, REGEX_EXPECTED_MATCHES_NODE_TYPE);
   String model =
       compareForTestFile(
           testFile.getNodeUri(), REGEX_MODEL_TREE_NODE_TYPE, REGEX_EXPECTED_MODEL_TREE_NODE_TYPE);
   return ResourcesPlugin.getInstance()
       .getMessage("regex.test.compare.result", testFile.getPropertyValue(NAME), matches, model);
 }
  private String compareForTestFile(String testFileUri, String actual, String expected) {
    String actualNodeUri = testFileUri.replaceFirst(REGEX_TEST_FILE_NODE_TYPE, actual);
    String expectedNodeUri = testFileUri.replaceFirst(REGEX_TEST_FILE_NODE_TYPE, expected);

    ResourceServiceRemote rsr = new ResourceServiceRemote();
    rsr.subscribeToParentResource(actualNodeUri);
    rsr.subscribeToParentResource(expectedNodeUri);

    Node actualNode = CorePlugin.getInstance().getResourceService().getNode(actualNodeUri);
    Node expectedNode = CorePlugin.getInstance().getResourceService().getNode(expectedNodeUri);
    String result = compare(actualNode, expectedNode);
    return result != null
        ? result
        : ResourcesPlugin.getInstance().getMessage("regex.test.compare.result.ok");
  }