protected virtual Dictionary <string, List <SemanticProperty> > LoadPropertySemantics(Type type) { lock (_semanticPropertiesCache) { // Try to get cached semantics Dictionary <string, List <SemanticProperty> > result; if (_semanticPropertiesCache.TryGetValue(type, out result)) { return(result); } result = ModelTypeRegistry.GetPropertySemantics(type); _semanticPropertiesCache.Add(type, result); return(result); } }
protected virtual void MapSemanticProperties(EntityModel stronglyTypedTopic, XmlElement rootElement) { Type modelType = stronglyTypedTopic.GetType(); IDictionary <string, List <SemanticProperty> > propertySemanticsMap = ModelTypeRegistry.GetPropertySemantics(modelType); foreach (KeyValuePair <string, List <SemanticProperty> > propertySemantics in propertySemanticsMap) { PropertyInfo modelProperty = modelType.GetProperty(propertySemantics.Key); List <SemanticProperty> semanticProperties = propertySemantics.Value; IEnumerable <XmlElement> htmlElements = null; foreach (SemanticProperty ditaProperty in semanticProperties.Where(sp => sp.SemanticType.Vocab == ViewModel.DitaVocabulary)) { string ditaPropertyName = ditaProperty.PropertyName; string propertyXPath = GetPropertyXPath(ditaPropertyName); Log.Debug($"Trying XPath \"{propertyXPath}\" for property '{modelProperty.Name}'"); XmlNodeList xPathResults = rootElement.SelectNodes(propertyXPath); htmlElements = FilterXPathResults(xPathResults, ditaPropertyName); if (htmlElements != null && htmlElements.Any()) { break; } Log.Debug($"No XHTML elements found for DITA property '{ditaPropertyName}'."); } if (htmlElements == null || !htmlElements.Any()) { Log.Debug($"Unable to map property '{modelProperty.Name}'"); continue; } Log.Debug($"{htmlElements.Count()} XHTML elements found."); try { object propertyValue = GetPropertyValue(modelProperty.PropertyType, htmlElements); modelProperty.SetValue(stronglyTypedTopic, propertyValue); } catch (Exception ex) { throw new DxaException($"Unable to map property {modelType.Name}.{modelProperty.Name}", ex); } } }
protected virtual void MapSemanticProperties(ViewModel viewModel, MappingData mappingData) { Type modelType = viewModel.GetType(); IDictionary <string, List <SemanticProperty> > propertySemanticsMap = ModelTypeRegistry.GetPropertySemantics(modelType); IDictionary <string, string> xpmPropertyMetadata = new Dictionary <string, string>(); Validation validation = mappingData.PropertyValidation; foreach (KeyValuePair <string, List <SemanticProperty> > propertySemantics in propertySemanticsMap) { PropertyInfo modelProperty = modelType.GetProperty(propertySemantics.Key); List <SemanticProperty> semanticProperties = propertySemantics.Value; bool isFieldMapped = false; string fieldXPath = null; foreach (SemanticProperty semanticProperty in semanticProperties) { if (semanticProperty.PropertyName == SemanticProperty.AllFields) { modelProperty.SetValue(viewModel, GetAllFieldsAsDictionary(mappingData)); isFieldMapped = true; break; } if ((semanticProperty.PropertyName == SemanticProperty.Self) && validation.MainSchema.HasSemanticType(semanticProperty.SemanticType)) { try { object mappedSelf = MapComponentLink((EntityModelData)mappingData.SourceViewModel, modelProperty.PropertyType, mappingData.Localization); modelProperty.SetValue(viewModel, mappedSelf); isFieldMapped = true; break; } catch (Exception ex) { Log.Debug($"Self mapping failed for {modelType.Name}.{modelProperty.Name}: {ex.Message}"); continue; } } FieldSemantics fieldSemantics = new FieldSemantics( semanticProperty.SemanticType.Vocab, semanticProperty.SemanticType.EntityName, semanticProperty.PropertyName, null); SemanticSchemaField semanticSchemaField = (mappingData.EmbeddedSemanticSchemaField == null) ? ValidateField(validation, fieldSemantics) : mappingData.EmbeddedSemanticSchemaField.FindFieldBySemantics(fieldSemantics); if (semanticSchemaField == null) { // No matching Semantic Schema Field found for this Semantic Property; maybe another one will match. continue; } // Matching Semantic Schema Field found fieldXPath = IsFieldFromMainSchema(validation, fieldSemantics) ? semanticSchemaField.GetXPath(mappingData.ContextXPath) : null; ContentModelData fields = semanticSchemaField.IsMetadata ? mappingData.MetadataFields : mappingData.Fields; object fieldValue = FindFieldValue(semanticSchemaField, fields, mappingData.EmbedLevel); if (fieldValue == null) { // No field value found; maybe we will find a value for another Semantic Property. continue; } try { object mappedPropertyValue = MapField(fieldValue, modelProperty.PropertyType, semanticSchemaField, mappingData); modelProperty.SetValue(viewModel, mappedPropertyValue); } catch (Exception ex) { throw new DxaException( $"Unable to map field '{semanticSchemaField.Name}' to property {modelType.Name}.{modelProperty.Name} of type '{modelProperty.PropertyType.FullName}'.", ex); } isFieldMapped = true; break; } if (fieldXPath != null) { xpmPropertyMetadata.Add(modelProperty.Name, fieldXPath); } else if (!isFieldMapped && Log.IsDebugEnabled) { string formattedSemanticProperties = string.Join(", ", semanticProperties.Select(sp => sp.ToString())); Log.Debug( $"Property {modelType.Name}.{modelProperty.Name} cannot be mapped to a CM field of {validation.MainSchema}. Semantic properties: {formattedSemanticProperties}."); } } EntityModel entityModel = viewModel as EntityModel; if ((entityModel != null) && mappingData.Localization.IsXpmEnabled) { entityModel.XpmPropertyMetadata = xpmPropertyMetadata; } }