class Deconstructor implements ComponentDeconstructor {

    @Override
    public void deconstruct(Collection<Object> components, Collection<Bundle> bundles) {
        Collection<AbstractComponent> destructibleComponents = new ArrayList<>();
        for (var component : components) {
            if (component instanceof AbstractComponent) {
                AbstractComponent abstractComponent = (AbstractComponent) component;
                if (abstractComponent.isDeconstructable()) {
                    destructibleComponents.add(abstractComponent);
                }
            } else if (component instanceof Provider) {
                // TODO Providers should most likely be deconstructed similarly to AbstractComponent
                log.log(FINE, () -> "Starting deconstruction of provider " + component);
                ((Provider<?>) component).deconstruct();
                log.log(FINE, () -> "Finished deconstruction of provider " + component);
            } else if (component instanceof SharedResource) {
                log.log(FINE, () -> "Releasing container reference to resource " + component);
                // No need to delay release, as jdisc does ref-counting
                ((SharedResource) component).release();
            }
        }
        if (! destructibleComponents.isEmpty() || ! bundles.isEmpty())
            executor.schedule(new DestructComponentTask(destructibleComponents, bundles),
                              delay.getSeconds(), TimeUnit.SECONDS);
    }

    public  Deconstructor(boolean delayDeconstruction);

}