| | |
| | | import it.geosolutions.geoserver.rest.GeoServerRESTManager; |
| | | import it.geosolutions.geoserver.rest.GeoServerRESTPublisher; |
| | | import it.geosolutions.geoserver.rest.GeoServerRESTReader; |
| | | import it.geosolutions.geoserver.rest.decoder.RESTDataStore; |
| | | import it.geosolutions.geoserver.rest.decoder.RESTLayerList; |
| | | import it.geosolutions.geoserver.rest.decoder.RESTStyleList; |
| | | import it.geosolutions.geoserver.rest.decoder.*; |
| | | import it.geosolutions.geoserver.rest.decoder.utils.NameLinkElem; |
| | | import it.geosolutions.geoserver.rest.encoder.GSLayerEncoder; |
| | | import it.geosolutions.geoserver.rest.encoder.GSLayerGroupEncoder; |
| | | import it.geosolutions.geoserver.rest.encoder.GSResourceEncoder; |
| | | import it.geosolutions.geoserver.rest.encoder.datastore.GSPostGISDatastoreEncoder; |
| | | import it.geosolutions.geoserver.rest.encoder.feature.GSFeatureTypeEncoder; |
| | |
| | | import org.apache.commons.logging.Log; |
| | | import org.apache.commons.logging.LogFactory; |
| | | import org.geotools.data.Transaction; |
| | | import org.geotools.data.jdbc.JDBCUtils; |
| | | import org.geotools.geometry.GeneralEnvelope; |
| | | import org.opengis.feature.type.FeatureType; |
| | | import org.opengis.feature.type.GeometryDescriptor; |
| | | import org.quartz.JobDataMap; |
| | |
| | | import org.xml.sax.SAXException; |
| | | |
| | | import java.io.IOException; |
| | | import java.net.MalformedURLException; |
| | | import java.net.URI; |
| | | import java.net.URISyntaxException; |
| | | import java.net.URL; |
| | |
| | | */ |
| | | private void resetPostgisViewMapping(JobExecutionContext executionContext) { |
| | | assert executionContext != null; |
| | | Connection connection = null; |
| | | try { |
| | | Connection connection = targetDataStore.getConnection(Transaction.AUTO_COMMIT); |
| | | connection = targetDataStore.getConnection(Transaction.AUTO_COMMIT); |
| | | String ownerName = _pgUsername; |
| | | String currentTargetSchema = retrieveCurrentSchemaName(connection, |
| | | DataReposVersionManager.VSSTATUS_READY); |
| | |
| | | } catch (SQLException e) { |
| | | logger.warn(e.getMessage(), e); |
| | | } finally { |
| | | if (connection != null) |
| | | JDBCUtils.close(connection, Transaction.AUTO_COMMIT, null); |
| | | // if (dataStore != null) dataStore.dispose(); |
| | | } |
| | | } |
| | |
| | | return result; |
| | | } |
| | | |
| | | private void resetFeatureTypesMapping(JobExecutionContext executionContext, GeoServerRESTReader reader) { |
| | | private String buildDefaultWMSLayerNames(String namespace, List xgeosConfigs, GSLayerGroupEncoder lgEncoder) { |
| | | StringBuilder sbLayers = new StringBuilder(); |
| | | boolean first = true; |
| | | |
| | | for (Object value : xgeosConfigs) { |
| | | if (!first) { |
| | | sbLayers.append(','); |
| | | } else { |
| | | first = false; |
| | | } |
| | | XGeosDataConfig xgeosConfig = (XGeosDataConfig) value; |
| | | |
| | | StringBuilder sbFullName = new StringBuilder(namespace); |
| | | sbFullName.append(':'); |
| | | |
| | | StringBuilder sbLayerName = new StringBuilder(namespace); |
| | | sbLayerName.append("fsc-"); |
| | | sbLayerName.append(xgeosConfig.getFSC()).append("-c"); |
| | | sbLayerName.append(xgeosConfig.getCOMP()).append("-l"); |
| | | sbLayerName.append(xgeosConfig.getLEV()).append("-w"); |
| | | sbLayerName.append(xgeosConfig.getWEIGHT()); |
| | | String layerName = sbLayerName.toString(); |
| | | if (lgEncoder != null) { |
| | | lgEncoder.addLayer(layerName); |
| | | } |
| | | sbFullName.append(layerName); |
| | | sbLayers.append(sbFullName.toString()); |
| | | } |
| | | |
| | | return sbLayers.toString(); |
| | | } |
| | | |
| | | protected String[] getTargetStoreTypeNames(Connection connection) { |
| | | try { |
| | | final int TABLE_NAME_COL = 3; |
| | | List list = new ArrayList(); |
| | | |
| | | DatabaseMetaData meta = connection.getMetaData(); |
| | | // String[] tableType = { "TABLE", "VIEW" }; |
| | | String[] tableType = { "VIEW" }; |
| | | ResultSet tables = meta.getTables(null, _pgSchema, "%", tableType); |
| | | |
| | | while (tables.next()) { |
| | | String tableName = tables.getString(TABLE_NAME_COL); |
| | | list.add(tableName); |
| | | /* |
| | | if (allowTable(tableName)) { |
| | | list.add(tableName); |
| | | } |
| | | */ |
| | | } |
| | | tables.close(); |
| | | return (String[]) list.toArray(new String[list.size()]); |
| | | } catch (SQLException e) { |
| | | logger.warn(e.getMessage(), e); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | private void resetFeatureTypesMapping(JobExecutionContext executionContext, GeoServerRESTManager manager) { |
| | | try { |
| | | GeoServerRESTReader reader = manager.getReader(); |
| | | GeoServerRESTPublisher publisher = manager.getPublisher(); |
| | | |
| | | Connection connection = targetDataStore.getConnection(Transaction.AUTO_COMMIT); |
| | | if (!checkCurrentRepositoryStatus(connection, DataReposVersionManager.VSSTATUS_LINKVIEW)) { |
| | | if (!checkCurrentRepositoryStatus(connection, DataReposVersionManager.VSSTATUS_CONFIG)) { |
| | | return; |
| | | } |
| | | |
| | | Set<String> styles = new TreeSet<String>(); |
| | | RESTStyleList styleList = reader.getStyles(); |
| | | |
| | | for (NameLinkElem style : styleList) { |
| | | styles.add(style.getName()); |
| | | } |
| | | RESTLayerList layers = reader.getLayers(); |
| | | for (NameLinkElem layer : layers) { |
| | | layer.getName(); |
| | | } |
| | | // Map styles = dataConfig.getStyles(); |
| | | |
| | | XGeosDataConfigMapping mapping = getConfigMapping(); |
| | | HashMap<String, String> defaultStyles = buildDefaultStylesMapping(mapping); |
| | | |
| | | try { |
| | | /* |
| | | String[] dsFTypeNames = dataStore.getTypeNames(); |
| | | String[] dsFTypeNames = getTargetStoreTypeNames(connection); |
| | | |
| | | for (String featureTypeName : dsFTypeNames) { |
| | | String ftKey = dsConf.getId() + DataConfig.SEPARATOR + featureTypeName; |
| | | FeatureTypeConfig ftConfig = dataConfig.getFeatureTypeConfig(ftKey); |
| | | if (ftConfig == null) { |
| | | if (!createFeatureTypeConfig(dataConfig, dsConf, dataStore, styles, featureTypeName, defaultStyles)) { |
| | | LOGGER.info("Create Feature Failed. [" + featureTypeName + "]"); |
| | | FeatureType featureType = null; |
| | | try { |
| | | featureType = targetDataStore.getFeatureSource(featureTypeName, Transaction.AUTO_COMMIT).getSchema(); |
| | | } catch (IOException e) { |
| | | logger.warn(e.getMessage(), e); |
| | | } |
| | | } else { |
| | | updateFeatureTypeConfig(ftConfig, dataStore, styles, defaultStyles); |
| | | if (featureType == null) continue; |
| | | |
| | | RESTLayer layer = reader.getLayer(DEFAULT_NAMESPACE, featureTypeName); |
| | | if (layer != null) { |
| | | // publisher.removeLayer(DEFAULT_NAMESPACE, featureTypeName); |
| | | if (!publisher.unpublishFeatureType(DEFAULT_NAMESPACE, DEFAULT_STORENAME, featureTypeName)) { |
| | | logger.info("Cannot remove featureType:" + featureTypeName); |
| | | } |
| | | } |
| | | */ |
| | | |
| | | final GSFeatureTypeEncoder fte = new GSFeatureTypeEncoder(); |
| | | |
| | | // fte.setProjectionPolicy(GSResourceEncoder.ProjectionPolicy.REPROJECT_TO_DECLARED); |
| | | fte.setProjectionPolicy(GSResourceEncoder.ProjectionPolicy.FORCE_DECLARED); |
| | | fte.addKeyword("KEYWORD"); |
| | | fte.setTitle(featureTypeName); |
| | | fte.setName(featureTypeName); |
| | | String srs = "EPSG:" + SRSID_TWD97_ZONE121; |
| | | if (!this._useZone121) { |
| | | srs = "EPSG:" + SRSID_TWD97_ZONE119; |
| | | } |
| | | fte.setNativeCRS(srs); |
| | | fte.setSRS(srs); // srs=null?"EPSG:4326":srs); |
| | | |
| | | String defaultStyle = getDefaultFeatureTypeStyleId(styles, defaultStyles, featureType); |
| | | final GSLayerEncoder le = new GSLayerEncoder(); |
| | | le.setDefaultStyle(defaultStyle); |
| | | |
| | | if (!publisher.publishDBLayer(DEFAULT_NAMESPACE, DEFAULT_STORENAME, fte, le)) { |
| | | logger.info("Create Feature Failed. [" + featureTypeName + "]"); |
| | | } |
| | | } |
| | | } finally { |
| | | // if (dataStore != null) dataStore.dispose(); |
| | | if (connection != null) |
| | | JDBCUtils.close(connection, Transaction.AUTO_COMMIT, null); |
| | | |
| | | } |
| | | } catch (IOException e) { |
| | | logger.warn(e.getMessage(), e); |
| | |
| | | } |
| | | |
| | | private void resetGeoServerConfig(JobExecutionContext jobExecutionContext) throws JobExecutionException { |
| | | Connection connection = null; |
| | | try { |
| | | Connection connection = targetDataStore.getConnection(Transaction.AUTO_COMMIT); |
| | | connection = targetDataStore.getConnection(Transaction.AUTO_COMMIT); |
| | | transferXGeosVersionStatus(connection, DataReposVersionManager.VSSTATUS_LINKVIEW, |
| | | DataReposVersionManager.VSSTATUS_CONFIG, false); |
| | | URL geoServerURL = new URL(_geoServerURL); |
| | |
| | | } |
| | | |
| | | |
| | | resetFeatureTypesMapping(jobExecutionContext, reader); |
| | | resetFeatureTypesMapping(jobExecutionContext, manager); |
| | | |
| | | resetGeoserverWMSConfig(jobExecutionContext, connection, manager, true); |
| | | resetWMSVirtualLayerMapping(jobExecutionContext, connection, manager, true); |
| | |
| | | } catch (URISyntaxException e) { |
| | | logger.warn(e.getMessage(), e); |
| | | throw new JobExecutionException("resetGeoServerConfig has error-" + e.getMessage(), e); |
| | | } finally { |
| | | if (connection != null) |
| | | JDBCUtils.close(connection, Transaction.AUTO_COMMIT, null); |
| | | |
| | | } |
| | | } |
| | | |
| | | public boolean publishPostGISLayer(GeoServerRESTPublisher publisher, String workspace, String storename, String layername, String srs, |
| | | String defaultStyle) { |
| | | |
| | | final GSFeatureTypeEncoder fte = new GSFeatureTypeEncoder(); |
| | | |
| | | fte.setProjectionPolicy(GSResourceEncoder.ProjectionPolicy.REPROJECT_TO_DECLARED); |
| | | fte.addKeyword("KEYWORD"); |
| | | fte.setTitle(layername); |
| | | fte.setName(layername); |
| | | fte.setSRS(srs); // srs=null?"EPSG:4326":srs); |
| | | final GSLayerEncoder layerEncoder = new GSLayerEncoder(); |
| | | layerEncoder.setDefaultStyle(defaultStyle); |
| | | return publisher.publishDBLayer(workspace, storename, fte, layerEncoder); |
| | | } |
| | | |
| | | protected String getDefaultFeatureTypeStyleId(Map styles, HashMap<String, String> defaultStyles, FeatureType featureType) { |
| | | protected String getDefaultFeatureTypeStyleId(Set<String> styles, HashMap<String, String> defaultStyles, FeatureType featureType) { |
| | | String ftName = featureType.getName().getLocalPart(); |
| | | boolean isNormalFeature = false; |
| | | boolean isLandBased = false; |
| | |
| | | if (ftName.indexOf("lnd") != -1) { |
| | | isLandBased = true; |
| | | } |
| | | /* |
| | | if (featureType.find("symbol") != -1) { |
| | | if (featureType.getDescriptor("symbol") != null) { |
| | | isSymbol = true; |
| | | } |
| | | */ |
| | | |
| | | if (Point.class.equals(geomType)) { |
| | | if (isSymbol) { |
| | | return retrieveDefaultStyle(styles, "pgTPC_Symbol", "point"); |
| | | return retrieveDefaultStyle(styles, "xtpc-symbol", "point"); |
| | | } else if (isIndex) { |
| | | return retrieveDefaultStyle(styles, "pgTPC_TpclidText", "point"); |
| | | return retrieveDefaultStyle(styles, "xtpc-text2", "point"); |
| | | } else { |
| | | return retrieveDefaultStyle(styles, "pgTPC_Text", "point"); |
| | | return retrieveDefaultStyle(styles, "xtpc-text", "point"); |
| | | } |
| | | } else if (LineString.class.equals(geomType)) { |
| | | if ((!isIndex) && (!isLandBased)) { |
| | | return retrieveDefaultStyle(styles, "pgTPC_Conductor", "line"); |
| | | return retrieveDefaultStyle(styles, "xtpc-conductor", "line"); |
| | | } else if (isIndex) { |
| | | if (isSmallIndex) |
| | | return retrieveDefaultStyle(styles, "pgTPC_INDEXSHAPES", "line"); |
| | | return retrieveDefaultStyle(styles, "xtpc-indexshapes", "line"); |
| | | |
| | | return retrieveDefaultStyle(styles, "pgTPC_INDEXSHAPE", "line"); |
| | | return retrieveDefaultStyle(styles, "xtpc-indexshape", "line"); |
| | | } else if (isLandBased) { |
| | | return retrieveDefaultStyle(styles, "pgTPC_LndcityLine", "line"); |
| | | return retrieveDefaultStyle(styles, "xtpc-lndcityLine", "line"); |
| | | } |
| | | } else if (MultiPoint.class.equals(geomType)) { |
| | | if (isSymbol) { |
| | | return retrieveDefaultStyle(styles, "pgTPC_Symbol", "point"); |
| | | return retrieveDefaultStyle(styles, "xtpc-symbol", "point"); |
| | | } else { |
| | | return retrieveDefaultStyle(styles, "pgTPC_Text", "point"); |
| | | return retrieveDefaultStyle(styles, "xtpc-text", "point"); |
| | | } |
| | | } else if (Polygon.class.equals(geomType)) { |
| | | if ((!isIndex) && (!isLandBased)) { |
| | | if (isSymbol) { |
| | | return retrieveDefaultStyle(styles, "xtpc-symbol", "polygon"); |
| | | } else if ((!isIndex) && (!isLandBased)) { |
| | | return retrieveDefaultStyle(styles, "polygon", "polygon"); |
| | | } else if (isIndex) { |
| | | return retrieveDefaultStyle(styles, "pgTPC_INDEXSHAPE", "polygon"); |
| | | return retrieveDefaultStyle(styles, "xtpc-indexshape", "polygon"); |
| | | } else if (isLandBased) { |
| | | return retrieveDefaultStyle(styles, "pgTPC_LndcityPolygon", "polygon"); |
| | | return retrieveDefaultStyle(styles, "xtpc-lndcityPolygon", "polygon"); |
| | | } |
| | | } else if (LinearRing.class.equals(geomType)) { |
| | | if (!isIndex) { |
| | | return retrieveDefaultStyle(styles, "polygon", "polygon"); |
| | | } else { |
| | | return retrieveDefaultStyle(styles, "pgTPC_INDEXSHAPE", "polygon"); |
| | | return retrieveDefaultStyle(styles, "xtpc-indexshape", "polygon"); |
| | | } |
| | | } else if (MultiLineString.class.equals(geomType)) { |
| | | if ((!isIndex) && (!isLandBased)) { |
| | | return retrieveDefaultStyle(styles, "pgTPC_Conductor", "line"); |
| | | return retrieveDefaultStyle(styles, "xtpc-conductor", "line"); |
| | | } else if (isLandBased) { |
| | | return retrieveDefaultStyle(styles, "pgTPC_LndcityLine", "line"); |
| | | return retrieveDefaultStyle(styles, "xtpc-lndcityLine", "line"); |
| | | } else { |
| | | return retrieveDefaultStyle(styles, "pgTPC_INDEXSHAPE", "line"); |
| | | return retrieveDefaultStyle(styles, "xtpc-indexshape", "line"); |
| | | } |
| | | } else if (MultiPolygon.class.equals(geomType)) { |
| | | return "polygon"; |
| | | } |
| | | |
| | | return "pgTPC_Symbol"; |
| | | return "xtpc-symbol"; |
| | | } |
| | | |
| | | private static String retrieveDefaultStyle(Map styles, String styleName, String defaultStyleName) { |
| | | if (styles.containsKey(styleName)) { |
| | | private static String retrieveDefaultStyle(Set styles, String styleName, String defaultStyleName) { |
| | | if (styles.contains(styleName)) { |
| | | return styleName; |
| | | } else |
| | | return defaultStyleName; |
| | |
| | | } |
| | | |
| | | GeoServerRESTReader reader = manager.getReader(); |
| | | GeoServerRESTPublisher publisher = manager.getPublisher(); |
| | | |
| | | RESTLayerList layers = reader.getLayers(); |
| | | |
| | | ArrayList<String> baseMapNames = new ArrayList<String>(); |
| | |
| | | defaultMapNames.remove(index); |
| | | |
| | | List configs = (List) configMapping.getMapping().get(baseMapTitle); |
| | | String defaultLayerNames = buildDefaultWMSLayerNames(DEFAULTNAMESPACE, configs); |
| | | wmsConfig.getBaseMapLayers().put(baseMapTitle, defaultLayerNames); |
| | | String defaultLayerNames = buildDefaultWMSLayerNames(DEFAULT_NAMESPACE, configs, null); |
| | | // wmsConfig.getBaseMapLayers().put(baseMapTitle, defaultLayerNames); |
| | | logger.info(baseMapTitle + ":" + defaultLayerNames); |
| | | } else { |
| | | logger.warn("lv='" + baseMapTitle + "' cannot found config information in XGeosDataConfigMapping."); |
| | | logger.warn(key.toString() + "-lv='" + baseMapTitle + "' cannot found config information in XGeosDataConfigMapping."); |
| | | } |
| | | } |
| | | |
| | | for (Object key : defaultMapNames) { |
| | | List configs = (List) configMapping.getMapping().get(key); |
| | | String defaultLayerNames = buildDefaultWMSLayerNames(DEFAULTNAMESPACE, configs); |
| | | wmsConfig.getBaseMapLayers().put(key, defaultLayerNames); |
| | | GSLayerGroupEncoder lge = new GSLayerGroupEncoder(); |
| | | String defaultLayerNames = buildDefaultWMSLayerNames(DEFAULT_NAMESPACE, configs, lge); |
| | | logger.info(key + ":" + defaultLayerNames); |
| | | // wmsConfig.getBaseMapLayers().put(key, defaultLayerNames); |
| | | String layerGroupName = key.toString(); |
| | | RESTLayerGroup layerGroup = reader.getLayerGroup(DEFAULT_NAMESPACE, layerGroupName); |
| | | if (layerGroup == null) { |
| | | publisher.createLayerGroup(DEFAULT_NAMESPACE, layerGroupName, lge); |
| | | } else { |
| | | publisher.configureLayerGroup(DEFAULT_NAMESPACE, layerGroupName, lge); |
| | | |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | GeoServerRESTReader reader = manager.getReader(); |
| | | RESTLayerList layers = reader.getLayers(); |
| | | |
| | | Map baseMapLayers = wmsConfig.getBaseMapLayers(); |
| | | Map baseMapEnvelopes = wmsConfig.getBaseMapEnvelopes(); |
| | | ArrayList baseMapNames = new ArrayList(baseMapLayers.keySet()); |
| | | // Map baseMapLayers = wmsConfig.getBaseMapLayers(); |
| | | // Map baseMapEnvelopes = wmsConfig.getBaseMapEnvelopes(); |
| | | ArrayList<String> baseMapNames = new ArrayList<String>(); |
| | | for (NameLinkElem elm : layers) { |
| | | baseMapNames.add(elm.getName()); |
| | | } |
| | | |
| | | for (Object key : baseMapNames) { |
| | | String baseMapTitle = (String) key; |
| | | if (baseMapTitle.startsWith("pg")) { |
| | | GeneralEnvelope envelope = (GeneralEnvelope) baseMapEnvelopes.get(baseMapTitle); |
| | | // GeneralEnvelope envelope = (GeneralEnvelope) baseMapEnvelopes.get(baseMapTitle); |
| | | |
| | | GeneralEnvelope selectedEnvelope = null; |
| | | String baseLayersValue = (String) wmsConfig.getBaseMapLayers().get(baseMapTitle); |
| | | // String baseLayersValue = (String) wmsConfig.getBaseMapLayers().get(baseMapTitle); |
| | | RESTLayerGroup layerGroup = reader.getLayerGroup(DEFAULT_NAMESPACE, baseMapTitle); |
| | | String baseLayersValue = layerGroup.getName(); |
| | | String[] layerNames = null; |
| | | if (baseLayersValue != null) { |
| | | layerNames = baseLayersValue.split(","); |
| | | } else { |
| | | LOGGER.info("vl='" + baseMapTitle + "' is empty value."); |
| | | logger.info("vl='" + baseMapTitle + "' is empty value."); |
| | | continue; |
| | | } |
| | | |
| | | // RESTLayer layer = reader.getLayer(DEFAULT_NAMESPACE, baseMapTitle); |
| | | // layer.Type. |
| | | |
| | | ArrayList<String> newLayerNames = new ArrayList<String>(); |
| | | for (int i = 0; i < layerNames.length; i++) { |
| | | String layerName = layerNames[i].trim(); |
| | | newLayerNames.add(layerName); |
| | | |
| | | /* |
| | | Integer layerType = catalog.getLayerType(layerName); |
| | | if (layerType != null) { |
| | | newLayerNames.add(layerName); |
| | | |
| | | if (layerType.intValue() == MapLayerInfo.TYPE_VECTOR) { |
| | | FeatureTypeInfo ftype = catalog.getFeatureTypeInfo(layerName); |
| | | ftype = ((ftype != null) ? ftype |
| | |
| | | return; |
| | | } |
| | | } catch (IOException e) { |
| | | LOGGER.log(Level.WARNING, e.getMessage(), e); |
| | | logger.warn(e.getMessage(), e); |
| | | return; |
| | | } |
| | | |
| | |
| | | return; |
| | | } |
| | | } catch (TransformException e) { |
| | | LOGGER.log(Level.WARNING, e.getMessage(), e); |
| | | logger.warn(e.getMessage(), e); |
| | | return; |
| | | } catch (FactoryException e) { |
| | | LOGGER.log(Level.WARNING, e.getMessage(), e); |
| | | logger.warn(e.getMessage(), e); |
| | | return; |
| | | } catch (IOException e) { |
| | | LOGGER.log(Level.WARNING, e.getMessage(), e); |
| | | logger.warn(e.getMessage(), e); |
| | | return; |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | } else { |
| | | LOGGER.warning("Cannot found layer " + layerName + " in " + baseMapTitle); |
| | | logger.warn("Cannot found layer " + layerName + " in " + baseMapTitle); |
| | | } |
| | | */ |
| | | } |
| | | |
| | | if (layerNames.length != newLayerNames.size()) { |
| | |
| | | } else bFirst = false; |
| | | layerBuilder.append(newlayerName); |
| | | } |
| | | baseMapLayers.put(baseMapTitle, layerBuilder.toString()); |
| | | // baseMapLayers.put(baseMapTitle, layerBuilder.toString()); |
| | | logger.info(baseMapTitle +":"+ layerBuilder.toString()); |
| | | } |
| | | |
| | | /* |
| | | if (selectedEnvelope != null) { |
| | | if (envelope != null) { |
| | | envelope.setCoordinateReferenceSystem(selectedEnvelope |
| | |
| | | baseMapEnvelopes.put(baseMapTitle, selectedEnvelope); |
| | | } |
| | | } |
| | | */ |
| | | } |
| | | } |
| | | } |