docs: @Nonnull
    public EChange setRoleData (@Nullable final String sRoleID,
                                @Nonnull @Nonempty final String sNewName,
                                @Nullable final String sNewDescription,
                                @Nullable final Map <String, String> aNewCustomAttrs)
    {
      // Resolve role
      final Role aRole = getOfID (sRoleID);
      if (aRole == null)
      {
        AuditHelper.onAuditModifyFailure (Role.OT, sRoleID, "no-such-role-id");
        return EChange.UNCHANGED;
      }
  
      m_aRWLock.writeLock ().lock ();
      try
      {
        EChange eChange = aRole.setName (sNewName);
        eChange = eChange.or (aRole.setDescription (sNewDescription));
        eChange = eChange.or (aRole.attrs ().setAll (aNewCustomAttrs));
        if (eChange.isUnchanged ())
          return EChange.UNCHANGED;
  
        BusinessObjectHelper.setLastModificationNow (aRole);
        internalUpdateItem (aRole);
      }
      finally
      {
        m_aRWLock.writeLock ().unlock ();
      }
      AuditHelper.onAuditModifySuccess (Role.OT, "all", aRole.getID (), sNewName, sNewDescription, aNewCustomAttrs);
  
      // Execute callback as the very last action
      m_aCallbacks.forEach (aCB -> aCB.onRoleUpdated (aRole));
  
      return EChange.CHANGED;
    }