All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.nu.art.modular.core.ModuleManager Maven / Gradle / Ivy

There is a newer version: 1.2.59
Show newest version
/*
 * The module-manager project, is THE infrastructure that all my frameworks
 *  are based on, it allows encapsulation of logic where needed, and allow
 *  modules to converse without other design patterns limitations.
 *
 * Copyright (C) 2018  Adam van der Kruk aka TacB0sS
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.nu.art.modular.core;

import com.nu.art.belog.Logger;
import com.nu.art.core.exceptions.runtime.BadImplementationException;
import com.nu.art.core.exceptions.runtime.ImplementationMissingException;
import com.nu.art.core.generics.GenericParamExtractor;
import com.nu.art.core.generics.Processor;
import com.nu.art.core.interfaces.Condition;
import com.nu.art.core.interfaces.ILogger;
import com.nu.art.core.tools.ArrayTools;
import com.nu.art.modular.interfaces.ModuleManagerDelegator;
import com.nu.art.reflection.injector.Injector;
import com.nu.art.reflection.tools.ART_Tools;
import com.nu.art.reflection.tools.ReflectiveTools;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * @author TacB0sS
 */
@SuppressWarnings("rawtypes")
public class ModuleManager
	extends Logger
	implements ModuleManagerDelegator {

	protected void onBuildPrepared() {
		logVerbose(" Application Starting...");
		logVerbose(" ");
		logVerbose(" _______  _______  _______  _       _________ _______  _______ __________________ _______  _          _______ _________ _______  _______ _________ _______  ______  ");
		logVerbose("(  ___  )(  ____ )(  ____ )( \\      \\__   __/(  ____ \\(  ___  )\\__   __/\\__   __/(  ___  )( (    /|  (  ____ \\\\__   __/(  ___  )(  ____ )\\__   __/(  ____ \\(  __  \\ ");
		logVerbose("| (   ) || (    )|| (    )|| (         ) (   | (    \\/| (   ) |   ) (      ) (   | (   ) ||  \\  ( |  | (    \\/   ) (   | (   ) || (    )|   ) (   | (    \\/| (  \\  )");
		logVerbose("| (___) || (____)|| (____)|| |         | |   | |      | (___) |   | |      | |   | |   | ||   \\ | |  | (_____    | |   | (___) || (____)|   | |   | (__    | |   ) |");
		logVerbose("|  ___  ||  _____)|  _____)| |         | |   | |      |  ___  |   | |      | |   | |   | || (\\ \\) |  (_____  )   | |   |  ___  ||     __)   | |   |  __)   | |   | |");
		logVerbose("| (   ) || (      | (      | |         | |   | |      | (   ) |   | |      | |   | |   | || | \\   |        ) |   | |   | (   ) || (\\ (      | |   | (      | |   ) |");
		logVerbose("| )   ( || )      | )      | (____/\\___) (___| (____/\\| )   ( |   | |   ___) (___| (___) || )  \\  |  /\\____) |   | |   | )   ( || ) \\ \\__   | |   | (____/\\| (__/  )");
		logVerbose("|/     \\||/       |/       (_______/\\_______/(_______/|/     \\|   )_(   \\_______/(_______)|/    )_)  \\_______)   )_(   |/     \\||/   \\__/   )_(   (_______/(______/ ");
		logVerbose(" ");
	}

	public interface ModuleInitializedListener {

		void onModuleInitialized(Module module);
	}

	public interface ModuleCreatedListener {

		void onModuleCreated(Module module);
	}

	public final class ModuleInjector
		extends Injector {

		private ModuleInjector() {}

		@Override
		@SuppressWarnings("unchecked")
		protected Object getValueForField(Object instance, Field field) {
			if (field.getType() == Module.class)
				return null;

			Module module = getModule((Class) field.getType(), false);
			if (module == null)
				throw new ImplementationMissingException("Cannot set module to field: " + field + "\n  MUST add the module of type: '" + field.getType() + "' to one of your ModulePacks");

			return module;
		}

		@Override
		protected Field[] extractFieldsFromInstance(Class injecteeType) {
			return ART_Tools.getAllFieldsInHierarchy(injecteeType, new Condition() {
				@Override
				public boolean checkCondition(Field field) {
					return Module.class.isAssignableFrom(field.getType()) && !Modifier.isStatic(field.getModifiers());
				}
			});
		}
	}

	private final ModuleInjector moduleInjector = new ModuleInjector();

	private ModuleInitializedListener moduleInitializedListener;
	private ModuleCreatedListener moduleCreatedListener;

	/**
	 * Holds a references to all the module types which have registered to this main module,
	 */
	private HashMap, Module> registeredModules = new HashMap<>();

	private EventDispatcher eventDispatcher;

	private Module[] orderedModules = {};

	public static ModuleManager ModuleManager;

	public ModuleManager() {
		this(GenericParamExtractor._GenericParamExtractor);
	}

	protected ModuleManager(GenericParamExtractor paramExtractor) {
		if (ModuleManager != null)
			throw new BadImplementationException("THERE CAN ONLY BE ONE MODULE MANAGER IN A JVM!!");

		eventDispatcher = new EventDispatcher("ModulesEventDispatcher", paramExtractor);
		ModuleManager = this;
	}

	public final ModuleInjector getInjector() {
		return moduleInjector;
	}

	@SuppressWarnings("unchecked")
	public final  Type[] getModulesAssignableFrom(Class classType) {
		ArrayList modules = new ArrayList<>();
		for (Module orderedModule : orderedModules) {
			if (!classType.isAssignableFrom(orderedModule.getClass()))
				continue;

			modules.add((Type) orderedModule);
		}
		return ArrayTools.asArray(modules, classType);
	}

	@Override
	public final  ModuleType getModule(Class moduleType) {
		return getModule(moduleType, true);
	}

	protected final Module[] getOrderedModules() {
		return orderedModules;
	}

	public final void setModuleInitializedListener(ModuleInitializedListener moduleInitializedListener) {
		this.moduleInitializedListener = moduleInitializedListener;
	}

	public final void setModuleCreatedListener(ModuleCreatedListener moduleCreatedListener) {
		this.moduleCreatedListener = moduleCreatedListener;
	}

	@SuppressWarnings("unchecked")
	private  ModuleType getModule(Class moduleType, boolean throwException) {
		ModuleType module = (ModuleType) registeredModules.get(moduleType);
		if (module == null && throwException) {
			throw new ImplementationMissingException("MUST add module of type: '" + moduleType.getName() + "' to one of your module packs");
		}
		return module;
	}

	final void init() {
		for (Module module : orderedModules) {
			module.assignToDefaultInterface();
		}

		for (Module module : orderedModules) {
			module.init();

			if (moduleInitializedListener == null)
				continue;

			moduleInitializedListener.onModuleInitialized(module);
		}
	}

	/**
	 * @param moduleType The module type to register with the Module Manager.
	 */
	@SuppressWarnings("unchecked")
	final <_Module extends Module> void registerModule(Class<_Module> moduleType) {
		_Module module = (_Module) registeredModules.get(moduleType);
		if (module != null)
			return;

		registerModuleType(moduleType);
	}

	final <_Module extends Module> void registerModuleType(Class<_Module> moduleType) {
		_Module module;
		module = ReflectiveTools.newInstance(moduleType);
		registerModuleInstance(module);
	}

	final <_Module extends Module> void registerModuleInstance(_Module module) {
		module.setMainManager(this);

		for (Class key : module.keys) {
			Module olderModule = registeredModules.put(key, module);
			if (olderModule != null)
				logWarning("Shared Module key " + key + " between modules: " + olderModule.getClass() + " and " + module.getClass());
		}

		eventDispatcher.addListener(module);
		this.orderedModules = ArrayTools.appendElement(this.orderedModules, module);

		if (moduleCreatedListener == null)
			return;

		moduleCreatedListener.onModuleCreated(module);
	}

	protected void onBuildCompleted() {}

	final void prepareModuleItem(ModuleItem moduleItem) {
		getInjector().injectToInstance(moduleItem);
		eventDispatcher.addListener(moduleItem);
	}

	final void disposeModuleItem(ModuleItem moduleItem) {
		eventDispatcher.removeListener(moduleItem);
	}

	@SuppressWarnings("unchecked")
	public  void dispatchModuleEvent(ILogger originator, String message, Class listenerType, Processor processor) {
		if (originator != null)
			originator.logInfo("Dispatching Module Event: " + message);
		eventDispatcher.dispatchEvent(null, listenerType, processor);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy