diff --git a/src/Umbraco.Core/Models/Content.cs b/src/Umbraco.Core/Models/Content.cs
new file mode 100644
index 0000000000..79112f26cc
--- /dev/null
+++ b/src/Umbraco.Core/Models/Content.cs
@@ -0,0 +1,531 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Globalization;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.Serialization;
+using Umbraco.Core.Models.EntityBase;
+
+namespace Umbraco.Core.Models
+{
+ ///
+ /// Defines a Content object
+ ///
+ [Serializable]
+ [DataContract(IsReference = true)]
+ public class Content : Entity, IContent
+ {
+ private IContentType _contentType;
+ private int _parentId;
+ private string _name;
+ private int _sortOrder;
+ private int _level;
+ private string _path;
+ private string _template;
+ private int _userId;
+ private bool _trashed;
+ private bool _published;
+ private string _language;
+ private int _contentTypeId;
+ private PropertyCollection _properties;
+ private DateTime? _releaseDate;
+ private DateTime? _expireDate;
+
+ ///
+ /// Constructor for creating a Content object
+ ///
+ /// Id of the Parent content
+ /// ContentType for the current Content object
+ public Content(int parentId, IContentType contentType) : this(parentId, contentType, new PropertyCollection())
+ {
+ }
+
+ ///
+ /// Constructor for creating a Content object
+ ///
+ /// Id of the Parent content
+ /// ContentType for the current Content object
+ /// Collection of properties
+ public Content(int parentId, IContentType contentType, PropertyCollection properties)
+ {
+ _parentId = parentId;
+ _contentTypeId = int.Parse(contentType.Id.ToString(CultureInfo.InvariantCulture));
+ _contentType = contentType;
+ _properties = properties;
+ _properties.EnsurePropertyTypes(PropertyTypes);
+ Version = Guid.NewGuid();
+ }
+
+ private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo(x => x.Name);
+ private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo(x => x.ParentId);
+ private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo(x => x.SortOrder);
+ private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo(x => x.Level);
+ private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo(x => x.Path);
+ private static readonly PropertyInfo TemplateSelector = ExpressionHelper.GetPropertyInfo(x => x.Template);
+ private static readonly PropertyInfo UserIdSelector = ExpressionHelper.GetPropertyInfo(x => x.UserId);
+ private static readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo(x => x.Trashed);
+ private static readonly PropertyInfo PublishedSelector = ExpressionHelper.GetPropertyInfo(x => x.Published);
+ private static readonly PropertyInfo LanguageSelector = ExpressionHelper.GetPropertyInfo(x => x.Language);
+ private static readonly PropertyInfo DefaultContentTypeIdSelector = ExpressionHelper.GetPropertyInfo(x => x.ContentTypeId);
+ private static readonly PropertyInfo ReleaseDateSelector = ExpressionHelper.GetPropertyInfo(x => x.ReleaseDate);
+ private static readonly PropertyInfo ExpireDateSelector = ExpressionHelper.GetPropertyInfo(x => x.ExpireDate);
+ private readonly static PropertyInfo PropertyCollectionSelector = ExpressionHelper.GetPropertyInfo(x => x.Properties);
+ void PropertiesChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ OnPropertyChanged(PropertyCollectionSelector);
+ }
+
+ ///
+ /// Gets or sets the Id of the Parent entity
+ ///
+ /// Might not be necessary if handled as a relation?
+ [DataMember]
+ public int ParentId
+ {
+ get { return _parentId; }
+ private set
+ {
+ _parentId = value;
+ OnPropertyChanged(ParentIdSelector);
+ }
+ }
+
+ ///
+ /// Gets or sets the name of the current entity
+ ///
+ [DataMember]
+ public string Name
+ {
+ get { return _name; }
+ set {
+ _name = value;
+ OnPropertyChanged(NameSelector);
+ }
+ }
+
+ [IgnoreDataMember]
+ public string UrlName { get { return Name.ToLower().Replace(" ", "-"); } } //TODO Needs to implement proper url casing/syntax
+
+ ///
+ /// Gets or sets the sort order of the content entity
+ ///
+ [DataMember]
+ public int SortOrder
+ {
+ get { return _sortOrder; }
+ set
+ {
+ _sortOrder = value;
+ OnPropertyChanged(SortOrderSelector);
+ }
+ }
+
+ ///
+ /// Gets or sets the level of the content entity
+ ///
+ [DataMember]
+ public int Level
+ {
+ get { return _level; }
+ set
+ {
+ _level = value;
+ OnPropertyChanged(LevelSelector);
+ }
+ }
+
+ ///
+ /// Gets or sets the path
+ ///
+ [DataMember]
+ public string Path //Setting this value should be handled by the class not the user
+ {
+ get { return _path; }
+ set
+ {
+ _path = value;
+ OnPropertyChanged(PathSelector);
+ }
+ }
+
+ ///
+ /// Path to the template used by this Content
+ /// This is used to override the default one from the ContentType
+ ///
+ /// If no template is explicitly set on the Content object, the Default template from the ContentType will be returned
+ [DataMember]
+ public virtual string Template
+ {
+ get
+ {
+ if (string.IsNullOrEmpty(_template) || _template == null)
+ return _contentType.DefaultTemplate;
+
+ return _template;
+ }
+ set
+ {
+ _template = value;
+ OnPropertyChanged(TemplateSelector);
+ }
+ }
+
+ ///
+ /// Id of the user who created this Content
+ ///
+ [DataMember]
+ public int UserId
+ {
+ get { return _userId; }
+ set
+ {
+ _userId = value;
+ OnPropertyChanged(UserIdSelector);
+ }
+ }
+
+ ///
+ /// Gets the current status of the Content
+ ///
+ public ContentStatus Status
+ {
+ get
+ {
+ if(Trashed)
+ return ContentStatus.Trashed;
+
+ if(ExpireDate.HasValue && DateTime.UtcNow > ExpireDate.Value)
+ return ContentStatus.Expired;
+
+ if(ReleaseDate.HasValue && ReleaseDate.Value > DateTime.UtcNow)
+ return ContentStatus.AwaitingRelease;
+
+ if(Published)
+ return ContentStatus.Published;
+
+ return ContentStatus.Unpublished;
+ }
+ }
+
+ ///
+ /// Boolean indicating whether this Content is Trashed or not.
+ /// If Content is Trashed it will be located in the Recyclebin.
+ ///
+ /// When content is trashed it should be unpublished
+ [DataMember]
+ public bool Trashed //Setting this value should be handled by the class not the user
+ {
+ get { return _trashed; }
+ internal set
+ {
+ _trashed = value;
+ OnPropertyChanged(TrashedSelector);
+ }
+ }
+
+ ///
+ /// Boolean indicating whether this Content is Published or not
+ ///
+ /// Setting Published to true/false should be private or internal
+ [DataMember]
+ public bool Published
+ {
+ get { return _published; }
+ internal set
+ {
+ _published = value;
+ OnPropertyChanged(PublishedSelector);
+ }
+ }
+
+ ///
+ /// Language of the data contained within this Content object
+ ///
+ [DataMember]
+ internal string Language
+ {
+ get { return _language; }
+ set
+ {
+ _language = value;
+ OnPropertyChanged(LanguageSelector);
+ }
+ }
+
+ ///
+ /// Guid Id of the curent Version
+ ///
+ [DataMember]
+ public Guid Version { get; internal set; }
+
+ ///
+ /// Integer Id of the default ContentType
+ ///
+ [DataMember]
+ public int ContentTypeId
+ {
+ get { return _contentTypeId; }
+ protected set
+ {
+ _contentTypeId = value;
+ OnPropertyChanged(DefaultContentTypeIdSelector);
+ }
+ }
+
+ ///
+ /// Collection of properties, which make up all the data available for this Content object
+ ///
+ /// Properties are loaded as part of the Content object graph
+ [DataMember]
+ public PropertyCollection Properties
+ {
+ get { return _properties; }
+ set
+ {
+ _properties = value;
+ _properties.CollectionChanged += PropertiesChanged;
+ }
+ }
+
+ ///
+ /// Set property values by alias with an annonymous object
+ ///
+ [IgnoreDataMember]
+ public object PropertyValues
+ {
+ set
+ {
+ if (value == null)
+ throw new Exception("No properties has been passed in");
+
+ var propertyInfos = value.GetType().GetProperties();
+ foreach (var propertyInfo in propertyInfos)
+ {
+ //Check if a PropertyType with alias exists thus being a valid property
+ var propertyType = PropertyTypes.FirstOrDefault(x => x.Alias == propertyInfo.Name);
+ if (propertyType == null)
+ throw new Exception(
+ string.Format(
+ "The property alias {0} is not valid, because no PropertyType with this alias exists",
+ propertyInfo.Name));
+
+ //Check if a Property with the alias already exists in the collection thus being updated or inserted
+ var item = Properties.FirstOrDefault(x => x.Alias == propertyInfo.Name);
+ if (item != null)
+ {
+ item.Value = propertyInfo.GetValue(value, null);
+ //Update item with newly added value
+ Properties.Add(item);
+ }
+ else
+ {
+ //Create new Property to add to collection
+ var property = propertyType.CreatePropertyFromValue(propertyInfo.GetValue(value, null));
+ Properties.Add(property);
+ }
+ }
+ }
+ }
+
+ ///
+ /// List of PropertyGroups available on this Content object
+ ///
+ [IgnoreDataMember]
+ public IEnumerable PropertyGroups { get { return _contentType.CompositionPropertyGroups; } }
+
+ ///
+ /// List of PropertyTypes available on this Content object
+ ///
+ [IgnoreDataMember]
+ public IEnumerable PropertyTypes { get { return _contentType.CompositionPropertyTypes; } }
+
+ ///
+ /// The date this Content should be released and thus be published
+ ///
+ [DataMember]
+ public DateTime? ReleaseDate
+ {
+ get { return _releaseDate; }
+ set
+ {
+ if(value.HasValue && value.Value > DateTime.UtcNow && Published)
+ ChangePublishedState(false);
+
+ if (value.HasValue && value.Value < DateTime.UtcNow && !Published)
+ ChangePublishedState(true);
+
+ _releaseDate = value;
+ OnPropertyChanged(ReleaseDateSelector);
+ }
+ }
+
+ ///
+ /// The date this Content should expire and thus be unpublished
+ ///
+ [DataMember]
+ public DateTime? ExpireDate
+ {
+ get { return _expireDate; }
+ set
+ {
+ if(value.HasValue && DateTime.UtcNow > value.Value && Published)
+ ChangePublishedState(false);
+
+ _expireDate = value;
+ OnPropertyChanged(ExpireDateSelector);
+ }
+ }
+
+ ///
+ /// Gets the ContentType used by this content object
+ ///
+ [IgnoreDataMember]
+ public IContentType ContentType
+ {
+ get { return _contentType; }
+ }
+
+ ///
+ /// Changes the for the current content object
+ ///
+ /// New ContentType for this content
+ /// Leaves PropertyTypes intact after change
+ public void ChangeContentType(IContentType contentType)
+ {
+ ContentTypeId = contentType.Id;
+ _contentType = contentType;
+ _properties.EnsurePropertyTypes(PropertyTypes);
+ _properties.CollectionChanged += PropertiesChanged;
+ }
+
+ ///
+ /// Changes the for the current content object and removes PropertyTypes,
+ /// which are not part of the new ContentType.
+ ///
+ /// New ContentType for this content
+ /// Boolean indicating whether to clear PropertyTypes upon change
+ public void ChangeContentType(IContentType contentType, bool clearProperties)
+ {
+ if(clearProperties)
+ {
+ ContentTypeId = contentType.Id;
+ _contentType = contentType;
+ _properties.EnsureCleanPropertyTypes(PropertyTypes);
+ _properties.CollectionChanged += PropertiesChanged;
+ return;
+ }
+
+ ChangeContentType(contentType);
+ }
+
+ ///
+ /// Indicates whether the content object has a property with the supplied alias
+ ///
+ /// Alias of the PropertyType
+ /// True if Property with given alias exists, otherwise False
+ public bool HasProperty(string propertyTypeAlias)
+ {
+ return Properties.Contains(propertyTypeAlias);
+ }
+
+ ///
+ /// Gets the value of a Property
+ ///
+ /// Alias of the PropertyType
+ /// Value as an
+ public object GetValue(string propertyTypeAlias)
+ {
+ return Properties[propertyTypeAlias].Value;
+ }
+
+ ///
+ /// Gets the value of a Property
+ ///
+ /// Type of the value to return
+ /// Alias of the PropertyType
+ /// Value as a
+ public TPassType GetValue(string propertyTypeAlias)
+ {
+ return (TPassType)Properties[propertyTypeAlias].Value;
+ }
+
+ ///
+ /// Sets the value of a Property
+ ///
+ /// Alias of the PropertyType
+ /// Value to set for the Property
+ public void SetValue(string propertyTypeAlias, object value)
+ {
+ if (Properties.Contains(propertyTypeAlias))
+ {
+ Properties[propertyTypeAlias].Value = value;
+ return;
+ }
+
+ var propertyType = PropertyTypes.FirstOrDefault(x => x.Alias == propertyTypeAlias);
+ if(propertyType == null)
+ {
+ throw new Exception(string.Format("No PropertyType exists with the supplied alias: {0}", propertyTypeAlias));
+ }
+ Properties.Add(propertyType.CreatePropertyFromValue(value));
+ }
+
+ ///
+ /// Method to call when Entity is being saved
+ ///
+ /// Created date is set and a Unique key is assigned
+ internal override void AddingEntity()
+ {
+ base.AddingEntity();
+ Key = Guid.NewGuid();
+ }
+
+ ///
+ /// Method to call when Entity is being updated
+ ///
+ /// Modified Date is set and a new Version guid is set
+ internal override void UpdatingEntity()
+ {
+ base.UpdatingEntity();
+ Version = Guid.NewGuid();
+ }
+
+ ///
+ /// Changes the Published state of the content object
+ ///
+ /// Boolean indicating whether content is published (true) or unpublished (false)
+ internal void ChangePublishedState(bool isPublished)
+ {
+ Published = isPublished;
+ //NOTE Should this be checked against the Expire/Release dates?
+ //TODO possibly create new (unpublished version)?
+ }
+
+ ///
+ /// Changes the Trashed state of the content object
+ ///
+ /// Boolean indicating whether content is trashed (true) or not trashed (false)
+ ///
+ internal void ChangeTrashedState(bool isTrashed, int parentId = -1)
+ {
+ Trashed = isTrashed;
+
+ //If Content is trashed the parent id should be set to that of the RecycleBin
+ if(isTrashed)
+ {
+ ParentId = -20;
+ }
+ else//otherwise set the parent id to the optional parameter, -1 being the fallback
+ {
+ ParentId = parentId;
+ }
+
+ //If the content is trashed and is published it should be marked as unpublished
+ if (isTrashed && Published)
+ {
+ ChangePublishedState(false);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Models/ContentStatus.cs b/src/Umbraco.Core/Models/ContentStatus.cs
new file mode 100644
index 0000000000..a50864fcc1
--- /dev/null
+++ b/src/Umbraco.Core/Models/ContentStatus.cs
@@ -0,0 +1,10 @@
+namespace Umbraco.Core.Models
+{
+ ///
+ /// Enum for the various statuses a Content object can have
+ ///
+ public enum ContentStatus
+ {
+ Unpublished, Published, Expired, Trashed, AwaitingRelease
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Models/ContentType.cs b/src/Umbraco.Core/Models/ContentType.cs
new file mode 100644
index 0000000000..579721901c
--- /dev/null
+++ b/src/Umbraco.Core/Models/ContentType.cs
@@ -0,0 +1,406 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.Serialization;
+using Umbraco.Core.Models.EntityBase;
+
+namespace Umbraco.Core.Models
+{
+ ///
+ /// Defines the type of a object
+ ///
+ [Serializable]
+ [DataContract(IsReference = true)]
+ public class ContentType : Entity, IContentType
+ {
+ private int _parentId;
+ private string _name;
+ private int _level;
+ private string _path;
+ private string _alias;
+ private string _description;
+ private int _sortOrder;
+ private string _icon;
+ private string _thumbnail;
+ private string _defaultTemplate;
+ private int _userId;
+ private bool _trashed;
+ private PropertyGroupCollection _propertyGroups;
+ private List _contentTypeComposition;
+ private IEnumerable _allowedTemplates;
+ private IEnumerable _allowedContentTypes;
+
+ public ContentType()
+ {
+ _allowedTemplates = new List();
+ _allowedContentTypes = new List();
+ _propertyGroups = new PropertyGroupCollection();
+ _contentTypeComposition = new List();
+ }
+
+ private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo(x => x.Name);
+ private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo(x => x.ParentId);
+ private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo(x => x.SortOrder);
+ private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo(x => x.Level);
+ private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo(x => x.Path);
+ private static readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo(x => x.Alias);
+ private static readonly PropertyInfo DescriptionSelector = ExpressionHelper.GetPropertyInfo(x => x.Description);
+ private static readonly PropertyInfo IconSelector = ExpressionHelper.GetPropertyInfo(x => x.Icon);
+ private static readonly PropertyInfo ThumbnailSelector = ExpressionHelper.GetPropertyInfo(x => x.Thumbnail);
+ private static readonly PropertyInfo DefaultTemplateSelector = ExpressionHelper.GetPropertyInfo(x => x.DefaultTemplate);
+ private static readonly PropertyInfo UserIdSelector = ExpressionHelper.GetPropertyInfo(x => x.UserId);
+ private static readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo(x => x.Trashed);
+ private static readonly PropertyInfo AllowedTemplatesSelector = ExpressionHelper.GetPropertyInfo>(x => x.AllowedTemplates);
+ private static readonly PropertyInfo AllowedContentTypesSelector = ExpressionHelper.GetPropertyInfo>(x => x.AllowedContentTypes);
+ private static readonly PropertyInfo ContentTypeCompositionSelector = ExpressionHelper.GetPropertyInfo>(x => x.ContentTypeComposition);
+ private readonly static PropertyInfo PropertyGroupCollectionSelector = ExpressionHelper.GetPropertyInfo(x => x.PropertyGroups);
+ void PropertyGroupsChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ OnPropertyChanged(PropertyGroupCollectionSelector);
+ }
+
+ ///
+ /// Gets or sets the Id of the Parent entity
+ ///
+ /// Might not be necessary if handled as a relation?
+ [DataMember]
+ public int ParentId
+ {
+ get { return _parentId; }
+ set
+ {
+ _parentId = value;
+ OnPropertyChanged(ParentIdSelector);
+ }
+ }
+
+ ///
+ /// Gets or sets the name of the current entity
+ ///
+ [DataMember]
+ public string Name
+ {
+ get { return _name; }
+ set
+ {
+ _name = value;
+ OnPropertyChanged(NameSelector);
+ }
+ }
+
+ ///
+ /// Gets or sets the level of the content entity
+ ///
+ [DataMember]
+ public int Level //NOTE Is this relevant for a ContentType?
+ {
+ get { return _level; }
+ set
+ {
+ _level = value;
+ OnPropertyChanged(LevelSelector);
+ }
+ }
+
+ ///
+ /// Gets of sets the path
+ ///
+ [DataMember]
+ public string Path //NOTE Is this relevant for a ContentType?
+ {
+ get { return _path; }
+ set
+ {
+ _path = value;
+ OnPropertyChanged(PathSelector);
+ }
+ }
+
+ ///
+ /// The Alias of the ContentType
+ ///
+ [DataMember]
+ public string Alias
+ {
+ get { return _alias; }
+ set
+ {
+ _alias = value;
+ OnPropertyChanged(AliasSelector);
+ }
+ }
+
+ ///
+ /// Description for the ContentType
+ ///
+ [DataMember]
+ public string Description
+ {
+ get { return _description; }
+ set
+ {
+ _description = value;
+ OnPropertyChanged(DescriptionSelector);
+ }
+ }
+
+ ///
+ /// Gets or sets the sort order of the content entity
+ ///
+ [DataMember]
+ public int SortOrder
+ {
+ get { return _sortOrder; }
+ set
+ {
+ _sortOrder = value;
+ OnPropertyChanged(SortOrderSelector);
+ }
+ }
+
+ ///
+ /// Name of the icon (sprite class) used to identify the ContentType
+ ///
+ [DataMember]
+ public string Icon
+ {
+ get { return _icon; }
+ set
+ {
+ _icon = value;
+ OnPropertyChanged(IconSelector);
+ }
+ }
+
+ ///
+ /// Name of the thumbnail used to identify the ContentType
+ ///
+ [DataMember]
+ public string Thumbnail
+ {
+ get { return _thumbnail; }
+ set
+ {
+ _thumbnail = value;
+ OnPropertyChanged(ThumbnailSelector);
+ }
+ }
+
+ ///
+ /// Gets or sets the Path to default Template
+ ///
+ [DataMember]
+ public string DefaultTemplate
+ {
+ get { return _defaultTemplate; }
+ set
+ {
+ _defaultTemplate = value;
+ OnPropertyChanged(DefaultTemplateSelector);
+ }
+ }
+
+ ///
+ /// Id of the user who created this Content
+ ///
+ [DataMember]
+ public int UserId
+ {
+ get { return _userId; }
+ set
+ {
+ _userId = value;
+ OnPropertyChanged(UserIdSelector);
+ }
+ }
+
+ ///
+ /// Boolean indicating whether this ContentType is Trashed or not.
+ /// If ContentType is Trashed it will be located in the Recyclebin.
+ ///
+ [DataMember]
+ public bool Trashed //NOTE Is this relevant for a ContentType?
+ {
+ get { return _trashed; }
+ set
+ {
+ _trashed = value;
+ OnPropertyChanged(TrashedSelector);
+ }
+ }
+
+ ///
+ /// Gets or sets a list of aliases for allowed Templates
+ ///
+ public IEnumerable AllowedTemplates
+ {
+ get { return _allowedTemplates; }
+ set
+ {
+ _allowedTemplates = value;
+ OnPropertyChanged(AllowedTemplatesSelector);
+ }
+ }
+
+ ///
+ /// Gets or sets a list of integer Ids for allowed ContentTypes
+ ///
+ public IEnumerable AllowedContentTypes
+ {
+ get { return _allowedContentTypes; }
+ set
+ {
+ _allowedContentTypes = value;
+ OnPropertyChanged(AllowedContentTypesSelector);
+ }
+ }
+
+ ///
+ /// List of PropertyGroups available on this ContentType
+ ///
+ /// A PropertyGroup corresponds to a Tab in the UI
+ [DataMember]
+ public PropertyGroupCollection PropertyGroups
+ {
+ get { return _propertyGroups; }
+ set
+ {
+ _propertyGroups = value;
+ _propertyGroups.CollectionChanged += PropertyGroupsChanged;
+ }
+ }
+
+ ///
+ /// List of PropertyTypes available on this ContentType.
+ /// This list aggregates PropertyTypes across the PropertyGroups.
+ ///
+ [IgnoreDataMember]
+ public IEnumerable PropertyTypes
+ {
+ get { return PropertyGroups.SelectMany(x => x.PropertyTypes); }
+ }
+
+ ///
+ /// List of ContentTypes that make up a composition of PropertyGroups and PropertyTypes for the current ContentType
+ ///
+ public List ContentTypeComposition
+ {
+ get { return _contentTypeComposition; }
+ set
+ {
+ _contentTypeComposition = value;
+ OnPropertyChanged(ContentTypeCompositionSelector);
+ }
+ }
+
+ ///
+ /// Returns a list of objects from the composition
+ ///
+ [IgnoreDataMember]
+ public IEnumerable CompositionPropertyGroups
+ {
+ get
+ {
+ var groups = PropertyGroups.Union(ContentTypeComposition.SelectMany(x => x.CompositionPropertyGroups));
+ return groups;
+ }
+ }
+
+ ///
+ /// Returns a list of objects from the composition
+ ///
+ [IgnoreDataMember]
+ public IEnumerable CompositionPropertyTypes
+ {
+ get
+ {
+ var propertyTypes = PropertyTypes.Union(ContentTypeComposition.SelectMany(x => x.CompositionPropertyTypes));
+ return propertyTypes;
+ }
+ }
+
+ ///
+ /// Adds a new ContentType to the list of composite ContentTypes
+ ///
+ /// to add
+ /// True if ContentType was added, otherwise returns False
+ public bool AddContentType(IContentTypeComposition contentType)
+ {
+ if(contentType.ContentTypeComposition.Any(x => x.CompositionAliases().Any(ContentTypeCompositionExists)))
+ return false;
+
+ if (!ContentTypeCompositionExists(contentType.Alias))
+ {
+ ContentTypeComposition.Add(contentType);
+ return true;
+ }
+ return false;
+ }
+
+ ///
+ /// Removes a ContentType with the supplied alias from the the list of composite ContentTypes
+ ///
+ /// Alias of a
+ /// True if ContentType was removed, otherwise returns False
+ public bool RemoveContentType(string alias)
+ {
+ if (!ContentTypeCompositionExists(alias))
+ {
+ var contentTypeComposition = ContentTypeComposition.First(x => x.Alias == alias);
+ return ContentTypeComposition.Remove(contentTypeComposition);
+ }
+ return false;
+ }
+
+ ///
+ /// Checks if a ContentType with the supplied alias exists in the list of composite ContentTypes
+ ///
+ /// Alias of a
+ /// True if ContentType with alias exists, otherwise returns False
+ public bool ContentTypeCompositionExists(string alias)
+ {
+ if (ContentTypeComposition.Any(x => x.Alias.Equals(alias)))
+ return true;
+
+ if (ContentTypeComposition.Any(x => x.ContentTypeCompositionExists(alias)))
+ return true;
+
+ return false;
+ }
+
+ ///
+ /// Gets a list of ContentType aliases from the current composition
+ ///
+ ///
+ /// Does not contain the alias of the Current ContentType
+ public IEnumerable CompositionAliases()
+ {
+ return ContentTypeComposition.Select(x => x.Alias).Union(ContentTypeComposition.SelectMany(x => x.CompositionAliases()));
+ }
+
+ //TODO Implement moving PropertyType between groups.
+ /*public bool MovePropertyTypeToGroup(string propertyTypeAlias, string groupName)
+ {}*/
+
+ ///
+ /// Method to call when Entity is being saved
+ ///
+ /// Created date is set and a Unique key is assigned
+ internal override void AddingEntity()
+ {
+ base.AddingEntity();
+ Key = Guid.NewGuid();
+ }
+
+ ///
+ /// Method to call when Entity is being updated
+ ///
+ /// Modified Date is set and a new Version guid is set
+ internal override void UpdatingEntity()
+ {
+ base.UpdatingEntity();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Models/IContent.cs b/src/Umbraco.Core/Models/IContent.cs
index b391c62e7e..cca852ebea 100644
--- a/src/Umbraco.Core/Models/IContent.cs
+++ b/src/Umbraco.Core/Models/IContent.cs
@@ -21,7 +21,7 @@ namespace Umbraco.Core.Models
///
/// Language of the data contained within the Content object
///
- string Language { get; set; }
+ //string Language { get; set; }
///
/// Gets the Guid Id of the Content's Version
diff --git a/src/Umbraco.Core/Models/IContentBase.cs b/src/Umbraco.Core/Models/IContentBase.cs
index 99d42b5828..3885d13460 100644
--- a/src/Umbraco.Core/Models/IContentBase.cs
+++ b/src/Umbraco.Core/Models/IContentBase.cs
@@ -12,7 +12,7 @@ namespace Umbraco.Core.Models
///
/// Gets or Sets the Id of the Parent for the Content
///
- int ParentId { get; set; }
+ int ParentId { get; }
///
/// Gets or Sets the Name of the Content
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index 2243896a52..8cd8d273bc 100644
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -92,6 +92,9 @@
+
+
+
diff --git a/src/Umbraco.Web/DefaultPublishedMediaStore.cs b/src/Umbraco.Web/DefaultPublishedMediaStore.cs
index 7f2289d088..0ce16c2f1c 100644
--- a/src/Umbraco.Web/DefaultPublishedMediaStore.cs
+++ b/src/Umbraco.Web/DefaultPublishedMediaStore.cs
@@ -10,6 +10,7 @@ using Umbraco.Core.Dynamics;
using Umbraco.Core.Models;
using umbraco;
using umbraco.cms.businesslogic;
+using ContentType = umbraco.cms.businesslogic.ContentType;
namespace Umbraco.Web
{
diff --git a/src/Umbraco.Web/DocumentExtensions.cs b/src/Umbraco.Web/DocumentExtensions.cs
index 647d0d694c..8f92c313eb 100644
--- a/src/Umbraco.Web/DocumentExtensions.cs
+++ b/src/Umbraco.Web/DocumentExtensions.cs
@@ -6,6 +6,7 @@ using Umbraco.Core.Models;
using Umbraco.Web.Routing;
using umbraco.cms.businesslogic;
using Umbraco.Core;
+using ContentType = umbraco.cms.businesslogic.ContentType;
namespace Umbraco.Web
{