using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Services
{
public class RelationService : IRelationService
{
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
private readonly RepositoryFactory _repositoryFactory;
private readonly IEntityService _entityService;
public RelationService(IDatabaseUnitOfWorkProvider uowProvider, RepositoryFactory repositoryFactory,
IEntityService entityService)
{
_uowProvider = uowProvider;
_repositoryFactory = repositoryFactory;
_entityService = entityService;
}
///
/// Gets a by its Id
///
/// Id of the
/// A object
public IRelation GetById(int id)
{
using (var repository = _repositoryFactory.CreateRelationRepository(_uowProvider.GetUnitOfWork()))
{
return repository.Get(id);
}
}
///
/// Gets a by its Id
///
/// Id of the
/// A object
public IRelationType GetRelationTypeById(int id)
{
using (var repository = _repositoryFactory.CreateRelationTypeRepository(_uowProvider.GetUnitOfWork()))
{
return repository.Get(id);
}
}
///
/// Gets a by its Alias
///
/// Alias of the
/// A object
public IRelationType GetRelationTypeByAlias(string alias)
{
using (var repository = _repositoryFactory.CreateRelationTypeRepository(_uowProvider.GetUnitOfWork()))
{
var query = new Query().Where(x => x.Alias == alias);
return repository.GetByQuery(query).FirstOrDefault();
}
}
///
/// Gets all objects
///
/// Optional array of integer ids to return relations for
/// An enumerable list of objects
public IEnumerable GetAllRelations(params int[] ids)
{
using (var repository = _repositoryFactory.CreateRelationRepository(_uowProvider.GetUnitOfWork()))
{
return repository.GetAll(ids);
}
}
///
/// Gets all objects by their
///
/// to retrieve Relations for
/// An enumerable list of objects
public IEnumerable GetAllRelationsByRelationType(RelationType relationType)
{
return GetAllRelationsByRelationType(relationType.Id);
}
///
/// Gets all objects by their 's Id
///
/// Id of the to retrieve Relations for
/// An enumerable list of objects
public IEnumerable GetAllRelationsByRelationType(int relationTypeId)
{
using (var repository = _repositoryFactory.CreateRelationRepository(_uowProvider.GetUnitOfWork()))
{
var query = new Query().Where(x => x.RelationTypeId == relationTypeId);
return repository.GetByQuery(query);
}
}
///
/// Gets all objects
///
/// Optional array of integer ids to return relationtypes for
/// An enumerable list of objects
public IEnumerable GetAllRelationTypes(params int[] ids)
{
using (var repository = _repositoryFactory.CreateRelationTypeRepository(_uowProvider.GetUnitOfWork()))
{
return repository.GetAll(ids);
}
}
///
/// Gets a list of objects by their parent Id
///
/// Id of the parent to retrieve relations for
/// An enumerable list of objects
public IEnumerable GetByParentId(int id)
{
using (var repository = _repositoryFactory.CreateRelationRepository(_uowProvider.GetUnitOfWork()))
{
var query = new Query().Where(x => x.ParentId == id);
return repository.GetByQuery(query);
}
}
///
/// Gets a list of objects by their parent entity
///
/// Parent Entity to retrieve relations for
/// An enumerable list of objects
public IEnumerable GetByParent(IUmbracoEntity parent)
{
return GetByParentId(parent.Id);
}
///
/// Gets a list of objects by their parent entity
///
/// Parent Entity to retrieve relations for
/// Alias of the type of relation to retrieve
/// An enumerable list of objects
public IEnumerable GetByParent(IUmbracoEntity parent, string relationTypeAlias)
{
return GetByParent(parent).Where(relation => relation.RelationType.Alias == relationTypeAlias);
}
///
/// Gets a list of objects by their child Id
///
/// Id of the child to retrieve relations for
/// An enumerable list of objects
public IEnumerable GetByChildId(int id)
{
using (var repository = _repositoryFactory.CreateRelationRepository(_uowProvider.GetUnitOfWork()))
{
var query = new Query().Where(x => x.ChildId == id);
return repository.GetByQuery(query);
}
}
///
/// Gets a list of objects by their child Entity
///
/// Child Entity to retrieve relations for
/// An enumerable list of objects
public IEnumerable GetByChild(IUmbracoEntity child)
{
return GetByChildId(child.Id);
}
///
/// Gets a list of objects by their child Entity
///
/// Child Entity to retrieve relations for
/// Alias of the type of relation to retrieve
/// An enumerable list of objects
public IEnumerable GetByChild(IUmbracoEntity child, string relationTypeAlias)
{
return GetByChild(child).Where(relation => relation.RelationType.Alias == relationTypeAlias);
}
///
/// Gets a list of objects by their child or parent Id.
/// Using this method will get you all relations regards of it being a child or parent relation.
///
/// Id of the child or parent to retrieve relations for
/// An enumerable list of objects
public IEnumerable GetByParentOrChildId(int id)
{
using (var repository = _repositoryFactory.CreateRelationRepository(_uowProvider.GetUnitOfWork()))
{
var query = new Query().Where(x => x.ChildId == id || x.ParentId == id);
return repository.GetByQuery(query);
}
}
///
/// Gets a list of objects by the Name of the
///
/// Name of the to retrieve Relations for
/// An enumerable list of objects
public IEnumerable GetByRelationTypeName(string relationTypeName)
{
List relationTypeIds = null;
using (var repository = _repositoryFactory.CreateRelationTypeRepository(_uowProvider.GetUnitOfWork()))
{
var query = new Query().Where(x => x.Name == relationTypeName);
var relationTypes = repository.GetByQuery(query);
if (relationTypes.Any())
{
relationTypeIds = relationTypes.Select(x => x.Id).ToList();
}
}
if (relationTypeIds == null)
return Enumerable.Empty();
return GetRelationsByListOfTypeIds(relationTypeIds);
}
///
/// Gets a list of objects by the Alias of the
///
/// Alias of the to retrieve Relations for
/// An enumerable list of objects
public IEnumerable GetByRelationTypeAlias(string relationTypeAlias)
{
List relationTypeIds = null;
using (var repository = _repositoryFactory.CreateRelationTypeRepository(_uowProvider.GetUnitOfWork()))
{
var query = new Query().Where(x => x.Alias == relationTypeAlias);
var relationTypes = repository.GetByQuery(query);
if (relationTypes.Any())
{
relationTypeIds = relationTypes.Select(x => x.Id).ToList();
}
}
if (relationTypeIds == null)
return Enumerable.Empty();
return GetRelationsByListOfTypeIds(relationTypeIds);
}
///
/// Gets a list of objects by the Id of the
///
/// Id of the to retrieve Relations for
/// An enumerable list of objects
public IEnumerable GetByRelationTypeId(int relationTypeId)
{
using (var repository = _repositoryFactory.CreateRelationRepository(_uowProvider.GetUnitOfWork()))
{
var query = new Query().Where(x => x.RelationTypeId == relationTypeId);
return repository.GetByQuery(query);
}
}
///
/// Gets the Child object from a Relation as an
///
/// Relation to retrieve child object from
/// Optional bool to load the complete object graph when set to False
/// An
public IUmbracoEntity GetChildEntityFromRelation(IRelation relation, bool loadBaseType = false)
{
var objectType = UmbracoObjectTypesExtensions.GetUmbracoObjectType(relation.RelationType.ChildObjectType);
return _entityService.Get(relation.ChildId, objectType, loadBaseType);
}
///
/// Gets the Parent object from a Relation as an
///
/// Relation to retrieve parent object from
/// Optional bool to load the complete object graph when set to False
/// An
public IUmbracoEntity GetParentEntityFromRelation(IRelation relation, bool loadBaseType = false)
{
var objectType = UmbracoObjectTypesExtensions.GetUmbracoObjectType(relation.RelationType.ParentObjectType);
return _entityService.Get(relation.ParentId, objectType, loadBaseType);
}
///
/// Gets the Parent and Child objects from a Relation as a "/> with .
///
/// Relation to retrieve parent and child object from
/// Optional bool to load the complete object graph when set to False
/// Returns a Tuple with Parent (item1) and Child (item2)
public Tuple GetEntitiesFromRelation(IRelation relation, bool loadBaseType = false)
{
var childObjectType = UmbracoObjectTypesExtensions.GetUmbracoObjectType(relation.RelationType.ChildObjectType);
var parentObjectType = UmbracoObjectTypesExtensions.GetUmbracoObjectType(relation.RelationType.ParentObjectType);
var child = _entityService.Get(relation.ChildId, childObjectType, loadBaseType);
var parent = _entityService.Get(relation.ParentId, parentObjectType, loadBaseType);
return new Tuple(parent, child);
}
///
/// Gets the Child objects from a list of Relations as a list of objects.
///
/// List of relations to retrieve child objects from
/// Optional bool to load the complete object graph when set to False
/// An enumerable list of
public IEnumerable GetChildEntitiesFromRelations(IEnumerable relations, bool loadBaseType = false)
{
foreach (var relation in relations)
{
var objectType = UmbracoObjectTypesExtensions.GetUmbracoObjectType(relation.RelationType.ChildObjectType);
yield return _entityService.Get(relation.ChildId, objectType, loadBaseType);
}
}
///
/// Gets the Parent objects from a list of Relations as a list of objects.
///
/// List of relations to retrieve parent objects from
/// Optional bool to load the complete object graph when set to False
/// An enumerable list of
public IEnumerable GetParentEntitiesFromRelations(IEnumerable relations,
bool loadBaseType = false)
{
foreach (var relation in relations)
{
var objectType = UmbracoObjectTypesExtensions.GetUmbracoObjectType(relation.RelationType.ParentObjectType);
yield return _entityService.Get(relation.ParentId, objectType, loadBaseType);
}
}
///
/// Gets the Parent and Child objects from a list of Relations as a list of objects.
///
/// List of relations to retrieve parent and child objects from
/// Optional bool to load the complete object graph when set to False
/// An enumerable list of with
public IEnumerable> GetEntitiesFromRelations(
IEnumerable relations,
bool loadBaseType = false)
{
foreach (var relation in relations)
{
var childObjectType = UmbracoObjectTypesExtensions.GetUmbracoObjectType(relation.RelationType.ChildObjectType);
var parentObjectType = UmbracoObjectTypesExtensions.GetUmbracoObjectType(relation.RelationType.ParentObjectType);
var child = _entityService.Get(relation.ChildId, childObjectType, loadBaseType);
var parent = _entityService.Get(relation.ParentId, parentObjectType, loadBaseType);
yield return new Tuple(parent, child);
}
}
///
/// Relates two objects that are based on the interface.
///
/// Parent entity
/// Child entity
/// The type of relation to create
/// The created
public IRelation Relate(IUmbracoEntity parent, IUmbracoEntity child, IRelationType relationType)
{
//Ensure that the RelationType has an indentity before using it to relate two entities
if (relationType.HasIdentity == false)
Save(relationType);
var relation = new Relation(parent.Id, child.Id, relationType);
if (SavingRelation.IsRaisedEventCancelled(new SaveEventArgs(relation), this))
return relation;
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateRelationRepository(uow))
{
repository.AddOrUpdate(relation);
uow.Commit();
}
SavedRelation.RaiseEvent(new SaveEventArgs(relation, false), this);
return relation;
}
///
/// Relates two objects that are based on the interface.
///
/// Parent entity
/// Child entity
/// Alias of the type of relation to create
/// The created
public IRelation Relate(IUmbracoEntity parent, IUmbracoEntity child, string relationTypeAlias)
{
var relationType = GetRelationTypeByAlias(relationTypeAlias);
if (relationType == null || string.IsNullOrEmpty(relationType.Alias))
throw new ArgumentNullException(string.Format("No RelationType with Alias '{0}' exists.", relationTypeAlias));
var relation = new Relation(parent.Id, child.Id, relationType);
if (SavingRelation.IsRaisedEventCancelled(new SaveEventArgs(relation), this))
return relation;
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateRelationRepository(uow))
{
repository.AddOrUpdate(relation);
uow.Commit();
}
SavedRelation.RaiseEvent(new SaveEventArgs(relation, false), this);
return relation;
}
///
/// Checks whether any relations exists for the passed in .
///
/// to check for relations
/// Returns True if any relations exists for the given , otherwise False
public bool HasRelations(IRelationType relationType)
{
using (var repository = _repositoryFactory.CreateRelationRepository(_uowProvider.GetUnitOfWork()))
{
var query = new Query().Where(x => x.RelationTypeId == relationType.Id);
return repository.GetByQuery(query).Any();
}
}
///
/// Checks whether any relations exists for the passed in Id.
///
/// Id of an object to check relations for
/// Returns True if any relations exists with the given Id, otherwise False
public bool IsRelated(int id)
{
using (var repository = _repositoryFactory.CreateRelationRepository(_uowProvider.GetUnitOfWork()))
{
var query = new Query().Where(x => x.ParentId == id || x.ChildId == id);
return repository.GetByQuery(query).Any();
}
}
///
/// Checks whether two items are related
///
/// Id of the Parent relation
/// Id of the Child relation
/// Returns True if any relations exists with the given Ids, otherwise False
public bool AreRelated(int parentId, int childId)
{
using (var repository = _repositoryFactory.CreateRelationRepository(_uowProvider.GetUnitOfWork()))
{
var query = new Query().Where(x => x.ParentId == parentId && x.ChildId == childId);
return repository.GetByQuery(query).Any();
}
}
///
/// Checks whether two items are related with a given relation type alias
///
/// Id of the Parent relation
/// Id of the Child relation
/// Alias of the relation type
/// Returns True if any relations exists with the given Ids and relation type, otherwise False
public bool AreRelated(int parentId, int childId, string relationTypeAlias)
{
var relType = GetRelationTypeByAlias(relationTypeAlias);
if (relType == null)
return false;
return AreRelated(parentId, childId, relType);
}
///
/// Checks whether two items are related with a given relation type
///
/// Id of the Parent relation
/// Id of the Child relation
/// Type of relation
/// Returns True if any relations exists with the given Ids and relation type, otherwise False
public bool AreRelated(int parentId, int childId, IRelationType relationType)
{
using (var repository = _repositoryFactory.CreateRelationRepository(_uowProvider.GetUnitOfWork()))
{
var query = new Query().Where(x => x.ParentId == parentId && x.ChildId == childId && x.RelationTypeId == relationType.Id);
return repository.GetByQuery(query).Any();
}
}
///
/// Checks whether two items are related
///
/// Parent entity
/// Child entity
/// Returns True if any relations exist between the entities, otherwise False
public bool AreRelated(IUmbracoEntity parent, IUmbracoEntity child)
{
return AreRelated(parent.Id, child.Id);
}
///
/// Checks whether two items are related
///
/// Parent entity
/// Child entity
/// Alias of the type of relation to create
/// Returns True if any relations exist between the entities, otherwise False
public bool AreRelated(IUmbracoEntity parent, IUmbracoEntity child, string relationTypeAlias)
{
return AreRelated(parent.Id, child.Id, relationTypeAlias);
}
///
/// Saves a
///
/// Relation to save
public void Save(IRelation relation)
{
if (SavingRelation.IsRaisedEventCancelled(new SaveEventArgs(relation), this))
return;
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateRelationRepository(uow))
{
repository.AddOrUpdate(relation);
uow.Commit();
}
SavedRelation.RaiseEvent(new SaveEventArgs(relation, false), this);
}
///
/// Saves a
///
/// RelationType to Save
public void Save(IRelationType relationType)
{
if (SavingRelationType.IsRaisedEventCancelled(new SaveEventArgs(relationType), this))
return;
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateRelationTypeRepository(uow))
{
repository.AddOrUpdate(relationType);
uow.Commit();
}
SavedRelationType.RaiseEvent(new SaveEventArgs(relationType, false), this);
}
///
/// Deletes a
///
/// Relation to Delete
public void Delete(IRelation relation)
{
if (DeletingRelation.IsRaisedEventCancelled(new DeleteEventArgs(relation), this))
return;
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateRelationRepository(uow))
{
repository.Delete(relation);
uow.Commit();
}
DeletedRelation.RaiseEvent(new DeleteEventArgs(relation, false), this);
}
///
/// Deletes a
///
/// RelationType to Delete
public void Delete(IRelationType relationType)
{
if (DeletingRelationType.IsRaisedEventCancelled(new DeleteEventArgs(relationType), this))
return;
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateRelationTypeRepository(uow))
{
repository.Delete(relationType);
uow.Commit();
}
DeletedRelationType.RaiseEvent(new DeleteEventArgs(relationType, false), this);
}
///
/// Deletes all objects based on the passed in
///
/// to Delete Relations for
public void DeleteRelationsOfType(IRelationType relationType)
{
var relations = new List();
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateRelationRepository(uow))
{
var query = new Query().Where(x => x.RelationTypeId == relationType.Id);
relations.AddRange(repository.GetByQuery(query).ToList());
foreach (var relation in relations)
{
repository.Delete(relation);
}
uow.Commit();
}
DeletedRelation.RaiseEvent(new DeleteEventArgs(relations, false), this);
}
#region Private Methods
private IEnumerable GetRelationsByListOfTypeIds(IEnumerable relationTypeIds)
{
var relations = new List();
using (var repository = _repositoryFactory.CreateRelationRepository(_uowProvider.GetUnitOfWork()))
{
foreach (var relationTypeId in relationTypeIds)
{
int id = relationTypeId;
var query = new Query().Where(x => x.RelationTypeId == id);
relations.AddRange(repository.GetByQuery(query).ToList());
}
}
return relations;
}
#endregion
#region Events Handlers
///
/// Occurs before Deleting a Relation
///
public static event TypedEventHandler> DeletingRelation;
///
/// Occurs after a Relation is Deleted
///
public static event TypedEventHandler> DeletedRelation;
///
/// Occurs before Saving a Relation
///
public static event TypedEventHandler> SavingRelation;
///
/// Occurs after a Relation is Saved
///
public static event TypedEventHandler> SavedRelation;
///
/// Occurs before Deleting a RelationType
///
public static event TypedEventHandler> DeletingRelationType;
///
/// Occurs after a RelationType is Deleted
///
public static event TypedEventHandler> DeletedRelationType;
///
/// Occurs before Saving a RelationType
///
public static event TypedEventHandler> SavingRelationType;
///
/// Occurs after a RelationType is Saved
///
public static event TypedEventHandler> SavedRelationType;
#endregion
}
}