C# uses strings for files everywhere. We need to be able to distinguish between strings and files, however. Therefore, we created this class. TODO This may be replacable by, e.g., an URI or URL class that is already present. Or, we could add whether files are local or remote.
Exemplo n.º 1
0
 public static IOResult<FileLocation> ExportPoiService(PoiService data, IExporter<PoiService, string> exporter, FileLocation destination = null, bool includeGuid = false)
 {
     if (destination == null)
     {
         destination = GetOutputFileLocation(data, exporter.DataFormatExtension, includeGuid);                
     }
     return ConvertFile(null, data, exporter, destination, includeGuid);
 }
Exemplo n.º 2
0
 /// <summary>
 /// Derive default description from the file name.
 /// </summary>
 /// <param name="file">The file.</param>
 /// <returns></returns>
 private string GetDefaultDescription(FileLocation file)
 {
     string descr = Path.GetFileNameWithoutExtension(file.LocationString);
     if (descr == null)
     {
         descr = "Layer";
     }
     if (descr.StartsWith("~"))
     {
         descr = descr.Substring(1);
     }
     return StripGuid.Strip(descr, '.', ' ');
 }
Exemplo n.º 3
0
        public static IOResult<FileLocation> ConvertFile(FileLocation source, IExporter<PoiService, FileLocation> exporter, FileLocation destination = null)
        {
            // Import.
            IOResult<PoiService> import = PoiServiceImporters.Instance.Import(source);
            if (import == null)
            {
                return new IOResult<FileLocation>(new Exception("Cannot read file '" + source + "'."));
            }
            if (!import.Successful)
            {
                return new IOResult<FileLocation>(import.Exception);
            }

            // Export.
            return exporter.ExportData(import.Result, destination);
        }
Exemplo n.º 4
0
        public static IOResult<FileLocation> ConvertFile(FileLocation source, IExporter<PoiService, string> exporter, FileLocation destination = null, bool includeGuid = false)
        {
            // Import the file.
            IOResult<PoiService> data = PoiServiceImporters.Instance.Import(source);
            if (data == null)
            {
                return new IOResult<FileLocation>(new Exception("Cannot read file '" + source + "'.")); 
            }
            if (!data.Successful)
            {
                return new IOResult<FileLocation>(data.Exception);
            }

            // Export the file.
            PoiService poiService = data.Result;
            return ConvertFile(source, poiService, exporter, destination, includeGuid);
        }
Exemplo n.º 5
0
        public static void Merge(PoiService mainDataService, string mainKey, PoiService secondaryDataService,
            string secKey,
            bool includeSecondaryPois,
            bool excludeNonExistentSecondaryPois,
            bool includeSecondaryColumns,
            bool overwriteDuplicateLabels, bool stopOnFirstHit, bool includeMetaData, FileLocation destination = null,
            TextBox txtMergeDebugOutput = null) {
            if (txtMergeDebugOutput != null)
                txtMergeDebugOutput.Text = "Merging files on [" + mainKey + " = " + secKey + "]";

            // Determine whether to use well-known text.
            var mainPoiType = mainDataService.PoITypes.FirstOrDefault();
            if (mainPoiType == null) {
                mainPoiType                = new PoI {
                    Name                   = "Default",
                    ContentId              = "Default",
                    Service                = mainDataService,
                    Style                  = new PoIStyle {
                        Name               = "default",
                        FillColor          = Colors.Transparent,
                        StrokeColor        = Color.FromArgb(255, 128, 128, 128),
                        CallOutOrientation = CallOutOrientation.Right,
                        FillOpacity        = 0.3,
                        TitleMode          = TitleModes.Bottom,
                        NameLabel          = "Name",
                        DrawingMode        = DrawingModes.Image,
                        StrokeWidth        = 2,
                        IconWidth          = 24,
                        IconHeight         = 24,
                        Icon               = "images/missing.png",
                        CallOutFillColor   = Colors.White,
                        CallOutForeground  = Colors.Black,
                        TapMode            = TapMode.CallOut
                    },
                    Id                     = Guid.NewGuid(),
                    DrawingMode            = DrawingModes.Image,
                    MetaInfo               = new List<MetaInfo>()
                };
                mainDataService.PoITypes.Add(mainPoiType);
            }

            if (mainPoiType != null && string.IsNullOrEmpty(mainPoiType.ContentId)) mainPoiType.ContentId = "Default";
            BaseContent secondaryPoiType = null;
            if (secondaryDataService.PoITypes != null && secondaryDataService.PoITypes.Any()) {
                secondaryPoiType = secondaryDataService.PoITypes.FirstOrDefault();
            }
            ;
            bool useWKT = mainPoiType != null && mainPoiType.Style != null && mainPoiType.Style.Name == "WKT";
            useWKT = (useWKT || secondaryPoiType != null && secondaryPoiType.Style != null) &&
                     secondaryPoiType.Style.Name == "WKT" && includeSecondaryColumns;
            if (useWKT) {
                if (mainPoiType != null) {
                    mainPoiType.ContentId = "WKT"; // We directly set the main PoI's "PoiId" to WKT.                    
                }
                mainDataService.StaticService = true; // Make sure we save the file as static.
                if (txtMergeDebugOutput != null)
                    txtMergeDebugOutput.AppendText(
                        "\nOne of the files uses well-known text; the output will be a static layer.");
            }

            // Merge the meta info. 
            if (txtMergeDebugOutput != null) txtMergeDebugOutput.AppendText("\nMerging meta info.");
            if (secondaryPoiType != null && secondaryPoiType.MetaInfo.Count == 0) {
                //if (txtMergeDebugOutput != null) txtMergeDebugOutput.AppendText("\nSecondary file has no meta info; nothing to merge.");
            }
            if (secondaryPoiType != null && includeSecondaryColumns)
                foreach (MetaInfo secMetaInfo in secondaryPoiType.MetaInfo) {
                    string secMetaInfoLabel = secMetaInfo.Label;
                    bool doAdd = true;
                    if (secMetaInfoLabel == secKey) {
                        //if (txtMergeDebugOutput != null) txtMergeDebugOutput.AppendText("\nLabel " + secMetaInfo.Label + " is the one we merge on, so we skip it.");
                        doAdd = false;
                    }
                    if (doAdd) {
                        if (mainPoiType != null) {
                            if (mainPoiType.MetaInfo.Any(mainMetaInfo => mainMetaInfo.Label == secMetaInfoLabel)) {
                                doAdd = false; // label already there.
                            }
                        }
                    }
                    if (!doAdd) continue;
                    if (mainPoiType != null)
                        mainPoiType.MetaInfo.Add(secMetaInfo);
                    //if (txtMergeDebugOutput != null) txtMergeDebugOutput.AppendText("\nInserted meta-info from secondary file into main file: " + secMetaInfo.Label + ".");
                }

            // Merge the Style info. If the right file has WKT, set the drawing mode to MultiPolygon.
            // TODO For now we completely ignore some important aspects of poitypes:
            // 1. Multiple PoITypes.
            // 2. Different PoiId attributes.
            if (txtMergeDebugOutput != null) txtMergeDebugOutput.AppendText("\nMerging styles.");
            if ((secondaryPoiType != null && secondaryPoiType.Style != null && (mainPoiType.Style == null))) {
                // We need to overwrite, or the main does not have something yet.                
                mainPoiType.Style = secondaryPoiType.Style;
                //if (txtMergeDebugOutput != null) txtMergeDebugOutput.AppendText("\nInserted style from secondary file into main file.");
            }
            else {
                //if (txtMergeDebugOutput != null) txtMergeDebugOutput.AppendText("\nMain file already has a style definition.");
            }
            if (useWKT) {
                mainPoiType.Style.DrawingMode = DrawingModes.MultiPolygon;
//                if (txtMergeDebugOutput != null) txtMergeDebugOutput.AppendText(
//                    "\nEnsuring main file uses drawing mode 'multi polygon' given the fact that well-known text is used.");
            }

            // Remember which PoIs were found in the main as well as secondary file.
            HashSet<BaseContent> unvisitedMainPois = new HashSet<BaseContent>();
            foreach (var poI in mainDataService.PoIs) {
                unvisitedMainPois.Add(poI);
            }

            // Merge data.
            if (txtMergeDebugOutput != null) txtMergeDebugOutput.AppendText("\n\nMerging data.");
            foreach (var secPoi in secondaryDataService.PoIs) {
                if (!secPoi.Labels.ContainsKey(secKey)) {
//                    if (txtMergeDebugOutput != null) txtMergeDebugOutput.AppendText("\n" + secPoi.Id + " does not have label " + secKey +
//                                                   " and will be skipped.");
                    continue;
                }
                var mainPoiFound = false;
                //var mainPoi = mainDataService.PoIs.FirstOrDefault(p => p.Labels.ContainsKey(mainKey) 
                //    && string.Equals(p.Labels[mainKey], secPoi.Labels[secKey], StringComparison.InvariantCultureIgnoreCase));
                foreach (var mainPoi in mainDataService.PoIs.Where(mainPoi =>
                    mainPoi.Labels.ContainsKey(mainKey)
                    &&
                    string.Equals(mainPoi.Labels[mainKey], secPoi.Labels[secKey],
                        StringComparison.InvariantCultureIgnoreCase)))
                    if (mainPoi != null) {
                        mainPoiFound = true;
                        if (mainPoi.PoiType == null) {
                            mainPoi.PoiType = mainPoiType;
                            mainPoi.ContentId = mainPoiType.ContentId;
                        }
                        unvisitedMainPois.Remove(mainPoi); // We visited this PoI! :)

                        if (!includeSecondaryColumns)
                            continue; // Do not copy information from the secondary to the first.
                        //if (txtMergeDebugOutput != null) txtMergeDebugOutput.AppendText("\nAdding new data to " + mainPoi.Labels[mainKey] + ".");
                        //GetShortFriendlyName(mainPoi.Name) + "." + mainKey + " = " + GetShortFriendlyName(secPoi.Name) + "." + secKey + "] = " + );

                        // Merge the labels part.
                        if (overwriteDuplicateLabels) {
                            //if (txtMergeDebugOutput != null) txtMergeDebugOutput.AppendText("\nCopying label/values with overwrite: ");
                            foreach (var label in secPoi.Labels) {
                                if (label.Key != secKey) {
                                    //if (txtMergeDebugOutput != null) txtMergeDebugOutput.AppendText("\n->" + label.Key + "=" + label.Value + ", ");
                                    mainPoi.Labels[label.Key] = label.Value;
                                }
                            }
                        }
                        else {
                            //if (txtMergeDebugOutput != null) txtMergeDebugOutput.AppendText("\nCopying label/values without overwrite: ");
                            foreach (var label in secPoi.Labels.Where(l => l.Key != secKey)) {
                                string value;
                                if (mainPoi.Labels.TryGetValue(label.Key, out value)) {
                                    //if (txtMergeDebugOutput != null) txtMergeDebugOutput.AppendText("\n->" + label.Key + " skipped (value already set to " + value + "), ");
                                    continue;
                                }
                                //if (label.Key == secKey)
                                //{
                                //    //if (txtMergeDebugOutput != null) txtMergeDebugOutput.AppendText("\n->" + label.Key + " is the label on which we merge; skipped (value " + mainPoi.Labels[mainKey] + "), ");
                                //    continue;
                                //}
                                //if (txtMergeDebugOutput != null) txtMergeDebugOutput.AppendText("\n->Setting " + label.Key + " to " + label.Value);
                                mainPoi.Labels[label.Key] = label.Value;
                            }
                        }

                        // Also merge WKT information there may be.
                        if (useWKT) {
                            mainPoi.PoiTypeId = "WKT";
                        }
                        if (!string.IsNullOrWhiteSpace(secPoi.WktText)) {
                            if (overwriteDuplicateLabels || string.IsNullOrWhiteSpace(mainPoi.WktText)) {
                                //if (txtMergeDebugOutput != null) txtMergeDebugOutput.AppendText("\nAlso merged well-known text elements.");
                                mainPoi.WktText = secPoi.WktText;
                            }
                        }

                        // Stop if needed.
                        if (!stopOnFirstHit) continue;
                        if (txtMergeDebugOutput != null) txtMergeDebugOutput.AppendText("\nStopping on first hit!");
                        break;

                        // And that's it.
                        //if (txtMergeDebugOutput != null) txtMergeDebugOutput.AppendText("\n");
                    }

                if (mainPoiFound) continue;
                if (includeSecondaryPois) {
                    var copyPoI = new PoI();
                    copyPoI.FromXml(secPoi.ToXml());
                    if (useWKT) {
                        copyPoI.PoiTypeId = "WKT";
                    }
                    else {
                        copyPoI.PoiType = mainPoiType;
                        copyPoI.PoiTypeId = mainPoiType.PoiId;
                    }
                    copyPoI.Labels[mainKey] = copyPoI.Labels[secKey]; // Rename the merge label.
                    copyPoI.Labels.Remove(secKey);
                    mainDataService.PoIs.Add(copyPoI);
                    if (txtMergeDebugOutput != null)
                        txtMergeDebugOutput.AppendText("\nMain file does not have PoI with label " + mainKey +
                                                       " set to " + secPoi.Labels[secKey] +
                                                       ", including PoI from secondary file.");
                }
                else {
                    if (txtMergeDebugOutput != null)
                        txtMergeDebugOutput.AppendText("\nMain file does not have PoI with label " + mainKey +
                                                       " set to " + secPoi.Labels[secKey] +
                                                       " and will be skipped.");
                }
            }

            // Report on unvisited PoIs in main file.
            // Remove any PoIs in the main file that are not in the secondary file (if the user selected this option).
            if (txtMergeDebugOutput != null) {
                if (unvisitedMainPois.Any()) {
                    if (txtMergeDebugOutput != null)
                        txtMergeDebugOutput.AppendText(
                            "\nSome PoIs in the main file were not matched with a PoI in the secondary file.");
                    if (excludeNonExistentSecondaryPois && txtMergeDebugOutput != null)
                        txtMergeDebugOutput.AppendText(" These PoIs will be removed from the main file.");
                }
                foreach (BaseContent unvisitedMainPoi in unvisitedMainPois) {
                    if (txtMergeDebugOutput != null) {
                        string unvisitedMainPoiValue;
                        bool found = unvisitedMainPoi.Labels.TryGetValue(mainKey, out unvisitedMainPoiValue);
                        if (!found) {
                            unvisitedMainPoiValue = "UNDEFINED";
                        }
                        txtMergeDebugOutput.AppendText("\n" + unvisitedMainPoi + ", " + mainKey + " = " +
                                                       unvisitedMainPoiValue + ".");
                    }
                }
                if (excludeNonExistentSecondaryPois) {
                    // Annoyingly, calling "remove" on a ContentList throws an exception.
                    // Therefore, we construct a new list of PoIs that should be kept, instead of removing the PoIs we should remove.
                    ContentList newMainPoIs = new ContentList();
                    foreach (BaseContent poI in mainDataService.PoIs.Where(poI => !unvisitedMainPois.Contains(poI))) {
                        newMainPoIs.Add(poI);
                    }
                    mainDataService.PoIs = newMainPoIs;
                }
            }

            // We are done.
            if (txtMergeDebugOutput != null) txtMergeDebugOutput.AppendText("\nMerge completed!");

            if (destination == null) {
                mainDataService.SaveXml();
            }
            else {
                PoiServiceExporters.Instance.Export(mainDataService, destination, includeMetaData);
            }
        }
Exemplo n.º 6
0
 /// <summary>
 /// Construct the object based on a file. Automatically derives a default description.
 /// </summary>
 /// <param name="file">The file. Note that this file is not accessed in any way.</param>
 public LayerFileDescription(FileLocation file)
 {
     _file = file;
     _description = GetDefaultDescription(file);
 }
Exemplo n.º 7
0
        private static IOResult<FileLocation> ConvertFile(FileLocation source, PoiService poiService, IExporter<PoiService, string> exporter, FileLocation destination, bool includeGuid)
        {
            // Load content if necessary and possible.
            if (! poiService.PoIs.Any() && ! poiService.ContentLoaded)
            {
                if (source == null)
                {
                    throw new Exception("Cannot save a PoI service to a file when it is not fully loaded!");                    
                }
                try
                {
                    DataServiceIO.LoadPoiServiceData(poiService, source);
                }
                catch (Exception e) // Will throw exception if we read from any source but a DS.                    
                {
                    return new IOResult<FileLocation>(e);
                }
            }

            // Export the data.
            IOResult<string> ioResult = exporter.ExportData(poiService, null); // No template for string export.
            if (! ioResult.Successful)
            {
                return new IOResult<FileLocation>(ioResult.Exception);
            }

            // Save the file.
            if (destination == null)
            {
                destination = GetOutputFileLocation(source, poiService, exporter.DataFormatExtension, includeGuid);
            }
            string exportString = ioResult.Result;
            using (var outputFileWriter = new StreamWriter(destination.LocationString)) // Encoding.UTF8 is default.
            {
                outputFileWriter.AutoFlush = true;
                outputFileWriter.Write(exportString);
            }

            // Save the header file (temporary functionality). TODO Make a setting in a global settings container (see GeoJsonIO for another setting that needs this).
            string headerFileString = Path.ChangeExtension(destination.LocationString, "headers");
            using (var outputFileWriter = new StreamWriter(headerFileString))
            {
                foreach (var poIType in poiService.PoITypes)
                {
                    outputFileWriter.WriteLine(poIType.PoiId);
                    MetaInfoCollection metaInfos = poIType.MetaInfo;
                    if (metaInfos == null) continue;
                    bool first = true;
                    foreach (var metaInfo in metaInfos)
                    {
                        if (!first)
                        {
                            outputFileWriter.Write(";");
                        }
                        outputFileWriter.Write(metaInfo.Label);
                        first = false;
                    }
                    outputFileWriter.Write("\n");
                }
            }

            return new IOResult<FileLocation>(new FileLocation(destination.LocationString));
        }
Exemplo n.º 8
0
 public static FileLocation GetOutputFileLocation(FileLocation file, PoiService poiService, string extension, bool includeGuid)
 {
     string directory = Path.GetDirectoryName(file.LocationString) ?? "";
     string filenameNoExt = Path.GetFileNameWithoutExtension(file.LocationString);
     filenameNoExt = StripGuid.Strip(filenameNoExt, '.');
     if (filenameNoExt.Length == 0)
     {
         filenameNoExt = "Unnamed";
     }
     if (includeGuid)
     {
         filenameNoExt = StripGuid.Strip(filenameNoExt, '.');
         filenameNoExt = Guid.NewGuid().ToString() + '.' + filenameNoExt;
         if (poiService.StaticService)
         {
             filenameNoExt = '~' + filenameNoExt;
         }
     }
     else
     {
         filenameNoExt = filenameNoExt + "_export";
     }
     string outputFile = Path.Combine(directory, filenameNoExt + "." + extension);
     return new FileLocation(outputFile);
 }
Exemplo n.º 9
0
        public static IOResult<PoiService> BrowseAndOpenFile(out FileLocation file, Window owner = null, IEnumerable<string> excludedExtensions = null)
        {
            file = BrowseFile(owner, excludedExtensions);
            if (file == null)
            {
                return null;
            }

            string selectedExtension = Path.GetExtension(file.LocationString);
            IImporter<FileLocation, PoiService> selectedImporter = PoiServiceImporters.Instance.GetImporter(selectedExtension);
            if (selectedImporter == null)
            {
                return null;
            }
            IOResult<PoiService> importData = selectedImporter.ImportData(file);
            if (importData.Successful)
            {
                if (!importData.Result.ContentLoaded && selectedImporter is DataServiceIO)
                {
                    // This only works with a DS file, which should be the only file format that needs this. TODO Quite ugly hack though.
                    try
                    {
                        DataServiceIO.LoadPoiServiceData(importData.Result, file);
                    }
                    catch (Exception e)
                    {
                        return new IOResult<PoiService>(new Exception("Cannot load PoI Service data.", e));
                    } 
                }
            }
            return importData;
        }