package mobac.mapsources.loader;
import java.io.File;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Arrays;
import javax.swing.JOptionPane;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.ValidationEvent;
import javax.xml.bind.ValidationEventHandler;
import javax.xml.bind.ValidationEventLocator;
import mobac.exceptions.MapSourceCreateException;
import mobac.mapsources.MapSourcesManager;
import mobac.mapsources.custom.CustomCloudMade;
import mobac.mapsources.custom.CustomLocalTileFilesMapSource;
import mobac.mapsources.custom.CustomLocalTileSQliteMapSource;
import mobac.mapsources.custom.CustomLocalTileZipMapSource;
import mobac.mapsources.custom.CustomMapSource;
import mobac.mapsources.custom.CustomMultiLayerMapSource;
import mobac.mapsources.custom.CustomWatermarkMapSource;
import mobac.mapsources.custom.CustomWmsMapSource;
import mobac.program.interfaces.FileBasedMapSource;
import mobac.program.interfaces.MapSource;
import mobac.program.interfaces.WrappedMapSource;
import mobac.program.model.MapSourceLoaderInfo;
import mobac.program.model.MapSourceLoaderInfo.LoaderType;
import mobac.utilities.file.FileExtFilter;
import org.apache.log4j.Logger;
public class CustomMapSourceLoader implements ValidationEventHandler {
private final Logger log = Logger.getLogger(MapPackManager.class);
private final MapSourcesManager mapSourcesManager;
private final File mapSourcesDir;
private final Unmarshaller unmarshaller;
public CustomMapSourceLoader(MapSourcesManager mapSourceManager, File mapSourcesDir) {
this.mapSourcesManager = mapSourceManager;
this.mapSourcesDir = mapSourcesDir;
try {
Class<?>[] customMapClasses = new Class[] { CustomMapSource.class, CustomWmsMapSource.class,
CustomMultiLayerMapSource.class, CustomCloudMade.class, CustomLocalTileFilesMapSource.class,
CustomLocalTileZipMapSource.class, CustomLocalTileSQliteMapSource.class, CustomWatermarkMapSource.class };
JAXBContext context = JAXBContext.newInstance(customMapClasses);
unmarshaller = context.createUnmarshaller();
unmarshaller.setEventHandler(this);
} catch (JAXBException e) {
throw new RuntimeException("Unable to create JAXB context for custom map sources", e);
}
}
public void loadCustomMapSources() {
File[] customMapSourceFiles = mapSourcesDir.listFiles(new FileExtFilter(".xml"));
Arrays.sort(customMapSourceFiles);
for (File f : customMapSourceFiles) {
try {
MapSource customMapSource;
Object o = unmarshaller.unmarshal(f);
if (o instanceof WrappedMapSource)
customMapSource = ((WrappedMapSource) o).getMapSource();
else
customMapSource = (MapSource) o;
customMapSource.setLoaderInfo(new MapSourceLoaderInfo(LoaderType.XML, f));
if (!(customMapSource instanceof FileBasedMapSource) && customMapSource.getTileImageType() == null)
log.warn("A problem occured while loading \"" + f.getName()
+ "\": tileType is null - some atlas formats will produce an error!");
log.trace("Custom map source loaded: " + customMapSource + " from file \"" + f.getName() + "\"");
mapSourcesManager.addMapSource(customMapSource);
} catch (Exception e) {
log.error("failed to load custom map source \"" + f.getName() + "\": " + e.getMessage(), e);
}
}
}
public MapSource loadCustomMapSource(InputStream in) throws MapSourceCreateException, JAXBException {
MapSource customMapSource;
Object o = unmarshaller.unmarshal(in);
if (o instanceof WrappedMapSource)
customMapSource = ((WrappedMapSource) o).getMapSource();
else
customMapSource = (MapSource) o;
customMapSource.setLoaderInfo(new MapSourceLoaderInfo(LoaderType.XML, null));
log.trace("Custom map source loaded: " + customMapSource);
return customMapSource;
}
public boolean handleEvent(ValidationEvent event) {
ValidationEventLocator loc = event.getLocator();
String file = loc.getURL().getFile();
try {
file = URLDecoder.decode(file, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
int lastSlash = file.lastIndexOf('/');
if (lastSlash > 0)
file = file.substring(lastSlash + 1);
String errorMsg = event.getMessage();
if (errorMsg == null) {
Throwable t = event.getLinkedException();
while (t != null && errorMsg == null) {
errorMsg = t.getMessage();
t = t.getCause();
}
}
JOptionPane
.showMessageDialog(null, "<html><h3>Failed to load a custom map</h3><p><i>" + errorMsg
+ "</i></p><br><p>file: \"<b>" + file + "</b>\"<br>line/column: <i>" + loc.getLineNumber()
+ "/" + loc.getColumnNumber() + "</i></p>", "Error: custom map loading failed",
JOptionPane.ERROR_MESSAGE);
log.error(event.toString());
return false;
}
public static class WrappedMap {
}
}