/******************************************************************************* * Copyright (c) MOBAC developers * * 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 2 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 mobac.program.atlascreators; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.text.SimpleDateFormat; import java.util.Date; import java.util.EnumSet; import mobac.exceptions.AtlasTestException; import mobac.exceptions.MapCreationException; import mobac.gui.AtlasProgress; import mobac.program.AtlasThread; import mobac.program.PauseResumeHandler; import mobac.program.atlascreators.tileprovider.TileProvider; import mobac.program.interfaces.AtlasInterface; import mobac.program.interfaces.LayerInterface; import mobac.program.interfaces.MapInterface; import mobac.program.interfaces.MapSource; import mobac.program.model.AtlasOutputFormat; import mobac.program.model.Settings; import mobac.program.model.TileImageFormat; import mobac.program.model.TileImageParameters; import mobac.utilities.Charsets; import mobac.utilities.Utilities; import org.apache.log4j.Logger; /** * Abstract base class for all AtlasCreator implementations. * * The general call schema is as follows: * <ol> * <li>AtlasCreator instantiation via {@link AtlasOutputFormat#createAtlasCreatorInstance()}</li> * <li>AtlasCreator atlas initialization via {@link #startAtlasCreation(AtlasInterface, File)}</li> * <li>1 to n times {@link #initializeMap(MapInterface, TileProvider)} followed by {@link #createMap()}</li> * <li>AtlasCreator atlas finalization via {@link #finishAtlasCreation()}</li> * </ol> */ public abstract class AtlasCreator { public static final Charset TEXT_FILE_CHARSET = Charsets.ISO_8859_1; protected final Logger log; /************************************************************/ /** atlas specific fields **/ /************************************************************/ protected AtlasInterface atlas; protected File atlasDir; protected AtlasProgress atlasProgress = null; protected PauseResumeHandler pauseResumeHandler = null; /************************************************************/ /** map specific fields **/ /************************************************************/ protected MapInterface map; protected int xMin; protected int xMax; protected int yMin; protected int yMax; protected int zoom; protected MapSource mapSource; protected int tileSize; /** * Custom tile processing parameters. <code>null</code> if disabled in GUI */ protected TileImageParameters parameters; protected AtlasOutputFormat atlasOutputFormat; protected TileProvider mapDlTileProvider; private boolean aborted = false; /** * Default constructor - initializes the logging environment */ protected AtlasCreator() { log = Logger.getLogger(this.getClass()); }; /** * @param customAtlasDir * if not <code>null</code> the customAtlasDir is used instead of the generated atlas directory name * @throws InterruptedException * @see AtlasCreator */ public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) throws AtlasTestException, IOException, InterruptedException { this.atlas = atlas; testAtlas(); if (customAtlasDir == null) { // No explicit atlas output directory has been set - generate a new directory name SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HHmmss"); String atlasDirName = atlas.getName() + "_" + sdf.format(new Date()); File atlasOutputDir = Settings.getInstance().getAtlasOutputDirectory(); atlasDir = new File(atlasOutputDir, atlasDirName); } else atlasDir = customAtlasDir; Utilities.mkDirs(atlasDir); } protected void testAtlas() throws AtlasTestException { } public void initLayerCreation(LayerInterface layer) throws IOException { } public void finishLayerCreation() throws IOException { } /** * @throws InterruptedException * @see AtlasCreator */ public void finishAtlasCreation() throws IOException, InterruptedException { } public void abortAtlasCreation() throws IOException { this.aborted = true; } public boolean isAborted() { return aborted; } /** * Test if the {@link AtlasCreator} instance supports the selected {@link MapSource} * * @param mapSource * @return <code>true</code> if supported otherwise <code>false</code> * @see AtlasCreator */ public abstract boolean testMapSource(MapSource mapSource); /** * @see AtlasCreator */ public void initializeMap(MapInterface map, TileProvider mapTileProvider) { LayerInterface layer = map.getLayer(); if (mapTileProvider == null) throw new NullPointerException(); this.mapDlTileProvider = mapTileProvider; this.map = map; this.mapSource = map.getMapSource(); this.tileSize = mapSource.getMapSpace().getTileSize(); this.parameters = map.getParameters(); xMin = map.getMinTileCoordinate().x / tileSize; xMax = map.getMaxTileCoordinate().x / tileSize; yMin = map.getMinTileCoordinate().y / tileSize; yMax = map.getMaxTileCoordinate().y / tileSize; this.zoom = map.getZoom(); this.atlasOutputFormat = layer.getAtlas().getOutputFormat(); Thread t = Thread.currentThread(); if (!(t instanceof AtlasThread)) throw new RuntimeException("Calling thread must be AtlasThread!"); AtlasThread at = (AtlasThread) t; atlasProgress = at.getAtlasProgress(); pauseResumeHandler = at.getPauseResumeHandler(); } /** * @throws InterruptedException * @see AtlasCreator */ public abstract void createMap() throws MapCreationException, InterruptedException; /** * Checks if the user has aborted atlas creation and if <code>true</code> an {@link InterruptedException} is thrown. * * @throws InterruptedException */ public void checkUserAbort() throws InterruptedException { if (Thread.currentThread().isInterrupted()) throw new InterruptedException(); pauseResumeHandler.pauseWait(); } public AtlasProgress getAtlasProgress() { return atlasProgress; } public int getXMin() { return xMin; } public int getXMax() { return xMax; } public int getYMin() { return yMin; } public int getYMax() { return yMax; } public MapInterface getMap() { return map; } public TileImageParameters getParameters() { return parameters; } public TileProvider getMapDlTileProvider() { return mapDlTileProvider; } /** * Tests all maps of the currently active atlas if a custom tile image format has been specified and if the * specified format is equal to the <code>allowedFormat</code>. * * @param allowedFormat * @throws AtlasTestException */ protected void performTest_AtlasTileFormat(EnumSet<TileImageFormat> allowedFormats) throws AtlasTestException { for (LayerInterface layer : atlas) { for (MapInterface map : layer) { TileImageParameters parameters = map.getParameters(); if (parameters == null) continue; if (!allowedFormats.contains(parameters.getFormat())) throw new AtlasTestException( "Selected custom tile format not supported - only the following format(s) are supported: " + allowedFormats, map); } } } protected void performTest_MaxMapZoom(int maxZoom) throws AtlasTestException { for (LayerInterface layer : atlas) { for (MapInterface map : layer) { if (map.getZoom() > maxZoom) throw new AtlasTestException("Maximum zoom is " + maxZoom + " for this atlas format", map); } } } }