public function synchronize(array $roles)
    {
        $result = new SynchronizationResult();

        $repository = $this;
        $this->entityManager->transactional(function (EntityManager $em) use ($roles, $repository, $result) {
            $idpsToBeRemoved = $repository->findAllIdentityProviderEntityIds();
            $spsToBeRemoved = $repository->findAllServiceProviderEntityIds();

            foreach ($roles as $role) {
                if ($role instanceof IdentityProvider) {
                    // Does the IDP already exist in the database?
                    $index = array_search($role->entityId, $idpsToBeRemoved);

                    if ($index === false) {
                        // The IDP is new: create it.
                        $em->persist($role);
                        $result->createdIdentityProviders[] = $role->entityId;
                    } else {
                        // Remove from the list of entity ids so it won't get deleted later on.
                        unset($idpsToBeRemoved[$index]);

                        // The IDP already exists: update it.
                        $identityProvider = $repository->findIdentityProviderByEntityId($role->entityId);
                        $role->id = $identityProvider->id;
                        $em->persist($em->merge($role));
                        $result->updatedIdentityProviders[] = $role->entityId;
                    }
                    continue;
                }

                if ($role instanceof ServiceProvider) {
                    // Does the SP already exist in the database?
                    $index = array_search($role->entityId, $spsToBeRemoved);
                    if ($index === false) {
                        // The SP is new: create it.
                        $em->persist($role);
                        $result->createdServiceProviders[] = $role->entityId;
                    } else {
                        // Remove from the list of entity ids so it won't get deleted later on.
                        unset($spsToBeRemoved[$index]);

                        // The SP already exists: update it.
                        $serviceProvider = $repository->findServiceProviderByEntityId($role->entityId);
                        $role->id = $serviceProvider->id;
                        $em->persist($em->merge($role));
                        $result->updatedServiceProviders[] = $role->entityId;
                    }
                    continue;
                }

                throw new RuntimeException('Unsupported role provided to synchonization: ' . var_export($role, true));
            }

            if ($idpsToBeRemoved) {
                $this->deleteRolesByEntityIds($this->idpRepository, $idpsToBeRemoved);

                $result->removedIdentityProviders = $idpsToBeRemoved;
            }

            if ($spsToBeRemoved) {
                $this->deleteRolesByEntityIds($this->spRepository, $spsToBeRemoved);

                $result->removedServiceProviders = $spsToBeRemoved;
            }
        });

        return $result;
    }