private static FieldType GetFieldType(ItemFieldDefinition field) => _fieldTypes[field.GetType()];
        private IEnumerable <SemanticPropertyData> GetSemanticProperties(ItemFieldDefinition schemaField, IEnumerable <SemanticTypeData> semanticTypes, Schema schema)
        {
            XmlElement typeOfExtensionElement   = null;
            XmlElement propertyExtensionElement = null;
            XmlElement extensionElement         = schemaField.ExtensionXml;

            if (extensionElement != null)
            {
                typeOfExtensionElement   = (XmlElement)extensionElement.SelectSingleNode("mapping:typeof", _namespaceManager);
                propertyExtensionElement = (XmlElement)extensionElement.SelectSingleNode("mapping:property", _namespaceManager);
            }

            // Create a set of distinct semantic types for this field.
            List <SemanticTypeData> fieldSemanticTypes = new List <SemanticTypeData>(semanticTypes);

            if (typeOfExtensionElement != null)
            {
                foreach (string typeOf in typeOfExtensionElement.InnerText.Split(','))
                {
                    string[] typeOfParts = typeOf.Split(':');
                    if (typeOfParts.Length != 2)
                    {
                        throw new DxaException(string.Format("Invalid format for semantic typeOf extension data of field '{0}' in Schema '{1}' ({2}): '{3}'.  Format must be <prefix>:<entity>.",
                                                             schemaField.Name, schema.Title, schema.Id, typeOf));
                    }
                    fieldSemanticTypes.Add(new SemanticTypeData {
                        Prefix = typeOfParts[0], Entity = typeOfParts[1]
                    });
                }
            }
            fieldSemanticTypes = fieldSemanticTypes.Distinct().ToList();

            // Create a list of semantic property names for this field
            string semanticProperties = string.Format("{0}:{1}", GetDefaultVocabularyPrefix(schema), schemaField.Name);

            if (_retrofitMode && string.IsNullOrEmpty(schema.NamespaceUri))
            {
                semanticProperties += string.Format(",{0}:{1}", GetDefaultVocabularyPrefix(_currentSchema), schemaField.Name);
            }
            if (propertyExtensionElement != null)
            {
                semanticProperties += "," + propertyExtensionElement.InnerText;
            }

            // Resolve the property name prefixes to semantic types
            List <SemanticPropertyData> result = new List <SemanticPropertyData>();

            foreach (string property in semanticProperties.Split(','))
            {
                string[] propertyParts = property.Split(':');
                if (propertyParts.Length != 2)
                {
                    throw new DxaException(string.Format("Invalid format for semantic property of field '{0}' in Schema '{1}' ({2}): '{3}'.  Format must be <prefix>:<property>.",
                                                         schemaField.Name, schema.Title, schema.Id, property));
                }

                string prefix       = propertyParts[0];
                string propertyName = propertyParts[1];

                SemanticTypeData[] propertySemanticTypes = fieldSemanticTypes.Where(s => s.Prefix == prefix).ToArray();
                if (propertySemanticTypes.Length == 0)
                {
                    Logger.Warning(string.Format("Semantic property of field '{0}' in Schema '{1}' ({2}) references an undeclared prefix '{3}'. Semantic types: {4}",
                                                 schemaField.Name, schema.Title, schema.Id, property, string.Join(", ", fieldSemanticTypes.Select(s => s.ToString()))));
                    continue;
                }

                result.AddRange(propertySemanticTypes.Select(s => new SemanticPropertyData {
                    Prefix = s.Prefix, Entity = s.Entity, Property = propertyName
                }));
            }

            return(result);
        }
        private IEnumerable<SemanticPropertyData> GetSemanticProperties(ItemFieldDefinition schemaField, IEnumerable<SemanticTypeData> semanticTypes, Schema schema)
        {
            XmlElement typeOfExtensionElement = null;
            XmlElement propertyExtensionElement = null;
            XmlElement extensionElement = schemaField.ExtensionXml;
            if (extensionElement != null)
            {
                typeOfExtensionElement = (XmlElement) extensionElement.SelectSingleNode("mapping:typeof", _namespaceManager);
                propertyExtensionElement = (XmlElement) extensionElement.SelectSingleNode("mapping:property", _namespaceManager);
            }

            // Create a set of distinct semantic types for this field.
            List<SemanticTypeData> fieldSemanticTypes =  new List<SemanticTypeData>(semanticTypes);
            if (typeOfExtensionElement != null)
            {
                foreach (string typeOf in typeOfExtensionElement.InnerText.Split(','))
                {
                    string[] typeOfParts = typeOf.Split(':');
                    if (typeOfParts.Length != 2)
                    {
                        throw new DxaException(string.Format("Invalid format for semantic typeOf extension data of field '{0}' in Schema '{1}' ({2}): '{3}'.  Format must be <prefix>:<entity>.",
                            schemaField.Name, schema.Title, schema.Id, typeOf));
                    }
                    fieldSemanticTypes.Add(new SemanticTypeData { Prefix = typeOfParts[0], Entity = typeOfParts[1] });
                }
            }
            fieldSemanticTypes = fieldSemanticTypes.Distinct().ToList();

            // Create a list of semantic property names for this field
            string semanticProperties = string.Format("{0}:{1}", GetDefaultVocabularyPrefix(schema), schemaField.Name);
            if (_retrofitMode && string.IsNullOrEmpty(schema.NamespaceUri))
            {
                semanticProperties += string.Format(",{0}:{1}", GetDefaultVocabularyPrefix(_currentSchema), schemaField.Name);
            }
            if (propertyExtensionElement != null)
            {
                semanticProperties += "," + propertyExtensionElement.InnerText;
            }

            // Resolve the property name prefixes to semantic types
            List<SemanticPropertyData> result = new List<SemanticPropertyData>();
            foreach (string property in semanticProperties.Split(','))
            {
                string[] propertyParts = property.Split(':');
                if (propertyParts.Length != 2)
                {
                    throw new DxaException(string.Format("Invalid format for semantic property of field '{0}' in Schema '{1}' ({2}): '{3}'.  Format must be <prefix>:<property>.",
                        schemaField.Name, schema.Title, schema.Id, property));
                }

                string prefix = propertyParts[0];
                string propertyName = propertyParts[1];

                SemanticTypeData[] propertySemanticTypes = fieldSemanticTypes.Where(s => s.Prefix == prefix).ToArray();
                if (propertySemanticTypes.Length == 0)
                {
                    Logger.Warning(string.Format("Semantic property of field '{0}' in Schema '{1}' ({2}) references an undeclared prefix '{3}'. Semantic types: {4}",
                        schemaField.Name, schema.Title, schema.Id, property, string.Join(", ", fieldSemanticTypes.Select(s => s.ToString()))));
                    continue;
                }

                result.AddRange(propertySemanticTypes.Select(s => new SemanticPropertyData { Prefix = s.Prefix, Entity = s.Entity, Property = propertyName }));
            }

            return result;
        }