/** * Copyright (c) 2013-2016, The SeedStack authors <http://seedstack.org> * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.seedstack.seed.core.internal.dependency; import io.nuun.kernel.api.plugin.InitState; import io.nuun.kernel.api.plugin.context.InitContext; import io.nuun.kernel.api.plugin.request.ClasspathScanRequest; import org.seedstack.seed.SeedException; import org.seedstack.seed.core.internal.AbstractSeedPlugin; import org.seedstack.seed.core.internal.CoreErrorCode; import org.seedstack.seed.spi.DependencyProvider; import org.seedstack.shed.reflect.Classes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Optional; public class DependencyPlugin extends AbstractSeedPlugin { private static final Logger LOGGER = LoggerFactory.getLogger(DependencyPlugin.class); private final Map<Class<?>, Optional<? extends DependencyProvider>> dependencies = new HashMap<>(); @Override public String name() { return "dependency"; } @Override public Collection<ClasspathScanRequest> classpathScanRequests() { return classpathScanRequestBuilder() .subtypeOf(DependencyProvider.class) .build(); } @Override @SuppressWarnings("unchecked") protected InitState initialize(InitContext initContext) { initContext.scannedSubTypesByParentClass().get(DependencyProvider.class) .stream() .filter(DependencyProvider.class::isAssignableFrom) .forEach(candidate -> getDependency((Class<DependencyProvider>) candidate)); return InitState.INITIALIZED; } @Override public Object nativeUnitModule() { return new DependencyModule(dependencies); } /** * Return {@link Optional} which contains the provider if dependency is present. * Always return a {@link Optional} instance. * * @param providerClass provider to use an optional dependency * @return {@link Optional} which contains the provider if dependency is present */ @SuppressWarnings("unchecked") public <T extends DependencyProvider> Optional<T> getDependency(Class<T> providerClass) { if (!dependencies.containsKey(providerClass)) { Optional<T> optionalDependency = Optional.empty(); try { T provider = providerClass.newInstance(); if (Classes.optional(provider.getClassToCheck()).isPresent()) { LOGGER.debug("Found a new optional provider [{}] for [{}]", providerClass.getName(), provider.getClassToCheck()); optionalDependency = Optional.of(provider); } } catch (Exception e) { throw SeedException.wrap(e, CoreErrorCode.UNABLE_TO_INSTANTIATE_CLASS).put("class", providerClass.getCanonicalName()); } dependencies.put(providerClass, optionalDependency); } return (Optional<T>) dependencies.get(providerClass); } }