/*
* This file is part of MyPet
*
* Copyright © 2011-2016 Keyle
* MyPet is licensed under the GNU Lesser General Public License.
*
* MyPet is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MyPet is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.Keyle.MyPet.api.util.service;
import com.google.common.base.Optional;
import com.google.common.collect.ArrayListMultimap;
import de.Keyle.MyPet.MyPetApi;
import org.apache.commons.lang.ClassUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* The {@link ServiceManager} manages all interactions with other plugins. Services are stored by class and by the
* interfaces they implement so they can also be retrieved by them. You can get instances of other plugins and check if
* other plugins are active.
*/
public class ServiceManager {
Map<Class<? extends ServiceContainer>, ServiceContainer> services = new HashMap<>();
Map<String, ServiceContainer> serviceByName = new HashMap<>();
ArrayListMultimap<Load.State, ServiceContainer> registeredServices = ArrayListMultimap.create();
public void listServices() {
MyPetApi.getLogger().info("Loaded services: " + serviceByName.keySet());
}
/**
* register new services here. A service needs the {@link ServiceName} annotation to be accepted.
*
* @param serviceClass the service class
*/
public void registerService(Class<? extends ServiceContainer> serviceClass) {
Load.State loadingState = Load.State.OnEnable;
if (serviceClass.isAnnotationPresent(Load.class)) {
loadingState = serviceClass.getAnnotation(Load.class).value();
}
try {
ServiceContainer service = serviceClass.newInstance();
registeredServices.put(loadingState, service);
} catch (Throwable e) {
MyPetApi.getLogger().warning("Error occured while creating the " + serviceClass.getName() + " service.");
e.printStackTrace();
}
}
@SuppressWarnings("unchecked")
private void registerService(ServiceContainer service) {
boolean genericService = true;
for (Object o : ClassUtils.getAllInterfaces(service.getClass())) {
if (o != ServiceContainer.class && ServiceContainer.class.isAssignableFrom((Class) o)) {
services.put((Class) o, service);
genericService = false;
}
}
for (Object o : ClassUtils.getAllSuperclasses(service.getClass())) {
if (o != ServiceContainer.class && ServiceContainer.class.isAssignableFrom((Class) o)) {
services.put((Class) o, service);
genericService = false;
}
}
if (genericService) {
services.put(ServiceContainer.class, service);
}
serviceByName.put(service.getServiceName(), service);
services.put(service.getClass(), service);
}
public void activate(Load.State state) {
List<ServiceContainer> services = registeredServices.get(state);
for (ServiceContainer service : services) {
if (service.onEnable()) {
registerService(service);
}
}
registeredServices.removeAll(state);
}
public void disableServices() {
for (ServiceContainer service : serviceByName.values()) {
service.onEnable();
}
}
/**
* returns all services that inherit from a specific class/interface
*
* @param serviceClass class that implements from {@link ServiceContainer}
* @return list of instances of the service class
*/
@SuppressWarnings("unchecked")
public <T extends ServiceContainer> List<T> getServices(Class<? extends T> serviceClass) {
List<T> list = new ArrayList<>();
for (ServiceContainer service : services.values()) {
if (service.getClass().isAssignableFrom(serviceClass) && !list.contains(service)) {
list.add((T) service);
}
}
return list;
}
/**
* returns if services that inherit from a specific class/interface are available
*
* @param serviceClass class that implements from {@link ServiceContainer}
* @return if any service was found
*/
public boolean hasServices(Class<? extends ServiceContainer> serviceClass) {
return services.containsKey(serviceClass);
}
/**
* returns the services of a specific class
*
* @param serviceClass class that implements from {@link ServiceContainer}
* @return instance of the service class
*/
@SuppressWarnings("unchecked")
public <T extends ServiceContainer> Optional<T> getService(Class<? extends T> serviceClass) {
return Optional.fromNullable((T) services.get(serviceClass));
}
/**
* returns the services with a specific {@link ServiceName}
*
* @param name name of the plugin
* @return instance of a service class associated with the plugin name
*/
public Optional<ServiceContainer> getService(String name) {
return Optional.fromNullable(serviceByName.get(name));
}
/**
* returns if a services with a specific {@link ServiceName} is available
*
* @param name name of the plugin
* @return if any service was found
*/
public boolean isServiceActive(String name) {
return serviceByName.containsKey(name);
}
/**
* returns if a service that inherit from a specific class/interface is available
*
* @param serviceClass class that implements from {@link ServiceContainer}
* @return if any service was found
*/
public boolean isServiceActive(Class<? extends ServiceContainer> serviceClass) {
return services.containsKey(serviceClass);
}
}