gov.nasa.worldwind.data.WWDotNetLayerSetConverter Maven / Gradle / Ivy
The newest version!
/*
* Copyright (C) 2012 United States Government as represented by the Administrator of the
* National Aeronautics and Space Administration.
* All Rights Reserved.
*/
package gov.nasa.worldwind.data;
import gov.nasa.worldwind.avlist.*;
import gov.nasa.worldwind.exception.WWRuntimeException;
import gov.nasa.worldwind.formats.dds.DDSCompressor;
import gov.nasa.worldwind.layers.BasicTiledImageLayer;
import gov.nasa.worldwind.util.*;
import org.w3c.dom.Document;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.XMLEvent;
import java.io.File;
/**
* @author dcollins
* @version $Id: WWDotNetLayerSetConverter.java 1171 2013-02-11 21:45:02Z dcollins $
*/
public class WWDotNetLayerSetConverter extends AbstractDataStoreProducer
{
protected static final String DEFAULT_IMAGE_FORMAT = "image/png";
protected static final String DEFAULT_TEXTURE_FORMAT = "image/dds";
protected static class ProductionState
{
// Production parameters.
AVList productionParams;
// Progress counters.
int numSources;
int curSource;
int[] numSourceFiles;
int[] numInstalledFiles;
}
public WWDotNetLayerSetConverter()
{
}
public String getDataSourceDescription()
{
return Logging.getMessage("WWDotNetLayerSetConverter.Description");
}
public void removeProductionState()
{
Iterable dataSources = this.getDataSourceList();
AVList params = this.getStoreParameters();
for (SourceInfo info : dataSources)
{
this.removeLayerSet(info.source, params);
}
}
protected void doStartProduction(AVList parameters) throws Exception
{
this.getProductionResultsList().clear();
Iterable dataSources = this.getDataSourceList();
ProductionState productionState = new ProductionState();
// Initialize any missing production parameters with suitable defaults.
this.initProductionParameters(parameters, productionState);
// Set the progress parameters for the current data sources.
this.setProgressParameters(dataSources, productionState);
if (this.isStopped())
return;
for (SourceInfo info : dataSources)
{
if (this.isStopped())
return;
productionState.curSource++;
this.convertLayerSet(info.source, productionState);
}
}
protected void initProductionParameters(AVList params, ProductionState productionState)
{
// Preserve backward compatibility with previous verisons of WWDotNetLayerSetConverter. If the caller specified
// a format suffix parameter, use it to compute the image format properties. This gives priority to the format
// suffix property to ensure applications which use format suffix continue to work.
if (params.getValue(AVKey.FORMAT_SUFFIX) != null)
{
String s = WWIO.makeMimeTypeForSuffix(params.getValue(AVKey.FORMAT_SUFFIX).toString());
if (s != null)
{
params.setValue(AVKey.IMAGE_FORMAT, s);
params.setValue(AVKey.AVAILABLE_IMAGE_FORMATS, new String[] {s});
}
}
// Use the default image format if none exists.
if (params.getValue(AVKey.IMAGE_FORMAT) == null)
params.setValue(AVKey.IMAGE_FORMAT, DEFAULT_IMAGE_FORMAT);
// Compute the available image formats if none exists.
if (params.getValue(AVKey.AVAILABLE_IMAGE_FORMATS) == null)
{
params.setValue(AVKey.AVAILABLE_IMAGE_FORMATS,
new String[] {params.getValue(AVKey.IMAGE_FORMAT).toString()});
}
// Compute the format suffix if none exists.
if (params.getValue(AVKey.FORMAT_SUFFIX) == null)
{
params.setValue(AVKey.FORMAT_SUFFIX,
WWIO.makeSuffixForMimeType(params.getValue(AVKey.IMAGE_FORMAT).toString()));
}
productionState.productionParams = params;
}
protected String validateProductionParameters(AVList parameters)
{
StringBuilder sb = new StringBuilder();
Object o = parameters.getValue(AVKey.FILE_STORE_LOCATION);
if (o == null || !(o instanceof String) || ((String) o).length() < 1)
sb.append((sb.length() > 0 ? ", " : "")).append(Logging.getMessage("term.fileStoreLocation"));
o = parameters.getValue(AVKey.DATA_CACHE_NAME);
// It's okay if the cache path is empty, but if specified it must be a String.
if (o != null && !(o instanceof String))
sb.append((sb.length() > 0 ? ", " : "")).append(Logging.getMessage("term.fileStoreFolder"));
if (sb.length() == 0)
return null;
return Logging.getMessage("DataStoreProducer.InvalidDataStoreParamters", sb.toString());
}
protected String validateDataSource(Object source, AVList params)
{
File file = this.getSourceConfigFile(source);
if (file == null)
return Logging.getMessage("WWDotNetLayerSetConverter.NoSourceLocation");
// Open the document in question as an XML event stream. Since we're only interested in testing the document
// element, we avoiding any unecessary overhead incurred from parsing the entire document as a DOM.
XMLEventReader eventReader = null;
try
{
eventReader = WWXML.openEventReader(file);
if (eventReader == null)
return Logging.getMessage("WWDotNetLayerSetConverter.CannotReadLayerSetConfigFile", file);
// Get the first start element event, if any exists, then determine if it represents a LayerSet
// configuration document.
XMLEvent event = WWXML.nextStartElementEvent(eventReader);
if (event == null || !DataConfigurationUtils.isWWDotNetLayerSetConfigEvent(event))
return Logging.getMessage("WWDotNetLayerSetConverter.FileNotLayerSet", file);
}
catch (Exception e)
{
Logging.logger().fine(Logging.getMessage("generic.ExceptionAttemptingToParseXml", file));
return Logging.getMessage("WWDotNetLayerSetConverter.CannotReadLayerSetConfigFile", file);
}
finally
{
WWXML.closeEventReader(eventReader, file.getPath());
}
// Return null, indicating the DataSource is a valid LayerSet configuration document.
return null;
}
protected Document readLayerSetDocument(Object source)
{
Document doc = null;
try
{
doc = WWXML.openDocument(source);
}
catch (Exception e)
{
String message = Logging.getMessage("generic.ExceptionAttemptingToParseXml", source);
Logging.logger().fine(message);
}
if (doc == null)
{
String message = Logging.getMessage("WWDotNetLayerSetConverter.CannotReadLayerSetConfigFile", source);
Logging.logger().severe(message);
throw new WWRuntimeException(message);
}
if (!DataConfigurationUtils.isWWDotNetLayerSetConfigDocument(doc.getDocumentElement()))
{
String message = Logging.getMessage("WWDotNetLayerSetConverter.FileNotLayerSet", source);
Logging.logger().severe(message);
throw new WWRuntimeException(message);
}
return doc;
}
//**************************************************************//
//******************** LayerSet Installation *****************//
//**************************************************************//
protected void convertLayerSet(Object source, ProductionState productionState) throws Exception
{
File sourceConfigFile = this.getSourceConfigFile(source);
if (sourceConfigFile == null)
{
String message = Logging.getMessage("WWDotNetLayerSetConverter.NoSourceLocation");
Logging.logger().severe(message);
throw new WWRuntimeException(message);
}
File sourceDataFile = sourceConfigFile.getParentFile();
if (sourceDataFile == null)
{
String message = Logging.getMessage("WWDotNetLayerSetConverter.FileWithoutParent", sourceConfigFile);
Logging.logger().severe(message);
throw new WWRuntimeException(message);
}
File destConfigFile = this.getDestConfigFile(productionState.productionParams);
if (destConfigFile == null)
{
String message = Logging.getMessage("WWDotNetLayerSetConverter.NoInstallLocation", sourceConfigFile);
Logging.logger().severe(message);
throw new WWRuntimeException(message);
}
File destDataFile = destConfigFile.getParentFile();
if (destDataFile == null)
{
String message = Logging.getMessage("WWDotNetLayerSetConverter.FileWithoutParent", destConfigFile);
Logging.logger().severe(message);
throw new WWRuntimeException(message);
}
if (WWIO.isAncestorOf(sourceDataFile, destDataFile) || WWIO.isAncestorOf(destDataFile, sourceDataFile))
{
String message = Logging.getMessage("WWDotNetLayerSetConverter.CannotInstallToSelf", sourceDataFile,
destDataFile);
Logging.logger().severe(message);
throw new WWRuntimeException(message);
}
if (this.isStopped())
return;
Document sourceConfigDoc = this.readLayerSetDocument(sourceConfigFile);
try
{
String imageFormat = productionState.productionParams.getStringValue(AVKey.IMAGE_FORMAT);
productionState.numSourceFiles[productionState.curSource] = this.countWWDotNetFiles(sourceDataFile);
this.copyWWDotNetDiretory(sourceDataFile, destDataFile, imageFormat, productionState);
}
catch (Exception e)
{
// Back out all file system changes made so far.
WWIO.deleteDirectory(destDataFile);
String message = Logging.getMessage("WWDotNetLayerSetConverter.CannotInstallLayerSet", sourceConfigFile);
Logging.logger().log(java.util.logging.Level.SEVERE, message, e);
throw new WWRuntimeException(message);
}
if (this.isStopped())
return;
Document destConfigDoc;
try
{
destConfigDoc = this.createDestConfigDoc(sourceConfigDoc, productionState.productionParams);
WWXML.saveDocumentToFile(destConfigDoc, destConfigFile.getAbsolutePath());
}
catch (Exception e)
{
// Back out all file system changes made so far.
WWIO.deleteDirectory(destDataFile);
//noinspection ResultOfMethodCallIgnored
destConfigFile.delete();
String message = Logging.getMessage("WWDotNetLayerSetConverter.CannotWriteLayerConfigFile", destConfigFile);
Logging.logger().severe(message);
throw new WWRuntimeException(message);
}
if (this.isStopped())
return;
this.getProductionResultsList().add(destConfigDoc);
}
protected File getSourceConfigFile(Object source)
{
if (source instanceof File)
{
return (File) source;
}
else if (source instanceof String && !WWUtil.isEmpty(source))
{
return new File((String) source);
}
return null;
}
protected File getDestConfigFile(AVList installParams)
{
String fileStoreLocation = installParams.getStringValue(AVKey.FILE_STORE_LOCATION);
if (fileStoreLocation != null)
fileStoreLocation = WWIO.stripTrailingSeparator(fileStoreLocation);
if (WWUtil.isEmpty(fileStoreLocation))
return null;
String cacheName = DataConfigurationUtils.getDataConfigFilename(installParams, ".xml");
if (cacheName != null)
cacheName = WWIO.stripLeadingSeparator(cacheName);
if (WWUtil.isEmpty(cacheName))
return null;
return new File(fileStoreLocation + File.separator + cacheName);
}
protected Document createDestConfigDoc(Document layerSetDoc, AVList installParams)
{
AVList params = new AVListImpl();
// Extract configuration parameters from the LayerSet document.
DataConfigurationUtils.getWWDotNetLayerSetConfigParams(layerSetDoc.getDocumentElement(), params);
// Override the LayerSet's display name with the name used by the converter.
if (installParams.getValue(AVKey.DISPLAY_NAME) != null)
params.setValue(AVKey.DISPLAY_NAME, installParams.getValue(AVKey.DISPLAY_NAME));
// Override the LayerSet's cache name with the cache name used by the converter.
if (installParams.getValue(AVKey.DATA_CACHE_NAME) != null)
params.setValue(AVKey.DATA_CACHE_NAME, installParams.getValue(AVKey.DATA_CACHE_NAME));
// Override the LayerSet's image format and available image format parameters with values used by the converter.
if (installParams.getValue(AVKey.IMAGE_FORMAT) != null)
params.setValue(AVKey.IMAGE_FORMAT, installParams.getValue(AVKey.IMAGE_FORMAT));
if (installParams.getValue(AVKey.AVAILABLE_IMAGE_FORMATS) != null)
params.setValue(AVKey.AVAILABLE_IMAGE_FORMATS, installParams.getValue(AVKey.AVAILABLE_IMAGE_FORMATS));
// Override the LayerSet's format suffix with the suffix used by the converter.
if (installParams.getValue(AVKey.FORMAT_SUFFIX) != null)
params.setValue(AVKey.FORMAT_SUFFIX, installParams.getValue(AVKey.FORMAT_SUFFIX));
// Set the texture format to DDS. If the texture data is already in DDS format, this parameter is benign.
params.setValue(AVKey.TEXTURE_FORMAT, DEFAULT_TEXTURE_FORMAT);
return BasicTiledImageLayer.createTiledImageLayerConfigDocument(params);
}
//**************************************************************//
//******************** Imagery Installation ******************//
//**************************************************************//
private void copyWWDotNetDiretory(java.io.File source, java.io.File destination, String installMimeType,
ProductionState productionState) throws java.io.IOException
{
if (this.isStopped())
return;
if (!destination.exists())
{
//noinspection ResultOfMethodCallIgnored
destination.mkdirs();
}
if (!destination.exists())
{
String message = Logging.getMessage("generic.CannotCreateFile", destination);
Logging.logger().severe(message);
throw new java.io.IOException(message);
}
java.io.File[] fileList = source.listFiles();
if (fileList == null)
return;
java.util.List childFiles = new java.util.ArrayList();
java.util.List childDirs = new java.util.ArrayList();
for (java.io.File child : fileList)
{
if (child == null) // Don't allow null subfiles.
continue;
if (child.isHidden()) // Ignore hidden files.
continue;
if (child.isDirectory())
childDirs.add(child);
else
childFiles.add(child);
}
for (java.io.File childFile : childFiles)
{
if (this.isStopped())
break;
if (!isWWDotNetFile(childFile))
continue;
java.io.File destFile = makeWWJavaFile(destination, childFile.getName(), installMimeType);
this.installWWDotNetFile(childFile, destFile, productionState);
if (!destFile.exists())
{
String message = Logging.getMessage("generic.CannotCreateFile", destFile);
Logging.logger().severe(message);
throw new java.io.IOException(message);
}
}
for (java.io.File childDir : childDirs)
{
if (this.isStopped())
break;
if (!isWWDotNetDirectory(childDir))
continue;
java.io.File destDir = makeWWJavaDirectory(destination, childDir.getName());
this.copyWWDotNetDiretory(childDir, destDir, installMimeType, productionState);
}
}
private void installWWDotNetFile(java.io.File source, java.io.File destination, ProductionState productionState)
throws java.io.IOException
{
// Bypass file installation if:
// (a) destination is newer than source, and
// (b) source and destination have identical size.
if (destination.exists() && source.lastModified() >= destination.lastModified()
&& source.length() == destination.length())
{
return;
}
String sourceSuffix = WWIO.getSuffix(source.getName());
String destinationSuffix = WWIO.getSuffix(destination.getName());
// Source and destination types match. Copy the source file directly.
if (sourceSuffix.equalsIgnoreCase(destinationSuffix))
{
WWIO.copyFile(source, destination);
}
// Destination type is different. Convert the source file and write the converstion to the destionation.
else
{
if (destinationSuffix.equalsIgnoreCase("dds"))
{
java.nio.ByteBuffer sourceBuffer = DDSCompressor.compressImageFile(source);
WWIO.saveBuffer(sourceBuffer, destination);
}
else
{
java.awt.image.BufferedImage sourceImage = javax.imageio.ImageIO.read(source);
javax.imageio.ImageIO.write(sourceImage, destinationSuffix, destination);
}
}
this.updateProgress(productionState);
}
private static java.io.File makeWWJavaDirectory(java.io.File dir, String dirname)
{
return new java.io.File(dir, WWIO.stripLeadingZeros(dirname));
}
private static java.io.File makeWWJavaFile(java.io.File dir, String filename, String installMimeType)
{
// If the filename does not match the standard pattern, then return a file with that name.
String[] tokens = filename.split("[._]");
if (tokens == null || tokens.length < 3 || tokens[0].length() < 1 || tokens[1].length() < 1)
return new java.io.File(dir, filename);
// If an installation type is specified, override the file extension with the new type.
if (installMimeType != null)
tokens[2] = WWIO.makeSuffixForMimeType(installMimeType);
// Otherwise keep the existing extension. Add a leading '.' so that both cases can be handled transparently.
else if (tokens[2].length() > 1)
tokens[2] = "." + tokens[2];
// If the filename is "000n_000m.foo", then the contents of tokens[] are:
// tokens[0] = "000n"
// tokens[1] = "000m"
// tokens[2] = "foo"
StringBuilder sb = new StringBuilder();
sb.append(WWIO.stripLeadingZeros(tokens[0])).append("_").append(WWIO.stripLeadingZeros(tokens[1]));
sb.append(tokens[2]);
return new java.io.File(dir, sb.toString());
}
private static boolean isWWDotNetDirectory(java.io.File file)
{
String pattern = "\\d+";
return file.getName().matches(pattern);
}
private static boolean isWWDotNetFile(java.io.File file)
{
String pattern = "\\d+[_]\\d+[.]\\w+";
return file.getName().matches(pattern);
}
//**************************************************************//
//******************** Progress and Verification *************//
//**************************************************************//
private int countWWDotNetFiles(java.io.File source)
{
int count = 0;
java.io.File[] fileList = source.listFiles();
if (fileList == null)
return count;
java.util.List childFiles = new java.util.ArrayList();
java.util.List childDirs = new java.util.ArrayList();
for (java.io.File child : fileList)
{
if (child == null) // Don't allow null subfiles.
continue;
if (child.isHidden()) // Ignore hidden files.
continue;
if (child.isDirectory())
childDirs.add(child);
else
childFiles.add(child);
}
for (java.io.File childFile : childFiles)
{
if (!isWWDotNetFile(childFile))
continue;
count++;
}
for (java.io.File childDir : childDirs)
{
if (!isWWDotNetDirectory(childDir))
continue;
count += countWWDotNetFiles(childDir);
}
return count;
}
//**************************************************************//
//******************** Progress Parameters *******************//
//**************************************************************//
protected void setProgressParameters(Iterable> dataSources, ProductionState productionState)
{
int numSources = 0;
//noinspection UnusedDeclaration
for (Object o : dataSources)
{
numSources++;
}
productionState.numSources = numSources;
productionState.curSource = -1;
productionState.numSourceFiles = new int[numSources];
productionState.numInstalledFiles = new int[numSources];
}
private void updateProgress(ProductionState productionState)
{
double oldProgress = this.computeProgress(productionState);
productionState.numInstalledFiles[productionState.curSource]++;
double newProgress = this.computeProgress(productionState);
this.firePropertyChange(AVKey.PROGRESS, oldProgress, newProgress);
}
private double computeProgress(ProductionState productionState)
{
double progress = 0.0;
for (int i = 0; i <= productionState.curSource; i++)
{
progress += (productionState.numInstalledFiles[i] /
(double) productionState.numSourceFiles[i]) * (1.0 / (double) productionState.numSources);
}
return progress;
}
//**************************************************************//
//******************** LayerSet Removal **********************//
//**************************************************************//
protected void removeLayerSet(Object source, AVList params)
{
File sourceConfigFile = this.getSourceConfigFile(source);
if (sourceConfigFile == null)
{
String message = Logging.getMessage("WWDotNetLayerSetConverter.NoSourceLocation");
Logging.logger().warning(message);
return;
}
File destConfigFile = this.getDestConfigFile(params);
if (destConfigFile == null)
{
String message = Logging.getMessage("WWDotNetLayerSetConverter.NoInstallLocation", sourceConfigFile);
Logging.logger().warning(message);
return;
}
File destDataFile = destConfigFile.getParentFile();
if (destDataFile == null)
{
String message = Logging.getMessage("WWDotNetLayerSetConverter.FileWithoutParent", destConfigFile);
Logging.logger().warning(message);
return;
}
try
{
WWIO.deleteDirectory(destDataFile);
}
catch (Exception e)
{
String message = Logging.getMessage("WWDotNetLayerSetConverter.ExceptionRemovingProductionState",
sourceConfigFile);
Logging.logger().log(java.util.logging.Level.SEVERE, message, e);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy