예제 #1
0
        /// <summary>
        /// Find problems in the changes between two schemas by comparing this
        /// recorded schema to a given schema (usually the current schema)
        /// </summary>
        /// <param name="codeSchema">The current schema</param>
        /// <returns>List of potential problems arising from the differences between the schemas</returns>
        public List <ChangeProblem> FindProblems(ContentModelSchema codeSchema)
        {
            var changeProblems = new List <ChangeProblem>();

            foreach (string typeName in this.ContentTypes.Except(codeSchema.ContentTypes))
            {
                changeProblems.Add(new ChangeProblem(typeName, null, ChangeProblemType.DeletionNeeded));
            }

            var otherTypes = new Dictionary <string, Type>();

            foreach (string typeName in codeSchema.TypeProperties.Keys)
            {
                // Check its binary serializable
                Type type = ContentTypeHierarchy.GetAnyType(typeName);
                if (type == null)
                {
                    type = ReflectionX.GetLoadedType(typeName);
                    otherTypes.Add(typeName, type);
                }
                if (type != null && type.GetCustomAttribute <SerializableAttribute>() == null)
                {
                    changeProblems.Add(new ChangeProblem(typeName, null, ChangeProblemType.NotBinarySerializable));
                }
            }

            foreach (string typeName in codeSchema.ContentTypes)
            {
                // Check it doesn't initialise with a null value for an object or list property
                Type type = ContentTypeHierarchy.GetAnyType(typeName);
                if (type == null)
                {
                    type = otherTypes[typeName];
                }
                PropertyInfo nullProperty = new NoNullObjectCheck().Run(type);
                // Exception for UniqueId of Summary
                if (nullProperty != null && !(nullProperty.DeclaringType == typeof(Summary) && nullProperty.Name == "UniqueId"))
                {
                    changeProblems.Add(new ChangeProblem(nullProperty.ReflectedType.FullName, nullProperty.Name, ChangeProblemType.NullObjectValue));
                }
            }

            // Types existing in both code and data schemas
            foreach (string typeName in codeSchema.TypeProperties.Keys.Intersect(TypeProperties.Keys))
            {
                bool isSummary = ContentTypeHierarchy.GetSummaryType(typeName) != null;
                if (isSummary && !this.SummaryMap.ContainsKey(typeName))
                {
                    log.Warn("Unused summary type: " + typeName);
                    continue;
                }
                foreach (string deletedProp in TypeProperties[typeName].Keys.Except(codeSchema.TypeProperties[typeName].Keys))
                {
                    if (isSummary)
                    {
                        // Test for when a property is dropped from the summary which was mapped to the content type
                        // In this case the property data needs copied from the Summary db field to the Content one
                        if (this.SummaryMap[typeName].ContainsValue(deletedProp) &&
                            this.SummaryTypes.ContainsValue(typeName))
                        {
                            var  oldContentProp            = this.SummaryMap[typeName].Single(kvp => kvp.Value == deletedProp).Key;
                            bool anyContentTypeHadProperty = this.SummaryTypes
                                                             .Where(kvp => kvp.Value == typeName)
                                                             .Any(kvp => TypeProperties[kvp.Key].ContainsKey(oldContentProp));
                            if (anyContentTypeHadProperty)
                            {
                                changeProblems.Add(new ChangeProblem(typeName, deletedProp, ChangeProblemType.PropertyDroppedFromSummary));
                            }
                        }
                    }
                    else
                    {
                        changeProblems.Add(new ChangeProblem(typeName, deletedProp, ChangeProblemType.PropertyDropped));
                    }
                }

                foreach (string addedProp in codeSchema.TypeProperties[typeName].Keys.Except(TypeProperties[typeName].Keys))
                {
                    if (isSummary)
                    {
                        // Test for when a property is added to the summary which is mapped from the content type
                        // In this case the data needs copied from the Content db field to the Summary
                        if (codeSchema.SummaryMap[typeName].ContainsValue(addedProp) &&
                            codeSchema.SummaryTypes.ContainsValue(typeName))
                        {
                            var newContentProp = codeSchema.SummaryMap[typeName].Single(kvp => kvp.Value == addedProp).Key;
                            var anyContentTypeContainedProp = codeSchema.SummaryTypes
                                                              .Where(kvp => kvp.Value == typeName)
                                                              .Any(kvp => TypeProperties[kvp.Key].ContainsKey(newContentProp));
                            if (anyContentTypeContainedProp)
                            {
                                changeProblems.Add(new ChangeProblem(typeName, addedProp, ChangeProblemType.PropertyAddedToSummary));
                            }
                        }
                    }
                }
            }

            return(changeProblems);
        }