/*
* 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.worldwind.layers;
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;
/**
* A <code>WWLayerRegistry</code> provides access to WorldWind Layers as described by their WWLayerDescriptor.
*/
public class WWLayerRegistry {
private static WWLayerRegistry instance = null;
private final Map<String, WWLayerDescriptor> wwLayerDescriptors = new HashMap<>();
public WWLayerRegistry() {
registerWWLayers();
}
public static WWLayerRegistry getInstance() {
if (instance == null) {
instance = new WWLayerRegistry();
}
return instance;
}
public WWLayerDescriptor[] getWWLayerDescriptors() {
return wwLayerDescriptors.values().toArray(new WWLayerDescriptor[wwLayerDescriptors.values().size()]);
}
private void registerWWLayers() {
final FileObject fileObj = FileUtil.getConfigFile("WorldWindLayers");
if (fileObj == null) {
SystemUtils.LOG.warning("No World Wind layers found.");
return;
}
final FileObject[] files = fileObj.getChildren();
final List<FileObject> orderedFiles = FileUtil.getOrder(Arrays.asList(files), true);
for (FileObject file : orderedFiles) {
WWLayerDescriptor WWLayerDescriptor = null;
try {
WWLayerDescriptor = createWWLayerDescriptor(file);
} catch (Exception e) {
SystemUtils.LOG.severe(String.format("Failed to create WWLayerDescriptor from layer.xml path '%s'", file.getPath()));
}
if (WWLayerDescriptor != null) {
final WWLayerDescriptor existingDescriptor = wwLayerDescriptors.get(WWLayerDescriptor.getId());
if (existingDescriptor != null) {
SystemUtils.LOG.warning(String.format("WWLayer [%s] has been redeclared!\n",
WWLayerDescriptor.getId()));
}
wwLayerDescriptors.put(WWLayerDescriptor.getId(), WWLayerDescriptor);
SystemUtils.LOG.fine(String.format("New WWLayer added from layer.xml path '%s': %s",
file.getPath(), WWLayerDescriptor.getId()));
}
}
}
public static WWLayerDescriptor createWWLayerDescriptor(final FileObject fileObject) {
final String id = fileObject.getName();
final String showInWorldMapToolView = (String) fileObject.getAttribute("showInWorldMapToolView");
final String showIn3DToolView = (String) fileObject.getAttribute("showIn3DToolView");
final Class<? extends WWLayer> WWLayerClass = getClassAttribute(fileObject, "WWLayerClass", WWLayer.class, false);
Assert.argument(showInWorldMapToolView != null &&
(showInWorldMapToolView.equalsIgnoreCase("true") || showInWorldMapToolView.equalsIgnoreCase("false")),
"Missing attribute 'showInWorldMapToolView'");
Assert.argument(showIn3DToolView != null &&
(showIn3DToolView.equalsIgnoreCase("true") || showIn3DToolView.equalsIgnoreCase("false")),
"Missing attribute 'showIn3DToolView'");
Assert.argument(WWLayerClass != null, "Attribute 'class' must be provided");
return new DefaultWWLayerDescriptor(id, Boolean.parseBoolean(showInWorldMapToolView),
Boolean.parseBoolean(showIn3DToolView), WWLayerClass);
}
public static <T> Class<T> getClassAttribute(final FileObject fileObject,
final String attributeName,
final Class<T> expectedType,
final boolean required) {
final 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;
}
final Collection<? extends ModuleInfo> modules = Lookup.getDefault().lookupAll(ModuleInfo.class);
for (ModuleInfo module : modules) {
if (module.isEnabled()) {
try {
final 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;
}
}