コード例 #1
0
        /// <summary>
        /// Runs the provided package by a set of rules
        /// </summary>
        /// <returns>null on success, or an IHttpActionResult on a failure</returns>
        private IHttpActionResult ValidatePackage(WorkPackageDTO package)
        {
            // get the list of child packages
            var allPackages = new ListSet<WorkPackageDTO>(package.AllChildren)
                              {
                                  package // include the root package to make coding life easier
                              };
            
            // load any existing packages from the context
            var childPackagesFromDb = this._workPackageRepository.GetAll(allPackages.Select(wp => wp.Id).Where(i => i > 0)).ToDictionary(wp => wp.Id);


            // first pass - replace non modifyable packages with their current data from the db
            var newPackageCount = -1;
            var newTaskCount = -1;
            for (var i = 0; i < allPackages.Count; i++)
            {
                var pkg = allPackages[i];

                if (childPackagesFromDb.ContainsKey(pkg.Id))
                {
                    // we're dealing with an existing package

                    var fromDb = childPackagesFromDb[pkg.Id];
                    if (fromDb.IsReadOnlyFor(this._currentUser))
                    {
                        // ignore any changes to packages the user has no right to change
                        allPackages[i] = Mapper.Map<WorkPackageDTO>(fromDb);
                        continue;
                    }
                    else
                    {
                        // note that we don't update the values here - it gets done by the repository
                    }
                }
                else
                {
                    // we're dealing with a new package

                    pkg.Id = newPackageCount--;
                    pkg.CreatedBy = this._currentUserDto;
                }

                // make sure each of the tasks have a unique Id
                foreach (var task in pkg.Tasks.Where(t => t.Id < 0))
                {
                    task.Id = newTaskCount--;
                }
            }


            // second pass - update the packages with correct references
            // note that whilst we don't update the read only package's content (tasks, name, etc) - we do have to make sure it has the correct package references
            //      so that EF doesn't try and add two of the same package
            var childDict = allPackages.ToDictionary(wp => wp.Id);
            var processedPackages = new HashSet<WorkPackageDTO>();
            foreach (var pkg in allPackages)
            {
                if (!Utilities.IsNullOrEmpty(pkg.ChildPackages) && // save a little time in processing packages with no children
                    !processedPackages.Contains(pkg)) // don't reprocess packages
                {
                    pkg.ChildPackages = new ListSet<WorkPackageDTO>(pkg.ChildPackages.Select(child => childDict[child.Id]));
                }
                processedPackages.Add(pkg);
            }

            // third pass - check for cycles
            // we do this last because we may remove a cycle when we clean up readonly packages
            var packageWithCycle = package.DetectCycles();
            if (packageWithCycle != null)
            {
                return this.BadRequest(string.Format(Resources.Error_CreatePackage_Cycles, packageWithCycle.Id));
            }
            return null;
        }