public override void Process(Configuration config)
        {
            var tables = GetTables(config);

            // create a resource resolver that will scan all plugins
            // TODO: we should only scan plugins that are tied to the specified PersistentStore, but there is currently no way to know this
            IResourceResolver resolver = new ResourceResolver(
                CollectionUtils.Map(Platform.PluginManager.Plugins, (PluginInfo pi) => pi.Assembly).ToArray());

            // find all dbi resources
            var rx       = new Regex("dbi.xml$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
            var dbiFiles = resolver.FindResources(rx);

            foreach (var dbiFile in dbiFiles)
            {
                using (var stream = resolver.OpenResource(dbiFile))
                {
                    var xmlDoc = new XmlDocument();
                    xmlDoc.Load(stream);
                    var indexElements = xmlDoc.SelectNodes("indexes/index");
                    if (indexElements == null)
                    {
                        continue;
                    }

                    foreach (XmlElement indexElement in indexElements)
                    {
                        ProcessIndex(indexElement, tables);
                    }
                }
            }
        }
Exemple #2
0
 private static PaletteColorLut CreateFromColorPaletteSopInstanceXml(string resourceName)
 {
     try
     {
         var resourceResolver = new ResourceResolver(Assembly.GetExecutingAssembly());
         using (var xmlStream = resourceResolver.OpenResource(resourceName))
         {
             var xmlDocument = new XmlDocument();
             xmlDocument.Load(xmlStream);
             var docRootNode = CollectionUtils.FirstElement(xmlDocument.GetElementsByTagName("ClearCanvasColorPaletteDefinition")) as XmlElement;
             if (docRootNode != null)
             {
                 var instanceNode = CollectionUtils.FirstElement(docRootNode.GetElementsByTagName("Instance")) as XmlElement;
                 if (instanceNode != null)
                 {
                     var instanceXml = new InstanceXml(instanceNode, null);
                     return(Create(instanceXml.Collection));
                 }
             }
         }
     }
     catch (Exception ex)
     {
         Platform.Log(LogLevel.Debug, ex, "Failed to load embedded standard color palette SOP from resource {0}", resourceName);
     }
     return(null);
 }
Exemple #3
0
        /// <summary>
        /// Translates the default value for a settings class given the raw value.
        /// </summary>
        /// <remarks>
        /// If the specified raw value is the name of an embedded resource (embedded in the same
        /// assembly as the specified settings class), the contents of the resource are returned.
        /// Otherwise, the raw value is simply returned.
        /// </remarks>
        public static string TranslateDefaultValue(Type settingsClass, string rawValue)
        {
            // short circuit if nothing translatable
            if (string.IsNullOrEmpty(rawValue))
            {
                return(rawValue);
            }

            // does the raw value look like it could be an embedded resource?
            if (Regex.IsMatch(rawValue, @"^([\w]+\.)+\w+$"))
            {
                try
                {
                    // try to open the resource
                    IResourceResolver resolver = new ResourceResolver(settingsClass.Assembly);
                    using (Stream resourceStream = resolver.OpenResource(rawValue))
                    {
                        StreamReader r = new StreamReader(resourceStream);
                        return(r.ReadToEnd());
                    }
                }
                catch (MissingManifestResourceException)
                {
                    // guess it was not an embedded resource, so return the raw value
                    return(rawValue);
                }
            }
            else
            {
                return(rawValue);
            }
        }
Exemple #4
0
        private void Initialize(bool reloadSettings)
        {
            lock (_syncLock)
            {
                if (Document != null && !reloadSettings)
                {
                    return;
                }

                AnnotationLayoutStoreSettings.Default.Reload();
                if (Document != null)
                {
                    return;
                }

                try
                {
                    XmlDocument      document = new XmlDocument();
                    ResourceResolver resolver = new ResourceResolver(this.GetType().Assembly);
                    using (Stream stream = resolver.OpenResource("AnnotationLayoutStoreDefaults.xml"))
                    {
                        document.Load(stream);
                        Document = document;
                    }
                }
                catch (Exception e)
                {
                    Platform.Log(LogLevel.Debug, e);
                    Clear();
                }
            }
        }
        public static void CreateDatabase(string fileName)
        {
            var filePath = GetDatabaseFilePath(fileName);

            // ensure the parent directory exists before trying to create database
            Directory.CreateDirectory(GetDatabaseDirectory());

            //NOTE: Since we're using CE 4.0, the LINQ CreateDatabase function won't work because it creates a 3.5 database.
            var resourceResolver = new ResourceResolver(typeof(TContext).Assembly);

            using (Stream resourceStream = resourceResolver.OpenResource(fileName))
            {
                using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    var buffer    = new byte[1024];
                    int bytesRead = resourceStream.Read(buffer, 0, buffer.Length);
                    // write the required bytes
                    while (bytesRead > 0)
                    {
                        fileStream.Write(buffer, 0, bytesRead);
                        bytesRead = resourceStream.Read(buffer, 0, buffer.Length);
                    }

                    fileStream.Close();
                }

                resourceStream.Close();
            }
        }
Exemple #6
0
 private static PaletteColorLut CreateFromColorPaletteSopInstanceXml(string resourceName)
 {
     try
     {
         var resourceResolver = new ResourceResolver(Assembly.GetExecutingAssembly());
         using (var xmlStream = resourceResolver.OpenResource(resourceName))
         {
             //var xmlDocument = new XmlDocument();
             //xmlDocument.Load(xmlStream);
             //var docRootNode = CollectionUtils.FirstElement(xmlDocument.GetElementsByTagName("UIHColorPaletteDefinition")) as XmlElement;
             //if (docRootNode != null)
             //{
             //    var instanceNode = CollectionUtils.FirstElement(docRootNode.GetElementsByTagName("Instance")) as XmlElement;
             //    if (instanceNode != null)
             //    {
             //        var instanceXml = new InstanceXml(instanceNode, null);
             //        return Create(instanceXml.Collection);
             //    }
             //}
         }
     }
     catch (Exception ex)
     {
         LogAdapter.Logger.Error(ex, "erorr load resource {0}", resourceName);
     }
     return(null);
 }
Exemple #7
0
		public TableView()
        {
			SuppressSelectionChangedEvent = false;
			InitializeComponent();

            // if we allow the framework to generate columns, there seems to be a bug with 
            // setting the minimum column width > 100 pixels
            // therefore, turn off the auto-generate and create the columns ourselves
            _dataGridView.AutoGenerateColumns = false;

            _rowHeight = this.DataGridView.RowTemplate.Height;
            this.DataGridView.RowPrePaint += SetCustomBackground;
            this.DataGridView.RowPostPaint += DisplayCellSubRows;
            this.DataGridView.RowPostPaint += OutlineCell;
            this.DataGridView.RowPostPaint += SetLinkColor;

			// System.Component.DesignMode does not work in control constructors
			if (LicenseManager.UsageMode != LicenseUsageMode.Designtime)
			{
				// Use a DelayedEventPublisher to make fixes for bugs 386 and 8032 a little clearer.  Previously used a Timer directly
				// to delay the events
				_delayedSelectionChangedPublisher = new DelayedEventPublisher((sender, args) => NotifySelectionChanged(), 50);
			}

			try
			{
				var resolver = new ResourceResolver(typeof (TableView), false);
				using (var s = resolver.OpenResource("checkmark.png"))
				{
					_checkmarkBitmap = new Bitmap(s);
				}
			}
			catch (Exception) {}
        }
Exemple #8
0
        public static void TestConfigResourceToFile(string fileName)
        {
            ResourceResolver resolver = new ResourceResolver(typeof(SettingsMigrationTests).Assembly);

            using (Stream resourceStream = resolver.OpenResource("TestPreviousConfiguration.config"))
            {
                StreamToFile(resourceStream, fileName);
                resourceStream.Close();
            }
        }
Exemple #9
0
        /// <summary>
        /// Gets the icon for the <see cref="ApplicationTheme"/>.
        /// </summary>
        /// <returns>A new <see cref="Stream"/> for the icon.</returns>
        /// <seealso cref="Icon"/>
        public Stream GetIcon()
        {
            if (string.IsNullOrEmpty(_providers[0].Icon))
            {
                return(null);
            }

            var resourceResolver = new ResourceResolver(_providers[0].GetType(), false);

            return(resourceResolver.OpenResource(_providers[0].Icon));
        }
        public AlertNotificationForm(DesktopForm owner, string title)
        {
            InitializeComponent();

            this.Text  = title;
            this.Owner = owner;

            _maxOpacity = 1.0;
            _minOpacity = 0.3;

            var resolver = new ResourceResolver(typeof(AlertNotificationForm).Assembly);

            using (var s = resolver.OpenResource("close.bmp"))
            {
                _closeButtonBitmap = new Bitmap(s);
            }

            owner.Move   += OwnerFormMoved;
            owner.Resize += OwnerFormResized;
        }
Exemple #11
0
        private EnumerationInfo ReadSoftEnum(Type enumValueClass, Table table)
        {
            // look for an embedded resource that matches the enum class
            string            res      = string.Format("{0}.enum.xml", enumValueClass.FullName);
            IResourceResolver resolver = new ResourceResolver(enumValueClass.Assembly);

            try
            {
                using (Stream xmlStream = resolver.OpenResource(res))
                {
                    XmlDocument xmlDoc = new XmlDocument();
                    xmlDoc.Load(xmlStream);
                    int displayOrder = 1;

                    return(new EnumerationInfo(enumValueClass.FullName, table.Name, false,
                                               CollectionUtils.Map <XmlElement, EnumerationMemberInfo>(xmlDoc.GetElementsByTagName("enum-value"),
                                                                                                       delegate(XmlElement enumValueElement)
                    {
                        XmlElement valueNode = CollectionUtils.FirstElement <XmlElement>(enumValueElement.GetElementsByTagName("value"));
                        XmlElement descNode = CollectionUtils.FirstElement <XmlElement>(enumValueElement.GetElementsByTagName("description"));

                        return new EnumerationMemberInfo(
                            enumValueElement.GetAttribute("code"),
                            valueNode != null ? valueNode.InnerText : null,
                            descNode != null ? descNode.InnerText : null,
                            displayOrder++,
                            false);
                    })));
                }
            }
            catch (Exception)
            {
                // no embedded resource found - no values defined
                return(new EnumerationInfo(enumValueClass.FullName, table.Name, false, new List <EnumerationMemberInfo>()));
            }
        }
        private void AddAssemblyIconToImage(Assembly pluginAssembly)
        {
            object[] pluginAttributes = pluginAssembly.GetCustomAttributes(typeof(PluginAttribute), false);

            foreach (PluginAttribute pluginAttribute in pluginAttributes)
            {
                if (!string.IsNullOrEmpty(pluginAttribute.Icon))
                {
                    try
                    {
                        IResourceResolver resolver = new ResourceResolver(pluginAssembly);
                        Bitmap            icon     = new Bitmap(resolver.OpenResource(pluginAttribute.Icon));

                        // Burn the icon into the background image
                        Graphics g = Graphics.FromImage(this.BackgroundImage);

                        int positionX = _nextIconPositionX;
                        int positionY = _nextIconPositionY;

                        g.DrawImage(icon, positionX, positionY, IconWidth, IconHeight);

                        // Burn the icon's name and version into the background image
                        string pluginName    = pluginAttribute.Name;
                        string pluginVersion = string.Empty;
                        try
                        {
                            FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(pluginAssembly.Location);
                            pluginVersion = versionInfo.ProductVersion;
                        }
                        catch
                        {
                        }

                        Font  font  = new Font("Tahoma", 10F, GraphicsUnit.Pixel);
                        Brush brush = new SolidBrush(Color.FromArgb(50, 50, 50));

                        StringFormat format = new StringFormat();
                        format.Alignment = StringAlignment.Center;

                        Rectangle layoutRect = new Rectangle(positionX - IconPaddingX / 2, positionY + IconHeight, IconWidth + IconPaddingX, IconTextHeight);

                        g.DrawString(pluginName + "\n" + pluginVersion, font, brush, layoutRect, format);

                        font.Dispose();
                        brush.Dispose();

                        g.Dispose();

                        // Advance to the next icon position within the plugin rectangle
                        _nextIconPositionX += (IconWidth + IconPaddingX);
                        if (_nextIconPositionX + IconWidth + IconPaddingX / 2 > _pluginIconsRectangle.Right)
                        {
                            _nextIconPositionX  = _pluginIconsRectangle.Left + IconPaddingX / 2;
                            _nextIconPositionY += IconPaddingY + IconHeight + IconTextHeight;
                        }

                        this.Invalidate();
                    }
                    catch
                    {
                    }
                }
            }
        }
Exemple #13
0
        public void Test()
        {
            List <IAnnotationItem> annotationItems = new List <IAnnotationItem>();

            AnnotationLayoutStore.Instance.Clear();

            IList <StoredAnnotationLayout> layouts = AnnotationLayoutStore.Instance.GetLayouts(annotationItems);

            Assert.AreEqual(0, layouts.Count);

            AnnotationLayoutStore.Instance.Update(this.CreateLayout("testLayout1"));
            layouts = AnnotationLayoutStore.Instance.GetLayouts(annotationItems);
            Assert.AreEqual(1, layouts.Count);

            layouts = new List <StoredAnnotationLayout>();
            layouts.Clear();
            layouts.Add(CreateLayout("testLayout1"));
            layouts.Add(CreateLayout("testLayout2"));
            layouts.Add(CreateLayout("testLayout3"));
            layouts.Add(CreateLayout("testLayout4"));

            AnnotationLayoutStore.Instance.Update(layouts);

            layouts = AnnotationLayoutStore.Instance.GetLayouts(annotationItems);
            Assert.AreEqual(4, layouts.Count);

            ResourceResolver resolver = new ResourceResolver(this.GetType().Assembly);

            using (Stream stream = resolver.OpenResource("AnnotationLayoutStoreDefaults.xml"))
            {
                AnnotationLayoutStoreSettings.Default.LayoutSettingsXml = new XmlDocument();
                AnnotationLayoutStoreSettings.Default.LayoutSettingsXml.Load(stream);
            }

            layouts = AnnotationLayoutStore.Instance.GetLayouts(annotationItems);
            int xmlLayoutCount = layouts.Count;

            StoredAnnotationLayout layout = AnnotationLayoutStore.Instance.GetLayout("Dicom.OT", annotationItems);

            layout = CopyLayout(layout, "Dicom.OT.Copied");

            AnnotationLayoutStore.Instance.Update(layout);
            layouts = AnnotationLayoutStore.Instance.GetLayouts(annotationItems);
            Assert.AreEqual(xmlLayoutCount + 1, layouts.Count);

            layout = AnnotationLayoutStore.Instance.GetLayout("Dicom.OT.Copied", annotationItems);
            Assert.IsNotNull(layout);

            AnnotationLayoutStore.Instance.RemoveLayout("Dicom.OT.Copied");
            layouts = AnnotationLayoutStore.Instance.GetLayouts(annotationItems);
            Assert.AreEqual(xmlLayoutCount, layouts.Count);

            layout = AnnotationLayoutStore.Instance.GetLayout("Dicom.OT.Copied", annotationItems);
            Assert.IsNull(layout);

            layout = AnnotationLayoutStore.Instance.GetLayout("Dicom.OT", annotationItems);
            Assert.IsNotNull(layout);

            layouts = new List <StoredAnnotationLayout>();
            layouts.Clear();
            layouts.Add(CreateLayout("testLayout1"));
            layouts.Add(CreateLayout("testLayout2"));
            layouts.Add(CreateLayout("testLayout3"));
            layouts.Add(CreateLayout("testLayout4"));

            AnnotationLayoutStore.Instance.Update(layouts);

            layouts = AnnotationLayoutStore.Instance.GetLayouts(annotationItems);
            Assert.AreEqual(xmlLayoutCount + 4, layouts.Count);

            AnnotationLayoutStore.Instance.RemoveLayout("testLayout1");
            layouts = AnnotationLayoutStore.Instance.GetLayouts(annotationItems);
            Assert.AreEqual(xmlLayoutCount + 3, layouts.Count);

            AnnotationLayoutStore.Instance.RemoveLayout("testLayout2");
            layouts = AnnotationLayoutStore.Instance.GetLayouts(annotationItems);
            Assert.AreEqual(xmlLayoutCount + 2, layouts.Count);

            layout = AnnotationLayoutStore.Instance.GetLayout("Dicom.OT", annotationItems);
            Assert.IsNotNull(layout);

            layout = AnnotationLayoutStore.Instance.GetLayout("testLayout3", annotationItems);
            Assert.AreEqual(1, layout.AnnotationBoxGroups.Count);

            layout = AnnotationLayoutStore.Instance.GetLayout("Dicom.OT", annotationItems);
            layout = CopyLayout(layout, "testLayout3");
            AnnotationLayoutStore.Instance.Update(layout);
            layout = AnnotationLayoutStore.Instance.GetLayout("testLayout3", annotationItems);
            Assert.AreEqual(5, layout.AnnotationBoxGroups.Count);
        }
Exemple #14
0
        public void Test()
        {
            DicomFilteredAnnotationLayoutStore.Instance.Clear();

            IList <DicomFilteredAnnotationLayout> layouts = DicomFilteredAnnotationLayoutStore.Instance.FilteredLayouts;

            Assert.AreEqual(0, layouts.Count);

            DicomFilteredAnnotationLayoutStore.Instance.Update(CreateLayout("testLayout1", "Dicom.MR", "MR"));
            layouts = DicomFilteredAnnotationLayoutStore.Instance.FilteredLayouts;
            Assert.AreEqual(1, layouts.Count);

            layouts = new List <DicomFilteredAnnotationLayout>();
            layouts.Clear();
            layouts.Add(CreateLayout("testLayout1", "Dicom.MR", "MR"));
            layouts.Add(CreateLayout("testLayout2", "Dicom.MG", "MG"));
            layouts.Add(CreateLayout("testLayout3", "Dicom.CT", "CT"));
            layouts.Add(CreateLayout("testLayout4", "Dicom.PT", "PT"));

            DicomFilteredAnnotationLayoutStore.Instance.Update(layouts);

            layouts = DicomFilteredAnnotationLayoutStore.Instance.FilteredLayouts;
            Assert.AreEqual(4, layouts.Count);

            ResourceResolver resolver = new ResourceResolver(this.GetType().Assembly);

            using (Stream stream = resolver.OpenResource("DicomFilteredAnnotationLayoutStoreDefaults.xml"))
            {
                StreamReader reader = new StreamReader(stream);
                DicomFilteredAnnotationLayoutStoreSettings.Default.FilteredLayoutSettingsXml = reader.ReadToEnd();
            }

            layouts = DicomFilteredAnnotationLayoutStore.Instance.FilteredLayouts;
            Assert.AreEqual(_countLayoutsInDicomFilteredLayoutStoreXml, layouts.Count);

            DicomFilteredAnnotationLayout layout = DicomFilteredAnnotationLayoutStore.Instance.GetFilteredLayout("Dicom.Filtered.MR");

            layout            = CopyLayout(layout, "Dicom.Filtered.RT");
            layout.Filters[0] = new KeyValuePair <string, string>("Modality", "RT");

            DicomFilteredAnnotationLayoutStore.Instance.Update(layout);
            layouts = DicomFilteredAnnotationLayoutStore.Instance.FilteredLayouts;
            Assert.AreEqual(_countLayoutsInDicomFilteredLayoutStoreXml + 1, layouts.Count);

            layout = DicomFilteredAnnotationLayoutStore.Instance.GetFilteredLayout("Dicom.Filtered.RT");
            Assert.IsNotNull(layout);

            DicomFilteredAnnotationLayoutStore.Instance.RemoveFilteredLayout("Dicom.Filtered.RT");
            layouts = DicomFilteredAnnotationLayoutStore.Instance.FilteredLayouts;
            Assert.AreEqual(_countLayoutsInDicomFilteredLayoutStoreXml, layouts.Count);

            layout = DicomFilteredAnnotationLayoutStore.Instance.GetFilteredLayout("Dicom.Filtered.RT");
            Assert.IsNull(layout);

            layout = DicomFilteredAnnotationLayoutStore.Instance.GetFilteredLayout("Dicom.Filtered.MR");
            Assert.IsNotNull(layout);

            layouts = new List <DicomFilteredAnnotationLayout>();
            layouts.Clear();
            layouts.Add(CreateLayout("Dicom.Filtered.RT", "Dicom.RT", "RT"));
            layouts.Add(CreateLayout("Dicom.Filtered.SC", "Dicom.SC", "SC"));
            layouts.Add(CreateLayout("Dicom.Filtered.US", "Dicom.US", "US"));
            layouts.Add(CreateLayout("Dicom.Filtered.ES", "Dicom.ES", "ES"));

            DicomFilteredAnnotationLayoutStore.Instance.Update(layouts);

            layouts = DicomFilteredAnnotationLayoutStore.Instance.FilteredLayouts;
            Assert.AreEqual(_countLayoutsInDicomFilteredLayoutStoreXml + 4, layouts.Count);

            DicomFilteredAnnotationLayoutStore.Instance.RemoveFilteredLayout("Dicom.Filtered.RT");
            layouts = DicomFilteredAnnotationLayoutStore.Instance.FilteredLayouts;
            Assert.AreEqual(_countLayoutsInDicomFilteredLayoutStoreXml + 3, layouts.Count);

            DicomFilteredAnnotationLayoutStore.Instance.RemoveFilteredLayout("Dicom.Filtered.SC");
            layouts = DicomFilteredAnnotationLayoutStore.Instance.FilteredLayouts;
            Assert.AreEqual(_countLayoutsInDicomFilteredLayoutStoreXml + 2, layouts.Count);

            layout = DicomFilteredAnnotationLayoutStore.Instance.GetFilteredLayout("Dicom.Filtered.AllMatch");
            Assert.IsNotNull(layout);
            Assert.AreEqual(0, layout.Filters.Count);

            layout = DicomFilteredAnnotationLayoutStore.Instance.GetFilteredLayout("Dicom.Filtered.MR");
            Assert.AreEqual(1, layout.Filters.Count);
        }
        // [Test]
        internal void ExportDefaultLayoutConfigurationData()
        {
            // this method exports the default layout in EnterpriseServer format

            var configBodyData = new StringBuilder();

            using (var configBodyDataWriter = new StringWriter(configBodyData))
            {
                var configBody = new XmlDocument();
                {
                    var sbValue = new StringBuilder();
                    using (var writer = new StringWriter(sbValue))
                    {
                        var resourceResolver = new ResourceResolver(typeof(AnnotationLayoutStoreTests).Assembly);
                        var defaultLayout    = new XmlDocument();
                        defaultLayout.Load(resourceResolver.OpenResource("AnnotationLayoutStoreDefaults.xml"));
                        defaultLayout.Save(writer);
                    }

                    var cdata = configBody.CreateCDataSection(sbValue.ToString());

                    var value = configBody.CreateElement("value");
                    value.AppendChild(cdata);

                    var setting = configBody.CreateElement("setting");
                    setting.SetAttribute("name", "LayoutSettingsXml");
                    setting.AppendChild(value);

                    var settings = configBody.CreateElement("settings");
                    settings.AppendChild(setting);

                    configBody.AppendChild(settings);
                }
                configBody.Save(configBodyDataWriter);
            }

            var configDocument = new XmlDocument();

            var nameElement = configDocument.CreateElement("Name");

            nameElement.InnerText = typeof(AnnotationLayoutStoreSettings).FullName ?? string.Empty;

            var versionElement = configDocument.CreateElement("Version");

            versionElement.InnerText = string.Format("{0:00000}.{1:00000}", ProductInformation.Version.Major, ProductInformation.Version.Minor);

            var bodyElement = configDocument.CreateElement("Body");

            bodyElement.InnerText = configBodyData.ToString();

            var configItem = configDocument.CreateElement("item");

            configItem.AppendChild(nameElement);
            configItem.AppendChild(versionElement);
            configItem.AppendChild(bodyElement);

            var rootConfigurations = configDocument.CreateElement("Configurations");

            rootConfigurations.SetAttribute("type", "array");
            rootConfigurations.AppendChild(configItem);

            configDocument.AppendChild(rootConfigurations);
            configDocument.Save(string.Format("{0}.xml", typeof(AnnotationLayoutStoreSettings).FullName));
        }
        public void TestDefaultLayout()
        {
            var resourceResolver = new ResourceResolver(typeof(AnnotationLayoutStoreTests).Assembly);

            var xmlDocument = new XmlDocument();

            xmlDocument.Load(resourceResolver.OpenResource("AnnotationLayoutStoreDefaults.xml"));

            var layouts = xmlDocument.SelectNodes("/annotation-configuration/annotation-layouts/annotation-layout");

            Assert.IsNotNull(layouts, "/annotation-configuration/annotation-layouts/annotation-layout");

            foreach (var layout in layouts.OfType <XmlElement>())
            {
                var layoutId = layout.GetAttribute("id");
                Assert.IsNotEmpty(layoutId, "/annotation-configuration/annotation-layouts/annotation-layout/@id");

                var groups = layout.SelectNodes("annotation-box-groups/annotation-box-group");
                Assert.IsNotNull(groups, "[{0}]: annotation-box-groups/annotation-box-group", layoutId);

                foreach (var group in groups.OfType <XmlElement>())
                {
                    var groupId = group.GetAttribute("id");
                    Assert.IsNotEmpty(groupId, "[{0}]: annotation-box-groups/annotation-box-group/@id", layoutId);

                    var boxes = group.SelectNodes("annotation-boxes/annotation-box");
                    Assert.IsNotNull(boxes, "[{0}/{1}]: annotation-boxes/annotation-box", layoutId, groupId);

                    var rectangles = new List <RectangleF>();
                    foreach (var box in boxes.OfType <XmlElement>())
                    {
                        var rectangleString = box.GetAttribute("normalized-rectangle");
                        Assert.IsNotEmpty(rectangleString, "[{0}/{1}]: annotation-boxes/annotation-box/@normalized-rectangle", layoutId, groupId);

                        var rectangleStringParts = rectangleString.Split('\\');
                        Assert.IsTrue(rectangleStringParts.Length == 4, "[{0}/{1}]: '{2}' does not have 4 elements", layoutId, groupId, rectangleString);

                        var rectangleComponents = rectangleStringParts.Select(s => AssertParseOrFail(s, "[{0}/{1}]: '{2}' failed to parse as 4 valid values between 0 and 1", layoutId, groupId, rectangleString)).ToArray();

                        Assert.IsTrue(rectangleComponents.All(d => d >= 0 && d <= 1), "[{0}/{1}]: '{2}' failed to parse as 4 valid values between 0 and 1", layoutId, groupId, rectangleString);

                        var rectangle = RectangleF.FromLTRB(rectangleComponents[0], rectangleComponents[1], rectangleComponents[2], rectangleComponents[3]);

                        Assert.IsTrue(rectangle.Width > 0 && rectangle.Height > 0, "[{0}/{1}]: '{2}' should define a rectangle with positive width and height", layoutId, groupId, rectangleString);

                        rectangles.Add(rectangle);
                    }

                    // skip overlap tests for all directional marker groups
                    if (groupId == "DirectionalMarkers")
                    {
                        continue;
                    }

                    rectangles.Sort((x, y) => x.Top.CompareTo(y.Top));
                    for (var n = 1; n < rectangles.Count; ++n)
                    {
                        Assert.IsTrue(rectangles[n].Top >= rectangles[n - 1].Bottom, "[{0}/{1}]: Found a vertically overlapping rectangle", layoutId, groupId);
                    }
                }
            }
        }