< Summary - Jellyfin

Information
Class: Jellyfin.Server.Implementations.Item.BaseItemMapper
Assembly: Jellyfin.Server.Implementations
File(s): /srv/git/jellyfin/Jellyfin.Server.Implementations/Item/BaseItemMapper.cs
Line coverage
71%
Covered lines: 183
Uncovered lines: 72
Coverable lines: 255
Total lines: 491
Line coverage: 71.7%
Branch coverage
50%
Covered branches: 85
Total branches: 168
Branch coverage: 50.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 5/4/2026 - 12:15:16 AM Line coverage: 71.5% (181/253) Branch coverage: 54.7% (92/168) Total lines: 4895/8/2026 - 12:15:13 AM Line coverage: 71.7% (183/255) Branch coverage: 54.7% (92/168) Total lines: 4915/20/2026 - 12:15:44 AM Line coverage: 71.7% (183/255) Branch coverage: 48.2% (81/168) Total lines: 4917/6/2026 - 12:16:28 AM Line coverage: 71.7% (183/255) Branch coverage: 50.5% (85/168) Total lines: 491 5/4/2026 - 12:15:16 AM Line coverage: 71.5% (181/253) Branch coverage: 54.7% (92/168) Total lines: 4895/8/2026 - 12:15:13 AM Line coverage: 71.7% (183/255) Branch coverage: 54.7% (92/168) Total lines: 4915/20/2026 - 12:15:44 AM Line coverage: 71.7% (183/255) Branch coverage: 48.2% (81/168) Total lines: 4917/6/2026 - 12:16:28 AM Line coverage: 71.7% (183/255) Branch coverage: 50.5% (85/168) Total lines: 491

Coverage delta

Coverage delta 7 -7

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
Map(...)45.12%2168272.91%
Map(...)51.61%956279.46%
MapImageFromEntity(...)0%7280%
MapImageToEntity(...)0%620%
GetType(...)100%11100%
TypeRequiresDeserialization(...)100%11100%
DeserializeBaseItem(...)83.33%161270.58%
GetPathToSave(...)50%2266.66%

File(s)

/srv/git/jellyfin/Jellyfin.Server.Implementations/Item/BaseItemMapper.cs

#LineLine coverage
 1#pragma warning disable RS0030 // Do not use banned APIs
 2
 3using System;
 4using System.Collections.Concurrent;
 5using System.Linq;
 6using System.Reflection;
 7using System.Text;
 8using System.Text.Json;
 9using Jellyfin.Database.Implementations.Entities;
 10using Jellyfin.Extensions;
 11using Jellyfin.Extensions.Json;
 12using MediaBrowser.Common;
 13using MediaBrowser.Controller;
 14using MediaBrowser.Controller.Entities;
 15using MediaBrowser.Controller.Entities.Audio;
 16using MediaBrowser.Controller.Entities.TV;
 17using MediaBrowser.Controller.LiveTv;
 18using MediaBrowser.Model.Entities;
 19using MediaBrowser.Model.LiveTv;
 20using Microsoft.Extensions.Logging;
 21using BaseItemDto = MediaBrowser.Controller.Entities.BaseItem;
 22using BaseItemEntity = Jellyfin.Database.Implementations.Entities.BaseItemEntity;
 23
 24namespace Jellyfin.Server.Implementations.Item;
 25
 26/// <summary>
 27/// Handles mapping between BaseItemEntity (database) and BaseItemDto (domain) objects.
 28/// </summary>
 29public static class BaseItemMapper
 30{
 31    /// <summary>
 32    /// This holds all the types in the running assemblies
 33    /// so that we can de-serialize properly when we don't have strong types.
 34    /// </summary>
 235    private static readonly ConcurrentDictionary<string, Type?> _typeMap = new ConcurrentDictionary<string, Type?>();
 36
 37    /// <summary>
 38    /// Maps a Entity to the DTO.
 39    /// </summary>
 40    /// <param name="entity">The entity.</param>
 41    /// <param name="dto">The dto base instance.</param>
 42    /// <param name="appHost">The Application server Host.</param>
 43    /// <returns>The dto to map.</returns>
 44    public static BaseItemDto Map(BaseItemEntity entity, BaseItemDto dto, IServerApplicationHost? appHost)
 45    {
 7946        dto.Id = entity.Id;
 7947        dto.ParentId = entity.ParentId.GetValueOrDefault();
 7948        dto.Path = appHost?.ExpandVirtualPath(entity.Path) ?? entity.Path;
 7949        dto.EndDate = entity.EndDate;
 7950        dto.CommunityRating = entity.CommunityRating;
 7951        dto.CustomRating = entity.CustomRating;
 7952        dto.IndexNumber = entity.IndexNumber;
 7953        dto.IsLocked = entity.IsLocked;
 7954        dto.Name = entity.Name;
 7955        dto.OfficialRating = entity.OfficialRating;
 7956        dto.Overview = entity.Overview;
 7957        dto.ParentIndexNumber = entity.ParentIndexNumber;
 7958        dto.PremiereDate = entity.PremiereDate;
 7959        dto.ProductionYear = entity.ProductionYear;
 7960        dto.SortName = entity.SortName;
 7961        dto.ForcedSortName = entity.ForcedSortName;
 7962        dto.RunTimeTicks = entity.RunTimeTicks;
 7963        dto.PreferredMetadataLanguage = entity.PreferredMetadataLanguage;
 7964        dto.PreferredMetadataCountryCode = entity.PreferredMetadataCountryCode;
 7965        dto.IsInMixedFolder = entity.IsInMixedFolder;
 7966        dto.InheritedParentalRatingValue = entity.InheritedParentalRatingValue;
 7967        dto.InheritedParentalRatingSubValue = entity.InheritedParentalRatingSubValue;
 7968        dto.CriticRating = entity.CriticRating;
 7969        dto.PresentationUniqueKey = entity.PresentationUniqueKey;
 7970        dto.OriginalTitle = entity.OriginalTitle;
 7971        dto.OriginalLanguage = entity.OriginalLanguage;
 7972        dto.Album = entity.Album;
 7973        dto.LUFS = entity.LUFS;
 7974        dto.NormalizationGain = entity.NormalizationGain;
 7975        dto.IsVirtualItem = entity.IsVirtualItem;
 7976        dto.ExternalSeriesId = entity.ExternalSeriesId;
 7977        dto.Tagline = entity.Tagline;
 7978        dto.TotalBitrate = entity.TotalBitrate;
 7979        dto.ExternalId = entity.ExternalId;
 7980        dto.Size = entity.Size;
 7981        dto.Genres = string.IsNullOrWhiteSpace(entity.Genres) ? [] : entity.Genres.Split('|');
 7982        dto.DateCreated = entity.DateCreated ?? DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
 7983        dto.DateModified = entity.DateModified ?? DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
 7984        dto.ChannelId = entity.ChannelId ?? Guid.Empty;
 7985        dto.DateLastRefreshed = entity.DateLastRefreshed ?? DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
 7986        dto.DateLastSaved = entity.DateLastSaved ?? DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
 7987        dto.OwnerId = entity.OwnerId ?? Guid.Empty;
 7988        dto.Width = entity.Width.GetValueOrDefault();
 7989        dto.Height = entity.Height.GetValueOrDefault();
 7990        dto.UserData = entity.UserData;
 91
 7992        if (entity.Provider is not null)
 93        {
 7894            dto.ProviderIds = entity.Provider.ToDictionary(e => e.ProviderId, e => e.ProviderValue);
 95        }
 96
 7997        if (entity.ExtraType is not null)
 98        {
 099            dto.ExtraType = (ExtraType)entity.ExtraType;
 100        }
 101
 79102        if (entity.LockedFields is not null)
 103        {
 78104            dto.LockedFields = entity.LockedFields?.Select(e => (MetadataField)e.Id).ToArray() ?? [];
 105        }
 106
 79107        if (entity.Audio is not null)
 108        {
 0109            dto.Audio = (ProgramAudio)entity.Audio;
 110        }
 111
 79112        dto.ProductionLocations = entity.ProductionLocations?.Split('|', StringSplitOptions.RemoveEmptyEntries) ?? [];
 79113        dto.Studios = entity.Studios?.Split('|') ?? [];
 79114        dto.Tags = string.IsNullOrWhiteSpace(entity.Tags) ? [] : entity.Tags.Split('|');
 115
 79116        if (dto is IHasProgramAttributes hasProgramAttributes)
 117        {
 0118            hasProgramAttributes.IsMovie = entity.IsMovie;
 0119            hasProgramAttributes.IsSeries = entity.IsSeries;
 0120            hasProgramAttributes.EpisodeTitle = entity.EpisodeTitle;
 0121            hasProgramAttributes.IsRepeat = entity.IsRepeat;
 122        }
 123
 79124        if (dto is LiveTvChannel liveTvChannel)
 125        {
 0126            liveTvChannel.ServiceName = entity.ExternalServiceId;
 127        }
 128
 79129        if (dto is Trailer trailer)
 130        {
 0131            trailer.TrailerTypes = entity.TrailerTypes?.Select(e => (TrailerType)e.Id).ToArray() ?? [];
 132        }
 133
 79134        if (dto is Video video)
 135        {
 3136            video.PrimaryVersionId = entity.PrimaryVersionId;
 137        }
 138
 79139        if (dto is IHasSeries hasSeriesName)
 140        {
 0141            hasSeriesName.SeriesName = entity.SeriesName;
 0142            hasSeriesName.SeriesId = entity.SeriesId.GetValueOrDefault();
 0143            hasSeriesName.SeriesPresentationUniqueKey = entity.SeriesPresentationUniqueKey;
 144        }
 145
 79146        if (dto is Episode episode)
 147        {
 0148            episode.SeasonName = entity.SeasonName;
 0149            episode.SeasonId = entity.SeasonId.GetValueOrDefault();
 150        }
 151
 79152        if (dto is IHasArtist hasArtists)
 153        {
 0154            hasArtists.Artists = entity.Artists?.Split('|', StringSplitOptions.RemoveEmptyEntries) ?? [];
 155        }
 156
 79157        if (dto is IHasAlbumArtist hasAlbumArtists)
 158        {
 0159            hasAlbumArtists.AlbumArtists = entity.AlbumArtists?.Split('|', StringSplitOptions.RemoveEmptyEntries) ?? [];
 160        }
 161
 79162        if (dto is LiveTvProgram program)
 163        {
 0164            program.ShowId = entity.ShowId;
 165        }
 166
 79167        if (entity.Images is not null)
 168        {
 78169            dto.ImageInfos = entity.Images.Select(e => MapImageFromEntity(e, appHost)).ToArray();
 170        }
 171
 79172        if (dto is IHasStartDate hasStartDate)
 173        {
 0174            hasStartDate.StartDate = entity.StartDate.GetValueOrDefault();
 175        }
 176
 177        // Fields that are present in the DB but are never actually used
 178        // dto.UnratedType = entity.UnratedType;
 179        // dto.TopParentId = entity.TopParentId;
 180        // dto.CleanName = entity.CleanName;
 181        // dto.UserDataKey = entity.UserDataKey;
 182
 79183        if (dto is Folder folder)
 184        {
 76185            folder.DateLastMediaAdded = entity.DateLastMediaAdded ?? DateTime.SpecifyKind(DateTime.MinValue, DateTimeKin
 76186            if (entity.LinkedChildEntities is not null && entity.LinkedChildEntities.Count > 0)
 187            {
 0188                folder.LinkedChildren = entity.LinkedChildEntities
 0189                    .OrderBy(e => e.SortOrder)
 0190                    .Select(e => new LinkedChild
 0191                    {
 0192                        ItemId = e.ChildId,
 0193                        Type = (MediaBrowser.Controller.Entities.LinkedChildType)e.ChildType
 0194                    })
 0195                    .ToArray();
 196            }
 197        }
 198
 79199        return dto;
 200    }
 201
 202    /// <summary>
 203    /// Maps a DTO to a database entity.
 204    /// </summary>
 205    /// <param name="dto">The DTO.</param>
 206    /// <param name="appHost">The application host for path resolution.</param>
 207    /// <returns>The database entity.</returns>
 208    public static BaseItemEntity Map(BaseItemDto dto, IServerApplicationHost appHost)
 209    {
 128210        var dtoType = dto.GetType();
 128211        var entity = new BaseItemEntity()
 128212        {
 128213            Type = dtoType.ToString(),
 128214            Id = dto.Id
 128215        };
 216
 128217        if (TypeRequiresDeserialization(dtoType))
 218        {
 106219            entity.Data = JsonSerializer.Serialize(dto, dtoType, JsonDefaults.Options);
 220        }
 221
 128222        entity.ParentId = !dto.ParentId.IsEmpty() ? dto.ParentId : null;
 128223        entity.Path = GetPathToSave(dto.Path, appHost);
 128224        entity.EndDate = dto.EndDate;
 128225        entity.CommunityRating = dto.CommunityRating;
 128226        entity.CustomRating = dto.CustomRating;
 128227        entity.IndexNumber = dto.IndexNumber;
 128228        entity.IsLocked = dto.IsLocked;
 128229        entity.Name = dto.Name;
 128230        entity.CleanName = dto.Name.GetCleanValue();
 128231        entity.OfficialRating = dto.OfficialRating;
 128232        entity.Overview = dto.Overview;
 128233        entity.ParentIndexNumber = dto.ParentIndexNumber;
 128234        entity.PremiereDate = dto.PremiereDate;
 128235        entity.ProductionYear = dto.ProductionYear;
 128236        entity.SortName = dto.SortName;
 128237        entity.ForcedSortName = dto.ForcedSortName;
 128238        entity.RunTimeTicks = dto.RunTimeTicks;
 128239        entity.PreferredMetadataLanguage = dto.PreferredMetadataLanguage;
 128240        entity.PreferredMetadataCountryCode = dto.PreferredMetadataCountryCode;
 128241        entity.IsInMixedFolder = dto.IsInMixedFolder;
 128242        entity.InheritedParentalRatingValue = dto.InheritedParentalRatingValue;
 128243        entity.InheritedParentalRatingSubValue = dto.InheritedParentalRatingSubValue;
 128244        entity.CriticRating = dto.CriticRating;
 128245        entity.PresentationUniqueKey = dto.PresentationUniqueKey;
 128246        entity.OriginalTitle = dto.OriginalTitle;
 128247        entity.OriginalLanguage = dto.OriginalLanguage;
 128248        entity.Album = dto.Album;
 128249        entity.LUFS = dto.LUFS;
 128250        entity.NormalizationGain = dto.NormalizationGain;
 128251        entity.IsVirtualItem = dto.IsVirtualItem;
 128252        entity.ExternalSeriesId = dto.ExternalSeriesId;
 128253        entity.Tagline = dto.Tagline;
 128254        entity.TotalBitrate = dto.TotalBitrate;
 128255        entity.ExternalId = dto.ExternalId;
 128256        entity.Size = dto.Size;
 128257        entity.Genres = string.Join('|', dto.Genres.Distinct(StringComparer.OrdinalIgnoreCase));
 128258        entity.DateCreated = dto.DateCreated == DateTime.MinValue ? null : dto.DateCreated;
 128259        entity.DateModified = dto.DateModified == DateTime.MinValue ? null : dto.DateModified;
 128260        entity.ChannelId = dto.ChannelId;
 128261        entity.DateLastRefreshed = dto.DateLastRefreshed == DateTime.MinValue ? null : dto.DateLastRefreshed;
 128262        entity.DateLastSaved = dto.DateLastSaved == DateTime.MinValue ? null : dto.DateLastSaved;
 128263        entity.OwnerId = dto.OwnerId == Guid.Empty ? null : dto.OwnerId;
 128264        entity.Width = dto.Width;
 128265        entity.Height = dto.Height;
 128266        entity.Provider = dto.ProviderIds.Select(e => new BaseItemProvider()
 128267        {
 128268            Item = entity,
 128269            ProviderId = e.Key,
 128270            ProviderValue = e.Value
 128271        }).ToList();
 272
 128273        if (dto.Audio.HasValue)
 274        {
 0275            entity.Audio = (ProgramAudioEntity)dto.Audio;
 276        }
 277
 128278        if (dto.ExtraType.HasValue)
 279        {
 0280            entity.ExtraType = (BaseItemExtraType)dto.ExtraType;
 281        }
 282
 128283        entity.ProductionLocations = dto.ProductionLocations is not null ? string.Join('|', dto.ProductionLocations.Wher
 128284        entity.Studios = dto.Studios is not null ? string.Join('|', dto.Studios.Distinct(StringComparer.OrdinalIgnoreCas
 128285        entity.Tags = dto.Tags is not null ? string.Join('|', dto.Tags.Distinct(StringComparer.OrdinalIgnoreCase)) : nul
 128286        entity.LockedFields = dto.LockedFields is not null ? dto.LockedFields
 128287            .Select(e => new BaseItemMetadataField()
 128288            {
 128289                Id = (int)e,
 128290                Item = entity,
 128291                ItemId = entity.Id
 128292            })
 128293            .ToArray() : null;
 294
 128295        if (dto is IHasProgramAttributes hasProgramAttributes)
 296        {
 0297            entity.IsMovie = hasProgramAttributes.IsMovie;
 0298            entity.IsSeries = hasProgramAttributes.IsSeries;
 0299            entity.EpisodeTitle = hasProgramAttributes.EpisodeTitle;
 0300            entity.IsRepeat = hasProgramAttributes.IsRepeat;
 301        }
 302
 128303        if (dto is LiveTvChannel liveTvChannel)
 304        {
 0305            entity.ExternalServiceId = liveTvChannel.ServiceName;
 306        }
 307
 128308        if (dto is Video video)
 309        {
 0310            entity.PrimaryVersionId = video.PrimaryVersionId;
 311        }
 312
 128313        if (dto is IHasSeries hasSeriesName)
 314        {
 0315            entity.SeriesName = hasSeriesName.SeriesName;
 0316            entity.SeriesId = hasSeriesName.SeriesId;
 0317            entity.SeriesPresentationUniqueKey = hasSeriesName.SeriesPresentationUniqueKey;
 318        }
 319
 128320        if (dto is Episode episode)
 321        {
 0322            entity.SeasonName = episode.SeasonName;
 0323            entity.SeasonId = episode.SeasonId;
 324        }
 325
 128326        if (dto is IHasArtist hasArtists)
 327        {
 0328            entity.Artists = hasArtists.Artists is not null ? string.Join('|', hasArtists.Artists.Distinct(StringCompare
 329        }
 330
 128331        if (dto is IHasAlbumArtist hasAlbumArtists)
 332        {
 0333            entity.AlbumArtists = hasAlbumArtists.AlbumArtists is not null ? string.Join('|', hasAlbumArtists.AlbumArtis
 334        }
 335
 128336        if (dto is LiveTvProgram program)
 337        {
 0338            entity.ShowId = program.ShowId;
 339        }
 340
 128341        if (dto.ImageInfos is not null)
 342        {
 128343            entity.Images = dto.ImageInfos.Select(f => MapImageToEntity(dto.Id, f)).ToArray();
 344        }
 345
 128346        if (dto is Trailer trailer)
 347        {
 0348            entity.TrailerTypes = trailer.TrailerTypes?.Select(e => new BaseItemTrailerType()
 0349            {
 0350                Id = (int)e,
 0351                Item = entity,
 0352                ItemId = entity.Id
 0353            }).ToArray() ?? [];
 354        }
 355
 128356        entity.MediaType = dto.MediaType.ToString();
 128357        if (dto is IHasStartDate hasStartDate)
 358        {
 0359            entity.StartDate = hasStartDate.StartDate;
 360        }
 361
 128362        entity.UnratedType = dto.GetBlockUnratedType().ToString();
 363
 364        // Fields that are present in the DB but are never actually used
 365        // dto.UserDataKey = entity.UserDataKey;
 366
 128367        if (dto is Folder folder)
 368        {
 128369            entity.DateLastMediaAdded = folder.DateLastMediaAdded == DateTime.MinValue ? null : folder.DateLastMediaAdde
 128370            entity.IsFolder = folder.IsFolder;
 371        }
 372
 128373        return entity;
 374    }
 375
 376    /// <summary>
 377    /// Maps a database image entity to a domain image info.
 378    /// </summary>
 379    /// <param name="e">The database image entity.</param>
 380    /// <param name="appHost">The application host.</param>
 381    /// <returns>The mapped image info.</returns>
 382    public static ItemImageInfo MapImageFromEntity(BaseItemImageInfo e, IServerApplicationHost? appHost)
 383    {
 0384        return new ItemImageInfo()
 0385        {
 0386            Path = appHost?.ExpandVirtualPath(e.Path) ?? e.Path,
 0387            BlurHash = e.Blurhash is null ? null : Encoding.UTF8.GetString(e.Blurhash),
 0388            DateModified = e.DateModified ?? DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc),
 0389            Height = e.Height,
 0390            Width = e.Width,
 0391            Type = (ImageType)e.ImageType
 0392        };
 393    }
 394
 395    /// <summary>
 396    /// Maps a domain image info to a database image entity.
 397    /// </summary>
 398    /// <param name="baseItemId">The parent item ID.</param>
 399    /// <param name="e">The image info to map.</param>
 400    /// <returns>The mapped database entity.</returns>
 401    public static BaseItemImageInfo MapImageToEntity(Guid baseItemId, ItemImageInfo e)
 402    {
 0403        return new BaseItemImageInfo()
 0404        {
 0405            ItemId = baseItemId,
 0406            Id = Guid.NewGuid(),
 0407            Path = e.Path,
 0408            Blurhash = e.BlurHash is null ? null : Encoding.UTF8.GetBytes(e.BlurHash),
 0409            DateModified = e.DateModified,
 0410            Height = e.Height,
 0411            Width = e.Width,
 0412            ImageType = (ImageInfoImageType)e.Type,
 0413            Item = null!
 0414        };
 415    }
 416
 417    /// <summary>
 418    /// Gets the type from a type name string.
 419    /// </summary>
 420    /// <param name="typeName">The type name.</param>
 421    /// <returns>The resolved type, or null.</returns>
 422    public static Type? GetType(string typeName)
 423    {
 159424        ArgumentException.ThrowIfNullOrEmpty(typeName);
 425
 159426        return _typeMap.GetOrAdd(typeName, k => AppDomain.CurrentDomain.GetAssemblies()
 159427            .Select(a => a.GetType(k))
 159428            .FirstOrDefault(t => t is not null));
 429    }
 430
 431    /// <summary>
 432    /// Checks whether a type requires JSON deserialization.
 433    /// </summary>
 434    /// <param name="type">The type to check.</param>
 435    /// <returns>True if the type requires deserialization.</returns>
 436    public static bool TypeRequiresDeserialization(Type type)
 437    {
 207438        return type.GetCustomAttribute<RequiresSourceSerialisationAttribute>() == null;
 439    }
 440
 441    /// <summary>
 442    /// Deserializes a BaseItemEntity and sets all properties.
 443    /// </summary>
 444    /// <param name="baseItemEntity">The DB entity.</param>
 445    /// <param name="logger">Logger.</param>
 446    /// <param name="appHost">The application server Host.</param>
 447    /// <param name="skipDeserialization">If only mapping should be processed.</param>
 448    /// <returns>A mapped BaseItem, or null if the item type is unknown.</returns>
 449    public static BaseItemDto? DeserializeBaseItem(BaseItemEntity baseItemEntity, ILogger logger, IServerApplicationHost
 450    {
 81451        var type = GetType(baseItemEntity.Type);
 81452        if (type is null)
 453        {
 2454            logger.LogWarning(
 2455                "Skipping item {ItemId} with unknown type '{ItemType}'. This may indicate a removed plugin or database c
 2456                baseItemEntity.Id,
 2457                baseItemEntity.Type);
 2458            return null;
 459        }
 460
 79461        BaseItemDto? dto = null;
 79462        if (TypeRequiresDeserialization(type) && baseItemEntity.Data is not null && !skipDeserialization)
 463        {
 464            try
 465            {
 13466                dto = JsonSerializer.Deserialize(baseItemEntity.Data, type, JsonDefaults.Options) as BaseItemDto;
 13467            }
 0468            catch (JsonException ex)
 469            {
 0470                logger.LogError(ex, "Error deserializing item with JSON: {Data}", baseItemEntity.Data);
 0471            }
 472        }
 473
 79474        if (dto is null)
 475        {
 66476            dto = Activator.CreateInstance(type) as BaseItemDto ?? throw new InvalidOperationException("Cannot deseriali
 477        }
 478
 79479        return Map(baseItemEntity, dto, appHost);
 480    }
 481
 482    private static string? GetPathToSave(string path, IServerApplicationHost appHost)
 483    {
 128484        if (path is null)
 485        {
 10486            return null;
 487        }
 488
 118489        return appHost.ReverseVirtualPath(path);
 490    }
 491}