/// <summary> /// Definition specifying which property (navigation) of ICollection type (many of one-to-many side) will be cloned /// </summary> /// <typeparam name="TInnerType">Inner type of generic collection</typeparam> /// <param name="clonedProperty">Property selector which property should be cloned</param> /// <returns>The self instance</returns> protected EntityCloner <TEntity> AddClone <TInnerType>(Expression <Func <TEntity, ICollection <TInnerType> > > clonedProperty) where TInnerType : class { var propertyName = ((clonedProperty.Body as MemberExpression)?.Member as PropertyInfo)?.Name; var collectionDefinition = entityPropsDefs.CollectionNavigationMap.First(i => i.Navigation.Name == propertyName); var entitySelectors = collectionDefinition.ForeignKeys.Select( foreignKey => CoreExtensions.CreateLambdaEqual <TInnerType>(foreignKey.DeclaringEntityColumn.Name, source.GetPropertyObjectValue(foreignKey.PrincipalEntityColumn.Name))) .ToList(); var propertyEntitySet = unitOfWork.GetSet <TInnerType>().AsQueryable(); entitySelectors.ForEach(q => propertyEntitySet = propertyEntitySet.Where(q)); var instancesToClone = propertyEntitySet.ToList(); var propertyCloner = resolveManager.Resolve <IEntityCloner <TInnerType> >(); if (cloningMode == CloningMode.Cloning || cloningMode == CloningMode.TreeCreating) { target.SetPropertyValue(clonedProperty, instancesToClone.Select(i => propertyCloner.PerformCloning(unitOfWork, i, tg => collectionDefinition.ForeignKeys.ForEach( foreignKey => tg.SetPropertyValue(foreignKey.DeclaringEntityColumn.Name, target.GetPropertyObjectValue(foreignKey.PrincipalEntityColumn.Name))), cloningMode: cloningMode )).ToList()); } if (cloningMode == CloningMode.Deleting) { instancesToClone.ForEach(i => propertyCloner.PerformCloning(unitOfWork, i, cloningMode: cloningMode)); } return(this); }
/// <summary> /// Publish specified entity, check latest version and create new version with published state /// </summary> /// <typeparam name="TEntityType">Type of entity which will be promoted to published state</typeparam> /// <param name="unitOfWork">Unit Of Work</param> /// <param name="entity">Entity which will be promoted to published state</param> /// <param name="targetPublishingStatus">Entity which will be promoted to published state</param> public IList <PublishingAffectedResult> PublishVersion <TEntityType>(ITranslationUnitOfWork unitOfWork, TEntityType entity, PublishingStatus targetPublishingStatus = PublishingStatus.Published) where TEntityType : class, IVersionedVolume, new() { var entitySet = unitOfWork.GetSet <TEntityType>(); var allVersions = GetAllVersions(unitOfWork, entity); var currentLatest = allVersions.LastOrDefault() ?? new VersionInfo(); var result = new List <PublishingAffectedResult>(); if ((currentLatest.PublishingStatusId == PublishingStatuses[targetPublishingStatus]) && (currentLatest.VersionId == entity.VersioningId)) { logger.LogDebug($"Publishing not needed, already in desired target publishing state. {entity.GetType().Name}, Id: {entity.Id}"); return(result); } Guid?originVersioning = null; if (targetPublishingStatus == PublishingStatus.Published) { var previousPublishedVersion = allVersions.LastOrDefault(i => i.PublishingStatusId == PublishingStatuses[PublishingStatus.Published]); originVersioning = previousPublishedVersion?.VersionId; if (previousPublishedVersion != null) { var previousEntity = entitySet.FirstOrDefault(i => i.Id == previousPublishedVersion.EntityId); result.Add(new PublishingAffectedResult() { Id = previousEntity.Id, PublishingStatusOld = previousEntity.PublishingStatusId, PublishingStatusNew = PublishingStatuses[PublishingStatus.OldPublished] }); previousEntity.PublishingStatus = null; previousEntity.PublishingStatusId = PublishingStatuses[PublishingStatus.OldPublished]; } currentLatest.VersionMajor++; currentLatest.VersionMinor = 0; } else { if (targetPublishingStatus == PublishingStatus.Modified) { if (allVersions.Any(i => i.PublishingStatusId == PublishingStatuses[PublishingStatus.Modified])) { throw new PublishModifiedExistsException(); } currentLatest.VersionMinor++; var versioningSet = unitOfWork.GetSet <Versioning>(); originVersioning = entity.VersioningId != null?versioningSet.Where(i => i.Id == entity.VersioningId).Select(i => i.PreviousVersionId).FirstOrDefault() : null; } else { throw new InvalidOperationException($"It is not allowed to 'publish' entity to {targetPublishingStatus} state."); } } result.Add(new PublishingAffectedResult() { Id = entity.Id, PublishingStatusOld = entity.PublishingStatusId, PublishingStatusNew = PublishingStatuses[targetPublishingStatus] }); entity.PublishingStatus = null; entity.PublishingStatusId = PublishingStatuses[targetPublishingStatus]; SetVersioning(entity, unitOfWork.GetSet <Versioning>(), currentLatest, originVersioning); return(result); }
public Guid?GetVersionId <TEntityType>(ITranslationUnitOfWork unitOfWork, Guid rootId, PublishingStatus?publishingStatus = null, bool ignoreDeleted = true) where TEntityType : class, IVersionedVolume { if (!rootId.IsAssigned()) { return(null); } var entityRep = unitOfWork.GetSet <TEntityType>(); Guid entityId; if (publishingStatus == null) { // Get the latest version regardless of the publishing status - NOTE! deleted/archived is ignored // update 12.9.2017: bug reported PTV-2795, because DELETED was ignored, it was not possible to restore archived/deleted version var deletedId = PublishingStatuses[PublishingStatus.Deleted]; var oldPublishedId = PublishingStatuses[PublishingStatus.OldPublished]; entityId = entityRep.Where(i => i.UnificRootId == rootId && i.VersioningId != null && (!ignoreDeleted || (ignoreDeleted && (i.PublishingStatusId != deletedId && i.PublishingStatusId != oldPublishedId)))) .OrderBy(i => i.Versioning.VersionMajor).ThenBy(i => i.Versioning.VersionMinor).Select(i => i.Id).LastOrDefault(); } else { var publishingStatusId = PublishingStatuses[publishingStatus.Value]; entityId = entityRep.Where(i => i.UnificRootId == rootId && i.PublishingStatusId == publishingStatusId).Select(i => i.Id).FirstOrDefault(); } if (!entityId.IsAssigned()) { return(null); } return(entityId); }
public ITranslationDefinitionsForVersioning <TIn, TOut> UseDataContextCreate(Func <TIn, bool> callCondition = null) { if ((callCondition != null) && SkipCallCondition(callCondition)) { return(this); } if (!autoTranslationExplicitlySet) { DisableAutoTranslation(); } if (unitOfWork == null) { EnsureCreateTargetInstance(); return(this); } if (targetInstance != null) { throw new DbEntityExistsInCreateException($"{CoreMessages.EntityExistsInCreate}. {typeof(TIn).Name} - {typeof(TOut).Name}"); } if (EnsureCreateTargetInstance()) { if (targetInstance == null) { throw new DbEntityNotFoundException($"{CoreMessages.EntityNotFoundToUpdate}. {typeof(TIn).Name} - {typeof(TOut).Name}"); } var entitySet = unitOfWork.GetSet <TOut>(); entitySet.Add(targetInstance); } return(this); }
/// <summary> /// Get versioned entity with specific publishing status. /// </summary> /// <typeparam name="TEntityType">Type of entity which will be filtered</typeparam> /// <param name="unitOfWork">Instance of unit of work</param> /// <param name="rootId">ID of unific root which is used as input for searching its specific version</param> /// <param name="publishingStatus">Searching criteria for publishing status</param> /// <returns></returns> public TEntityType GetSpecificVersionByRoot <TEntityType>(ITranslationUnitOfWork unitOfWork, Guid rootId, PublishingStatus publishingStatus) where TEntityType : class, IVersionedVolume, new() { var publishingStatusId = PublishingStatuses[publishingStatus]; var entityRep = unitOfWork.GetSet <TEntityType>(); return(entityRep.FirstOrDefault(i => i.UnificRootId == rootId && i.PublishingStatusId == publishingStatusId)); }
public TranslationDefinitions(IResolveManager resolveManager, ITranslationPrimitives translationPrimitives, ITranslationUnitOfWork unitOfWork, TranslationDirection directionDefinition, IVersioningManager versioningManager, Type typeToInstantiate = null, TOut predefinedTarget = null, Guid?requestlanguageId = null, TranslationPolicy translationPolicies = TranslationPolicy.Defaults) { this.resolveManager = resolveManager; this.translationPrimitives = translationPrimitives; this.directionDefinition = directionDefinition; this.typeToInstantiate = typeToInstantiate ?? typeof(TOut); this.unitOfWork = unitOfWork; this.targetInstance = predefinedTarget; this.requestlanguageIdAssigned = requestlanguageId; var cacheManager = resolveManager.Resolve <ICacheManager>(); this.languageCache = cacheManager.LanguageCache; this.publishingStatusCache = cacheManager.PublishingStatusCache; this.versioningManager = versioningManager; this.translationPolicies = translationPolicies; this.entityOutSet = unitOfWork?.GetSet <TOut>() as IQueryable <TOut>; if (this.unitOfWork != null && this.targetInstance != null) { var cached = unitOfWork.TranslationCloneCache.GetFromCachedSet <TOut>(); clonedTargetApplied = cached.Any(i => i.ClonedEntity == this.targetInstance); } }
/// <summary> /// Acquire UnificRootId from versioned entity by its ID /// </summary> /// <typeparam name="T">Type of versioned entity</typeparam> /// <param name="unitOfWork">Instance of unit of work</param> /// <param name="versionedEntityId">ID of versioned entity</param> /// <returns></returns> public Guid?GetUnificRootId <T>(ITranslationUnitOfWork unitOfWork, Guid?versionedEntityId) where T : class, IVersionedVolume { if (versionedEntityId == null) { return(null); } return(unitOfWork.GetSet <T>().Where(i => i.Id == versionedEntityId).Select(i => i.UnificRootId).FirstOrDefault()); }
public IList <PublishingAffectedResult> ChangeToModified <TEntityType>(ITranslationUnitOfWork unitOfWork, TEntityType entity, List <PublishingStatus> onlyAllowedSourceState = null) where TEntityType : class, IVersionedVolume { var result = new List <PublishingAffectedResult>(); if (onlyAllowedSourceState != null && !onlyAllowedSourceState.Select(i => PublishingStatuses[i]).Contains(entity.PublishingStatusId)) { return(result); } var entitySet = unitOfWork.GetSet <TEntityType>(); var modifiedExists = entitySet.Any(i => i.UnificRootId == entity.UnificRootId && (i.PublishingStatusId == PublishingStatuses[PublishingStatus.Modified] || i.PublishingStatusId == PublishingStatuses[PublishingStatus.Draft])); if (modifiedExists) { throw new InvalidOperationException(); } var targetPublishingStatus = PublishingStatuses[PublishingStatus.Modified]; result.Add(new PublishingAffectedResult() { Id = entity.Id, PublishingStatusOld = entity.PublishingStatusId, PublishingStatusNew = targetPublishingStatus }); entity.PublishingStatus = null; entity.PublishingStatusId = targetPublishingStatus; var versioningSet = unitOfWork.GetSet <Versioning>(); if (entity.VersioningId != null && entity.Versioning == null) { entity.Versioning = versioningSet.FirstOrDefault(i => i.Id == entity.VersioningId); } var allVersions = GetAllVersions(unitOfWork, entity); var lastVersion = allVersions.LastOrDefault() ?? new VersionInfo() { EntityId = entity.Id, VersionMajor = 0, VersionMinor = 0 }; lastVersion.VersionMinor++; SetVersioning(entity, versioningSet, lastVersion, entity.Versioning?.PreviousVersionId); return(result); }
/// <summary> /// Get and return all available versions of entity /// </summary> /// <typeparam name="TEntityType"></typeparam> /// <param name="unitOfWork">Unit Of Work must be provided for correct functionality</param> /// <param name="unificRootId">Entity unificrootId which versions will be retrieved</param> /// <returns>List of available versions of specified entity</returns> public List <VersionInfo> GetAllVersions <TEntityType>(ITranslationUnitOfWork unitOfWork, Guid unificRootId) where TEntityType : class, IVersionedVolume { var entityRep = unitOfWork.GetSet <TEntityType>(); List <TEntityType> relatedEntitiesList = entityRep.Where(i => (i.UnificRootId == unificRootId) && (i.VersioningId != null)).Include(i => i.Versioning).ToList(); return(relatedEntitiesList.Select(i => new VersionInfo() { EntityId = i.Id, VersionMajor = i.Versioning.VersionMajor, VersionMinor = i.Versioning.VersionMinor, Modified = i.Versioning.Modified, PublishingStatusId = i.PublishingStatusId, // ReSharper disable once PossibleInvalidOperationException VersionId = i.VersioningId.Value }) .OrderBy(i => i.VersionMajor) .ThenBy(i => i.VersionMinor) .ToList()); }
/// <summary> /// Perform cloning of entity by calling spcified definitions /// </summary> /// <param name="unitOfWork">Unit of work instance for creating requests to DB</param> /// <param name="entity">Instance of entity which will be cloned</param> /// <param name="beforeAddAction">Optional additional action which can be called before entity is added to db set</param> /// <param name="cloningMode"></param> /// <returns>Copy of entity</returns> public TEntity PerformCloning(ITranslationUnitOfWork unitOfWork, TEntity entity, Action <TEntity> beforeAddAction = null, CloningMode cloningMode = CloningMode.Cloning) { this.cloningMode = cloningMode; if (entity == null) { return(null); } this.unitOfWork = unitOfWork; if (this.entitySet == null) { this.entitySet = unitOfWork.GetSet <TEntity>(); } source = entity; if (cloningMode == CloningMode.Cloning) { target = Activator.CreateInstance <TEntity>(); BaseTranslator.TranslateWithExceptions(entity, target, foreignKeys.Select(i => i.Name)); entityPropsDefs.PrimaryKeysDefinition.Where(i => !i.IsPrimaryAndForeign && i.Type == typeof(Guid)).ForEach(i => { target.SetPropertyValue(i.Name, Guid.NewGuid()); }); } CloningDefinition(); if (cloningMode == CloningMode.Cloning) { TranslateProperties(entity, target, foreignKeys.Select(i => i.Name).Except(affectedForeignKeys)); beforeAddAction?.Invoke(target); this.entitySet.Add(target); } if (cloningMode == CloningMode.Cloning || cloningMode == CloningMode.TreeCreating) { unitOfWork.TranslationCloneCache.AddToCachedSet(source, target); } if (cloningMode == CloningMode.Deleting) { this.entitySet.Remove(source); } return(target); }
/// <summary> /// Change publishing status of language version of specific entity which is of IMultilanguagedEntity type /// </summary> /// <typeparam name="T">Type of entity</typeparam> /// <typeparam name="TLang">Type of langauge version relation</typeparam> /// <param name="unitOfWork">Unit of work instance</param> /// <param name="entityId">Entity to change</param> /// <param name="languageAvailabilities">languages to change</param> public void ChangeStatusOfLanguageVersion <T, TLang>(ITranslationUnitOfWork unitOfWork, Guid entityId, IEnumerable <VmLanguageAvailabilityInfo> languageAvailabilities) where T : class, IEntityIdentifier, IMultilanguagedEntity <TLang>, new() where TLang : class, ILanguageAvailability { var entity = unitOfWork.GetSet <T>().Include(i => i.LanguageAvailabilities).FirstOrDefault(i => i.Id == entityId); ChangeStatusOfLanguageVersion <T, TLang>(unitOfWork, entity, languageAvailabilities); }
/// <summary> /// Create requested version of entity if it is needed. Status of entity is checked, if it is already Published, then entity is copied and marked as Modified. /// </summary> /// <typeparam name="TEntityType">Type of entity which will be checked and cloned if needed.</typeparam> /// <param name="unitOfWork">Instance of unit of work</param> /// <param name="entity">Entity which will be checked and cloned if needed.</param> /// <param name="versioningMode">Optional parameter how versionig should work, default is Standard mode, when Modified is created in case of update operation</param> /// <param name="targetStatus">target status of cloned entity</param> /// <returns></returns> public TEntityType CreateEntityVersion <TEntityType>(ITranslationUnitOfWork unitOfWork, TEntityType entity, VersioningMode versioningMode = VersioningMode.Standard, PublishingStatus?targetStatus = null) where TEntityType : class, IVersionedVolume, new() { if (entity == null) { return(null); } if (!AllowedToProcessVersioned(entity)) { throw new Exception(CoreMessages.CannotProcessThisVersion); } var allVersions = GetAllVersions(unitOfWork, entity); var versioningSet = unitOfWork.GetSet <Versioning>(); var currentLatest = allVersions.LastOrDefault(); if (currentLatest == null) { var publishingStatusDraftId = PublishingStatuses[PublishingStatus.Draft]; if ((entity.PublishingStatusId == Guid.Empty) || (entity.PublishingStatusId == publishingStatusDraftId)) { entity.PublishingStatusId = publishingStatusDraftId; currentLatest = new VersionInfo() { VersionMajor = 0, VersionMinor = 1 }; } else { currentLatest = new VersionInfo() { VersionMajor = 1, VersionMinor = 0 }; } return(SetVersioning(entity, versioningSet, currentLatest)); } if (versioningMode == VersioningMode.UseTheLatest) { return(GetRelatedEntity(unitOfWork, entity, currentLatest)); } if (versioningMode == VersioningMode.UseDraftOrPublishedOnly) { return(GetRelatedEntity(unitOfWork, entity, allVersions.LastOrDefault(i => i.PublishingStatusId == PublishingStatuses[PublishingStatus.Published] || i.PublishingStatusId == PublishingStatuses[PublishingStatus.Draft]))); } if (versioningMode == VersioningMode.UsePublishedOnly) { return(GetRelatedEntity(unitOfWork, entity, allVersions.LastOrDefault(i => i.PublishingStatusId == PublishingStatuses[PublishingStatus.Published]))); } var modifiedVersions = allVersions.Where(i => (i.PublishingStatusId == PublishingStatuses[PublishingStatus.Modified]) || (i.PublishingStatusId == PublishingStatuses[PublishingStatus.Draft])).ToList(); if (modifiedVersions.Any() && targetStatus == null) { var modifiedVersion = modifiedVersions.LastOrDefault(i => i.EntityId == entity.Id) ?? modifiedVersions.Last(); currentLatest.VersionMinor++; var verInfo = versioningSet.First(i => i.Id == modifiedVersion.VersionId); verInfo.VersionMinor = currentLatest.VersionMinor; verInfo.VersionMajor = currentLatest.VersionMajor; return(GetRelatedEntity(unitOfWork, entity, modifiedVersion)); } if (targetStatus == PublishingStatus.Published) { var pCloned = entity.PublishingStatusId == PublishingStatuses[PublishingStatus.Modified] || entity.PublishingStatusId == PublishingStatuses[PublishingStatus.Draft] ? entity : cloningManager.CloneEntity(entity, unitOfWork); currentLatest.VersionMajor++; currentLatest.VersionMinor = 0; entity.PublishingStatusId = PublishingStatuses[PublishingStatus.OldPublished]; SetVersioning(pCloned, versioningSet, currentLatest, entity.VersioningId, true); pCloned.PublishingStatusId = PublishingStatuses[targetStatus.Value]; return(pCloned); } var previousVersionId = entity.VersioningId; var cloned = cloningManager.CloneEntity(entity, unitOfWork); currentLatest.VersionMinor++; SetVersioning(cloned, versioningSet, currentLatest, previousVersionId, true); cloned.PublishingStatusId = PublishingStatuses[PublishingStatus.Modified]; return(cloned); }
public bool IsEntityArchived <TEntityType>(ITranslationUnitOfWork unitOfWork, Guid entityId) where TEntityType : class, IVersionedVolume { var entity = unitOfWork.GetSet <TEntityType>().FirstOrDefault(i => i.Id == entityId); return(entity.PublishingStatusId == PublishingStatuses[PublishingStatus.Deleted] || entity.PublishingStatusId == PublishingStatuses[PublishingStatus.OldPublished]); }
public bool IsAllowedForEditing <TEntityType>(ITranslationUnitOfWork unitOfWork, Guid entityId) where TEntityType : class, IVersionedVolume { var entity = unitOfWork.GetSet <TEntityType>().FirstOrDefault(i => i.Id == entityId); return(IsAllowedForEditing(unitOfWork, entity)); }