private void getIgnoredNodes(Node node, List<Node> ignoredNodes) {
    if (node.isIgnored()) {
      ignoredNodes.add(node);
    }

    if (node.getChildren() != null) {
      for (Node child : node.getChildren()) {
        getIgnoredNodes(child, ignoredNodes);
      }
    }
  }
  protected void applyMetadataInheritance(Node node) {
    Set<org.dataconservancy.packaging.tool.model.dprofile.PropertyType> inheritablePropertyTypes =
        view.getInheritMetadataCheckBoxMap().keySet();

    if (node.getChildren() != null) {
      inheritablePropertyTypes
          .stream()
          .filter(
              inheritablePropertyType ->
                  view.getInheritMetadataCheckBoxMap().get(inheritablePropertyType).isSelected())
          .forEach(
              inheritablePropertyType -> {
                List<Property> inheritablePropertyValues =
                    controller
                        .getDomainProfileService()
                        .getProperties(node, inheritablePropertyType);
                if (inheritablePropertyValues != null) {
                  for (Property inheritablePropertyValue : inheritablePropertyValues) {
                    node.getChildren()
                        .stream()
                        .filter(child -> !child.isIgnored() && child.getDomainObject() != null)
                        .forEach(
                            child -> {
                              child
                                  .getNodeType()
                                  .getPropertyConstraints()
                                  .stream()
                                  .filter(
                                      constraint ->
                                          constraint
                                              .getPropertyType()
                                              .equals(inheritablePropertyType))
                                  .forEach(
                                      constraint ->
                                          controller
                                              .getDomainProfileService()
                                              .addProperty(child, inheritablePropertyValue));
                              if (child.getChildren() != null) {
                                applyMetadataInheritance(child);
                              }
                            });
                  }
                }
              });
    }
  }
  private boolean updateUnassignedNode(Node node) {
    if (!node.isIgnored()) {
      if (node.getNodeType() == null) {
        if (!getController()
            .getDomainProfileService()
            .assignNodeTypes(getController().getPrimaryDomainProfile(), node)) {
          return false;
        }
      }

      if (node.getChildren() != null) {
        for (Node child : node.getChildren()) {
          if (!updateUnassignedNode(child)) {
            return false;
          }
        }
      }
    }

    return true;
  }
  /*
   * Validates that all required properties are filled in for a given node.
   */
  private void validateNodeProperties(Node node, StringBuilder errBuilder) {
    if (Thread.currentThread().isInterrupted()) {
      return;
    }
    List<PropertyConstraint> violatedConstraints =
        controller.getDomainProfileService().validateProperties(node, node.getNodeType());
    if (!violatedConstraints.isEmpty()) {
      markNodeAsInvalid(node);

      if (node.getFileInfo() != null) {
        errBuilder.append(node.getFileInfo().getLocation().toString()).append("\n");
      } else {
        errBuilder.append(node.getIdentifier().toString()).append("\n");
      }

      for (PropertyConstraint violation : violatedConstraints) {
        errBuilder.append("\t--").append(violation.getPropertyType().getLabel()).append("\n");
      }

      errBuilder.append("\n");
    } else {
      markNodeAsValid(node);
    }

    if (node.getChildren() != null) {
      for (Node child : node.getChildren()) {
        validateNodeProperties(child, errBuilder);
        if (Thread.currentThread().isInterrupted()) {
          break;
        }
      }
    }
  }
  protected TreeItem<Node> buildTree(Node node, boolean showIgnoredArtifacts) {
    final TreeItem<Node> item = new TreeItem<>(node);

    item.expandedProperty()
        .addListener(
            (observableValue, oldValue, newValue) -> {
              if (!oldValue && newValue) {
                expandedNodes.add(item.getValue().getIdentifier());
              } else if (oldValue && !newValue) {
                expandedNodes.remove(item.getValue().getIdentifier());
              }
            });

    if (node.getChildren() != null) {
      node.getChildren()
          .stream()
          .filter(child -> showIgnoredArtifacts || !child.isIgnored())
          .forEach(child -> item.getChildren().add(buildTree(child, showIgnoredArtifacts)));
    }

    return item;
  }
  private TreeItem<Node> findItem(TreeItem<Node> tree, Node node) {
    if (node.equals(tree.getValue())) {
      return tree;
    }

    for (TreeItem<Node> child : tree.getChildren()) {
      TreeItem<Node> result = findItem(child, node);

      if (result != null) {
        return result;
      }
    }

    return null;
  }
  @Override
  public List<NodeType> getPossibleChildTypes(Node node) {
    List<NodeType> childNodes = new ArrayList<>();
    for (NodeType nodeType : controller.getPrimaryDomainProfile().getNodeTypes()) {
      if (nodeType.getParentConstraints() != null) {
        for (NodeConstraint parentConstraint : nodeType.getParentConstraints()) {
          if (parentConstraint.matchesAny()
              || (parentConstraint.getNodeType() != null
                  && parentConstraint.getNodeType().equals(node.getNodeType()))) {
            childNodes.add(nodeType);
            break;
          }
        }
      }
    }

    return childNodes;
  }
  @Override
  public void addToTree(Node parent, Path contentToAdd) {
    try {
      Node node = ipmService.createTreeFromFileSystem(contentToAdd);
      parent.addChild(node);
      controller
          .getDomainProfileService()
          .assignNodeTypes(controller.getPrimaryDomainProfile(), parent);

      // Refresh the tree display
      displayPackageTree();

    } catch (IOException e) {
      log.error(e.getMessage());
      view.getErrorLabel()
          .setText(TextFactory.getText(ErrorKey.ADD_CONTENT_ERROR) + e.getMessage());
      view.getErrorLabel().setVisible(true);
    }
  }
  // Sorts the tree items in the provided list. //This has been made profile agnostic it now just
  // sorts based on whether the node is a directory
  private void sortChildren(ObservableList<TreeItem<Node>> children) {
    FXCollections.sort(
        children,
        (o1, o2) -> {
          Node nodeOne = o1.getValue();
          Node nodeTwo = o2.getValue();

          // File info is null if it's a data item created for a metadata file transformation.
          if (nodeOne.getFileInfo() == null) {
            if (nodeTwo.getFileInfo() == null) {
              return 0;
            } else if (nodeTwo.getFileInfo().isDirectory()) {
              return 1;
            } else {
              return -1;
            }
          } else if (nodeTwo.getFileInfo() == null) {
            if (nodeOne.getFileInfo().isDirectory()) {
              return -1;
            } else {
              return 1;
            }
          }

          if (nodeOne.getFileInfo().isDirectory() == nodeTwo.getFileInfo().isDirectory()) {
            return 0;
          }

          if (nodeOne.getFileInfo().isDirectory() && nodeTwo.getFileInfo().isFile()) {
            return -1;
          }

          return 1;
        });
  }