/// <summary>
        /// Reverts part of the schema relevant to a problem to the state which when compared to its current
        /// state, regenerates the problem. The inverse of ResolveProblem.
        /// </summary>
        /// <param name="oldSchema">the old schema which generated the problem when compared to the current schema</param>
        /// <param name="problem">the problem it generated</param>
        public void ApplyProblem(ContentModelSchema oldSchema, ChangeProblem problem)
        {
            string aqTypeName = problem.GetAssemblyQualifiedTypeName();

            switch (problem.ProblemType)
            {
            case ChangeProblemType.DeletionNeeded:
                // copy the deleted type to the new schema
                TypeProperties.Add(aqTypeName, oldSchema.TypeProperties[aqTypeName]);
                break;

            case ChangeProblemType.PropertyDropped:
                // copy the dropped property to the new schema
                TypeProperties[aqTypeName].Add(problem.PropertyName, oldSchema.TypeProperties[aqTypeName][problem.PropertyName]);
                break;

            case ChangeProblemType.PropertyDroppedFromSummary:
                Type   contentType       = ContentTypeHierarchy.GetContentType(problem.TypeName);
                string aqSummaryTypeName = ContentTypeHierarchy.SummaryTypes[contentType].AssemblyQualifiedName;
                TypeProperties[aqTypeName].Add(problem.PropertyName, oldSchema.TypeProperties[aqTypeName][problem.PropertyName]);
                TypeProperties[aqSummaryTypeName].Add(problem.PropertyName, oldSchema.TypeProperties[aqSummaryTypeName][problem.PropertyName]);
                break;

            // Problems not requiring data modification
            case ChangeProblemType.NullObjectValue:
                break;
            }
        }
示例#2
0
 /// <summary>
 /// Build a ContentModelSchema from the current state of the content types
 /// </summary>
 /// <returns>A ContentModelSchema storing the current state</returns>
 public static ContentModelSchema Build()
 {
     var schema = new ContentModelSchema();
     var contentPersistenceTypes = ContentTypeHierarchy.AllContentTypes
         .Where(ct => Collator.Instance.Registered(ct) is ContentCollator);
     foreach (Type t in contentPersistenceTypes)
         schema.AddContentType(t);
     foreach (var kvp in ContentTypeHierarchy.SummaryTypes)
         schema.AddSummaryType(kvp.Key, kvp.Value);
     return schema;
 }
        public ContentModelSchema Copy()
        {
            var copy = new ContentModelSchema
            {
                ContentTypes   = this.ContentTypes.ToList(),
                SummaryMap     = this.SummaryMap.ToDictionary(kvp => kvp.Key, kvp => kvp.Value),
                SummaryTypes   = this.SummaryTypes.ToDictionary(kvp => kvp.Key, kvp => kvp.Value),
                TypeProperties = this.TypeProperties.ToDictionary(kvp => kvp.Key,
                                                                  kvp => kvp.Value.ToDictionary(kvp2 => kvp2.Key, kvp2 => kvp2.Value)),
            };

            return(copy);
        }
        /// <summary>
        /// Build a ContentModelSchema from the current state of the content types
        /// </summary>
        /// <returns>A ContentModelSchema storing the current state</returns>
        public static ContentModelSchema Build()
        {
            var schema = new ContentModelSchema();
            var contentPersistenceTypes = ContentTypeHierarchy.AllContentTypes
                                          .Where(ct => Collator.Instance.Registered(ct) is ContentCollator);

            foreach (Type t in contentPersistenceTypes)
            {
                schema.AddContentType(t);
            }
            foreach (var kvp in ContentTypeHierarchy.SummaryTypes)
            {
                schema.AddSummaryType(kvp.Key, kvp.Value);
            }
            return(schema);
        }
示例#5
0
        /// <summary>
        /// Reverts part of the schema relevant to a problem to the state which when compared to its current
        /// state, regenerates the problem. The inverse of ResolveProblem.
        /// </summary>
        /// <param name="oldSchema">the old schema which generated the problem when compared to the current schema</param>
        /// <param name="problem">the problem it generated</param>
        public void ApplyProblem(ContentModelSchema oldSchema, ChangeProblem problem)
        {
            switch (problem.ProblemType)
            {
            case ChangeProblemType.DeletionNeeded:
                // copy the deleted type to the new schema
                TypeProperties.Add(problem.TypeName, oldSchema.TypeProperties[problem.TypeName]);
                break;

            case ChangeProblemType.PropertyDropped:
            case ChangeProblemType.PropertyDroppedFromSummary:
                // copy the dropped property to the new schema
                TypeProperties[problem.TypeName].Add(problem.PropertyName, oldSchema.TypeProperties[problem.TypeName][problem.PropertyName]);
                break;

            // Problems not requiring data modification
            case ChangeProblemType.NotBinarySerializable:
            case ChangeProblemType.NullObjectValue:
                break;
            }
        }
示例#6
0
 public override bool Initialise()
 {
     LastSchema = null;
     Load();
     CurrentSchema = ContentModelSchema.Build();
     if (LastSchema != null)
     {
         ContentRepository.ChangeProblems = LastSchema.FindProblems(CurrentSchema);
         if (ContentRepository.ChangeProblems.Any())
             LyniconUi.Instance.ShowProblemAlert = true;
     }
     return true;
 }
示例#7
0
        public void Load()
        {
            FileInfo fi = new FileInfo(Paths.AppDataPath + "\\ContentSchema\\LastSchema.json");

            if (fi.Exists)
            {
                try
                {
                    var sz = new JsonSerializer();
                    using (var stream = fi.OpenRead())
                    using (var reader = new StreamReader(stream))
                    using (var jsonTextReader = new JsonTextReader(reader))
                    {
                        LastSchema = sz.Deserialize<ContentModelSchema>(jsonTextReader);
                    }
                }
                catch (Exception ex)
                {
                    log.Error(ex);
                }
            }
        }
        /// <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 aqTypeName in codeSchema.TypeProperties.Keys)
            {
                string typeName = aqTypeName.UpTo(",");
                Type   type     = ContentTypeHierarchy.GetAnyType(typeName);
                if (type == null)
                {
                    type = Type.GetType(aqTypeName);
                    otherTypes.Add(aqTypeName, type);
                }
            }

            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(type.FullName, nullProperty.Name, ChangeProblemType.NullObjectValue));
                }
            }

            // Types existing in both code and data schemas
            foreach (string aqTypeName in codeSchema.TypeProperties.Keys.Intersect(TypeProperties.Keys))
            {
                string typeName  = aqTypeName.UpTo(",");
                bool   isSummary = ContentTypeHierarchy.GetSummaryType(typeName) != null;
                if (isSummary && !this.SummaryMap.ContainsKey(typeName))
                {
                    log.Warn("Unused summary type: " + typeName);
                    continue;
                }
                foreach (string deletedProp in TypeProperties[aqTypeName].Keys.Except(codeSchema.TypeProperties[aqTypeName].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[ContentTypeHierarchy.GetContentType(kvp.Key).AssemblyQualifiedName].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[aqTypeName].Keys.Except(TypeProperties[aqTypeName].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[ContentTypeHierarchy.GetContentType(kvp.Key).AssemblyQualifiedName].ContainsKey(newContentProp));
                            if (anyContentTypeContainedProp)
                            {
                                changeProblems.Add(new ChangeProblem(typeName, addedProp, ChangeProblemType.PropertyAddedToSummary));
                            }
                        }
                    }
                }
            }

            return(changeProblems);
        }
示例#9
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;
        }
示例#10
0
        /// <summary>
        /// Reverts part of the schema relevant to a problem to the state which when compared to its current
        /// state, regenerates the problem. The inverse of ResolveProblem.
        /// </summary>
        /// <param name="oldSchema">the old schema which generated the problem when compared to the current schema</param>
        /// <param name="problem">the problem it generated</param>
        public void ApplyProblem(ContentModelSchema oldSchema, ChangeProblem problem)
        {
            switch (problem.ProblemType)
            {
                case ChangeProblemType.DeletionNeeded:
                    // copy the deleted type to the new schema
                    TypeProperties.Add(problem.TypeName, oldSchema.TypeProperties[problem.TypeName]);
                    break;
                case ChangeProblemType.PropertyDropped:
                case ChangeProblemType.PropertyDroppedFromSummary:
                    // copy the dropped property to the new schema
                    TypeProperties[problem.TypeName].Add(problem.PropertyName, oldSchema.TypeProperties[problem.TypeName][problem.PropertyName]);
                    break;

                // Problems not requiring data modification
                case ChangeProblemType.NotBinarySerializable:
                case ChangeProblemType.NullObjectValue:
                    break;
            }
        }