/*
* This file is part of JGrasstools (http://www.jgrasstools.org)
* (C) HydroloGIS - www.hydrologis.com
*
* JGrasstools 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.
*
* This program 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 org.jgrasstools.gui.spatialtoolbox.core;
import java.lang.reflect.Field;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import org.jgrasstools.Modules;
import org.jgrasstools.gears.JGrassGears;
import org.jgrasstools.gears.libs.logging.JGTLogger;
import org.jgrasstools.gears.libs.modules.JGTConstants;
import org.jgrasstools.hortonmachine.HortonMachine;
import org.jgrasstools.lesto.Lesto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import oms3.Access;
import oms3.ComponentAccess;
import oms3.annotations.Description;
import oms3.annotations.Label;
import oms3.annotations.Range;
import oms3.annotations.Status;
import oms3.annotations.UI;
import oms3.annotations.Unit;
/**
* Singleton in which the modules discovery and load/unload occurrs.
*
* @author Andrea Antonello (www.hydrologis.com)
*/
@SuppressWarnings("nls")
public class JGrasstoolsModulesManager {
private static final Logger logger = LoggerFactory.getLogger(JGrasstoolsModulesManager.class);
private static JGrasstoolsModulesManager modulesManager;
private List<String> loadedJarsList = new ArrayList<String>();
private List<String> modulesJarsList = new ArrayList<String>();
private TreeMap<String, List<ModuleDescription>> modulesMap = new TreeMap<String, List<ModuleDescription>>();
private URLClassLoader jarClassloader;
private JGrasstoolsModulesManager() {
}
public synchronized static JGrasstoolsModulesManager getInstance() {
if (modulesManager == null) {
modulesManager = new JGrasstoolsModulesManager();
}
return modulesManager;
}
public TreeMap<String, List<ModuleDescription>> getModulesMap() {
return modulesMap;
}
public void init() throws Exception {
synchronized (modulesMap) {
if (modulesMap.size() > 0) {
return;
}
}
LinkedHashMap<String, Class< ? >> moduleNames2Classes = Modules.getInstance().moduleName2Class;
// LinkedHashMap<String, List<ClassField>> moduleName2Fields =
// Modules.getInstance().moduleName2Fields;
LinkedHashMap<String, Class< ? >> lestoModuleNames2Class = Lesto.getInstance().moduleName2Class;
// LinkedHashMap<String, List<ClassField>> lestoModuleName2Fields =
// Lesto.getInstance().moduleName2Fields;
// also gather horton and gears
logger.debug("init HortonMachine");
HortonMachine.getInstance();
logger.debug("init JGrassGears");
Map<String, Class< ? >> gearsModuleName2Class = JGrassGears.getInstance().moduleName2Class;
logger.debug("Collecting classes:");
for( Entry<String, Class< ? >> entry : lestoModuleNames2Class.entrySet() ) {
String name = entry.getKey();
if (name.startsWith("Oms")) {
continue;
}
logger.debug("\t-> " + name);
moduleNames2Classes.put(name, entry.getValue());
}
for( Entry<String, Class< ? >> entry : gearsModuleName2Class.entrySet() ) {
String name = entry.getKey();
if (name.startsWith("Oms")) {
continue;
}
logger.debug("\t-> " + name);
moduleNames2Classes.put(name, entry.getValue());
}
Collection<Class< ? >> classesList = moduleNames2Classes.values();
for( Class< ? > moduleClass : classesList ) {
try {
String simpleName = moduleClass.getSimpleName();
UI uiHints = moduleClass.getAnnotation(UI.class);
if (uiHints != null) {
String uiHintStr = uiHints.value();
if (uiHintStr.contains(JGTConstants.HIDE_UI_HINT)) {
continue;
}
}
Label category = moduleClass.getAnnotation(Label.class);
String categoryStr = JGTConstants.OTHER;
if (category != null && categoryStr.trim().length() > 1) {
categoryStr = category.value();
}
Description description = moduleClass.getAnnotation(Description.class);
String descrStr = null;
if (description != null) {
descrStr = description.value();
}
Status status = moduleClass.getAnnotation(Status.class);
ModuleDescription module = new ModuleDescription(moduleClass, categoryStr, descrStr, status);
Object newInstance = null;
try {
newInstance = moduleClass.newInstance();
} catch (Throwable e) {
// ignore module
continue;
}
try {
// generate the html docs
String className = module.getClassName();
// FIXME
// SpatialToolboxUtils.generateModuleDocumentation(className);
} catch (Exception e) {
// ignore doc if it breaks
}
ComponentAccess cA = new ComponentAccess(newInstance);
Collection<Access> inputs = cA.inputs();
for( Access access : inputs ) {
addInput(access, module);
}
Collection<Access> outputs = cA.outputs();
for( Access access : outputs ) {
addOutput(access, module);
}
if (categoryStr.equals(JGTConstants.GRIDGEOMETRYREADER) || categoryStr.equals(JGTConstants.RASTERREADER)
|| categoryStr.equals(JGTConstants.RASTERWRITER) || categoryStr.equals(JGTConstants.FEATUREREADER)
|| categoryStr.equals(JGTConstants.FEATUREWRITER) || categoryStr.equals(JGTConstants.GENERICREADER)
|| categoryStr.equals(JGTConstants.GENERICWRITER) || categoryStr.equals(JGTConstants.HASHMAP_READER)
|| categoryStr.equals(JGTConstants.HASHMAP_WRITER) || categoryStr.equals(JGTConstants.LIST_READER)
|| categoryStr.equals(JGTConstants.LIST_WRITER)) {
// ignore for now
} else {
List<ModuleDescription> modulesList4Category = modulesMap.get(categoryStr);
if (modulesList4Category == null) {
modulesList4Category = new ArrayList<ModuleDescription>();
modulesMap.put(categoryStr, modulesList4Category);
}
modulesList4Category.add(module);
}
} catch (NoClassDefFoundError e) {
if (moduleClass != null)
JGTLogger.logError(this, "ERROR", e.getCause());
}
}
// sort
Set<Entry<String, List<ModuleDescription>>> entrySet = modulesMap.entrySet();
for( Entry<String, List<ModuleDescription>> entry : entrySet ) {
Collections.sort(entry.getValue(), new ModuleDescription.ModuleDescriptionNameComparator());
}
}
private void addInput( Access access, ModuleDescription module ) throws Exception {
Field field = access.getField();
Description descriptionAnn = field.getAnnotation(Description.class);
String descriptionStr = "No description available";
if (descriptionAnn != null) {
descriptionStr = AnnotationUtilities.getLocalizedDescription(descriptionAnn);
}
StringBuilder sb = new StringBuilder();
sb.append(descriptionStr);
Unit unitAnn = field.getAnnotation(Unit.class);
if (unitAnn != null) {
sb.append(" [");
sb.append(unitAnn.value());
sb.append("]");
}
Range rangeAnn = field.getAnnotation(Range.class);
if (rangeAnn != null) {
sb.append(" [");
sb.append(rangeAnn.min());
sb.append(" ,");
sb.append(rangeAnn.max());
sb.append("]");
}
descriptionStr = sb.toString();
String fieldName = field.getName();
if (doIgnore(fieldName)) {
return;
}
Class< ? > fieldClass = field.getType();
Object fieldValue = access.getFieldValue();
String defaultValue = ""; //$NON-NLS-1$
if (fieldValue != null) {
defaultValue = fieldValue.toString();
}
UI uiHintAnn = field.getAnnotation(UI.class);
String uiHint = null;
if (uiHintAnn != null) {
uiHint = uiHintAnn.value();
}
module.addInput(fieldName, fieldClass.getCanonicalName(), descriptionStr, defaultValue, uiHint);
}
private boolean doIgnore( String fieldName ) {
return fieldName.equals("doProcess");
}
private void addOutput( Access access, ModuleDescription module ) throws Exception {
Field field = access.getField();
Description descriptionAnn = field.getAnnotation(Description.class);
String descriptionStr = "No description available";
if (descriptionAnn != null) {
descriptionStr = AnnotationUtilities.getLocalizedDescription(descriptionAnn);
}
StringBuilder sb = new StringBuilder();
sb.append(descriptionStr);
Unit unitAnn = field.getAnnotation(Unit.class);
if (unitAnn != null) {
sb.append(" [");
sb.append(unitAnn.value());
sb.append("]");
}
Range rangeAnn = field.getAnnotation(Range.class);
if (rangeAnn != null) {
sb.append(" [");
sb.append(rangeAnn.min());
sb.append(" ,");
sb.append(rangeAnn.max());
sb.append("]");
}
descriptionStr = sb.toString();
String fieldName = field.getName();
if (doIgnore(fieldName)) {
return;
}
Class< ? > fieldClass = field.getType();
Object fieldValue = access.getFieldValue();
String defaultValue = ""; //$NON-NLS-1$
if (fieldValue != null) {
defaultValue = fieldValue.toString();
}
UI uiHintAnn = field.getAnnotation(UI.class);
String uiHint = null;
if (uiHintAnn != null) {
uiHint = uiHintAnn.value();
}
module.addOutput(fieldName, fieldClass.getCanonicalName(), descriptionStr, defaultValue, uiHint);
}
}