/*
 * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.jersey.model.internal;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import javax.ws.rs.ConstrainedTo;
import javax.ws.rs.Priorities;
import javax.ws.rs.RuntimeType;
import javax.ws.rs.core.Configuration;
import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;

import javax.annotation.Priority;

import org.glassfish.jersey.ExtendedConfig;
import org.glassfish.jersey.internal.LocalizationMessages;
import org.glassfish.jersey.internal.ServiceFinder;
import org.glassfish.jersey.internal.inject.Binder;
import org.glassfish.jersey.internal.inject.CompositeBinder;
import org.glassfish.jersey.internal.inject.InjectionManager;
import org.glassfish.jersey.internal.inject.ProviderBinder;
import org.glassfish.jersey.internal.spi.AutoDiscoverable;
import org.glassfish.jersey.internal.spi.ForcedAutoDiscoverable;
import org.glassfish.jersey.internal.util.PropertiesHelper;
import org.glassfish.jersey.model.ContractProvider;
import org.glassfish.jersey.process.Inflector;

/**
 * Common immutable {@link javax.ws.rs.core.Configuration} implementation for
 * server and client.
 *
 * @author Michal Gajdos
 * @author Marek Potociar
 */
public class CommonConfig implements FeatureContext, ExtendedConfig {

    private static final Logger LOGGER = Logger.getLogger(CommonConfig.class.getName());
    private static final Function<Object, Binder> CAST_TO_BINDER = Binder.class::cast;

    /**
     * Configuration runtime type.
     */
    private final RuntimeType type;
    /**
     * Configuration properties collection and it's immutable views.
     */
    private final Map<String, Object> properties;
    private final Map<String, Object> immutablePropertiesView;
    private final Collection<String> immutablePropertyNames;
    /**
     * Configured providers, does not include features and binders.
     */
    private final ComponentBag componentBag;
    /**
     * Collection of unprocessed feature registrations.
     */
    private final List<FeatureRegistration> newFeatureRegistrations;
    /**
     * Collection of enabled feature classes.
     */
    private final Set<Class<? extends Feature>> enabledFeatureClasses;
    /**
     * Collection of enabled feature instances.
     */
    private final Set<Feature> enabledFeatures;

    /**
     * Flag determining whether the configuration of meta-providers (excl. binders) should be disabled.
     */
    private boolean disableMetaProviderConfiguration;

    /**
     * A single feature registration record.
     */
    private static final class FeatureRegistration {

        private final Class<? extends Feature> featureClass;
        private final Feature feature;
        private final RuntimeType runtimeType;
        private final int priority;

        private FeatureRegistration(final Class<? extends Feature> featureClass, int priority) {
            this.featureClass = featureClass;
            this.feature = null;
            final ConstrainedTo runtimeTypeConstraint = featureClass.getAnnotation(ConstrainedTo.class);
            this.runtimeType = runtimeTypeConstraint == null ? null : runtimeTypeConstraint.value();
            this.priority = priority(featureClass, priority);
        }

        private FeatureRegistration(final Feature feature, int priority) {
            this.featureClass = feature.getClass();
            this.feature = feature;
            final ConstrainedTo runtimeTypeConstraint = featureClass.getAnnotation(ConstrainedTo.class);
            this.runtimeType = runtimeTypeConstraint == null ? null : runtimeTypeConstraint.value();
            this.priority = priority(featureClass, priority);
        }

        private static int priority(Class<? extends Feature> featureClass, int priority) {
            if (priority != ContractProvider.NO_PRIORITY) {
                return priority;
            }
            final Priority priorityAnnotation = featureClass.getAnnotation(Priority.class);
            if (priorityAnnotation != null) {
                return priorityAnnotation.value();
            } else {
                return Priorities.USER;
            }
        }

        /**
         * Get the registered feature class.
         *
         * @return registered feature class.
         */
        private Class<? extends Feature> getFeatureClass() {
            return featureClass;
        }

        /**
         * Get the registered feature instance or {@code null} if this is a
         * class based feature registration.
         *
         * @return the registered feature instance or {@code null} if this is a
         *         class based feature registration.
         */
        private Feature getFeature() {
            return feature;
        }

        /**
         * Get the {@code RuntimeType} constraint given by {@code ConstrainedTo} annotated
         * the Feature or {@code null} if not annotated.
         *
         * @return the {@code RuntimeType} constraint given by {@code ConstrainedTo} annotated
         *         the Feature or {@code null} if not annotated.
         */
        private RuntimeType getFeatureRuntimeType() {
            return runtimeType;
        }

        @Override
        public boolean equals(final Object obj) {
            if (this == obj) {
                return true;
            }
            if (!(obj instanceof FeatureRegistration)) {
                return false;
            }
            final FeatureRegistration other = (FeatureRegistration) obj;

            return (featureClass == other.featureClass)
                    || (feature != null && (feature == other.feature || feature.equals(other.feature)));
        }

        @Override
        public int hashCode() {
            int hash = 47;
            hash = 13 * hash + (feature != null ? feature.hashCode() : 0);
            hash = 13 * hash + (featureClass != null ? featureClass.hashCode() : 0);
            return hash;
        }
    }

    /**
     * Create a new {@code RuntimeConfig} instance.
     * <p>
     * The constructor provides a way for defining a {@link ContractProvider contract
     * provider model} registration strategy. Once a registration model is built
     * for a newly registered contract, the provided registration strategy filter is
     * consulted whether the model should be registered or not.
     * </p>
     * <p>
     * Clients can use the method to cancel any contract provider model registration
     * that does not meet the criteria of a given configuration context, such as a model
     * that does not have any recognized contracts associated with it.
     * </p>
     *
     * @param type                 configuration runtime type.
     * @param registrationStrategy function driving the decision (based on the introspected
     *                             {@link ContractProvider contract provider model}) whether
     *                             or not should the component class registration continue
     *                             towards a successful completion.
     */
    public CommonConfig(final RuntimeType type, final Predicate<ContractProvider> registrationStrategy) {
        this.type = type;

        this.properties = new HashMap<>();
        this.immutablePropertiesView = Collections.unmodifiableMap(properties);
        this.immutablePropertyNames = Collections.unmodifiableCollection(properties.keySet());

        this.componentBag = ComponentBag.newInstance(registrationStrategy);

        this.newFeatureRegistrations = new LinkedList<>();

        this.enabledFeatureClasses = Collections.newSetFromMap(new IdentityHashMap<>());
        this.enabledFeatures = new HashSet<>();

        this.disableMetaProviderConfiguration = false;
    }

    /**
     * Copy constructor.
     *
     * @param config configurable to copy class properties from.
     */
    public CommonConfig(final CommonConfig config) {
        this.type = config.type;

        this.properties = new HashMap<>(config.properties.size());
        this.immutablePropertiesView = Collections.unmodifiableMap(this.properties);
        this.immutablePropertyNames = Collections.unmodifiableCollection(this.properties.keySet());

        this.componentBag = config.componentBag.copy();

        this.newFeatureRegistrations = new LinkedList<>();
        this.enabledFeatureClasses = Collections.newSetFromMap(new IdentityHashMap<>());
        this.enabledFeatures = new HashSet<>();

        copy(config, false);
    }

    /**
     * Copy config properties, providers from given {@code config} to this instance.
     *
     * @param config configurable to copy class properties from.
     * @param loadComponentBag {@code true} if the component bag from config should be copied as well, {@code false} otherwise.
     */
    private void copy(final CommonConfig config, final boolean loadComponentBag) {
        this.properties.clear();
        this.properties.putAll(config.properties);

        this.newFeatureRegistrations.clear();
        this.newFeatureRegistrations.addAll(config.newFeatureRegistrations);

        this.enabledFeatureClasses.clear();
        this.enabledFeatureClasses.addAll(config.enabledFeatureClasses);

        this.enabledFeatures.clear();
        this.enabledFeatures.addAll(config.enabledFeatures);

        this.disableMetaProviderConfiguration = config.disableMetaProviderConfiguration;

        if (loadComponentBag) {
            this.componentBag.loadFrom(config.componentBag);
        }
    }

    @Override
    public ExtendedConfig getConfiguration() {
        return this;
    }

    @Override
    public RuntimeType getRuntimeType() {
        return type;
    }

    @Override
    public Map<String, Object> getProperties() {
        return immutablePropertiesView;
    }

    @Override
    public Object getProperty(final String name) {
        return properties.get(name);
    }

    @Override
    public boolean isProperty(final String name) {
        return PropertiesHelper.isProperty(getProperty(name));
    }

    @Override
    public Collection<String> getPropertyNames() {
        return immutablePropertyNames;
    }

    @Override
    public boolean isEnabled(final Class<? extends Feature> featureClass) {
        return enabledFeatureClasses.contains(featureClass);
    }

    @Override
    public boolean isEnabled(final Feature feature) {
        return enabledFeatures.contains(feature);
    }

    @Override
    public boolean isRegistered(final Object component) {
        return componentBag.getInstances().contains(component);
    }

    @Override
    public boolean isRegistered(final Class<?> componentClass) {
        return componentBag.getRegistrations().contains(componentClass);
    }

    @Override
    public Map<Class<?>, Integer> getContracts(final Class<?> componentClass) {
        final ContractProvider model = componentBag.getModel(componentClass);
        return (model == null) ? Collections.emptyMap() : model.getContractMap();
    }

    @Override
    public Set<Class<?>> getClasses() {
        return componentBag.getClasses();
    }

    @Override
    public Set<Object> getInstances() {
        return componentBag.getInstances();
    }

    /**
     * Returns a {@link ComponentBag} instance associated with the configuration.
     *
     * @return a non-null component bag instance.
     */
    public final ComponentBag getComponentBag() {
        return componentBag;
    }

    /**
     * An extension point that provides a way how to define a custom enhancement/update
     * operation of a contract provider model registration being produced for a given
     * component class.
     * Default implementation return an enhancer just builds the model.
     * <p>
     * Derived implementations may use this method to e.g. filter out all contracts not
     * applicable in the given configuration context or change the model scope. The returned
     * set of filtered contracts is then used for the actual provider registration.
     * </p>
     *
     * @param componentClass class of the component being registered.
     * @return filter for the contracts that being registered for a given component class.
     */
    protected Inflector<ContractProvider.Builder, ContractProvider> getModelEnhancer(final Class<?> componentClass) {
        return ComponentBag.AS_IS;
    }

    /**
     * Set the configured properties to the provided map of properties.
     *
     * @param properties new map of properties to be set.
     * @return updated configuration instance.
     */
    public CommonConfig setProperties(final Map<String, ?> properties) {
        this.properties.clear();

        if (properties != null) {
            this.properties.putAll(properties);
        }
        return this;
    }

    /**
     * Add properties to {@code ResourceConfig}.
     *
     * If any of the added properties exists already, he values of the existing
     * properties will be replaced with new values.
     *
     * @param properties properties to add.
     * @return updated configuration instance.
     */
    public CommonConfig addProperties(final Map<String, ?> properties) {
        if (properties != null) {
            this.properties.putAll(properties);
        }
        return this;
    }

    @Override
    public CommonConfig property(final String name, final Object value) {
        if (value == null) {
            properties.remove(name);
        } else {
            properties.put(name, value);
        }
        return this;
    }

    @Override
    public CommonConfig register(final Class<?> componentClass) {
        checkComponentClassNotNull(componentClass);
        if (componentBag.register(componentClass, getModelEnhancer(componentClass))) {
            processFeatureRegistration(null, componentClass, ContractProvider.NO_PRIORITY);
        }

        return this;
    }

    @Override
    public CommonConfig register(final Class<?> componentClass, final int bindingPriority) {
        checkComponentClassNotNull(componentClass);
        if (componentBag.register(componentClass, bindingPriority, getModelEnhancer(componentClass))) {
            processFeatureRegistration(null, componentClass, bindingPriority);
        }

        return this;
    }

    @Override
    public CommonConfig register(final Class<?> componentClass, final Class<?>... contracts) {
        checkComponentClassNotNull(componentClass);
        if (contracts == null || contracts.length == 0) {
            LOGGER.warning(LocalizationMessages.COMPONENT_CONTRACTS_EMPTY_OR_NULL(componentClass));
            return this;
        }
        if (componentBag.register(componentClass, asNewIdentitySet(contracts), getModelEnhancer(componentClass))) {
            processFeatureRegistration(null, componentClass, ContractProvider.NO_PRIORITY);
        }

        return this;
    }

    @Override
    public CommonConfig register(final Class<?> componentClass, final Map<Class<?>, Integer> contracts) {
        checkComponentClassNotNull(componentClass);
        if (componentBag.register(componentClass, contracts, getModelEnhancer(componentClass))) {
            processFeatureRegistration(null, componentClass, ContractProvider.NO_PRIORITY);
        }

        return this;
    }

    @Override
    public CommonConfig register(final Object component) {
        checkProviderNotNull(component);

        final Class<?> componentClass = component.getClass();
        if (componentBag.register(component, getModelEnhancer(componentClass))) {
            processFeatureRegistration(component, componentClass, ContractProvider.NO_PRIORITY);
        }

        return this;
    }

    @Override
    public CommonConfig register(final Object component, final int bindingPriority) {
        checkProviderNotNull(component);
        final Class<?> componentClass = component.getClass();
        if (componentBag.register(component, bindingPriority, getModelEnhancer(componentClass))) {
            processFeatureRegistration(component, componentClass, bindingPriority);
        }

        return this;
    }

    @Override
    public CommonConfig register(final Object component, final Class<?>... contracts) {
        checkProviderNotNull(component);
        final Class<?> componentClass = component.getClass();
        if (contracts == null || contracts.length == 0) {
            LOGGER.warning(LocalizationMessages.COMPONENT_CONTRACTS_EMPTY_OR_NULL(componentClass));
            return this;
        }
        if (componentBag.register(component, asNewIdentitySet(contracts), getModelEnhancer(componentClass))) {
            processFeatureRegistration(component, componentClass, ContractProvider.NO_PRIORITY);
        }

        return this;
    }

    @Override
    public CommonConfig register(final Object component, final Map<Class<?>, Integer> contracts) {
        checkProviderNotNull(component);
        final Class<?> componentClass = component.getClass();
        if (componentBag.register(component, contracts, getModelEnhancer(componentClass))) {
            processFeatureRegistration(component, componentClass, ContractProvider.NO_PRIORITY);
        }

        return this;
    }

    private void processFeatureRegistration(final Object component, final Class<?> componentClass, int priority) {
        final ContractProvider model = componentBag.getModel(componentClass);
        if (model.getContracts().contains(Feature.class)) {
            @SuppressWarnings("unchecked")
            final FeatureRegistration registration = (component != null)
                    ? new FeatureRegistration((Feature) component, priority)
                    : new FeatureRegistration((Class<? extends Feature>) componentClass, priority);
            newFeatureRegistrations.add(registration);
        }
    }

    /**
     * Load the internal configuration state from an externally provided configuration state.
     * <p/>
     * Calling this method effectively replaces existing configuration state of the instance with the state represented by the
     * externally provided configuration. If the features, auto-discoverables of given config has been already configured then
     * this method will make sure to not configure them for the second time.
     *
     * @param config external configuration state to replace the configuration of this configurable instance.
     * @return the updated common configuration instance.
     */
    public CommonConfig loadFrom(final Configuration config) {
        if (config instanceof CommonConfig) {
            // If loading from CommonConfig then simply copy properties and check whether given config has been initialized.
            final CommonConfig commonConfig = (CommonConfig) config;

            copy(commonConfig, true);
            this.disableMetaProviderConfiguration = !commonConfig.enabledFeatureClasses.isEmpty();
        } else {
            setProperties(config.getProperties());

            this.enabledFeatures.clear();
            this.enabledFeatureClasses.clear();

            componentBag.clear();
            resetFeatureRegistrations();

            for (final Class<?> clazz : config.getClasses()) {
                if (Feature.class.isAssignableFrom(clazz) && config.isEnabled((Class<? extends Feature>) clazz)) {
                    this.disableMetaProviderConfiguration = true;
                }

                register(clazz, config.getContracts(clazz));
            }

            for (final Object instance : config.getInstances()) {
                if (instance instanceof Feature && config.isEnabled((Feature) instance)) {
                    this.disableMetaProviderConfiguration = true;
                }

                register(instance, config.getContracts(instance.getClass()));
            }
        }

        return this;
    }

    private Set<Class<?>> asNewIdentitySet(final Class<?>... contracts) {
        final Set<Class<?>> result = Collections.newSetFromMap(new IdentityHashMap<>());
        result.addAll(Arrays.asList(contracts));
        return result;
    }

    private void checkProviderNotNull(final Object provider) {
        if (provider == null) {
            throw new IllegalArgumentException(LocalizationMessages.COMPONENT_CANNOT_BE_NULL());
        }
    }

    private void checkComponentClassNotNull(final Class<?> componentClass) {
        if (componentClass == null) {
            throw new IllegalArgumentException(LocalizationMessages.COMPONENT_CLASS_CANNOT_BE_NULL());
        }
    }

    /**
     * Configure {@link AutoDiscoverable auto-discoverables} in the injection manager.
     *
     * @param injectionManager  injection manager in which the auto-discoverables should be configured.
     * @param autoDiscoverables list of registered auto discoverable components.
     * @param forcedOnly        defines whether all or only forced auto-discoverables should be configured.
     */
    public void configureAutoDiscoverableProviders(final InjectionManager injectionManager,
                                                   final Collection<AutoDiscoverable> autoDiscoverables,
                                                   final boolean forcedOnly) {
        // Check whether meta providers have been initialized for a config this config has been loaded from.
        if (!disableMetaProviderConfiguration) {
            final Set<AutoDiscoverable> providers = new TreeSet<>((o1, o2) -> {
                final int p1 = o1.getClass().isAnnotationPresent(Priority.class)
                        ? o1.getClass().getAnnotation(Priority.class).value() : Priorities.USER;
                final int p2 = o2.getClass().isAnnotationPresent(Priority.class)
                        ? o2.getClass().getAnnotation(Priority.class).value() : Priorities.USER;

                return (p1 < p2 || p1 == p2) ? -1 : 1;
            });

            // Forced (always invoked).
            final List<ForcedAutoDiscoverable> forcedAutoDiscroverables = new LinkedList<>();
            for (Class<ForcedAutoDiscoverable> forcedADType : ServiceFinder.find(ForcedAutoDiscoverable.class, true)
                    .toClassArray()) {
                forcedAutoDiscroverables.add(injectionManager.createAndInitialize(forcedADType));
            }
            providers.addAll(forcedAutoDiscroverables);

            // Regular.
            if (!forcedOnly) {
                providers.addAll(autoDiscoverables);
            }

            for (final AutoDiscoverable autoDiscoverable : providers) {
                final ConstrainedTo constrainedTo = autoDiscoverable.getClass().getAnnotation(ConstrainedTo.class);

                if (constrainedTo == null || type.equals(constrainedTo.value())) {
                    try {
                        autoDiscoverable.configure(this);
                    } catch (final Exception e) {
                        LOGGER.log(Level.FINE,
                                LocalizationMessages.AUTODISCOVERABLE_CONFIGURATION_FAILED(autoDiscoverable.getClass()), e);
                    }
                }
            }
        }
    }

    /**
     * Configure binders in the injection manager and enable JAX-RS features.
     *
     * @param injectionManager injection manager in which the binders and features should be configured.
     */
    public void configureMetaProviders(InjectionManager injectionManager, ManagedObjectsFinalizer finalizer) {
        final Set<Object> configuredExternals = Collections.newSetFromMap(new IdentityHashMap<>());

        // First, configure existing binders
        final Set<Binder> configuredBinders = configureBinders(injectionManager, Collections.emptySet());

        // Check whether meta providers have been initialized for a config this config has been loaded from.
        if (!disableMetaProviderConfiguration) {
            // Next, register external meta objects
            configureExternalObjects(injectionManager, configuredExternals);
            // Configure all features
            configureFeatures(injectionManager, new HashSet<>(), resetFeatureRegistrations(), finalizer);
            // Next, register external meta objects registered by features
            configureExternalObjects(injectionManager, configuredExternals);
            // At last, configure any new binders added by features
            configureBinders(injectionManager, configuredBinders);
        }
    }

    private Set<Binder> configureBinders(InjectionManager injectionManager, Set<Binder> configured) {
        Set<Binder> allConfigured = Collections.newSetFromMap(new IdentityHashMap<>());
        allConfigured.addAll(configured);

        Collection<Binder> binders = getBinder(configured);
        if (!binders.isEmpty()) {
            injectionManager.register(CompositeBinder.wrap(binders));
            allConfigured.addAll(binders);
        }

        return allConfigured;
    }

    private Collection<Binder> getBinder(Set<Binder> configured) {
        return componentBag.getInstances(ComponentBag.BINDERS_ONLY)
                .stream()
                .map(CAST_TO_BINDER)
                .filter(binder -> !configured.contains(binder))
                .collect(Collectors.toList());
    }

    private void configureExternalObjects(InjectionManager injectionManager, Set<Object> externalObjects) {
        Consumer<Object> registerOnce = o -> {
            if (!externalObjects.contains(o)) {
                injectionManager.register(o);
                externalObjects.add(o);
            }
        };
        componentBag.getInstances(model -> ComponentBag.EXTERNAL_ONLY.test(model, injectionManager))
                .forEach(registerOnce);
        componentBag.getClasses(model -> ComponentBag.EXTERNAL_ONLY.test(model, injectionManager))
                .forEach(registerOnce);
    }

    private void configureFeatures(InjectionManager injectionManager,
                                   Set<FeatureRegistration> processed,
                                   List<FeatureRegistration> unprocessed,
                                   ManagedObjectsFinalizer managedObjectsFinalizer) {
        FeatureContextWrapper featureContextWrapper = null;
        for (final FeatureRegistration registration : unprocessed) {
            if (processed.contains(registration)) {
                LOGGER.config(LocalizationMessages.FEATURE_HAS_ALREADY_BEEN_PROCESSED(registration.getFeatureClass()));
                continue;
            }

            final RuntimeType runtimeTypeConstraint = registration.getFeatureRuntimeType();
            if (runtimeTypeConstraint != null && !type.equals(runtimeTypeConstraint)) {
                LOGGER.config(LocalizationMessages.FEATURE_CONSTRAINED_TO_IGNORED(
                        registration.getFeatureClass(), registration.runtimeType, type));
                continue;
            }

            Feature feature = registration.getFeature();
            if (feature == null) {
                feature = injectionManager.createAndInitialize(registration.getFeatureClass());
                managedObjectsFinalizer.registerForPreDestroyCall(feature);
            } else {
                // Disable injection of Feature instances on the client-side. Instances may be registered into multiple
                // web-targets which means that injecting anything into these instances is not safe.
                if (!RuntimeType.CLIENT.equals(type)) {
                    injectionManager.inject(feature);
                }
            }

            if (enabledFeatures.contains(feature)) {
                LOGGER.config(LocalizationMessages.FEATURE_HAS_ALREADY_BEEN_PROCESSED(feature));
                continue;
            }

            if (featureContextWrapper == null) {
                // init lazily
                featureContextWrapper = new FeatureContextWrapper(this, injectionManager);
            }
            final boolean success = feature.configure(featureContextWrapper);

            if (success) {
                processed.add(registration);
                final ContractProvider providerModel = componentBag.getModel(feature.getClass());
                if (providerModel != null) {
                    ProviderBinder.bindProvider(feature, providerModel, injectionManager);
                }
                configureFeatures(injectionManager, processed, resetFeatureRegistrations(), managedObjectsFinalizer);
                enabledFeatureClasses.add(registration.getFeatureClass());
                enabledFeatures.add(feature);
            }
        }
    }

    private List<FeatureRegistration> resetFeatureRegistrations() {
        final List<FeatureRegistration> result = new ArrayList<>(newFeatureRegistrations);
        newFeatureRegistrations.clear();
        Collections.sort(result, (o1, o2) -> o1.priority < o2.priority ? -1 : 1);
        return result;
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof CommonConfig)) {
            return false;
        }

        final CommonConfig that = (CommonConfig) o;

        if (type != that.type) {
            return false;
        }
        if (!properties.equals(that.properties)) {
            return false;
        }
        if (!componentBag.equals(that.componentBag)) {
            return false;
        }
        if (!enabledFeatureClasses.equals(that.enabledFeatureClasses)) {
            return false;
        }
        if (!enabledFeatures.equals(that.enabledFeatures)) {
            return false;
        }
        if (!newFeatureRegistrations.equals(that.newFeatureRegistrations)) {
            return false;
        }

        return true;
    }

    @Override
    public int hashCode() {
        int result = type.hashCode();
        result = 31 * result + properties.hashCode();
        result = 31 * result + componentBag.hashCode();
        result = 31 * result + newFeatureRegistrations.hashCode();
        result = 31 * result + enabledFeatures.hashCode();
        result = 31 * result + enabledFeatureClasses.hashCode();
        return result;
    }
}
