protected virtual void CreateTemplate([NotNull] ICompileContext context, [NotNull] IProject project, [NotNull] Item templateItem)
        {
            var template = Factory.Template(templateItem.Database, templateItem.Uri.Guid, templateItem.ItemName, templateItem.ItemIdOrPath).With(templateItem.SourceTextNode, false, templateItem.IsImport);

            template.IsSynthetic = true;

            var baseTemplateField = templateItem.Fields.FirstOrDefault(f => f.FieldName == Constants.FieldNames.BaseTemplate);

            if (baseTemplateField != null)
            {
                template.BaseTemplatesProperty.SetValue(baseTemplateField.ValueProperty);
            }

            var iconField = templateItem.Fields.FirstOrDefault(f => f.FieldName == Constants.FieldNames.Icon);

            if (iconField != null)
            {
                template.IconProperty.SetValue(iconField.ValueProperty);
            }

            foreach (var sectionItem in templateItem.Children)
            {
                var templateSection = Factory.TemplateSection(template, sectionItem.Uri.Guid).With(sectionItem.SourceTextNode);
                templateSection.IsSynthetic = true;
                template.Sections.Add(templateSection);
                templateSection.SectionNameProperty.SetValue(sectionItem.ItemNameProperty);

                var sectionIconField = sectionItem.Fields.FirstOrDefault(f => f.FieldName == Constants.FieldNames.Icon);
                if (sectionIconField != null)
                {
                    templateSection.IconProperty.SetValue(sectionIconField.ValueProperty);
                }

                var sectionSortorderField = sectionItem.Fields.FirstOrDefault(f => f.FieldName == Constants.FieldNames.SortOrder);
                if (sectionSortorderField != null)
                {
                    if (int.TryParse(sectionSortorderField.Value, out var sortorder))
                    {
                        templateSection.SortorderProperty.SetValue(sortorder);
                    }
                }

                foreach (var fieldItem in sectionItem.Children)
                {
                    var templateField = Factory.TemplateField(template, fieldItem.Uri.Guid).With(fieldItem.SourceTextNode);
                    templateField.IsSynthetic = true;
                    templateSection.Fields.Add(templateField);
                    templateField.FieldNameProperty.SetValue(fieldItem.ItemNameProperty);

                    var typeField = fieldItem.Fields.FirstOrDefault(f => f.FieldName == Constants.FieldNames.Type);
                    if (typeField != null)
                    {
                        templateField.TypeProperty.SetValue(typeField.ValueProperty);
                    }
                }
            }

            project.AddOrMerge(template);
        }
        protected virtual void ExtractItem([NotNull] IProject project, [NotNull] string entryName, [NotNull] XElement element)
        {
            var parts        = entryName.Split('/');
            var databaseName = parts[1];
            var itemIdOrPath = '/' + string.Join("/", parts.Take(parts.Length - 4).Skip(2));

            var itemName         = element.GetAttributeValue("name");
            var guid             = Guid.Parse(element.GetAttributeValue("id"));
            var templateIdOrPath = element.GetAttributeValue("tid");

            var database = project.GetDatabase(databaseName);
            var item     = Factory.Item(database, guid, itemName, itemIdOrPath, templateIdOrPath);

            item.IsEmittable = true;

            item.Sortorder = int.Parse(element.GetAttributeValue("sortorder"));

            var language = Factory.Language(element.GetAttributeValue("language"));
            var version  = Factory.Version(int.Parse(element.GetAttributeValue("version")));

            var fieldsElement = element.Element("fields");

            if (fieldsElement != null)
            {
                foreach (var fieldElement in fieldsElement.Elements())
                {
                    var field = Factory.Field(item, fieldElement.GetAttributeValue("key"), fieldElement.GetElementValue("content"));
                    field.FieldId  = Guid.Parse(fieldElement.GetAttributeValue("tfid"));
                    field.Language = language;
                    field.Version  = version;

                    item.Fields.Add(field);
                }
            }

            project.AddOrMerge(item);
        }
        protected virtual void ImportElement([NotNull] IProject project, [NotNull] string fileName, [NotNull] string defaultDatabaseName, [NotNull] XElement element)
        {
            Guid guid;

            if (!Guid.TryParse(element.GetAttributeValue("Id"), out guid))
            {
                Trace.TraceError(Msg.I1003, Texts.Failed_to_parse_Id_, fileName);
                return;
            }

            var databaseName = element.GetAttributeValue("Database", defaultDatabaseName) ?? defaultDatabaseName;
            var database     = project.GetDatabase(databaseName);
            var itemIdOrPath = element.GetAttributeValue("Path");
            var itemName     = itemIdOrPath.Mid(itemIdOrPath.LastIndexOf('/') + 1);

            switch (element.Name.LocalName)
            {
            case "Item":
                var item = Factory.Item(database, guid, itemName, itemIdOrPath, element.GetAttributeValue("Template"));
                item.IsImport    = true;
                item.IsEmittable = false;

                foreach (var field in element.Elements())
                {
                    item.Fields.Add(Factory.Field(item, field.GetAttributeValue("Name"), field.GetAttributeValue("Value")));
                }

                project.AddOrMerge(item);
                break;

            case "Template":
                var template = Factory.Template(database, guid, itemName, itemIdOrPath);
                template.IsImport      = true;
                template.IsEmittable   = false;
                template.BaseTemplates = element.GetAttributeValue("BaseTemplates");

                if (string.IsNullOrEmpty(template.BaseTemplates))
                {
                    template.BaseTemplates = Constants.Templates.StandardTemplateId;
                }

                foreach (var sectionElement in element.Elements())
                {
                    Guid sectionGuid;
                    if (!Guid.TryParse(sectionElement.GetAttributeValue("Id"), out sectionGuid))
                    {
                        Trace.TraceError(Msg.I1004, Texts.Failed_to_parse_Id_, fileName);
                        return;
                    }

                    var templateSection = Factory.TemplateSection(template, sectionGuid);
                    templateSection.SectionName = sectionElement.GetAttributeValue("Name");

                    foreach (var fieldElement in sectionElement.Elements())
                    {
                        Guid fieldGuid;
                        if (!Guid.TryParse(fieldElement.GetAttributeValue("Id"), out fieldGuid))
                        {
                            Trace.TraceError(Msg.I1005, Texts.Failed_to_parse_Id_, fileName);
                            return;
                        }

                        var templateField = Factory.TemplateField(template, fieldGuid);
                        templateField.FieldName = fieldElement.GetAttributeValue("Name");
                        templateField.Type      = fieldElement.GetAttributeValue("Type", "Single-Line Text") ?? "Single-Line Text";

                        switch (fieldElement.GetAttributeValue("Sharing"))
                        {
                        case "Unversioned":
                            templateField.Unversioned = true;
                            break;

                        case "Versioned":
                            break;

                        default:
                            templateField.Shared = true;
                            break;
                        }

                        templateSection.Fields.Add(templateField);
                    }

                    template.Sections.Add(templateSection);
                }

                project.AddOrMerge(template);
                break;
            }
        }
        protected virtual void CreateItems([NotNull] ICompileContext context, [NotNull] IProject project, [NotNull] Template template)
        {
            var item = Factory.Item(template.Database, template.Uri.Guid, template.ItemName, template.ItemIdOrPath, Constants.Templates.TemplateId).With(template.SourceTextNode);

            item.IsEmittable = false;
            item.IsImport    = template.IsImport;
            item.IsSynthetic = true;
            item.IconProperty.SetValue(template.IconProperty);
            item.Fields.Add(Factory.Field(item, Constants.FieldNames.BaseTemplate, template.BaseTemplates).With(template.BaseTemplatesProperty.SourceTextNode));

            if (!string.IsNullOrEmpty(template.LongHelp))
            {
                var field = Factory.Field(item, Constants.FieldNames.LongDescription, template.LongHelp).With(template.LongHelpProperty.SourceTextNode);
                field.Language = context.Project.Context.Language;
                field.Version  = Version.Latest;
                item.Fields.Add(field);
            }

            if (!string.IsNullOrEmpty(template.ShortHelp))
            {
                var field = Factory.Field(item, Constants.FieldNames.ShortDescription, template.ShortHelp).With(template.ShortHelpProperty.SourceTextNode);
                field.Language = context.Project.Context.Language;
                field.Version  = Version.Latest;
                item.Fields.Add(field);
            }

            ((ISourcePropertyBag)item).NewSourceProperty("__origin", item.Uri);
            ((ISourcePropertyBag)item).NewSourceProperty("__origin_reason", nameof(CreateItemsFromTemplates));

            foreach (var templateSection in template.Sections)
            {
                var templateSectionItemIdOrPath = template.ItemIdOrPath + "/" + templateSection.SectionName;
                var templateSectionItem         = Factory.Item(template.Database, templateSection.Uri.Guid, templateSection.SectionName, templateSectionItemIdOrPath, Constants.Templates.TemplateSection.Format()).With(templateSection.SourceTextNode);
                templateSectionItem.IsEmittable = false;
                templateSectionItem.IsImport    = template.IsImport;
                templateSectionItem.IsSynthetic = true;
                templateSectionItem.IconProperty.SetValue(templateSection.IconProperty);
                ((ISourcePropertyBag)templateSectionItem).NewSourceProperty("__origin", item.Uri);
                ((ISourcePropertyBag)templateSectionItem).NewSourceProperty("__origin_reason", nameof(CreateItemsFromTemplates));

                foreach (var templateField in templateSection.Fields)
                {
                    var templateFieldItemIdOrPath = templateSectionItemIdOrPath + "/" + templateField.FieldName;
                    var templateFieldItem         = Factory.Item(template.Database, templateField.Uri.Guid, templateField.FieldName, templateFieldItemIdOrPath, Constants.Templates.TemplateFieldId).With(templateField.SourceTextNode);
                    templateFieldItem.IsEmittable = false;
                    templateFieldItem.IsImport    = template.IsImport;
                    templateFieldItem.IsSynthetic = true;

                    if (!string.IsNullOrEmpty(templateField.LongHelp))
                    {
                        var field = Factory.Field(templateFieldItem, Constants.FieldNames.LongDescription, templateField.LongHelp).With(templateField.LongHelpProperty.SourceTextNode);
                        field.Language = context.Project.Context.Language;
                        field.Version  = Version.Latest;
                        templateFieldItem.Fields.Add(field);
                    }

                    if (!string.IsNullOrEmpty(templateField.ShortHelp))
                    {
                        var field = Factory.Field(templateFieldItem, Constants.FieldNames.ShortDescription, templateField.ShortHelp).With(templateField.ShortHelpProperty.SourceTextNode);
                        field.Language = context.Project.Context.Language;
                        field.Version  = Version.Latest;
                        templateFieldItem.Fields.Add(field);
                    }

                    templateFieldItem.Fields.Add(Factory.Field(templateFieldItem, Constants.FieldNames.Shared, templateField.Shared ? "True" : "False"));
                    templateFieldItem.Fields.Add(Factory.Field(templateFieldItem, Constants.FieldNames.Unversioned, templateField.Unversioned ? "True" : "False"));
                    templateFieldItem.Fields.Add(Factory.Field(templateFieldItem, Constants.FieldNames.Source, templateField.Source).With(templateField.SourceProperty.SourceTextNode));
                    templateFieldItem.Fields.Add(Factory.Field(templateFieldItem, Constants.FieldNames.SortOrder, templateField.Sortorder.ToString()).With(templateField.SortorderProperty.SourceTextNode));
                    templateFieldItem.Fields.Add(Factory.Field(templateFieldItem, Constants.FieldNames.Type, templateField.Type).With(templateField.TypeProperty.SourceTextNode));
                    ((ISourcePropertyBag)templateFieldItem).NewSourceProperty("__origin", item.Uri);
                    ((ISourcePropertyBag)templateFieldItem).NewSourceProperty("__origin_reason", nameof(CreateItemsFromTemplates));

                    project.AddOrMerge(templateFieldItem);
                }

                project.AddOrMerge(templateSectionItem);
            }

            project.AddOrMerge(item);
        }