public override ParameterCollection ToDatasourceParameters(CartoDatasource datasource)
    {
      ParameterCollection parameters = new ParameterCollection();

      if (datasource == null)
        return parameters;

      string dsType = datasource.Type.ToLower();
      string paramValue;
      string providerName = null;

      switch (dsType)
      {
        case "shape":
          providerName = "Shape";
          parameters.Add(new Parameter("File", datasource["file"]));

          if (datasource.TryGetValue("indexed", out paramValue))
            parameters.Add(new Parameter("FileBasedIndex", paramValue));
          else
            parameters.Add(new Parameter("FileBasedIndex", "True"));

          if (datasource.TryGetValue("encoding", out paramValue))
            parameters.Add(new Parameter("Encoding", paramValue));
          else
            parameters.Add(new Parameter("Encoding", "UTF-8"));

          if (datasource.TryGetValue("row_limit", out paramValue))
            parameters.Add(new Parameter("RowLimit", paramValue)); // Is not supported
          break;
        case "postgis":
          providerName = "PostGIS";

          string host = "localhost";
          if (datasource.TryGetValue("host", out paramValue))
            host = paramValue;

          string port = "5432";
          if (datasource.TryGetValue("port", out paramValue))
            port = paramValue;

          string dbname = string.Empty;
          if (datasource.TryGetValue("dbname", out paramValue))
            dbname = paramValue;

          string user = string.Empty;
          if (datasource.TryGetValue("user", out paramValue))
            user = paramValue;
          string password = string.Empty;
          if (datasource.TryGetValue("password", out paramValue))
            password = paramValue;

          string connection = string.Format("Host={0};Port={1};Database={2};User ID={3};Password={4};", host, port, dbname, user, password);
          parameters.Add(new Parameter("Connection", connection));

          if (datasource.TryGetValue("extent", out paramValue))
            parameters.Add(new Parameter("Extent", paramValue));

          if (datasource.TryGetValue("table", out paramValue))
          {
            parameters.Add(new Parameter("Table_Origin", paramValue));
            paramValue = PrepareSqlQuery(paramValue);
            parameters.Add(new Parameter("Query", paramValue));
            parameters.Add(new Parameter("Table", GetSqlTableName(paramValue)));
          }

          if (datasource.TryGetValue("geometry_field", out paramValue))
            parameters.Add(new Parameter("GeometryField", paramValue));
          break;
        case "mssqlspatial":
          providerName = "MsSQLSpatial";

          if (datasource.TryGetValue("connection", out paramValue))
            parameters.Add(new Parameter("Connection", paramValue));
          if (datasource.TryGetValue("geometry_field", out paramValue))
            parameters.Add(new Parameter("GeometryField", paramValue));
          if (datasource.TryGetValue("table", out paramValue))
            parameters.Add(new Parameter("Table", paramValue));
          if (datasource.TryGetValue("query", out paramValue))
            parameters.Add(new Parameter("Query", paramValue));
          if (datasource.TryGetValue("spatial_index", out paramValue))
            parameters.Add(new Parameter("SpatialIndex", paramValue));
          if (datasource.TryGetValue("extent", out paramValue))
            parameters.Add(new Parameter("Extent", paramValue));
          break;
        case "spatialite":
          providerName = "SpatiaLite";

          if (datasource.TryGetValue("connection", out paramValue))
            parameters.Add(new Parameter("Connection", paramValue));
          if (datasource.TryGetValue("geometry_field", out paramValue))
            parameters.Add(new Parameter("GeometryField", paramValue));
          if (datasource.TryGetValue("table", out paramValue))
            parameters.Add(new Parameter("Table", paramValue));
          if (datasource.TryGetValue("query", out paramValue))
            parameters.Add(new Parameter("Query", paramValue));
          if (datasource.TryGetValue("extent", out paramValue))
            parameters.Add(new Parameter("Extent", paramValue));
          break;
        case "geojson":
          providerName = "GeoJson";
          parameters.Add(new Parameter("File", datasource["file"]));

          if (datasource.TryGetValue("indexed", out paramValue))
            parameters.Add(new Parameter("FileBasedIndex", paramValue));
          else
            parameters.Add(new Parameter("FileBasedIndex", "False"));

          if (datasource.TryGetValue("encoding", out paramValue))
            parameters.Add(new Parameter("Encoding", paramValue));
          break;
        case "ogr":
          providerName = "OGR";
          parameters.Add(new Parameter("File", datasource["file"]));
          if (datasource.TryGetValue("layer", out paramValue))
            parameters.Add(new Parameter("LayerName", paramValue));
          else
            parameters.Add(new Parameter("LayerIndex", "0"));
          break;
        case "dem":
          providerName = "DEM";
          if (datasource.TryGetValue("path", out paramValue))
            parameters.Add(new Parameter("Path", paramValue));
          if (datasource.TryGetValue("datasource_type", out paramValue))
            parameters.Add(new Parameter("DataSourceType", paramValue));
          if (datasource.TryGetValue("cache_size", out paramValue))
            parameters.Add(new Parameter("CacheSize", paramValue));
          if (datasource.TryGetValue("file_extension", out paramValue))
            parameters.Add(new Parameter("FileExtension", paramValue));
          if (datasource.TryGetValue("data_type", out paramValue))
            parameters.Add(new Parameter("DataType", paramValue));
          if (datasource.TryGetValue("isoline_interval", out paramValue))
            parameters.Add(new Parameter("IsolineInterval", paramValue));
          if (datasource.TryGetValue("min_elevation", out paramValue))
            parameters.Add(new Parameter("MinElevation", paramValue));
          if (datasource.TryGetValue("max_elevation", out paramValue))
            parameters.Add(new Parameter("MaxElevation", paramValue));
          if (datasource.TryGetValue("restore_data", out paramValue))
            parameters.Add(new Parameter("RestoreData", paramValue));
          if (datasource.TryGetValue("resampling_algorithm", out paramValue))
            parameters.Add(new Parameter("ResampleAlgorithm", paramValue));
          if (datasource.TryGetValue("auto_resolution", out paramValue))
            parameters.Add(new Parameter("AutoResolution", paramValue));
          if (datasource.TryGetValue("downsample_resolution", out paramValue))
            parameters.Add(new Parameter("DownsampleResolution", paramValue));
          if (datasource.TryGetValue("cache_id", out paramValue))
            parameters.Add(new Parameter("CacheID", paramValue));
          break;
        case "gdal":
          providerName = "GDAL";
          parameters.Add(new Parameter("File", datasource["file"]));

          if (datasource.ContainsKey("DownsampleResolution"))
            parameters.Add(new Parameter("DownsampleResolution", datasource["DownsampleResolution"]));
          else
            parameters.Add(new Parameter("DownsampleResolution", "True"));

          if (datasource.ContainsKey("ResampleAlgorithm"))
            parameters.Add(new Parameter("ResampleAlgorithm", datasource["ResampleAlgorithm"]));
          else
            parameters.Add(new Parameter("ResampleAlgorithm", "Cubic"));
          break;
        case "osm":
          providerName = "OSM";
          parameters.Add(new Parameter("File", datasource["file"]));

          if (datasource.ContainsKey("query"))
            parameters.Add(new Parameter("Query", datasource["query"]));
          if (datasource.ContainsKey("tags_filter"))
            parameters.Add(new Parameter("TagsFilter", datasource["tags_filter"]));
          if (datasource.ContainsKey("spatial_index"))
            parameters.Add(new Parameter("BuildSpatialIndex", datasource["spatial_index"]));
          if (datasource.ContainsKey("spatial_index_file"))
            parameters.Add(new Parameter("FileBasedIndex", datasource["spatial_index_file"]));
          break;
        case "esrifilegeodb":
          providerName = "EsriFileGeoDB";
          parameters.Add(new Parameter("Path", datasource["path"]));
          if (datasource.TryGetValue("table", out paramValue))
            parameters.Add(new Parameter("Table", paramValue));
          if (datasource.TryGetValue("query", out paramValue))
            parameters.Add(new Parameter("Query", paramValue));
          break;
        case "vectortiles":
          providerName = "VectorTiles";
          if (datasource.TryGetValue("compression", out paramValue))
            parameters.Add(new Parameter("Compression", datasource["compression"]));
          if (datasource.TryGetValue("datasource", out paramValue))
            parameters.Add(new Parameter("Datasource", datasource["datasource"]));
          if (datasource.TryGetValue("extent", out paramValue))
            parameters.Add(new Parameter("Extent", datasource["extent"]));
          if (datasource.TryGetValue("format", out paramValue))
            parameters.Add(new Parameter("Format", datasource["format"]));
          if (datasource.TryGetValue("layers", out paramValue))
            parameters.Add(new Parameter("Layers", datasource["layers"]));
          if (datasource.TryGetValue("littleendian", out paramValue))
            parameters.Add(new Parameter("LittleEndian", datasource["littleendian"]));
          if (datasource.TryGetValue("minzoom", out paramValue))
            parameters.Add(new Parameter("MinZoom", datasource["minzoom"]));
          if (datasource.TryGetValue("maxzoom", out paramValue))
            parameters.Add(new Parameter("MaxZoom", datasource["maxzoom"]));
          if (datasource.TryGetValue("mode", out paramValue))
            parameters.Add(new Parameter("Mode", datasource["mode"]));
          if (datasource.TryGetValue("properties", out paramValue))
            parameters.Add(new Parameter("Properties", datasource["properties"]));
          if (datasource.TryGetValue("threads_number", out paramValue))
            parameters.Add(new Parameter("ThreadsNumber", datasource["threads_number"]));
          if (datasource.TryGetValue("tile_cache", out paramValue))
            parameters.Add(new Parameter("TileCache", datasource["tile_cache"]));
          break;
        default:

          break;
      }

      parameters.Add(new Parameter("Type", providerName));

      return parameters;
    }
    public override CartoDatasource ToDatasource(ParameterCollection parameters)
    {
      CartoDatasource ds = new CartoDatasource();

      if (parameters != null)
      {
        string type = parameters.GetValue("Type");
        string paramValue = null;

        switch (type.ToLower())
        {
          case "shape":
            if (parameters.TryGetValue("File", out paramValue))
            {
              if (paramValue.EndsWith(".shp"))
                ds.Add("type", type.ToLower());
            }
            else
              throw new Exception("'File' parameter is required.");

            ds.Add("file", paramValue);
            if (parameters.TryGetValue("FileBasedIndex", out paramValue))
              ds.Add("indexed", paramValue.ToLower());
            if (parameters.TryGetValue("Encoding", out paramValue))
              ds.Add("encoding", paramValue.ToLower());
            break;
          case "geojson":
            // ds.Add("type", type.ToLower());
            if (parameters.TryGetValue("File", out paramValue))
              ds.Add("file", paramValue);
            else
              throw new Exception("'File' parameter is required.");

            if (parameters.TryGetValue("FileBasedIndex", out paramValue))
              ds.Add("indexed", paramValue.ToLower());
            if (parameters.TryGetValue("Encoding", out paramValue) && !string.Equals(paramValue, "UTF-8", StringComparison.OrdinalIgnoreCase))
              ds.Add("encoding", paramValue.ToLower());
            break;
          case "ogr":
            ds.Add("type", type.ToLower());
            if (parameters.TryGetValue("File", out paramValue))
              ds.Add("file", paramValue);
            else
              throw new Exception("'File' parameter is required.");

            if (ds.TryGetValue("LayerName", out paramValue))
              ds.Add("layer", paramValue);
            break;
          case "postgis":
            ds.Add("type", type.ToLower());

            if (parameters.TryGetValue("Connection", out paramValue) && !string.IsNullOrEmpty(paramValue))
            {
              System.Data.Common.DbConnectionStringBuilder connParams = new System.Data.Common.DbConnectionStringBuilder();
              connParams.ConnectionString = paramValue;
              if (connParams.ContainsKey("Host") && !string.Equals(connParams["Host"], "localhost"))
                ds.Add("host", connParams["Host"]);
              if (connParams.ContainsKey("Port") && !string.Equals(connParams["Port"], "5432"))
                ds.Add("port", connParams["Port"]);
              if (connParams.ContainsKey("Database"))
                ds.Add("dbname", connParams["Database"]);

              if (connParams.ContainsKey("User ID") && !string.IsNullOrEmpty((string)connParams["User ID"]))
                ds.Add("user", connParams["User ID"]);

              if (connParams.ContainsKey("Password") && !string.IsNullOrEmpty((string)connParams["Password"]))
                ds.Add("password", connParams["Password"]);
            }

            if (parameters.TryGetValue("Extent", out paramValue))
              ds.Add("extent", paramValue);

            if (parameters.TryGetValue("Table_Origin", out paramValue))
              ds.Add("table", paramValue);
            if (parameters.TryGetValue("Query", out paramValue))
              ds.Add("table", paramValue);
            else if (parameters.TryGetValue("Table", out paramValue))
              ds.Add("table", paramValue);


            if (parameters.TryGetValue("GeometryField", out paramValue))
              ds.Add("geometry_field", paramValue);
            break;
          case "mssqlspatial":
            ds.Add("type", type.ToLower());

            if (parameters.TryGetValue("Connection", out paramValue))
              ds.Add("connection", paramValue);
            if (parameters.TryGetValue("GeometryField", out paramValue))
              ds.Add("geometry_field", paramValue);
            if (parameters.TryGetValue("Table", out paramValue))
              ds.Add("table", paramValue);
            if (parameters.TryGetValue("Query", out paramValue) && !string.IsNullOrEmpty(paramValue))
              ds.Add("query", paramValue);
            if (parameters.TryGetValue("SpatialIndex", out paramValue) && !string.IsNullOrEmpty(paramValue))
              ds.Add("spatial_index", paramValue);
            if (parameters.TryGetValue("Extent", out paramValue))
              ds.Add("extent", paramValue);
            break;
          case "spatialite":
            ds.Add("type", type.ToLower());

            if (parameters.TryGetValue("Connection", out paramValue))
              ds.Add("connection", paramValue);
            if (parameters.TryGetValue("GeometryField", out paramValue))
              ds.Add("geometry_field", paramValue);
            if (parameters.TryGetValue("Table", out paramValue))
              ds.Add("table", paramValue);
            if (parameters.TryGetValue("Query", out paramValue))
              ds.Add("query", paramValue);
            if (parameters.TryGetValue("Extent", out paramValue))
              ds.Add("extent", paramValue);
            break;
          case "dem":
            ds.Add("type", type.ToLower());

            if (parameters.TryGetValue("Path", out paramValue))
              ds.Add("path", paramValue);
            if (parameters.TryGetValue("DataSourceType", out paramValue))
              ds.Add("datasource_type", paramValue);
            if (parameters.TryGetValue("CacheSize", out paramValue))
              ds.Add("cache_size", paramValue);
            if (parameters.TryGetValue("FileExtension", out paramValue))
              ds.Add("file_extension", paramValue);
            if (parameters.TryGetValue("DataType", out paramValue))
              ds.Add("data_type", paramValue);
            if (parameters.TryGetValue("IsolineInterval", out paramValue))
              ds.Add("isoline_interval", paramValue);
            if (parameters.TryGetValue("MinElevation", out paramValue))
              ds.Add("min_elevation", paramValue);
            if (parameters.TryGetValue("MaxElevation", out paramValue))
              ds.Add("max_elevation", paramValue);
            if (parameters.TryGetValue("RestoreData", out paramValue))
              ds.Add("restore_data", paramValue);
            if (parameters.TryGetValue("ResampleAlgorithm", out paramValue))
              ds.Add("resampling_algorithm", paramValue);
            if (parameters.TryGetValue("AutoResolution", out paramValue))
              ds.Add("auto_resolution", paramValue);
            if (parameters.TryGetValue("DownsampleResolution", out paramValue))
              ds.Add("downsample_resolution", paramValue);
            if (parameters.TryGetValue("CacheID", out paramValue))
              ds.Add("cache_id", paramValue);
            break;
          case "osm":
            ds.Add("type", type.ToLower());
            if (parameters.TryGetValue("File", out paramValue))
              ds.Add("file", paramValue);
            else
              throw new Exception("'File' parameter is required.");

            if (parameters.TryGetValue("Query", out paramValue))
              ds.Add("query", paramValue);
            if (parameters.TryGetValue("TagsFilter", out paramValue))
              ds.Add("tags_filter", paramValue);
            if (parameters.TryGetValue("BuildSpatialIndex", out paramValue) && !string.IsNullOrEmpty(paramValue))
              ds.Add("spatial_index", paramValue.ToLower());
            if (parameters.TryGetValue("FileBasedIndex", out paramValue) && !string.IsNullOrEmpty(paramValue))
              ds.Add("spatial_index_file", paramValue.ToLower());
            break;
          case "esrifilegeodb":
            ds.Add("type", type.ToLower());

            if (parameters.TryGetValue("Path", out paramValue))
              ds.Add("path", paramValue);
            if (parameters.TryGetValue("Table", out paramValue))
              ds.Add("table", paramValue);
            if (parameters.TryGetValue("Query", out paramValue))
              ds.Add("query", paramValue);
            break;
        }
      }

      return ds;
    }