@Override
    public boolean merge(final SAML2Configuration configuration) throws Exception {
        var metadataResolver = buildMetadataResolver();
        try {
            var existingEntity = metadataResolver.resolveSingle(new CriteriaSet(
                new EntityIdCriterion(entityId),
                new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME)));
            if (existingEntity != null) {
                logger.debug("Merging metadata for entity id {}", existingEntity.getEntityID());
                var currentEntity = buildEntityDescriptor();
                var currentSP = Objects.requireNonNull(currentEntity.getSPSSODescriptor(SAMLConstants.SAML20P_NS));
                var existingSP = Objects.requireNonNull(existingEntity.getSPSSODescriptor(SAMLConstants.SAML20P_NS));

                var currentEntityHasChanged = new AtomicBoolean(false);
                if (existingSP.getExtensions() != null) {
                    var addInitiator = existingSP.getExtensions().getUnknownXMLObjects()
                        .stream()
                        .noneMatch(object -> object instanceof final RequestInitiator init
                            && StringUtils.equalsIgnoreCase(init.getBinding(), RequestInitiator.DEFAULT_ELEMENT_NAME.getNamespaceURI())
                            && StringUtils.equalsIgnoreCase(init.getLocation(), configuration.resolveRequestInitiatorLocation()));
                    if (addInitiator) {
                        var builderFactory = Configuration.getBuilderFactory();
                        var builderReq = (SAMLObjectBuilder<RequestInitiator>)
                            builderFactory.getBuilder(RequestInitiator.DEFAULT_ELEMENT_NAME);

                        var requestInitiator = Objects.requireNonNull(builderReq).buildObject();
                        requestInitiator.setLocation(configuration.resolveRequestInitiatorLocation());
                        requestInitiator.setBinding(RequestInitiator.DEFAULT_ELEMENT_NAME.getNamespaceURI());
                        existingSP.getExtensions().getUnknownXMLObjects().add(requestInitiator);
                        logger.debug("Adding request initiator {} to existing entity", requestInitiator.getLocation());
                        currentEntityHasChanged.set(true);
                    }
                }

                currentSP.getSingleLogoutServices().forEach(service -> {
                    if (!existingSP.getSingleLogoutServices().contains(service)) {
                        service.detach();
                        existingSP.getSingleLogoutServices().add(service);
                        logger.debug("Adding single logout service {} to existing entity", service.getLocation());
                        currentEntityHasChanged.set(true);
                    }
                });
                currentSP.getAssertionConsumerServices().forEach(service -> {
                    if (!existingSP.getAssertionConsumerServices().contains(service)) {
                        service.detach();
                        service.setIndex(existingSP.getAssertionConsumerServices().size());
                        existingSP.getAssertionConsumerServices().add(service);
                        logger.debug("Adding assertion consumer service {} to existing entity", service.getLocation());
                        currentEntityHasChanged.set(true);
                    }
                });
                if (currentEntityHasChanged.get()) {
                    var metadata = getMetadata(existingEntity);
                    logger.debug("Storing metadata after the merge: {}", metadata);
                    return storeMetadata(metadata, true);
                }
            }
            return false;
        } finally {
            if (metadataResolver instanceof DestructableComponent dc) {
                try {
                    dc.destroy();
                } catch (final Exception e) {
                    logger.error("Error destroying metadata resolver", e);
                }
            }
        }
    }
Generates metadata object with standard values and overridden user defined values.

@author Misagh Moayyed
@since 4.0.1
pac4j-saml/src/main/java/org/pac4j/saml/metadata/BaseSAML2MetadataGenerator.java