/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2013 - 2016, 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.catalog.index; import java.io.File; import java.util.List; import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.bind.JAXBException; import org.geotools.data.DataUtilities; import org.geotools.gce.imagemosaic.Utils; 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.ParametersType.Parameter; import org.geotools.resources.coverage.CoverageUtilities; import org.geotools.util.Utilities; public class IndexerUtils { public final static String INDEXER_XML = "indexer.xml"; public final static String INDEXER_PROPERTIES = "indexer.properties"; private final static Logger LOGGER = org.geotools.util.logging.Logging .getLogger(IndexerUtils.class.toString()); /** * Build {@link Collectors} element by parsing the specified propertyCollectors, and put them on the specified indexer object. * * @param indexer * @param propertyCollectors */ public static void setPropertyCollectors(Indexer indexer, String propertyCollectors) { final Collectors collectors = Utils.OBJECT_FACTORY.createIndexerCollectors(); indexer.setCollectors(collectors); final List<Collector> collectorList = collectors.getCollector(); propertyCollectors = propertyCollectors.trim(); if (propertyCollectors != null && propertyCollectors.length() > 0) { final String[] propColls = propertyCollectors.split(","); for (String pcDef : propColls) { // parse this def as NAME[CONFIG_FILE](PROPERTY;PROPERTY;....;PROPERTY) final int squareLPos = pcDef.indexOf("["); final int squareRPos = pcDef.indexOf("]"); final int squareRPosLast = pcDef.lastIndexOf("]"); final int roundLPos = pcDef.indexOf("("); final int roundRPos = pcDef.indexOf(")"); final int roundRPosLast = pcDef.lastIndexOf(")"); if (roundRPos != roundRPosLast) { if (LOGGER.isLoggable(Level.INFO)) { LOGGER.info("Skipping unparseable PropertyCollector definition: " + pcDef); } continue; } if (roundLPos == -1 || roundRPos == -1) { if (LOGGER.isLoggable(Level.INFO)) { LOGGER.info("Skipping unparseable PropertyCollector definition: " + pcDef); } continue; } if (roundLPos == 0) { if (LOGGER.isLoggable(Level.INFO)) { LOGGER.info("Skipping unparseable PropertyCollector definition: " + pcDef); } continue; } if (roundRPos != (pcDef.length() - 1)) {// end with ) if (LOGGER.isLoggable(Level.INFO)) { LOGGER.info("Skipping unparseable PropertyCollector definition: " + pcDef); } continue; } // name String spi = null; if (squareLPos != -1) { spi = pcDef.substring(0, squareLPos); } else { spi = pcDef.substring(0, roundLPos); } // config final String config = squareLPos < squareRPos ? pcDef.substring(squareLPos + 1, squareRPos) : ""; String value = null; //only need config if provided, some property collectors don't need it if (config.length() > 0) { final File configFile = new File(getParameter(Utils.Prop.ROOT_MOSAIC_DIR, indexer), config + ".properties"); if (!Utils.checkFileReadable(configFile)) { if (LOGGER.isLoggable(Level.INFO)) { LOGGER.info("Unable to access the file for this PropertyCollector: " + configFile.getAbsolutePath()); } } else { final Properties properties = CoverageUtilities .loadPropertiesFromURL(DataUtilities.fileToURL(configFile)); if (properties.containsKey("regex")) { value = properties.getProperty("regex"); } } } // property names final String propertyNames[] = pcDef.substring(roundLPos + 1, roundRPos).split(","); Collector collector = Utils.OBJECT_FACTORY.createIndexerCollectorsCollector(); collector.setSpi(spi); // only 1 propertyCollector for property collector.setMapped(propertyNames[0]); collector.setValue(value); collectorList.add(collector); } } } /** * Return an indexer {@link Coverage} object from the specified {@link Indexer}, referring to the requested name. * * @param indexer the main {@link Indexer} instance * @param name the name of the {@link Coverage} element to be retrieved. * * @return the {@link Coverage} element for the specified name (if any). */ public static Coverage getCoverage(Indexer indexer, String name) { Coverages coverages = indexer.getCoverages(); if (coverages != null) { List<Coverage> coverageList = coverages.getCoverage(); for (Coverage coverage : coverageList) { String coverageName = coverage.getName(); if (coverageName != null && coverageName.equalsIgnoreCase(name)) { return coverage; } } } return null; } /** * Utility method which does special checks on specific parameters * * @param parameterName * @param parameterValue * @return */ public static String refineParameterValue(String parameterName, String parameterValue) { if (parameterName.equalsIgnoreCase(Utils.Prop.ROOT_MOSAIC_DIR)) { // Special management for Root mosaic dir Utilities.ensureNonNull("parameterValue", parameterValue); String testingDirectory = parameterValue; parameterValue = Utils.checkDirectory(testingDirectory, false); } return parameterValue; } /** * Set the attributes of the specified domain, getting values from the value String In case the value contains a ";" separator, add a different * attribute for each element. * * @param domain * @param values */ public static void setAttributes(DomainType domain, String values) { if (values.contains(";")) { String properties[] = values.split(";"); for (String prop : properties) { addAttribute(domain, prop); } } else { addAttribute(domain, values); } } /** * Add a single attribute to that domain with the specified value * * @param domain * @param attributeValue */ private static void addAttribute(DomainType domain, String attributeValue) { AttributeType attribute = Utils.OBJECT_FACTORY.createAttributeType(); attribute.setAttribute(attributeValue); List<AttributeType> listAttributes = domain.getAttributes(); listAttributes.add(attribute); } /** * Set the parameter having the specified name with the specified value * * @param parameters * @param parameterName * @param parameterValue */ public static void setParam(List<Parameter> parameters, String parameterName, String parameterValue) { Parameter param = null; for (Parameter parameter : parameters) { if (parameter.getName().equalsIgnoreCase(parameterName)) { param = parameter; break; } } if (param == null) { param = Utils.OBJECT_FACTORY.createParametersTypeParameter(); parameters.add(param); } param.setName(parameterName); param.setValue(refineParameterValue(parameterName, parameterValue)); } /** * Get the value of a property name from a properties object and set that value to a parameter with the same name * * @param parameters * @param props * @param propName */ public static void setParam(List<Parameter> parameters, Properties props, String propName) { setParam(parameters, propName, props.getProperty(propName)); } /** * Return the parameter value (as a boolean) of the specified parameter name from the provider indexer * * @param parameterName * @param indexer * @return */ public static boolean getParameterAsBoolean(String parameterName, Indexer indexer) { String value = getParameter(parameterName, indexer); if (value != null) { return Boolean.parseBoolean(value); } return false; } /** * Return the parameter string value of the specified parameter name from the provided parameters element * * @param params * @param parameterName * @return */ public static String getParam(ParametersType params, String parameterName) { List<Parameter> parameters = null; if (params != null) { parameters = params.getParameter(); for (Parameter param : parameters) { if (param.getName().equalsIgnoreCase(parameterName)) { return param.getValue(); } } } return null; } /** * Return the parameter string value of the specified parameter name from the provided indexer * * @param parameterName * @param indexer * @return */ public static String getParameter(String parameterName, Indexer indexer) { final ParametersType params = indexer.getParameters(); return getParam(params, parameterName); } /** * Return the parameter string value of the specified parameter name from the indexer defined in the specified file (if exists). * * @param parameterName * @param indexerFile * @return */ public static String getParameter(String parameterName, File indexerFile) { if (indexerFile != null && indexerFile.exists()) { try { Indexer indexerInstance = Utils.unmarshal(indexerFile); if (indexerInstance != null) { String value = IndexerUtils.getParameter(parameterName, indexerInstance); if (value != null) { return value; } } } catch (JAXBException e) { throw new RuntimeException(e); } } return null; } /** * Parse additional domains * * @param attributes * @param domainList */ public static void parseAdditionalDomains(String attributes, List<DomainType> domainList) { final String[] domainsAttributes = attributes.split(","); for (String domainAttributes : domainsAttributes) { DomainType domain = Utils.OBJECT_FACTORY.createDomainType(); String domainName = domainAttributes.trim(); String domainAttribs = domainName; if (domainAttributes.contains("(") && domainAttributes.contains(")")) { domainName = domainName.substring(0, domainName.indexOf("(")).trim(); domainAttribs = domainAttribs.substring(domainAttribs.indexOf("(")).replace("(", "") .replace(")", ""); } domain.setName(domainName); // TODO: CHECK THAT setAttributes(domain, domainAttribs); domainList.add(domain); } } /** * Get the attributes from the specified domain. The boolean specifies whether we need to add a domain prefix before returning the attributes. * * @param domain * @param domainPrefix * @return */ private static String getAttributesAsString(final DomainType domain, final boolean domainPrefix) { final String currentDomainName = domain.getName(); final List<AttributeType> listAttributes = domain.getAttributes(); if (!listAttributes.isEmpty()) { String attribs = null; if (listAttributes.size() == 1) { attribs = listAttributes.get(0).getAttribute().trim(); } else { // Only support up to 2 attributes (start;end/low;high/...) String attr0 = listAttributes.get(0).getAttribute().trim(); String attr1 = listAttributes.get(1).getAttribute().trim(); attribs = attr0 + ";" + attr1; } if (domainPrefix) { return currentDomainName + "(" + attribs + ")"; } else { return attribs; } } return null; } public static DomainType getDomain(DomainType domain, DomainsType refDomains) { String currentDomainName = domain.getName(); if (currentDomainName == null) { String domainRef = domain.getRef(); if (domainRef != null && refDomains != null) { for (DomainType refDomain : refDomains.getDomain()) { if (refDomain.getName().equalsIgnoreCase(domainRef)) { currentDomainName = domainRef; return refDomain; } } } } return domain; } /** * Look for the specified coverageName inside the provided Indexer and return the attributes of the specified domain. * * @param coverageName * @param domainName * @param indexer * @return * * TODO: Code is going complex. We should use a visitor */ public static String getAttribute(final String coverageName, final String domainName, final Indexer indexer) { if (indexer != null) { final Coverages coverages = indexer.getCoverages(); final DomainsType refDomains = indexer.getDomains(); if (coverages != null) { final List<Coverage> coverageList = coverages.getCoverage(); if (coverageList != null && !coverageList.isEmpty()) { for (Coverage coverage : coverageList) { // Look for the specified coverage name final String currentCoverageName = coverage.getName(); if (currentCoverageName == null || currentCoverageName.equalsIgnoreCase(coverageName)) { final DomainsType domains = coverage.getDomains(); if (domains != null) { final List<DomainType> domainList = domains.getDomain(); if (domainList != null) { // Look for the specified domain if (!domainName.equalsIgnoreCase(Utils.ADDITIONAL_DOMAIN)) { for (DomainType domain : domainList) { DomainType currentDomain = getDomain(domain, refDomains); String currentDomainName = currentDomain.getName(); if (currentDomainName != null && currentDomainName .equalsIgnoreCase(domainName)) { return getAttributesAsString(currentDomain, false); } } } else { StringBuilder additionalDomainAttributes = new StringBuilder(); for (DomainType domain : domainList) { DomainType currentDomain = getDomain(domain, refDomains); String domName = currentDomain.getName(); if (!domName.equalsIgnoreCase(Utils.TIME_DOMAIN) && !domName.equalsIgnoreCase( Utils.ELEVATION_DOMAIN)) { additionalDomainAttributes.append( getAttributesAsString(currentDomain, true)); additionalDomainAttributes.append(","); } } String attribs = additionalDomainAttributes.toString(); if (attribs != null && attribs.length() > 0) { // remove the last "," attribs = attribs.substring(0, attribs.length() - 1); } if (attribs.length() > 0) { return attribs; } return null; } } } } } } } } return null; } /** * Get a {@link SchemaType} element for the specified {@link Coverage}. The {@link Indexer} object will be used in case of an externally * referenced schema. * * @param indexer the main {@link Indexer} instance * @param coverage the {@link Coverage} element with the Schema to be returned. */ public static SchemaType getSchema(Indexer indexer, Coverage coverage) { Utilities.ensureNonNull("coverage", coverage); SchemaType schema = coverage.getSchema(); if (schema != null) { String schemaRef = schema.getRef(); if (schemaRef != null) { schema = getSchemaRef(indexer, schemaRef); if (schema != null) { return schema; } } return schema; } return null; } private static SchemaType getSchemaRef(Indexer indexer, String schemaRef) { Utilities.ensureNonNull("schemaRef", schemaRef); Utilities.ensureNonNull("indexer", indexer); SchemasType schemas = indexer.getSchemas(); if (schemas != null) { List<SchemaType> schemaList = schemas.getSchema(); for (SchemaType schema : schemaList) { final String schemaName = schema.getName(); if (schemaName != null && schemaName.equalsIgnoreCase(schemaRef)) { return schema; } } } return null; } public static Indexer createDefaultIndexer() { final Indexer defaultIndexer = Utils.OBJECT_FACTORY.createIndexer(); final ParametersType parameters = Utils.OBJECT_FACTORY.createParametersType(); final List<Parameter> parameterList = parameters.getParameter(); defaultIndexer.setParameters(parameters); setParam(parameterList, Utils.Prop.LOCATION_ATTRIBUTE, Utils.DEFAULT_LOCATION_ATTRIBUTE); setParam(parameterList, Utils.Prop.WILDCARD, Utils.DEFAULT_WILCARD); setParam(parameterList, Utils.Prop.FOOTPRINT_MANAGEMENT, Boolean.toString(Utils.DEFAULT_FOOTPRINT_MANAGEMENT)); setParam(parameterList, Utils.Prop.ABSOLUTE_PATH, Boolean.toString(Utils.DEFAULT_PATH_BEHAVIOR)); setParam(parameterList, Utils.Prop.RECURSIVE, Boolean.toString(Utils.DEFAULT_RECURSION_BEHAVIOR)); setParam(parameterList, Utils.Prop.INDEX_NAME, Utils.DEFAULT_INDEX_NAME); return defaultIndexer; } public static Indexer initializeIndexer(ParametersType params, File parent) { File indexerFile = new File(parent, INDEXER_XML); Indexer indexer = null; if (Utils.checkFileReadable(indexerFile)) { try { 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, INDEXER_PROPERTIES); if (Utils.checkFileReadable(indexerFile)) { // load it and parse it final Properties props = CoverageUtilities .loadPropertiesFromURL(DataUtilities.fileToURL(indexerFile)); indexer = createIndexer(props, params); } } if (indexer != null) { indexer.setIndexerFile(indexerFile); } return indexer; } /** * Setup default params to the indexer. * * @param params * @param indexer */ private static 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 (getParameter(defaultParameterName, indexer) == null) { setParam(parameterList, defaultParameterName, defaultParameter.getValue()); } } } } } private static 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(Utils.Prop.NAME)) { setParam(parameters, props, Utils.Prop.NAME); coverage.setName(props.getProperty(Utils.Prop.NAME)); } // type name if (props.containsKey(Utils.Prop.TYPENAME)) { setParam(parameters, props, Utils.Prop.TYPENAME); coverage.setName(props.getProperty(Utils.Prop.TYPENAME)); } // absolute if (props.containsKey(Utils.Prop.ABSOLUTE_PATH)) setParam(parameters, props, Utils.Prop.ABSOLUTE_PATH); // recursive if (props.containsKey(Utils.Prop.RECURSIVE)) setParam(parameters, props, Utils.Prop.RECURSIVE); // wildcard if (props.containsKey(Utils.Prop.WILDCARD)) setParam(parameters, props, Utils.Prop.WILDCARD); // granule acceptors string if (props.containsKey(Utils.Prop.GRANULE_ACCEPTORS)) { setParam(parameters, props, Utils.Prop.GRANULE_ACCEPTORS); } if (props.containsKey(Utils.Prop.GEOMETRY_HANDLER)) { setParam(parameters, props, Utils.Prop.GEOMETRY_HANDLER); } if (props.containsKey(Utils.Prop.COVERAGE_NAME_COLLECTOR_SPI)) { IndexerUtils.setParam(parameters, props, Utils.Prop.COVERAGE_NAME_COLLECTOR_SPI); } // schema if (props.containsKey(Utils.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(Utils.Prop.SCHEMA)); schema.setName(getParameter(Utils.Prop.INDEX_NAME, indexer)); } DomainsType domains = coverage.getDomains(); List<DomainType> domainList = null; // time attr if (props.containsKey(Utils.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()); setAttributes(domain, props.getProperty(Utils.Prop.TIME_ATTRIBUTE)); domainList.add(domain); } // elevation attr if (props.containsKey(Utils.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()); setAttributes(domain, props.getProperty(Utils.Prop.ELEVATION_ATTRIBUTE)); domainList.add(domain); } // Additional domain attr if (props.containsKey(Utils.Prop.ADDITIONAL_DOMAIN_ATTRIBUTES)) { if (domains == null) { domains = Utils.OBJECT_FACTORY.createDomainsType(); coverage.setDomains(domains); domainList = domains.getDomain(); } String attributes = props.getProperty(Utils.Prop.ADDITIONAL_DOMAIN_ATTRIBUTES); parseAdditionalDomains(attributes, domainList); } // imposed BBOX if (props.containsKey(Utils.Prop.ENVELOPE2D)) setParam(parameters, props, Utils.Prop.ENVELOPE2D); // imposed Pyramid Layout if (props.containsKey(Utils.Prop.RESOLUTION_LEVELS)) setParam(parameters, props, Utils.Prop.RESOLUTION_LEVELS); // collectors if (props.containsKey(Utils.Prop.PROPERTY_COLLECTORS)) { setPropertyCollectors(indexer, props.getProperty(Utils.Prop.PROPERTY_COLLECTORS)); } if (props.containsKey(Utils.Prop.CACHING)) setParam(parameters, props, Utils.Prop.CACHING); if (props.containsKey(Utils.Prop.ROOT_MOSAIC_DIR)) { // Overriding root mosaic directory setParam(parameters, props, Utils.Prop.ROOT_MOSAIC_DIR); } if (props.containsKey(Utils.Prop.INDEXING_DIRECTORIES)) { setParam(parameters, props, Utils.Prop.INDEXING_DIRECTORIES); } if (props.containsKey(Utils.Prop.AUXILIARY_FILE)) { setParam(parameters, props, Utils.Prop.AUXILIARY_FILE); } if (props.containsKey(Utils.Prop.AUXILIARY_DATASTORE_FILE)) { setParam(parameters, props, Utils.Prop.AUXILIARY_DATASTORE_FILE); } if (props.containsKey(Utils.Prop.CAN_BE_EMPTY)) { setParam(parameters, props, Utils.Prop.CAN_BE_EMPTY); } if (props.containsKey(Utils.Prop.WRAP_STORE)) { setParam(parameters, props, Utils.Prop.WRAP_STORE); } if (props.containsKey(Utils.Prop.USE_EXISTING_SCHEMA)) { setParam(parameters, props, Utils.Prop.USE_EXISTING_SCHEMA); } if (props.containsKey(Utils.Prop.CHECK_AUXILIARY_METADATA)) { setParam(parameters, props, Utils.Prop.CHECK_AUXILIARY_METADATA); } if (props.containsKey(Utils.Prop.GRANULE_COLLECTOR_FACTORY)) { setParam(parameters, props, Utils.Prop.GRANULE_COLLECTOR_FACTORY); } if (props.containsKey(Utils.Prop.HETEROGENEOUS_CRS)) { setParam(parameters, props, Utils.Prop.HETEROGENEOUS_CRS); } if (props.containsKey(Utils.Prop.MOSAIC_CRS)) { setParam(parameters, props, Utils.Prop.MOSAIC_CRS); } return indexer; } /** * Set the given parameter on the given indexer * @param indexer indexer on which to set the param * @param paramName parameter name * @param paramValue parameter value */ public static void setParam(Indexer indexer, String paramName, String paramValue) { setParam(indexer.getParameters().getParameter(), paramName, paramValue); } }