Java tutorial
/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2013, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library 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 * Lesser General Public License for more details. */ package org.geotools.gce.imagemosaic; import java.awt.image.ColorModel; import java.awt.image.IndexColorModel; import java.awt.image.SampleModel; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.imageio.spi.ImageReaderSpi; import javax.media.jai.ImageLayout; import javax.xml.bind.JAXBException; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.geotools.coverage.grid.io.GridCoverage2DReader; import org.geotools.coverage.grid.io.StructuredGridCoverage2DReader; import org.geotools.data.DataUtilities; import org.geotools.data.DefaultTransaction; import org.geotools.factory.Hints; import org.geotools.gce.imagemosaic.Utils.Prop; import org.geotools.gce.imagemosaic.catalog.CatalogConfigurationBean; import org.geotools.gce.imagemosaic.catalog.GranuleCatalog; import org.geotools.gce.imagemosaic.catalog.index.DomainType; import org.geotools.gce.imagemosaic.catalog.index.DomainsType; import org.geotools.gce.imagemosaic.catalog.index.Indexer; import org.geotools.gce.imagemosaic.catalog.index.Indexer.Collectors; import org.geotools.gce.imagemosaic.catalog.index.Indexer.Collectors.Collector; import org.geotools.gce.imagemosaic.catalog.index.Indexer.Coverages; import org.geotools.gce.imagemosaic.catalog.index.Indexer.Coverages.Coverage; import org.geotools.gce.imagemosaic.catalog.index.IndexerUtils; import org.geotools.gce.imagemosaic.catalog.index.ParametersType; import org.geotools.gce.imagemosaic.catalog.index.ParametersType.Parameter; import org.geotools.gce.imagemosaic.catalog.index.SchemaType; import org.geotools.gce.imagemosaic.catalog.index.SchemasType; import org.geotools.gce.imagemosaic.catalogbuilder.CatalogBuilderConfiguration; import org.geotools.gce.imagemosaic.catalogbuilder.MosaicBeanBuilder; import org.geotools.gce.imagemosaic.properties.DefaultPropertiesCollectorSPI; import org.geotools.gce.imagemosaic.properties.PropertiesCollector; import org.geotools.gce.imagemosaic.properties.PropertiesCollectorFinder; import org.geotools.gce.imagemosaic.properties.PropertiesCollectorSPI; import org.geotools.geometry.GeneralEnvelope; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.referencing.CRS; import org.geotools.util.Utilities; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.referencing.crs.CoordinateReferenceSystem; /** * This class is in responsible for creating and managing the catalog and the configuration of the mosaic * * @author Carlo Cancellieri - GeoSolutions SAS * * @source $URL$ */ public class ImageMosaicConfigHandler { /** Default Logger * */ final static Logger LOGGER = org.geotools.util.logging.Logging.getLogger(ImageMosaicConfigHandler.class); private List<PropertiesCollector> propertiesCollectors = null; private Map<String, MosaicConfigurationBean> configurations = new HashMap<String, MosaicConfigurationBean>(); /** * Proper way to stop a thread is not by calling Thread.stop() but by using a shared variable that can be checked in order to notify a terminating * condition. */ private volatile boolean stop = false; private GranuleCatalog catalog; private CatalogBuilderConfiguration runConfiguration; private ImageReaderSpi cachedReaderSPI; private ReferencedEnvelope imposedBBox; private ImageMosaicReader parentReader; private File indexerFile; private File parent; private ImageMosaicEventHandlers eventHandler; private boolean useExistingSchema; /** * Default constructor * * @throws * @throws IllegalArgumentException */ public ImageMosaicConfigHandler(final CatalogBuilderConfiguration configuration, final ImageMosaicEventHandlers eventHandler) { Utilities.ensureNonNull("runConfiguration", configuration); Utilities.ensureNonNull("eventHandler", eventHandler); this.eventHandler = eventHandler; Indexer defaultIndexer = configuration.getIndexer(); ParametersType params = null; String rootMosaicDir = null; if (defaultIndexer != null) { params = defaultIndexer.getParameters(); rootMosaicDir = IndexerUtils.getParam(params, Prop.ROOT_MOSAIC_DIR); IndexerUtils.getParameterAsBoolean(Prop.USE_EXISTING_SCHEMA, defaultIndexer); } Utilities.ensureNonNull("root location", rootMosaicDir); // look for and indexer.properties file parent = new File(rootMosaicDir); indexerFile = new File(parent, Utils.INDEXER_XML); Indexer indexer = null; Hints hints = configuration.getHints(); String ancillaryFile = null; if (Utils.checkFileReadable(indexerFile)) { try { indexer = (Indexer) Utils.unmarshal(indexerFile); if (indexer != null) { copyDefaultParams(params, indexer); } } catch (JAXBException e) { LOGGER.log(Level.WARNING, e.getMessage(), e); } } else { // Backward compatible with old indexing indexerFile = new File(parent, Utils.INDEXER_PROPERTIES); if (Utils.checkFileReadable(indexerFile)) { // load it and parse it final Properties props = Utils.loadPropertiesFromURL(DataUtilities.fileToURL(indexerFile)); indexer = createIndexer(props, params); } } if (indexer != null) { // Overwrite default indexer only when indexer is available configuration.setIndexer(indexer); String param = IndexerUtils.getParameter(Utils.Prop.AUXILIARY_FILE, indexer); if (param != null) { ancillaryFile = param; setReader(hints, false); } if (IndexerUtils.getParameterAsBoolean(Utils.Prop.USE_EXISTING_SCHEMA, indexer)) { this.useExistingSchema = true; } } updateConfigurationHints(configuration, hints, ancillaryFile, IndexerUtils.getParam(params, Prop.ROOT_MOSAIC_DIR)); // check config configuration.check(); this.runConfiguration = new CatalogBuilderConfiguration(configuration); } private void setReader(Hints hints, final boolean updateHints) { if (hints != null && hints.containsKey(Utils.MOSAIC_READER)) { Object reader = hints.get(Utils.MOSAIC_READER); if (reader instanceof ImageMosaicReader) { if (getParentReader() == null) { setParentReader((ImageMosaicReader) reader); } if (updateHints) { Hints readerHints = getParentReader().getHints(); readerHints.add(hints); } } } } private void updateConfigurationHints(final CatalogBuilderConfiguration configuration, Hints hints, final String ancillaryFile, final String rootMosaicDir) { String ancillaryFilePath = null; if (ancillaryFile != null) { ancillaryFilePath = rootMosaicDir + File.separatorChar + ancillaryFile; if (hints != null) { hints.put(Utils.AUXILIARY_FILES_PATH, ancillaryFilePath); } else { hints = new Hints(Utils.AUXILIARY_FILES_PATH, ancillaryFilePath); configuration.setHints(hints); } } setReader(hints, true); } /** * Setup default params to the indexer. * * @param params * @param indexer */ private void copyDefaultParams(ParametersType params, Indexer indexer) { if (params != null) { List<Parameter> defaultParamList = params.getParameter(); if (defaultParamList != null && !defaultParamList.isEmpty()) { ParametersType parameters = indexer.getParameters(); if (parameters == null) { parameters = Utils.OBJECT_FACTORY.createParametersType(); indexer.setParameters(parameters); } List<Parameter> parameterList = parameters.getParameter(); for (Parameter defaultParameter : defaultParamList) { final String defaultParameterName = defaultParameter.getName(); if (IndexerUtils.getParameter(defaultParameterName, indexer) == null) { IndexerUtils.setParam(parameterList, defaultParameterName, defaultParameter.getValue()); } } } } } /** * Perform proper clean up. * * <p> * Make sure to call this method when you are not running the {@link ImageMosaicConfigHandler} or bad things can happen. If it is running, please * stop it first. */ public void reset() { eventHandler.removeAllProcessingEventListeners(); // clear stop stop = false; closeIndexObjects(); // fileIndex = 0; runConfiguration = null; } public boolean getStop() { return stop; } public void stop() { stop = true; } void indexingPreamble() throws IOException { // // create the index // catalog = CatalogManager.createCatalog(runConfiguration, !useExistingSchema); getParentReader().granuleCatalog = catalog; // // IMPOSED ENVELOPE // String bbox = runConfiguration.getParameter(Prop.ENVELOPE2D); try { this.imposedBBox = Utils.parseEnvelope(bbox); } catch (Exception e) { this.imposedBBox = null; if (LOGGER.isLoggable(Level.WARNING)) LOGGER.log(Level.WARNING, "Unable to parse imposed bbox", e); } // // load property collectors // loadPropertyCollectors(); } /** * Load properties collectors from the configuration */ private void loadPropertyCollectors() { // load property collectors Indexer indexer = runConfiguration.getIndexer(); Collectors collectors = indexer.getCollectors(); if (collectors == null) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("No properties collector have been found"); } return; } List<Collector> collectorList = collectors.getCollector(); // load the SPI set final Set<PropertiesCollectorSPI> pcSPIs = PropertiesCollectorFinder.getPropertiesCollectorSPI(); // parse the string final List<PropertiesCollector> pcs = new ArrayList<PropertiesCollector>(); for (Collector collector : collectorList) { PropertiesCollectorSPI selectedSPI = null; final String spiName = collector.getSpi(); for (PropertiesCollectorSPI spi : pcSPIs) { if (spi.isAvailable() && spi.getName().equalsIgnoreCase(spiName)) { selectedSPI = spi; break; } } if (selectedSPI == null) { if (LOGGER.isLoggable(Level.INFO)) { LOGGER.info("Unable to find a PropertyCollector for this definition: " + spiName); } continue; } // property names String collectorValue = collector.getValue(); final String config; if (!collectorValue.startsWith(DefaultPropertiesCollectorSPI.REGEX_PREFIX)) { config = DefaultPropertiesCollectorSPI.REGEX_PREFIX + collector.getValue(); } else { config = collector.getValue(); } // create the PropertiesCollector final PropertiesCollector pc = selectedSPI.create(config, Arrays.asList(collector.getMapped())); if (pc != null) { pcs.add(pc); } else { if (LOGGER.isLoggable(Level.INFO)) { LOGGER.info("Unable to create PropertyCollector"); } } } this.propertiesCollectors = pcs; } void indexingPostamble(final boolean success) throws IOException { // close shapefile elements if (success) { Indexer indexer = runConfiguration.getIndexer(); boolean supportsEmpty = false; if (indexer != null) { supportsEmpty = IndexerUtils.getParameterAsBoolean(Prop.CAN_BE_EMPTY, indexer); } // complete initialization of mosaic configuration boolean haveConfigs = configurations != null && !configurations.isEmpty(); if (haveConfigs || supportsEmpty) { // We did found some MosaicConfigurations Set<String> keys = configurations.keySet(); int keySize = keys.size(); if (haveConfigs || !supportsEmpty) { final boolean useName = keySize > 1; for (String key : keys) { MosaicConfigurationBean mosaicConfiguration = configurations.get(key); RasterManager manager = parentReader.getRasterManager(key); manager.initialize(supportsEmpty); // create sample image if the needed elements are available createSampleImage(mosaicConfiguration, useName); eventHandler.fireEvent(Level.INFO, "Creating final properties file ", 99.9); createPropertiesFiles(mosaicConfiguration); } } final String base = FilenameUtils.getName(parent.getAbsolutePath()); // we create a root properties file if we have more than one coverage, or if the // one coverage does not have the default name if (supportsEmpty || keySize > 1 || (keySize > 0 && !base.equals(keys.iterator().next()))) { File mosaicFile = null; File originFile = null; if (indexerFile.getAbsolutePath().endsWith("xml")) { mosaicFile = new File( indexerFile.getAbsolutePath().replace(Utils.INDEXER_XML, (base + ".xml"))); originFile = indexerFile; } else if (indexerFile.getAbsolutePath().endsWith("properties")) { mosaicFile = new File(indexerFile.getAbsolutePath().replace(Utils.INDEXER_PROPERTIES, (base + ".properties"))); originFile = indexerFile; } else { final String source = runConfiguration.getParameter(Prop.ROOT_MOSAIC_DIR) + File.separatorChar + configurations.get(keys.iterator().next()).getName() + ".properties"; mosaicFile = new File(indexerFile.getAbsolutePath().replace(Utils.INDEXER_PROPERTIES, (base + ".properties"))); originFile = new File(source); } if (!mosaicFile.exists()) { FileUtils.copyFile(originFile, mosaicFile); } } // processing information eventHandler.fireEvent(Level.FINE, "Done!!!", 100); } else { // processing information eventHandler.fireEvent(Level.FINE, "Nothing to process!!!", 100); } } else { // processing information eventHandler.fireEvent(Level.FINE, "Canceled!!!", 100); } closeIndexObjects(); } /** * Store a sample image frmo which we can derive the default SM and CM */ private void createSampleImage(final MosaicConfigurationBean mosaicConfiguration, final boolean useName) { // create a sample image to store SM and CM Utilities.ensureNonNull("mosaicConfiguration", mosaicConfiguration); String filePath = null; if (mosaicConfiguration.getSampleModel() != null && mosaicConfiguration.getColorModel() != null) { // sample image file // TODO: Consider revisit this using different name/folder final String baseName = runConfiguration.getParameter(Prop.ROOT_MOSAIC_DIR) + "/"; filePath = baseName + (useName ? mosaicConfiguration.getName() : "") + Utils.SAMPLE_IMAGE_NAME; try { Utils.storeSampleImage(new File(filePath), mosaicConfiguration.getSampleModel(), mosaicConfiguration.getColorModel()); } catch (IOException e) { eventHandler.fireEvent(Level.SEVERE, e.getLocalizedMessage(), 0); } } } private Indexer createIndexer(Properties props, ParametersType params) { // Initializing Indexer objects Indexer indexer = Utils.OBJECT_FACTORY.createIndexer(); indexer.setParameters(params != null ? params : Utils.OBJECT_FACTORY.createParametersType()); Coverages coverages = Utils.OBJECT_FACTORY.createIndexerCoverages(); indexer.setCoverages(coverages); List<Coverage> coverageList = coverages.getCoverage(); Coverage coverage = Utils.OBJECT_FACTORY.createIndexerCoveragesCoverage(); coverageList.add(coverage); indexer.setParameters(params); List<Parameter> parameters = params.getParameter(); // name if (props.containsKey(Prop.NAME)) { IndexerUtils.setParam(parameters, props, Prop.NAME); coverage.setName(props.getProperty(Prop.NAME)); } // absolute if (props.containsKey(Prop.ABSOLUTE_PATH)) IndexerUtils.setParam(parameters, props, Prop.ABSOLUTE_PATH); // recursive if (props.containsKey(Prop.RECURSIVE)) IndexerUtils.setParam(parameters, props, Prop.RECURSIVE); // wildcard if (props.containsKey(Prop.WILDCARD)) IndexerUtils.setParam(parameters, props, Prop.WILDCARD); // schema if (props.containsKey(Prop.SCHEMA)) { SchemasType schemas = Utils.OBJECT_FACTORY.createSchemasType(); SchemaType schema = Utils.OBJECT_FACTORY.createSchemaType(); indexer.setSchemas(schemas); schemas.getSchema().add(schema); schema.setAttributes(props.getProperty(Prop.SCHEMA)); schema.setName(IndexerUtils.getParameter(Prop.INDEX_NAME, indexer)); } DomainsType domains = coverage.getDomains(); List<DomainType> domainList = null; // time attr if (props.containsKey(Prop.TIME_ATTRIBUTE)) { if (domains == null) { domains = Utils.OBJECT_FACTORY.createDomainsType(); coverage.setDomains(domains); domainList = domains.getDomain(); } DomainType domain = Utils.OBJECT_FACTORY.createDomainType(); domain.setName(Utils.TIME_DOMAIN.toLowerCase()); IndexerUtils.setAttributes(domain, props.getProperty(Prop.TIME_ATTRIBUTE)); domainList.add(domain); } // elevation attr if (props.containsKey(Prop.ELEVATION_ATTRIBUTE)) { if (domains == null) { domains = Utils.OBJECT_FACTORY.createDomainsType(); coverage.setDomains(domains); domainList = domains.getDomain(); } DomainType domain = Utils.OBJECT_FACTORY.createDomainType(); domain.setName(Utils.ELEVATION_DOMAIN.toLowerCase()); IndexerUtils.setAttributes(domain, props.getProperty(Prop.ELEVATION_ATTRIBUTE)); domainList.add(domain); } // Additional domain attr if (props.containsKey(Prop.ADDITIONAL_DOMAIN_ATTRIBUTES)) { if (domains == null) { domains = Utils.OBJECT_FACTORY.createDomainsType(); coverage.setDomains(domains); domainList = domains.getDomain(); } String attributes = props.getProperty(Prop.ADDITIONAL_DOMAIN_ATTRIBUTES); IndexerUtils.parseAdditionalDomains(attributes, domainList); } // imposed BBOX if (props.containsKey(Prop.ENVELOPE2D)) IndexerUtils.setParam(parameters, props, Prop.ENVELOPE2D); // imposed Pyramid Layout if (props.containsKey(Prop.RESOLUTION_LEVELS)) IndexerUtils.setParam(parameters, props, Prop.RESOLUTION_LEVELS); // collectors if (props.containsKey(Prop.PROPERTY_COLLECTORS)) { IndexerUtils.setPropertyCollectors(indexer, props.getProperty(Prop.PROPERTY_COLLECTORS)); } if (props.containsKey(Prop.CACHING)) IndexerUtils.setParam(parameters, props, Prop.CACHING); if (props.containsKey(Prop.ROOT_MOSAIC_DIR)) { // Overriding root mosaic directory IndexerUtils.setParam(parameters, props, Prop.ROOT_MOSAIC_DIR); } if (props.containsKey(Prop.INDEXING_DIRECTORIES)) { IndexerUtils.setParam(parameters, props, Prop.INDEXING_DIRECTORIES); } if (props.containsKey(Prop.AUXILIARY_FILE)) { IndexerUtils.setParam(parameters, props, Prop.AUXILIARY_FILE); } if (props.containsKey(Prop.CAN_BE_EMPTY)) { IndexerUtils.setParam(parameters, props, Prop.CAN_BE_EMPTY); } if (props.containsKey(Prop.USE_EXISTING_SCHEMA)) { IndexerUtils.setParam(parameters, props, Prop.USE_EXISTING_SCHEMA); } if (props.containsKey(Prop.CHECK_AUXILIARY_METADATA)) { IndexerUtils.setParam(parameters, props, Prop.CHECK_AUXILIARY_METADATA); } return indexer; } private void closeIndexObjects() { // // TODO: We may consider avoid disposing the catalog to allow the reader to use the already available catalog // try { // if (catalog != null) { // catalog.dispose(); // } // } catch (Throwable e) { // LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e); // } // // catalog = null; // getParentReader().granuleCatalog = null; } /** * Creates the final properties file. */ private void createPropertiesFiles(MosaicConfigurationBean mosaicConfiguration) { // // FINAL STEP // // CREATING GENERAL INFO FILE // CatalogConfigurationBean catalogConfigurationBean = mosaicConfiguration.getCatalogConfigurationBean(); // envelope final Properties properties = new Properties(); properties.setProperty(Utils.Prop.ABSOLUTE_PATH, Boolean.toString(catalogConfigurationBean.isAbsolutePath())); properties.setProperty(Utils.Prop.LOCATION_ATTRIBUTE, catalogConfigurationBean.getLocationAttribute()); // Time final String timeAttribute = mosaicConfiguration.getTimeAttribute(); if (timeAttribute != null) { properties.setProperty(Utils.Prop.TIME_ATTRIBUTE, mosaicConfiguration.getTimeAttribute()); } // Elevation final String elevationAttribute = mosaicConfiguration.getElevationAttribute(); if (elevationAttribute != null) { properties.setProperty(Utils.Prop.ELEVATION_ATTRIBUTE, mosaicConfiguration.getElevationAttribute()); } // Additional domains final String additionalDomainAttribute = mosaicConfiguration.getAdditionalDomainAttributes(); if (additionalDomainAttribute != null) { properties.setProperty(Utils.Prop.ADDITIONAL_DOMAIN_ATTRIBUTES, mosaicConfiguration.getAdditionalDomainAttributes()); } final int numberOfLevels = mosaicConfiguration.getLevelsNum(); final double[][] resolutionLevels = mosaicConfiguration.getLevels(); properties.setProperty(Utils.Prop.LEVELS_NUM, Integer.toString(numberOfLevels)); final StringBuilder levels = new StringBuilder(); for (int k = 0; k < numberOfLevels; k++) { levels.append(Double.toString(resolutionLevels[k][0])).append(",") .append(Double.toString(resolutionLevels[k][1])); if (k < numberOfLevels - 1) { levels.append(" "); } } properties.setProperty(Utils.Prop.LEVELS, levels.toString()); properties.setProperty(Utils.Prop.NAME, mosaicConfiguration.getName()); properties.setProperty(Utils.Prop.TYPENAME, mosaicConfiguration.getName()); properties.setProperty(Utils.Prop.EXP_RGB, Boolean.toString(mosaicConfiguration.isExpandToRGB())); properties.setProperty(Utils.Prop.CHECK_AUXILIARY_METADATA, Boolean.toString(mosaicConfiguration.isCheckAuxiliaryMetadata())); properties.setProperty(Utils.Prop.HETEROGENEOUS, Boolean.toString(catalogConfigurationBean.isHeterogeneous())); if (cachedReaderSPI != null) { // suggested spi properties.setProperty(Utils.Prop.SUGGESTED_SPI, cachedReaderSPI.getClass().getName()); } // write down imposed bbox if (imposedBBox != null) { properties.setProperty(Utils.Prop.ENVELOPE2D, imposedBBox.getMinX() + "," + imposedBBox.getMinY() + " " + imposedBBox.getMaxX() + "," + imposedBBox.getMaxY()); } properties.setProperty(Utils.Prop.CACHING, Boolean.toString(catalogConfigurationBean.isCaching())); if (mosaicConfiguration.getAuxiliaryFilePath() != null) { properties.setProperty(Utils.Prop.AUXILIARY_FILE, mosaicConfiguration.getAuxiliaryFilePath()); } OutputStream outStream = null; String filePath = runConfiguration.getParameter(Prop.ROOT_MOSAIC_DIR) + "/" // + runConfiguration.getIndexName() + ".properties")); + mosaicConfiguration.getName() + ".properties"; try { outStream = new BufferedOutputStream(new FileOutputStream(filePath)); properties.store(outStream, "-Automagically created from GeoTools-"); } catch (FileNotFoundException e) { eventHandler.fireEvent(Level.SEVERE, e.getLocalizedMessage(), 0); } catch (IOException e) { eventHandler.fireEvent(Level.SEVERE, e.getLocalizedMessage(), 0); } finally { if (outStream != null) { IOUtils.closeQuietly(outStream); } } } /** * Check whether the specified coverage already exist in the reader. This allows to get the rasterManager associated with that coverage instead of * creating a new one. * * @param coverageName the name of the coverage to be searched * @return {@code true} in case that coverage already exists * @throws IOException */ protected boolean coverageExists(String coverageName) throws IOException { String[] coverages = getParentReader().getGridCoverageNames(); for (String coverage : coverages) { if (coverage.equals(coverageName)) { return true; } } return false; } /** * Use the passed coverageReader to create or update the all the needed configurations<br/> * It not responsible of the passed coverageReader which should be disposed outside (in the caller). * * @param coverageReader * @param inputCoverageName * @param fileBeingProcessed * @param fileIndex * @param numFiles * @param transaction * @throws IOException */ public void updateConfiguration(GridCoverage2DReader coverageReader, final String inputCoverageName, File fileBeingProcessed, int fileIndex, double numFiles, DefaultTransaction transaction) throws IOException { final String indexName = getRunConfiguration().getParameter(Prop.INDEX_NAME); final String coverageName = coverageReader instanceof StructuredGridCoverage2DReader ? inputCoverageName : indexName; final Indexer indexer = getRunConfiguration().getIndexer(); // checking whether the coverage already exists final boolean coverageExists = coverageExists(coverageName); MosaicConfigurationBean mosaicConfiguration = null; MosaicConfigurationBean currentConfigurationBean = null; RasterManager rasterManager = null; if (coverageExists) { // Get the manager for this coverage so it can be updated rasterManager = getParentReader().getRasterManager(coverageName); mosaicConfiguration = rasterManager.getConfiguration(); } // STEP 2 // Collecting all Coverage properties to setup a MosaicConfigurationBean through // the builder final MosaicBeanBuilder configBuilder = new MosaicBeanBuilder(); final GeneralEnvelope envelope = (GeneralEnvelope) coverageReader.getOriginalEnvelope(inputCoverageName); final CoordinateReferenceSystem actualCRS = coverageReader.getCoordinateReferenceSystem(inputCoverageName); SampleModel sm = null; ColorModel cm = null; int numberOfLevels = 1; double[][] resolutionLevels = null; CatalogBuilderConfiguration catalogConfig; if (mosaicConfiguration == null) { catalogConfig = getRunConfiguration(); // We don't have a configuration for this configuration // Get the type specifier for this image and the check that the // image has the correct sample model and color model. // If this is the first cycle of the loop we initialize everything. // ImageLayout layout = coverageReader.getImageLayout(inputCoverageName); cm = layout.getColorModel(null); sm = layout.getSampleModel(null); numberOfLevels = coverageReader.getNumOverviews(inputCoverageName) + 1; resolutionLevels = coverageReader.getResolutionLevels(inputCoverageName); // at the first step we initialize everything that we will // reuse afterwards starting with color models, sample // models, crs, etc.... configBuilder.setSampleModel(sm); configBuilder.setColorModel(cm); ColorModel defaultCM = cm; // Checking palette if (defaultCM instanceof IndexColorModel) { IndexColorModel icm = (IndexColorModel) defaultCM; int numBands = defaultCM.getNumColorComponents(); byte[][] defaultPalette = new byte[3][icm.getMapSize()]; icm.getReds(defaultPalette[0]); icm.getGreens(defaultPalette[0]); icm.getBlues(defaultPalette[0]); if (numBands == 4) { icm.getAlphas(defaultPalette[0]); } configBuilder.setPalette(defaultPalette); } // STEP 2.A // Preparing configuration configBuilder.setCrs(actualCRS); configBuilder.setLevels(resolutionLevels); configBuilder.setLevelsNum(numberOfLevels); configBuilder.setName(coverageName); configBuilder.setTimeAttribute(IndexerUtils.getAttribute(coverageName, Utils.TIME_DOMAIN, indexer)); configBuilder.setElevationAttribute( IndexerUtils.getAttribute(coverageName, Utils.ELEVATION_DOMAIN, indexer)); configBuilder.setAdditionalDomainAttributes( IndexerUtils.getAttribute(coverageName, Utils.ADDITIONAL_DOMAIN, indexer)); final Hints runHints = getRunConfiguration().getHints(); if (runHints != null && runHints.containsKey(Utils.AUXILIARY_FILES_PATH)) { String auxiliaryFilePath = (String) runHints.get(Utils.AUXILIARY_FILES_PATH); if (auxiliaryFilePath != null && auxiliaryFilePath.trim().length() > 0) { configBuilder.setAuxiliaryFilePath(auxiliaryFilePath); } } final CatalogConfigurationBean catalogConfigurationBean = new CatalogConfigurationBean(); catalogConfigurationBean.setCaching(IndexerUtils.getParameterAsBoolean(Prop.CACHING, indexer)); catalogConfigurationBean .setAbsolutePath(IndexerUtils.getParameterAsBoolean(Prop.ABSOLUTE_PATH, indexer)); catalogConfigurationBean .setLocationAttribute(IndexerUtils.getParameter(Prop.LOCATION_ATTRIBUTE, indexer)); catalogConfigurationBean.setTypeName(coverageName); configBuilder.setCatalogConfigurationBean(catalogConfigurationBean); configBuilder.setCheckAuxiliaryMetadata( IndexerUtils.getParameterAsBoolean(Prop.CHECK_AUXILIARY_METADATA, indexer)); currentConfigurationBean = configBuilder.getMosaicConfigurationBean(); // Creating a rasterManager which will be initialized after populating the catalog rasterManager = getParentReader().addRasterManager(currentConfigurationBean, false); // Creating a granuleStore if (!useExistingSchema) { // creating the schema SimpleFeatureType indexSchema = CatalogManager.createSchema(getRunConfiguration(), currentConfigurationBean.getName(), actualCRS); getParentReader().createCoverage(coverageName, indexSchema); // } else { // rasterManager.typeName = coverageName; } getConfigurations().put(currentConfigurationBean.getName(), currentConfigurationBean); } else { catalogConfig = new CatalogBuilderConfiguration(); CatalogConfigurationBean bean = mosaicConfiguration.getCatalogConfigurationBean(); catalogConfig.setParameter(Prop.LOCATION_ATTRIBUTE, (bean.getLocationAttribute())); catalogConfig.setParameter(Prop.ABSOLUTE_PATH, Boolean.toString(bean.isAbsolutePath())); catalogConfig.setParameter(Prop.ROOT_MOSAIC_DIR/* setRootMosaicDirectory( */, getRunConfiguration().getParameter(Prop.ROOT_MOSAIC_DIR)); // We already have a Configuration for this coverage. // Check its properties are compatible with the existing coverage. CatalogConfigurationBean catalogConfigurationBean = bean; if (!catalogConfigurationBean.isHeterogeneous()) { // There is no need to check resolutions if the mosaic // has been already marked as heterogeneous numberOfLevels = coverageReader.getNumOverviews(inputCoverageName) + 1; boolean needUpdate = false; // // Heterogeneousity check // if (numberOfLevels != mosaicConfiguration.getLevelsNum()) { catalogConfigurationBean.setHeterogeneous(true); if (numberOfLevels > mosaicConfiguration.getLevelsNum()) { resolutionLevels = coverageReader.getResolutionLevels(inputCoverageName); mosaicConfiguration.setLevels(resolutionLevels); mosaicConfiguration.setLevelsNum(numberOfLevels); needUpdate = true; } } else { final double[][] mosaicLevels = mosaicConfiguration.getLevels(); resolutionLevels = coverageReader.getResolutionLevels(inputCoverageName); final boolean homogeneousLevels = Utils.homogeneousCheck(numberOfLevels, resolutionLevels, mosaicLevels); if (!homogeneousLevels) { catalogConfigurationBean.setHeterogeneous(true); needUpdate = true; } } // configuration need to be updated if (needUpdate) { getConfigurations().put(mosaicConfiguration.getName(), mosaicConfiguration); } } ImageLayout layout = coverageReader.getImageLayout(inputCoverageName); cm = layout.getColorModel(null); sm = layout.getSampleModel(null); // comparing ColorModel // comparing SampeModel // comparing CRSs ColorModel actualCM = cm; CoordinateReferenceSystem expectedCRS; if (mosaicConfiguration.getCrs() != null) { expectedCRS = mosaicConfiguration.getCrs(); } else { expectedCRS = rasterManager.spatialDomainManager.coverageCRS; } if (!(CRS.equalsIgnoreMetadata(expectedCRS, actualCRS))) { // if ((fileIndex > 0 ? !(CRS.equalsIgnoreMetadata(defaultCRS, actualCRS)) : false)) { eventHandler.fireFileEvent(Level.INFO, fileBeingProcessed, false, "Skipping image " + fileBeingProcessed + " because CRSs do not match.", (((fileIndex + 1) * 99.0) / numFiles)); return; } byte[][] palette = mosaicConfiguration.getPalette(); ColorModel colorModel = mosaicConfiguration.getColorModel(); if (colorModel == null) { palette = rasterManager.getConfiguration().getPalette(); colorModel = rasterManager.defaultCM; } if (Utils.checkColorModels(colorModel, palette, mosaicConfiguration, actualCM)) { // if (checkColorModels(defaultCM, defaultPalette, actualCM)) { eventHandler.fireFileEvent(Level.INFO, fileBeingProcessed, false, "Skipping image " + fileBeingProcessed + " because color models do not match.", (((fileIndex + 1) * 99.0) / numFiles)); return; } } // STEP 3 if (!useExistingSchema) { // create and store features CatalogManager.updateCatalog(coverageName, fileBeingProcessed, coverageReader, getParentReader(), catalogConfig, envelope, transaction, getPropertiesCollectors()); } } public void dispose() { reset(); } public Map<String, MosaicConfigurationBean> getConfigurations() { return configurations; } public GranuleCatalog getCatalog() { return catalog; } public CatalogBuilderConfiguration getRunConfiguration() { return runConfiguration; } public ImageMosaicReader getParentReader() { return parentReader; } public void setParentReader(ImageMosaicReader parentReader) { this.parentReader = parentReader; } public List<PropertiesCollector> getPropertiesCollectors() { return propertiesCollectors; } public boolean isUseExistingSchema() { return useExistingSchema; } }