コード例 #1
0
ファイル: Folder.cs プロジェクト: hxhlb/wwt-tile-sdk
        /// <summary>
        /// Initializes a new instance of the Folder class.
        /// </summary>
        /// <param name="name">Folder name</param>
        /// <param name="parent">Parent folder</param>
        internal Folder(string name, Folder parent)
        {
            Name = name;
            Parent = parent;
            Children = new Collection<Folder>();
            Links = new Collection<Place>();
            Tours = new Collection<Tour>();

            // Only for community root folder, parent will be null.
            if (parent == null)
            {
                Group = "Explorer";
                Searchable = "True";
                FolderType = "Earth";
                RootFolder = this;
            }
            else
            {
                parent.Children.Add(this);
                RootFolder = Parent.RootFolder;
            }
        }
コード例 #2
0
        /// <summary>
        /// Loops through all the items and adds them in to the payload xml. And also recursively loops through all the folders and do the same.
        /// </summary>
        /// <param name="currentDirectory">Current folder getting processed</param>
        /// <param name="folder">Current folder object</param>
        private void ProcessFolderItems(DirectoryInfo currentDirectory, Folder folder)
        {
            bool containOnlySingleWTMLFile = true;

            // Get all the directories excluding hidden, system and reparse point directories.
            List<DirectoryInfo> directories = currentDirectory.GetDirectories().Where(
                    e => !e.Attributes.HasFlag(FileAttributes.Hidden) & !e.Attributes.HasFlag(FileAttributes.System) & !e.Attributes.HasFlag(FileAttributes.ReparsePoint)).ToList();
            foreach (DirectoryInfo childDirectory in directories)
            {
                // 1. If any pyramid/plate/DEM plate folders are present, ignore them since they will be used only by WTML.
                // 2. In the root community folder, if any folder with name "All Tours" or "Latest", ignore them also.
                if ((childDirectory.Name.Equals(Constants.PyramidFolder, StringComparison.OrdinalIgnoreCase) ||
                        childDirectory.Name.Equals(Constants.PlatesFolder, StringComparison.OrdinalIgnoreCase) ||
                        childDirectory.Name.Equals(Constants.DEMPlatesFolder, StringComparison.OrdinalIgnoreCase)) ||
                        (this.CommunityLocation.Equals(currentDirectory.Parent.FullName, StringComparison.OrdinalIgnoreCase) &&
                        (childDirectory.Name.Equals(Constants.AllToursFolder, StringComparison.OrdinalIgnoreCase) ||
                        childDirectory.Name.Equals(Constants.LatestFolder, StringComparison.OrdinalIgnoreCase))))
                {
                    continue;
                }

                // If any folders are there (other than pyramid), don't consider as a folder which contains only single WTML file.
                containOnlySingleWTMLFile = false;

                Folder child = new Folder(childDirectory.Name, folder);

                // Process the folders/files present inside the child folder. This will be recursive.
                ProcessFolderItems(childDirectory, child);
            }

            ProcessFiles(currentDirectory, folder, containOnlySingleWTMLFile);
        }
コード例 #3
0
        /// <summary>
        /// Process all the files in the current folder and adds them to the appropriate folder object.
        /// </summary>
        /// <param name="currentDirectory">Current folder being processed</param>
        /// <param name="folder">Folder object representing current folder</param>
        /// <param name="containOnlySingleWTMLFile">Current directory contains only a single WTML file</param>
        private void ProcessFiles(DirectoryInfo currentDirectory, Folder folder, bool containOnlySingleWTMLFile)
        {
            int wtmlFileCount = 0;

            // Ignore system and hidden files.
            List<FileInfo> files = currentDirectory.GetFiles().Where(e => !e.Attributes.HasFlag(FileAttributes.Hidden) & !e.Attributes.HasFlag(FileAttributes.System)).ToList();
            foreach (FileInfo file in files)
            {
                // Ignore thumbnail files, description files and plate files.
                if ((Path.GetFileNameWithoutExtension(file.Name).Equals("Thumbnail", StringComparison.OrdinalIgnoreCase) && file.IsImageFile()) ||
                        file.Extension.Equals(Constants.PlateFileExtension, StringComparison.OrdinalIgnoreCase) ||
                        file.Name.Equals(Constants.DescriptionFileName, StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }

                // For local WTML files (WTML not served by SharingService), thumbnail file will have the same name as WTML file. Need
                // to find such image files (images and WTML files with same name) and ignore them also.
                if (file.IsImageFile())
                {
                    string searchPattern = string.Format(CultureInfo.InvariantCulture, Constants.WTMLFile, Path.GetFileNameWithoutExtension(file.Name));
                    FileInfo[] wtmlFile = currentDirectory.GetFiles(searchPattern);
                    if (wtmlFile.Length > 0)
                    {
                        continue;
                    }
                }

                // Get the file Id, i.e. relative path by removing the community folder location.
                string fileId = file.FullName.Replace(this.CommunityLocation, string.Empty).TrimStartSlashes();

                if (file.Extension.Equals(Constants.WTMLExtension, StringComparison.OrdinalIgnoreCase))
                {
                    // Processing WTML files (.wtml) here.

                    // Get number of WTML files in current folder. If there is only one WTML file along with its Pyramid, plate and
                    // thumbnail files in a folder, then the folder containing the WTML file will not be shown in WWT.
                    wtmlFileCount++;

                    // For WTML files, replace the URLs if they are having local URLs, leave them as it is if they are http or https.
                    XmlDocument wtmlFileDoc = new XmlDocument();
                    wtmlFileDoc.Load(file.FullName);
                    ReplaceLocalUrlWithRelative(wtmlFileDoc, currentDirectory.FullName);
                    string innerText = string.Empty;
                    bool latestFile = file.IsLatestFile(this.CommunityServiceLatestFileDays);

                    // In case if there is only one item inside a WTML file, then the root node/document element which
                    // displays a folder for the WTML will be ignored. In case if there are more then one items in a WTML file,
                    // then the folder will be displayed which will be grouping the items in WWT.
                    if (wtmlFileDoc.DocumentElement.ChildNodes.Count == 1)
                    {
                        if (latestFile)
                        {
                            // Adding the ModifiedDate attribute to the FirstChild element which will be added as children of Latest folder.
                            // This is needed for sorting the WTML collection in Latest folder.
                            XmlAttribute modifiedDateAttrib = wtmlFileDoc.CreateAttribute(Constants.ModifiedDateAttribute);
                            modifiedDateAttrib.Value = XmlConvert.ToString(file.GetModifiedDate(), XmlDateTimeSerializationMode.Utc);
                            wtmlFileDoc.DocumentElement.FirstChild.Attributes.Append(modifiedDateAttrib);
                        }

                        innerText = wtmlFileDoc.DocumentElement.InnerXml;
                    }
                    else
                    {
                        if (latestFile)
                        {
                            // Adding the ModifiedDate attribute to the Document element which will be added as children of Latest folder.
                            // This is needed for sorting the WTML collection in Latest folder.
                            XmlAttribute modifiedDateAttrib = wtmlFileDoc.CreateAttribute(Constants.ModifiedDateAttribute);
                            modifiedDateAttrib.Value = XmlConvert.ToString(file.GetModifiedDate(), XmlDateTimeSerializationMode.Utc);
                            wtmlFileDoc.DocumentElement.Attributes.Append(modifiedDateAttrib);
                        }

                        innerText = wtmlFileDoc.DocumentElement.OuterXml;
                    }

                    folder.InnerText += innerText;
                    if (latestFile)
                    {
                        // Add the WTML inner text to the "Latest" folder which is the second children of RootFolder only if the file is modified with
                        // the specified date in the configuration file.
                        folder.RootFolder.Children[1].InnerText += innerText;
                    }

                    if (wtmlFileCount > 1)
                    {
                        containOnlySingleWTMLFile = false;
                    }
                }
                else if (file.Extension.Equals(Constants.TourExtension, StringComparison.OrdinalIgnoreCase))
                {
                    // Processing Tour files (.wtt) here.

                    // If any files other than WTML files, don't consider as a folder which contains only WTML file.
                    containOnlySingleWTMLFile = false;

                    // For tour files, get the properties needed for constructing the Tour tag from WTT file itself.
                    XmlDocument tourFile = ParseTourFile(file);

                    if (tourFile != null)
                    {
                        // Creating the tour object by extracting the required properties from Tour XML file.
                        Tour tour = new Tour(
                                tourFile.GetAttributeValue("Tour", "Title"),
                                tourFile.GetAttributeValue("Tour", "ID"),
                                fileId,
                                tourFile.GetAttributeValue("Tour", "ThumbnailUrl"));

                        tour.Description = tourFile.GetAttributeValue("Tour", "Descirption");
                        tour.Author = tourFile.GetAttributeValue("Tour", "Author");
                        tour.OrganizationUrl = tourFile.GetAttributeValue("Tour", "OrganizationUrl");
                        tour.OrganizationName = tourFile.GetAttributeValue("Tour", "OrganizationName");
                        tour.AuthorImageUrl = tourFile.GetAttributeValue("Tour", "AuthorImageUrl");
                        tour.ModifiedDate = file.GetModifiedDate();

                        tour.Parent = folder;

                        // Add the tour to the "Latest" folder which is the second children of RootFolder only if the file is modified with
                        // the specified date in the configuration file.
                        if (file.IsLatestFile(this.CommunityServiceLatestFileDays))
                        {
                            Tour existingTour = folder.RootFolder.Children[1].Tours.FirstOrDefault(e => e.ID == tour.ID);

                            // Make sure the same Tour is not added already which could be there in some other folder.
                            // If the tour already exists, replace the current tour if it is the latest one.
                            if (existingTour == null)
                            {
                                folder.RootFolder.Children[1].Tours.Add(tour);
                            }
                            else if (tour.ModifiedDate > existingTour.ModifiedDate)
                            {
                                folder.RootFolder.Children[1].Tours.Remove(existingTour);
                                folder.RootFolder.Children[1].Tours.Add(tour);
                            }
                        }
                    }
                }
                else if (file.Extension.Equals(Constants.TextExtension, StringComparison.OrdinalIgnoreCase) &&
                        file.Name.StartsWith("Link", StringComparison.OrdinalIgnoreCase))
                {
                    // Processing external link files (Link*.txt) here.

                    // If any files other than WTML files, don't consider as a folder which contains only WTML file.
                    containOnlySingleWTMLFile = false;

                    // For link files (Link*.txt), read the links from the file content.
                    ParseLinkFile(folder, file);
                }
                else
                {
                    // Processing all other local files here.

                    // If any files other than WTML files, don't consider as a folder which contains only WTML file.
                    containOnlySingleWTMLFile = false;

                    // Add links for all other files.
                    Place place = new Place(file.Name, fileId, string.Empty);
                    place.IsLocal = true;
                    place.Parent = folder;
                    place.ModifiedDate = file.GetModifiedDate();

                    // Add the Place to the "Latest" folder which is the second children of RootFolder only if the file is modified with
                    // the specified date in the configuration file.
                    if (file.IsLatestFile(this.CommunityServiceLatestFileDays))
                    {
                        Place existingPlace = folder.RootFolder.Children[1].Links.FirstOrDefault(e => (e.Name == place.Name && e.Thumbnail == place.Thumbnail));

                        // Make sure the same Link is not added already which could be there in some other folder. Links will be
                        // identified same based on their name and thumbnail.
                        // If the Link already exists, replace the current Link if it is the latest one.
                        if (existingPlace == null)
                        {
                            folder.RootFolder.Children[1].Links.Add(place);
                        }
                        else if (place.ModifiedDate > existingPlace.ModifiedDate)
                        {
                            folder.RootFolder.Children[1].Links.Remove(existingPlace);
                            folder.RootFolder.Children[1].Links.Add(place);
                        }
                    }
                }
            }

            if (containOnlySingleWTMLFile && currentDirectory.GetFiles().Length > 0)
            {
                // If only WTML files are there in the current directory, remove folder which contains the WTML file and
                // add the WTML file to its parent. If current folder is community folder (parent will be null), don't do this.
                if (folder.Parent != null)
                {
                    folder.Parent.InnerText += folder.InnerText;
                    folder.Parent.Children.Remove(folder);
                }
            }
        }
コード例 #4
0
        /// <summary>
        /// Parses link file and adds Place objects to folder object for the links present inside the text file.
        /// </summary>
        /// <param name="folder">Folder to which the link belongs to</param>
        /// <param name="file">Link file object</param>
        private void ParseLinkFile(Folder folder, FileInfo file)
        {
            try
            {
                FileStream fileStream = null;

                try
                {
                    fileStream = file.OpenRead();
                    using (StreamReader streamReader = new StreamReader(fileStream))
                    {
                        string lineText = string.Empty;
                        while (null != (lineText = streamReader.ReadLine()))
                        {
                            // Link file is tab delimited. Its format is Name\tUrl\tThumbnail. Thumbnail is optional.
                            string[] urlParts = lineText.Split(new char[] { '\t' }, StringSplitOptions.RemoveEmptyEntries);

                            if (urlParts.Length == 2)
                            {
                                AddPlaceElementToFolder(
                                        urlParts[0],
                                        urlParts[1],
                                        string.Empty,
                                        file.IsLatestFile(this.CommunityServiceLatestFileDays),
                                        folder,
                                        file.GetModifiedDate());
                            }
                            else if (urlParts.Length == 3)
                            {
                                AddPlaceElementToFolder(
                                        urlParts[0],
                                        urlParts[1],
                                        urlParts[3],
                                        file.IsLatestFile(this.CommunityServiceLatestFileDays),
                                        folder,
                                        file.GetModifiedDate());
                            }
                        }
                    }
                }
                finally
                {
                    if (fileStream != null)
                    {
                        fileStream.Dispose();
                    }
                }
            }
            catch (XmlException ex)
            {
                // Consume any Xml Exception.
                ErrorHandler.LogException(ex);
            }
            catch (IOException ex)
            {
                // Consume any IO Exception.
                ErrorHandler.LogException(ex);
            }
        }
コード例 #5
0
        /// <summary>
        /// Saves the payload Folder in to Cache.
        /// </summary>
        /// <param name="payloadFilePath">Payload file path for the community</param>
        /// <param name="folder">Root folder object which needs to cached</param>
        /// <returns>True if saved to cache, false otherwise</returns>
        private static bool SavePayloadToCache(string payloadFilePath, Folder folder)
        {
            bool savedToCache = false;

            try
            {
                if (folder != null)
                {
                    using (FileStream fileStream = new FileStream(payloadFilePath, FileMode.Create, FileAccess.Write))
                    {
                        // IsLocal property of the Place object needs to be serialized so that while
                        // De-serialized and processed for URL rewriting, IsLocal property can be used.
                        XmlAttributeOverrides overrides = new XmlAttributeOverrides();
                        XmlAttributes attributes = new XmlAttributes();
                        attributes.XmlIgnore = false;
                        overrides.Add(typeof(Place), "IsLocal", attributes);

                        XmlTextWriter xmlTextWriter = new XmlTextWriter(fileStream, ASCIIEncoding.Unicode);
                        XmlSerializer xmlSerializer = new XmlSerializer(typeof(Folder), overrides);
                        xmlSerializer.Serialize(xmlTextWriter, folder);
                        savedToCache = true;
                    }
                }
            }
            catch (IOException ex)
            {
                ErrorHandler.LogException(ex);
            }
            catch (UnauthorizedAccessException ex)
            {
                ErrorHandler.LogException(ex);
            }

            return savedToCache;
        }
コード例 #6
0
        /// <summary>
        /// Adds the place object to the folder with the given name, URL, thumbnail. If the link file is latest, then 
        /// Place will be added the "Latest" folder also.
        /// </summary>
        /// <param name="name">Name of the link</param>
        /// <param name="url">Url for the link</param>
        /// <param name="thumbnail">Thumbnail image of the link</param>
        /// <param name="latestFile">Is the link file latest?</param>
        /// <param name="folder">Folder to which the link belongs to</param>
        /// <param name="modifiedDate">Links file modified date</param>
        private static void AddPlaceElementToFolder(string name, string url, string thumbnail, bool latestFile, Folder folder, DateTime modifiedDate)
        {
            Place place = new Place(name, url, thumbnail);
            place.Parent = folder;
            place.ModifiedDate = modifiedDate;

            // Add the Place to the "Latest" folder which is the second children of RootFolder only if the file is modified with
            // the specified date in the configuration file.
            if (latestFile)
            {
                Place existingPlace = folder.RootFolder.Children[1].Links.FirstOrDefault(e => (e.Name == place.Name && e.Thumbnail == place.Thumbnail));

                // Make sure the same Link is not added already which could be there in some other folder. Links will be
                // identified same based on their name and thumbnail.
                // If the Link already exists, replace the current Link if it is the latest one.
                if (existingPlace == null)
                {
                    folder.RootFolder.Children[1].Links.Add(place);
                }
                else if (place.ModifiedDate > existingPlace.ModifiedDate)
                {
                    folder.RootFolder.Children[1].Links.Remove(existingPlace);
                    folder.RootFolder.Children[1].Links.Add(place);
                }
            }
        }
コード例 #7
0
        public Folder GetPayloadDetails(string communityId)
        {
            Folder rootFolder = null;

            try
            {
                string communityFolder = Path.Combine(this.CommunityLocation, communityId);
                string payloadFilePath = string.Format(CultureInfo.CurrentCulture, "{0}\\{1}_payload.xml", communityFolder, communityId);
                DirectoryInfo dirInfo = new DirectoryInfo(communityFolder);

                // Delete if any payload files are pending to be deleted, because cache dependency could not delete last time.
                for (int i = communityFolderCacheDependency.FilesToBeDeleted.Count - 1; i >= 0; i--)
                {
                    try
                    {
                        string filePath = communityFolderCacheDependency.FilesToBeDeleted[i];
                        File.Delete(filePath);
                        communityFolderCacheDependency.FilesToBeDeleted.Remove(filePath);
                    }
                    catch (IOException ex)
                    {
                        ErrorHandler.LogException(ex);
                    }
                }

                if (File.Exists(payloadFilePath))
                {
                    try
                    {
                        using (Stream stream = File.OpenRead(payloadFilePath))
                        {
                            // IsLocal property of the Place object needs to be serialized so that while
                            // De-serialized and processed for URL rewriting, IsLocal property can be used.
                            XmlAttributeOverrides overrides = new XmlAttributeOverrides();
                            XmlAttributes attributes = new XmlAttributes();
                            attributes.XmlIgnore = false;
                            overrides.Add(typeof(Place), "IsLocal", attributes);

                            XmlSerializer serializer = new XmlSerializer(typeof(Folder), overrides);
                            XmlReader reader = new XmlTextReader(stream);
                            rootFolder = (Folder)serializer.Deserialize(reader);
                        }
                    }
                    catch (IOException ex)
                    {
                        ErrorHandler.LogException(ex);
                    }
                }
                else
                {
                    // Get thumbnail relative file path, if any image file with name Thumbnail exists.
                    string thumbnailFile = dirInfo.GetThumbnailFilePath(this.CommunityLocation);

                    // Creating the root community folder object.
                    rootFolder = new Folder(dirInfo.Name, null);
                    rootFolder.Thumbnail = thumbnailFile;

                    // By default, two folder with name "All Tours" and "Latest" will be added to all communities.
                    // "All Tours" will be having all the tours which are present in the community anywhere in the folder structure.
                    // "Latest" will be having all the tours, WTMLs and Places/Links which are modified in last n days and present
                    // in the community anywhere in the folder structure.
                    Folder allToursFolder = new Folder(Constants.AllToursFolder, rootFolder);
                    Folder latestFolder = new Folder(Constants.LatestFolder, rootFolder);

                    // Loop through all the folder contents recursively.
                    ProcessFolderItems(dirInfo, rootFolder);

                    // This will make sure that there are not events fired while creating/overwriting the payload XML file.
                    communityFolderCacheDependency.CommunityFolderWatcher.EnableRaisingEvents = false;

                    SavePayloadToCache(payloadFilePath, rootFolder);
                }
            }
            catch (DirectoryNotFoundException ex)
            {
                ErrorHandler.LogException(ex);
                throw new FaultException(ex.Message);
            }
            catch (SecurityException ex)
            {
                ErrorHandler.LogException(ex);
                throw new FaultException(ex.Message);
            }
            catch (UnauthorizedAccessException ex)
            {
                ErrorHandler.LogException(ex);
                throw new FaultException(ex.Message);
            }
            catch (ArgumentException ex)
            {
                ErrorHandler.LogException(ex);
                throw new FaultException(ex.Message);
            }
            catch (IOException ex)
            {
                ErrorHandler.LogException(ex);
                throw new FaultException(ex.Message);
            }
            finally
            {
                // If the community folder watcher is not enabled for events, enable them.
                if (!communityFolderCacheDependency.CommunityFolderWatcher.EnableRaisingEvents)
                {
                    communityFolderCacheDependency.CommunityFolderWatcher.EnableRaisingEvents = true;
                }
            }

            return rootFolder;
        }