/*
* Copyright (C) 2015 by Array Systems Computing Inc. http://www.array.ca
*
* This program 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.esa.snap.graphbuilder.gpf.ui;
import com.bc.ceres.core.Assert;
import org.esa.snap.core.util.SystemUtils;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.modules.ModuleInfo;
import org.openide.util.Lookup;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* An <code>OperatorUIRegistry</code> provides access to operator user interfaces as described by their OperatorUIDescriptor.
*/
public class OperatorUIRegistry {
private static OperatorUIRegistry instance = null;
private final Map<String, OperatorUIDescriptor> operatorUIDescriptors = new HashMap<>();
public OperatorUIRegistry() {
registerOperatorUIs();
}
public static OperatorUIRegistry getInstance() {
if(instance == null) {
instance = new OperatorUIRegistry();
}
return instance;
}
public OperatorUIDescriptor[] getOperatorUIDescriptors() {
return operatorUIDescriptors.values().toArray(new OperatorUIDescriptor[operatorUIDescriptors.values().size()]);
}
public OperatorUIDescriptor getOperatorUIDescriptor(final String operatorName) {
return operatorUIDescriptors.get(operatorName);
}
private void registerOperatorUIs() {
FileObject fileObj = FileUtil.getConfigFile("OperatorUIs");
if(fileObj == null) {
SystemUtils.LOG.warning("No operatorUIs found.");
return;
}
final FileObject[] files = fileObj.getChildren();
final List<FileObject> orderedFiles = FileUtil.getOrder(Arrays.asList(files), true);
for (FileObject file : orderedFiles) {
OperatorUIDescriptor operatorUIDescriptor = null;
try {
operatorUIDescriptor = createOperatorUIDescriptor(file);
} catch (Exception e) {
SystemUtils.LOG.severe(String.format("Failed to create operatorUI from layer.xml path '%s'", file.getPath()));
}
if (operatorUIDescriptor != null) {
// must have only one operatorUI per operator
final OperatorUIDescriptor existingDescriptor = operatorUIDescriptors.get(operatorUIDescriptor.getOperatorName());
if (existingDescriptor != null) {
SystemUtils.LOG.info(String.format("OperatorUI [%s] has been redeclared for [%s]!\n",
operatorUIDescriptor.getId(), operatorUIDescriptor.getOperatorName()));
}
operatorUIDescriptors.put(operatorUIDescriptor.getOperatorName(), operatorUIDescriptor);
SystemUtils.LOG.fine(String.format("New operatorUI added from layer.xml path '%s': %s",
file.getPath(), operatorUIDescriptor.getOperatorName()));
}
}
}
public static OperatorUIDescriptor createOperatorUIDescriptor(FileObject fileObject) {
final String id = fileObject.getName();
final String operatorName = (String) fileObject.getAttribute("operatorName");
Assert.argument(operatorName != null && !operatorName.isEmpty(), "Missing attribute 'operatorName'");
final Class<? extends OperatorUI> operatorUIClass = getClassAttribute(fileObject, "operatorUIClass", OperatorUI.class, false);
Boolean disableFromGraphBuilder = false;
try {
final String disableFromGraphBuilderStr = (String) fileObject.getAttribute("disableFromGraphBuilder");
if (disableFromGraphBuilderStr != null) {
disableFromGraphBuilder = Boolean.parseBoolean(disableFromGraphBuilderStr);
}
} catch (Exception e) {
SystemUtils.LOG.severe("OperatorUIRegistry: Unable to parse disableFromGraphBuilder "+e.toString());
//continue
}
return new DefaultOperatorUIDescriptor(id, operatorName, operatorUIClass, disableFromGraphBuilder);
}
public static OperatorUI CreateOperatorUI(final String operatorName) {
final OperatorUIRegistry reg = OperatorUIRegistry.getInstance();
if (reg != null) {
OperatorUIDescriptor desc = reg.getOperatorUIDescriptor(operatorName);
if (desc != null) {
return desc.createOperatorUI();
}
desc = OperatorUIRegistry.getInstance().getOperatorUIDescriptor("DefaultUI");
if (desc != null) {
return desc.createOperatorUI();
}
}
return new DefaultUI();
}
public static boolean showInGraphBuilder(final String operatorName) {
final OperatorUIRegistry reg = OperatorUIRegistry.getInstance();
if (reg != null) {
OperatorUIDescriptor desc = reg.getOperatorUIDescriptor(operatorName);
if (desc != null) {
if(desc.disableFromGraphBuilder()) {
SystemUtils.LOG.warning(operatorName + " disabled from GraphBuilder");
}
return !desc.disableFromGraphBuilder();
}
}
return true;
}
public static <T> Class<T> getClassAttribute(FileObject fileObject,
String attributeName,
Class<T> expectedType,
boolean required) {
String className = (String) fileObject.getAttribute(attributeName);
if (className == null || className.isEmpty()) {
if (required) {
throw new IllegalArgumentException(String.format("Missing attribute '%s' of type %s",
attributeName, expectedType.getName()));
}
return null;
}
Collection<? extends ModuleInfo> modules = Lookup.getDefault().lookupAll(ModuleInfo.class);
for (ModuleInfo module : modules) {
if (module.isEnabled()) {
try {
Class<?> implClass = module.getClassLoader().loadClass(className);
if (expectedType.isAssignableFrom(implClass)) {
//noinspection unchecked
return (Class<T>) implClass;
} else {
throw new IllegalArgumentException(String.format("Value %s of attribute '%s' must be a %s",
implClass.getName(),
attributeName,
expectedType.getName()));
}
} catch (ClassNotFoundException e) {
// it's ok, continue
}
}
}
return null;
}
}