U4-8469 - xml cache TLC
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
@@ -26,44 +25,26 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
/// </summary>
|
||||
/// <param name="xmlNode">The Xml node.</param>
|
||||
/// <param name="isPreviewing">A value indicating whether the published content is being previewed.</param>
|
||||
public XmlPublishedContent(XmlNode xmlNode, bool isPreviewing)
|
||||
private XmlPublishedContent(XmlNode xmlNode, bool isPreviewing)
|
||||
{
|
||||
_xmlNode = xmlNode;
|
||||
_isPreviewing = isPreviewing;
|
||||
InitializeStructure();
|
||||
Initialize();
|
||||
InitializeChildren();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <c>XmlPublishedContent</c> class with an Xml node,
|
||||
/// and a value indicating whether to lazy-initialize the instance.
|
||||
/// </summary>
|
||||
/// <param name="xmlNode">The Xml node.</param>
|
||||
/// <param name="isPreviewing">A value indicating whether the published content is being previewed.</param>
|
||||
/// <param name="lazyInitialize">A value indicating whether to lazy-initialize the instance.</param>
|
||||
/// <remarks>Lazy-initializationg is NOT thread-safe.</remarks>
|
||||
internal XmlPublishedContent(XmlNode xmlNode, bool isPreviewing, bool lazyInitialize)
|
||||
{
|
||||
_xmlNode = xmlNode;
|
||||
_isPreviewing = isPreviewing;
|
||||
InitializeStructure();
|
||||
if (lazyInitialize == false)
|
||||
{
|
||||
Initialize();
|
||||
InitializeChildren();
|
||||
}
|
||||
}
|
||||
|
||||
private readonly XmlNode _xmlNode;
|
||||
|
||||
private bool _initialized;
|
||||
private readonly bool _isPreviewing;
|
||||
|
||||
private bool _nodeInitialized;
|
||||
private bool _parentInitialized;
|
||||
private bool _childrenInitialized;
|
||||
|
||||
private readonly ICollection<IPublishedContent> _children = new Collection<IPublishedContent>();
|
||||
private IEnumerable<IPublishedContent> _children = Enumerable.Empty<IPublishedContent>();
|
||||
private IPublishedContent _parent;
|
||||
|
||||
private int _id;
|
||||
private PublishedContentType _contentType;
|
||||
private Dictionary<string, IPublishedProperty> _properties;
|
||||
|
||||
private int _id;
|
||||
private Guid _key;
|
||||
private int _template;
|
||||
private string _name;
|
||||
@@ -78,28 +59,24 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
private DateTime _createDate;
|
||||
private DateTime _updateDate;
|
||||
private Guid _version;
|
||||
private IPublishedProperty[] _properties;
|
||||
private int _sortOrder;
|
||||
private int _level;
|
||||
private bool _isDraft;
|
||||
private readonly bool _isPreviewing;
|
||||
private PublishedContentType _contentType;
|
||||
|
||||
public override IEnumerable<IPublishedContent> Children
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
if (_childrenInitialized == false)
|
||||
InitializeChildren();
|
||||
return _children.OrderBy(x => x.SortOrder);
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
if (_childrenInitialized == false) InitializeChildren();
|
||||
return _children;
|
||||
}
|
||||
}
|
||||
|
||||
public override IPublishedProperty GetProperty(string alias)
|
||||
{
|
||||
return Properties.FirstOrDefault(x => x.PropertyTypeAlias.InvariantEquals(alias));
|
||||
IPublishedProperty property;
|
||||
return _properties.TryGetValue(alias, out property) ? property : null;
|
||||
}
|
||||
|
||||
// override to implement cache
|
||||
@@ -135,8 +112,8 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
if (_parentInitialized == false) InitializeParent();
|
||||
return _parent;
|
||||
}
|
||||
}
|
||||
@@ -145,8 +122,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _id;
|
||||
}
|
||||
}
|
||||
@@ -155,8 +131,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _key;
|
||||
}
|
||||
}
|
||||
@@ -165,8 +140,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _template;
|
||||
}
|
||||
}
|
||||
@@ -175,8 +149,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _sortOrder;
|
||||
}
|
||||
}
|
||||
@@ -185,8 +158,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _name;
|
||||
}
|
||||
}
|
||||
@@ -195,8 +167,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _docTypeAlias;
|
||||
}
|
||||
}
|
||||
@@ -205,8 +176,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _docTypeId;
|
||||
}
|
||||
}
|
||||
@@ -215,8 +185,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _writerName;
|
||||
}
|
||||
}
|
||||
@@ -225,8 +194,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _creatorName;
|
||||
}
|
||||
}
|
||||
@@ -235,8 +203,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _writerId;
|
||||
}
|
||||
}
|
||||
@@ -245,8 +212,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _creatorId;
|
||||
}
|
||||
}
|
||||
@@ -255,8 +221,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _path;
|
||||
}
|
||||
}
|
||||
@@ -265,8 +230,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _createDate;
|
||||
}
|
||||
}
|
||||
@@ -275,8 +239,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _updateDate;
|
||||
}
|
||||
}
|
||||
@@ -285,8 +248,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _version;
|
||||
}
|
||||
}
|
||||
@@ -295,8 +257,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _urlName;
|
||||
}
|
||||
}
|
||||
@@ -305,8 +266,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _level;
|
||||
}
|
||||
}
|
||||
@@ -315,8 +275,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _isDraft;
|
||||
}
|
||||
}
|
||||
@@ -325,9 +284,8 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
return _properties;
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _properties.Values;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,24 +293,26 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_initialized == false)
|
||||
Initialize();
|
||||
if (_nodeInitialized == false) InitializeNode();
|
||||
return _contentType;
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeStructure()
|
||||
private void InitializeParent()
|
||||
{
|
||||
// load parent if it exists and is a node
|
||||
if (_xmlNode == null) return;
|
||||
|
||||
var parent = _xmlNode == null ? null : _xmlNode.ParentNode;
|
||||
var parent = _xmlNode.ParentNode;
|
||||
if (parent == null) return;
|
||||
|
||||
if (parent.Name == "node" || (parent.Attributes != null && parent.Attributes.GetNamedItem("isDoc") != null))
|
||||
_parent = (new XmlPublishedContent(parent, _isPreviewing, true)).CreateModel();
|
||||
_parent = Get(parent, _isPreviewing);
|
||||
|
||||
// warn: this is not thread-safe...
|
||||
_parentInitialized = true;
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
private void InitializeNode()
|
||||
{
|
||||
if (_xmlNode == null) return;
|
||||
|
||||
@@ -423,22 +383,27 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
if (nodes != null)
|
||||
foreach (XmlNode n in nodes)
|
||||
{
|
||||
var attrs = n.Attributes;
|
||||
if (attrs == null) continue;
|
||||
var alias = UmbracoConfig.For.UmbracoSettings().Content.UseLegacyXmlSchema
|
||||
? n.Attributes.GetNamedItem("alias").Value
|
||||
? attrs.GetNamedItem("alias").Value
|
||||
: n.Name;
|
||||
propertyNodes[alias.ToLowerInvariant()] = n;
|
||||
}
|
||||
|
||||
_properties = _contentType.PropertyTypes.Select(p =>
|
||||
{
|
||||
XmlNode n;
|
||||
return propertyNodes.TryGetValue(p.PropertyTypeAlias.ToLowerInvariant(), out n)
|
||||
? new XmlPublishedProperty(p, _isPreviewing, n)
|
||||
: new XmlPublishedProperty(p, _isPreviewing);
|
||||
}).Cast<IPublishedProperty>().ToArray();
|
||||
_properties = _contentType.PropertyTypes.Select(p =>
|
||||
{
|
||||
XmlNode n;
|
||||
return propertyNodes.TryGetValue(p.PropertyTypeAlias.ToLowerInvariant(), out n)
|
||||
? new XmlPublishedProperty(p, _isPreviewing, n)
|
||||
: new XmlPublishedProperty(p, _isPreviewing);
|
||||
}).Cast<IPublishedProperty>().ToDictionary(
|
||||
x => x.PropertyTypeAlias,
|
||||
x => x,
|
||||
StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
// warn: this is not thread-safe...
|
||||
_initialized = true;
|
||||
_nodeInitialized = true;
|
||||
}
|
||||
|
||||
private void InitializeChildren()
|
||||
@@ -449,14 +414,37 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
var childXPath = UmbracoConfig.For.UmbracoSettings().Content.UseLegacyXmlSchema ? "node" : "* [@isDoc]";
|
||||
var nav = _xmlNode.CreateNavigator();
|
||||
var expr = nav.Compile(childXPath);
|
||||
expr.AddSort("@sortOrder", XmlSortOrder.Ascending, XmlCaseOrder.None, "", XmlDataType.Number);
|
||||
//expr.AddSort("@sortOrder", XmlSortOrder.Ascending, XmlCaseOrder.None, "", XmlDataType.Number);
|
||||
var iterator = nav.Select(expr);
|
||||
while (iterator.MoveNext())
|
||||
_children.Add(
|
||||
(new XmlPublishedContent(((IHasXmlNode)iterator.Current).GetNode(), _isPreviewing, true)).CreateModel());
|
||||
|
||||
|
||||
_children = iterator.Cast<XPathNavigator>()
|
||||
.Select(n => Get(((IHasXmlNode) n).GetNode(), _isPreviewing))
|
||||
.OrderBy(x => x.SortOrder)
|
||||
.ToList();
|
||||
|
||||
// warn: this is not thread-safe
|
||||
_childrenInitialized = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an IPublishedContent corresponding to an Xml cache node.
|
||||
/// </summary>
|
||||
/// <param name="node">The Xml node.</param>
|
||||
/// <param name="isPreviewing">A value indicating whether we are previewing or not.</param>
|
||||
/// <returns>The IPublishedContent corresponding to the Xml cache node.</returns>
|
||||
/// <remarks>Maintains a per-request cache of IPublishedContent items in order to make
|
||||
/// sure that we create only one instance of each for the duration of a request. The
|
||||
/// returned IPublishedContent is a model, if models are enabled.</remarks>
|
||||
public static IPublishedContent Get(XmlNode node, bool isPreviewing)
|
||||
{
|
||||
// only 1 per request
|
||||
|
||||
var attrs = node.Attributes;
|
||||
var id = attrs == null ? null : attrs.GetNamedItem("id").Value;
|
||||
if (id.IsNullOrWhiteSpace()) throw new InvalidOperationException("Node has no ID attribute.");
|
||||
var cache = ApplicationContext.Current.ApplicationCache.RequestCache;
|
||||
var key = "XMLPUBLISHEDCONTENT_" + id; // dont bother with preview, wont change during request in v7
|
||||
return (IPublishedContent) cache.GetCacheItem(key, () => (new XmlPublishedContent(node, isPreviewing)).CreateModel());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user