docs: private void addProviderRelationships(DefaultDirectedWeightedGraph<RuleProvider, DefaultEdge> graph)
      {
          linkRulePhases();
  
          for (RuleProvider provider : providers)
          {
              RuleProvider phaseProvider = getByClass(provider.getMetadata().getPhase());
  
              List<String> errors = new LinkedList<>();
  
              for (Class<? extends RuleProvider> clz : provider.getMetadata().getExecuteAfter())
              {
                  // add connections to ruleproviders that should execute before this one
                  addExecuteAfterRelationship(graph, provider, errors, clz);
              }
  
              if (phaseProvider != null)
              {
                  if (provider.getMetadata().getPhase() != Proxies.unwrap(provider).getClass())
                      addExecuteAfterRelationship(graph, provider, errors, provider.getMetadata().getPhase());
  
                  for (Class<? extends RuleProvider> clz : phaseProvider.getMetadata().getExecuteAfter())
                  {
                      addExecuteAfterRelationship(graph, provider, errors, clz);
                  }
              }
  
              for (Class<? extends RuleProvider> clz : provider.getMetadata().getExecuteBefore())
              {
                  // add connections to ruleproviders that should execute after this one
                  addExecuteBeforeRelationship(graph, provider, errors, clz);
              }
  
              if (phaseProvider != null)
              {
                  for (Class<? extends RuleProvider> clz : phaseProvider.getMetadata().getExecuteBefore())
                  {
                      addExecuteBeforeRelationship(graph, provider, errors, clz);
                  }
              }
  
              for (String depID : provider.getMetadata().getExecuteAfterIDs())
              {
                  // add connections to ruleproviders that should execute before this one (by String ID)
                  RuleProvider otherProvider = getByID(depID);
                  if (otherProvider == null)
                  {
                      errors.add("RuleProvider " + provider.getMetadata().getID() + " is specified to execute after: "
                                  + depID + " but this provider could not be found.");
                  }
                  else
                      graph.addEdge(otherProvider, provider);
              }
  
              for (String depID : provider.getMetadata().getExecuteBeforeIDs())
              {
                  // add connections to ruleproviders that should execute before this one (by String ID)
                  RuleProvider otherProvider = getByID(depID);
                  if (otherProvider == null)
                  {
                      errors.add("RuleProvider " + provider.getMetadata().getID() + " is specified to execute before: "
                                  + depID + " but this provider could not be found.");
                  }
                  else
                      graph.addEdge(provider, otherProvider);
              }
  
              if (!errors.isEmpty())
                  throw new WindupMultiStringException("Some rules to be executed before or after were not found:", errors);
  
          }
      }