public void CheckIn()
        {
            AssertValidAction(StateAction.CheckIn);

            if (!HasApproving)
            {
                // Approving OFF
                switch (VersioningMode)
                {
                case VersioningMode.None:
                    DeleteVersionsAndApprove();
                    break;

                case VersioningMode.Major:
                    // remove all working versions, except current
                    DeletableVersionIds.AddRange(GetLastWorkingVersions().Select(x => x.VersionId));
                    DeletableVersionIds.Remove(CurrentVersionId);

                    var lastApproved = GetLastApprovedVersion();
                    ExpectedVersion = lastApproved != null?
                                      GetNextPublicVersion(lastApproved.VersionNumber, VersionStatus.Approved) :
                                          ComputeNewVersion();

                    ExpectedVersionId = CurrentVersionId;
                    break;

                case VersioningMode.Full:
                    ExpectedVersion   = CurrentVersion.ChangeStatus(VersionStatus.Draft);
                    ExpectedVersionId = CurrentVersionId;
                    break;
                }
            }
            else
            {
                // Approving ON
                switch (VersioningMode)
                {
                case VersioningMode.None:
                    DeleteVersionsAndPreserveLastWorking();
                    break;

                case VersioningMode.Major:
                    ExpectedVersion   = CurrentVersion.ChangeStatus(VersionStatus.Pending);
                    ExpectedVersionId = CurrentVersionId;
                    break;

                case VersioningMode.Full:
                    ExpectedVersion   = CurrentVersion.ChangeStatus(VersionStatus.Draft);
                    ExpectedVersionId = CurrentVersionId;
                    break;
                }
            }

            // Unlock
            this.LockerUserId = 0;
        }
        public void Reject()
        {
            AssertValidAction(StateAction.Reject);

            if (!HasApproving)
            {
                return;
            }

            ExpectedVersion   = CurrentVersion.ChangeStatus(VersionStatus.Rejected);
            ExpectedVersionId = CurrentVersionId;
        }
        public void Publish()
        {
            AssertValidAction(StateAction.Publish);

            if (!HasApproving)
            {
                // Approving OFF
                switch (VersioningMode)
                {
                case VersioningMode.None:
                    DeleteVersionsAndApprove();
                    break;

                case VersioningMode.Major:
                    ExpectedVersion   = GetNextPublicVersion(VersionStatus.Approved);
                    ExpectedVersionId = CurrentVersionId;
                    break;

                case VersioningMode.Full:
                    ExpectedVersion   = GetNextPublicVersion(VersionStatus.Approved);
                    ExpectedVersionId = CurrentVersionId;
                    break;
                }
            }
            else
            {
                // Approving ON
                if (VersioningMode != VersioningMode.Full)
                {
                    throw new SnNotSupportedException();
                }

                if (CurrentVersion.Status == VersionStatus.Rejected)
                {
                    ExpectedVersion = GetNextNonpublicVersion(VersionStatus.Pending);
                }
                else
                {
                    ExpectedVersion   = CurrentVersion.ChangeStatus(VersionStatus.Pending);
                    ExpectedVersionId = CurrentVersionId;
                }
            }

            // Unlock
            this.LockerUserId = 0;
        }
        public void CheckOutAndSaveAndCheckIn()
        {
            if (CurrentVersion == null)
            {
                Create();
                return;
            }
            AssertValidAction(StateAction.SaveAndCheckIn);
            // Expected version
            if (!HasApproving)
            {
                // Approving OFF
                switch (VersioningMode)
                {
                case VersioningMode.None:
                    DeleteVersionsAndApprove();
                    break;

                case VersioningMode.Major:
                    // remove all working versions, except current
                    var irrelevantIds = GetLastWorkingVersions().Select(x => x.VersionId);

                    DeletableVersionIds.AddRange(irrelevantIds);
                    DeletableVersionIds.Remove(CurrentVersionId);

                    var lastApproved = GetLastApprovedVersion();

                    ExpectedVersion = lastApproved != null?
                                      GetNextPublicVersion(lastApproved.VersionNumber, VersionStatus.Approved) :
                                          ComputeNewVersion();

                    // preserve last working version
                    if (CurrentVersion.Status != VersionStatus.Approved && CurrentVersion.Status != VersionStatus.Rejected)
                    {
                        ExpectedVersionId = CurrentVersionId;
                    }

                    break;

                case VersioningMode.Full:
                    this.ExpectedVersion = GetNextNonpublicVersion(VersionStatus.Draft);
                    this.LockerUserId    = 0;
                    ExpectedVersionId    = 0;
                    break;
                }
            }
            else
            {
                // Approving ON
                switch (VersioningMode)
                {
                case VersioningMode.None:
                    DeleteVersionsAndPreserveLastWorking();
                    break;

                case VersioningMode.Major:
                    switch (CurrentVersion.Status)
                    {
                    case VersionStatus.Approved:         // raise
                    case VersionStatus.Rejected:         // raise
                        this.ExpectedVersion = GetNextNonpublicVersion(VersionStatus.Pending);
                        break;

                    case VersionStatus.Draft:            // preserve
                    case VersionStatus.Pending:          // preserve
                        ExpectedVersion   = CurrentVersion.ChangeStatus(VersionStatus.Pending);
                        ExpectedVersionId = CurrentVersionId;
                        break;

                    default:
                        throw new NotSupportedException();
                    }
                    break;

                case VersioningMode.Full:
                    this.ExpectedVersion = GetNextNonpublicVersion(VersionStatus.Draft);
                    ExpectedVersionId    = 0;
                    break;
                }
            }

            // Unlock
            this.LockerUserId = 0;
        }