using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Dynamics;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
using log4net.Util.TypeConverters;
namespace Umbraco.Core
{
///
/// Utility class for dealing with data types and value conversions
///
///
/// TODO: The logic for the GetDataType + cache should probably be moved to a service, no ?
///
/// We inherit from ApplicationEventHandler so we can bind to the ContentTypeService events to ensure that our local cache
/// object gets cleared when content types change.
///
internal class PublishedContentHelper : ApplicationEventHandler
{
///
/// Used to invalidate the cache from the ICacherefresher
///
internal static void ClearPropertyTypeCache()
{
PropertyTypeCache.Clear();
}
///
/// This callback is used only for unit tests which enables us to return any data we want and not rely on having the data in a database
///
internal static Func GetDataTypeCallback = null;
private static readonly ConcurrentDictionary, string> PropertyTypeCache = new ConcurrentDictionary, string>();
///
/// Return the GUID Id for the data type assigned to the document type with the property alias
///
///
///
///
///
///
internal static string GetPropertyEditor(ApplicationContext applicationContext, string docTypeAlias, string propertyAlias, PublishedItemType itemType)
{
if (GetDataTypeCallback != null)
return GetDataTypeCallback(docTypeAlias, propertyAlias);
var key = new Tuple(docTypeAlias, propertyAlias, itemType);
return PropertyTypeCache.GetOrAdd(key, tuple =>
{
IContentTypeComposition result = null;
switch (itemType)
{
case PublishedItemType.Content:
result = applicationContext.Services.ContentTypeService.GetContentType(docTypeAlias);
break;
case PublishedItemType.Media:
result = applicationContext.Services.ContentTypeService.GetMediaType(docTypeAlias);
break;
default:
throw new ArgumentOutOfRangeException("itemType");
}
if (result == null) return string.Empty;
//SD: we need to check for 'any' here because the collection is backed by KeyValuePair which is a struct
// and can never be null so FirstOrDefault doesn't actually work. Have told Seb and Morten about thsi
// issue.
if (!result.CompositionPropertyTypes.Any(x => x.Alias.InvariantEquals(propertyAlias)))
{
return string.Empty;
}
var property = result.CompositionPropertyTypes.FirstOrDefault(x => x.Alias.InvariantEquals(propertyAlias));
//as per above, this will never be null but we'll keep the check here anyways.
if (property == null) return string.Empty;
return property.PropertyEditorAlias;
});
}
///
/// Converts the currentValue to a correctly typed value based on known registered converters, then based on known standards.
///
///
///
///
internal static Attempt