Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 44 additions & 64 deletions web-application/Sdl.Web.DD4T/Mapping/DD4TModelBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ protected virtual object CreateEntity(object sourceEntity, Type type, List<objec
mapData.TargetEntitiesByPrefix = GetEntityDataFromType(type);
mapData.Content = component.Fields;
mapData.Meta = component.MetadataFields;
mapData.TargetType = type;
mapData.TargetType = ProcessType(type,component);
mapData.SourceEntity = component;
var model = CreateModelFromMapData(mapData);
if (model is IEntity)
Expand All @@ -93,6 +93,31 @@ protected virtual object CreateEntity(object sourceEntity, Type type, List<objec
return null;
}

protected virtual Type ProcessType(Type type, IComponent source)
{
//Extension point for specific type processing
//For example, here we can ensure a model with a
//Generic MediaItem link is populated with a specific
//subtype (Image, YoutubeVideo, Download) model
if (source.Multimedia!=null && type==typeof(MediaItem))
{
string schemaTitle = source.Schema.Title;
if (type.IsAssignableFrom(typeof(Image)) && schemaTitle.ToLower().Contains("image"))
{
return typeof(Image);
}
if (type.IsAssignableFrom(typeof(Download)) && schemaTitle.ToLower().Contains("download"))
{
return typeof(Download);
}
if (type.IsAssignableFrom(typeof(YouTubeVideo)) && schemaTitle.ToLower().Contains("youtube"))
{
return typeof(YouTubeVideo);
}
}
return type;
}

protected virtual object CreateModelFromMapData(MappingData mapData)
{
var model = Activator.CreateInstance(mapData.TargetType);
Expand Down Expand Up @@ -122,7 +147,7 @@ protected virtual object CreateModelFromMapData(MappingData mapData)
{
if (propertyType == typeof(MediaItem) && mapData.SourceEntity.Multimedia != null)
{
pi.SetValue(model, GetMultiMediaLinks(new List<IComponent> { mapData.SourceEntity }, propertyType, multival));
pi.SetValue(model, GetMultiComponentLinks(new List<IComponent> { mapData.SourceEntity }, propertyType, multival));
processed = true;
}
else if (propertyType == typeof(Link) || propertyType == typeof(String))
Expand Down Expand Up @@ -263,7 +288,7 @@ private object GetFieldValues(IField field, Type propertyType, bool multival, Ma
case (FieldType.Number):
return GetNumbers(field, propertyType, multival);
case (FieldType.MultiMediaLink):
return GetMultiMediaLinks(field, propertyType, multival);
return GetMultiComponentLinks(field, propertyType, multival);
case (FieldType.ComponentLink):
return GetMultiComponentLinks(field, propertyType, multival);
case (FieldType.Embedded):
Expand Down Expand Up @@ -354,50 +379,6 @@ private static object GetNumbers(IField field, Type modelType, bool multival)
return null;
}

private static object GetMultiMediaLinks(IField field, Type modelType, bool multival)
{
return GetMultiMediaLinks(field.LinkedComponentValues, modelType, multival);
}

private static object GetMultiMediaLinks(IEnumerable<IComponent> items, Type modelType, bool multival)
{
var components = items as IList<IComponent> ?? items.ToList();
if (components.Any())
{
// TODO find better way to determine image or video
string schemaTitle = components.First().Schema.Title;
if (modelType.IsAssignableFrom(typeof(YouTubeVideo)) && schemaTitle.ToLower().Contains("youtube"))
{
if (multival)
{
return GetYouTubeVideos(components);
}

return GetYouTubeVideos(components)[0];
}
if (modelType.IsAssignableFrom(typeof(Download)) && schemaTitle.ToLower().Contains("download"))
{
if (multival)
{
return GetDownloads(components);
}

return GetDownloads(components)[0];
}
if (modelType.IsAssignableFrom(typeof(Image)))
{
if (multival)
{
return GetImages(components);
}

return GetImages(components)[0];
}
// TODO handle other types
}
return null;
}

private object GetMultiKeywords(IField field, Type linkedItemType, bool multival)
{
return GetMultiKeywords(field.Keywords, linkedItemType, multival);
Expand Down Expand Up @@ -501,7 +482,22 @@ private object GetMultiComponentLinks(IEnumerable<IComponent> items, Type linked
//TODO is reflection the only way to do this?
MethodInfo method = GetType().GetMethod("GetCompLink" + (multival ? "s" : String.Empty), BindingFlags.NonPublic | BindingFlags.Instance);
method = method.MakeGenericMethod(new[] { linkedItemType });
return method.Invoke(this, new object[] { items, linkedItemType });
return method.Invoke(this, new object[] { items });
}

private List<T> GetCompLinks<T>(IEnumerable<IComponent> components)
{
List<T> list = new List<T>();
foreach (var comp in components)
{
list.Add((T)Create(comp, typeof(T)));
}
return list;
}

private T GetCompLink<T>(IEnumerable<IComponent> components)
{
return GetCompLinks<T>(components)[0];
}

private object GetMultiEmbedded(IField field, Type propertyType, bool multival, MappingData mapData)
Expand Down Expand Up @@ -557,22 +553,6 @@ object GetStrings(IField field, Type modelType, bool multival)
return null;
}

private static List<Image> GetImages(IEnumerable<IComponent> components)
{
return components.Select(c => new Image { Url = c.Multimedia.Url, FileName = c.Multimedia.FileName, FileSize = c.Multimedia.Size, MimeType = c.Multimedia.MimeType}).ToList();
}

private static List<YouTubeVideo> GetYouTubeVideos(IEnumerable<IComponent> components)
{
return components.Select(c => new YouTubeVideo { Url = c.Multimedia.Url, FileSize = c.Multimedia.Size, MimeType = c.Multimedia.MimeType, YouTubeId = c.MetadataFields["youTubeId"].Value }).ToList();
}

private static List<Download> GetDownloads(IEnumerable<IComponent> components)
{
//todo this contains hardcoded metadata while we would expect this to semantiaclly ma
return components.Select(c => new Download { Url = c.Multimedia.Url, FileName = c.Multimedia.FileName, FileSize = c.Multimedia.Size, MimeType = c.Multimedia.MimeType, Description = (c.MetadataFields.ContainsKey("description") ? c.MetadataFields["description"].Value : null) }).ToList();
}

protected Dictionary<string, string> GetAllFieldsAsDictionary(IComponent component)
{
Dictionary<string, string> values = new Dictionary<string, string>();
Expand Down