コード例 #1
0
 private void AddSharedNodesToAlphaConfigurations(DictionaryConfigurationModel model)
 {
     if (model.SharedItems.Any())
     {
         m_logger.WriteLine("Not adding shared nodes because some already exist:");
         m_logger.IncreaseIndent();
         model.SharedItems.ForEach(si => m_logger.WriteLine(DCM.BuildPathStringFromNode(si)));
         m_logger.DecreaseIndent();
         return;
     }
     DCM.PerformActionOnNodes(model.Parts, SetReferenceItem);
     if (model.IsReversal)
     {
         var reversalSubEntries = FindMainEntryDescendant(model, "SubentriesOS");
         AddSubsubNodeIfNeeded(reversalSubEntries);
         DictionaryConfigurationController.ShareNodeAsReference(model.SharedItems, reversalSubEntries, "allreversalsubentries");
     }
     else             // is Configured Dictionary
     {
         var mainEntrySubSenseNode = FindMainEntryDescendant(model, "SensesOS", "SensesOS");
         AddSubsubNodeIfNeeded(mainEntrySubSenseNode);
         DictionaryConfigurationController.ShareNodeAsReference(model.SharedItems, mainEntrySubSenseNode, "mainentrysubsenses");
         var mainEntrySubEntries = FindMainEntryDescendant(model, "Subentries");
         AddSubsubEntriesOptionsIfNeeded(mainEntrySubEntries);
         DictionaryConfigurationController.ShareNodeAsReference(model.SharedItems, mainEntrySubEntries, "mainentrysubentries");
     }
     // Remove direct children from nodes with referenced children
     DCM.PerformActionOnNodes(model.PartsAndSharedItems, n => { if (!string.IsNullOrEmpty(n.ReferenceItem))
                                                                {
                                                                    n.Children = null;
                                                                }
                              });
 }
コード例 #2
0
        internal DictionaryConfigurationModel LoadBetaDefaultForAlphaConfig(DictionaryConfigurationModel config)
        {
            var dictionaryFolder = Path.Combine(FwDirectoryFinder.DefaultConfigurations, DictionaryConfigurationListener.DictionaryConfigurationDirectoryName);
            var reversalFolder   = Path.Combine(FwDirectoryFinder.DefaultConfigurations, DictionaryConfigurationListener.ReversalIndexConfigurationDirectoryName);

            string configPath;

            // There is only one default config for reversals
            if (config.IsReversal)
            {
                configPath = Path.Combine(reversalFolder, DictionaryConfigurationModel.AllReversalIndexesFilenameBase + DictionaryConfigurationModel.FileExtension);
            }
            else if (config.IsRootBased)
            {
                configPath = Path.Combine(dictionaryFolder, DCM.RootFileName + DictionaryConfigurationModel.FileExtension);
            }
            else if (config.IsHybrid)             // Hybrid configs have subentries
            {
                configPath = Path.Combine(dictionaryFolder, DCM.HybridFileName + DictionaryConfigurationModel.FileExtension);
            }
            else             // Must be Lexeme
            {
                configPath = Path.Combine(dictionaryFolder, DCM.LexemeFileName + DictionaryConfigurationModel.FileExtension);
            }
            return(new DictionaryConfigurationModel(configPath, Cache));
        }
コード例 #3
0
        /// <param name="model"></param>
        /// <param name="ancestors">Fields in the desired node's ancestry, included the desired node's field, but not including Main Entry</param>
        /// <remarks>Currently ignores nodes' subfields</remarks>
        private ConfigurableDictionaryNode FindMainEntryDescendant(DictionaryConfigurationModel model, params string[] ancestors)
        {
            var failureMessage = "Unable to find 'Main Entry";
            var nextNode       = model.Parts.FirstOrDefault();

            foreach (var ancestor in ancestors)
            {
                if (nextNode == null)
                {
                    break;
                }
                failureMessage += DCM.NodePathSeparator + ancestor;
                nextNode        = nextNode.Children.Find(n => n.FieldDescription == ancestor && string.IsNullOrEmpty(n.LabelSuffix));
            }
            if (nextNode != null)
            {
                return(nextNode);
            }
            // If we couldn't find the node, this is probably a test that didn't have a full model
            m_logger.WriteLine(string.Format("Unable to find '{0}'", string.Join(DCM.NodePathSeparator, new[] { "Main Entry" }.Concat(ancestors))));
            m_logger.WriteLine(failureMessage + "'");
            return(new ConfigurableDictionaryNode {
                Children = new List <ConfigurableDictionaryNode>()
            });
        }
コード例 #4
0
        public void MigrateOldConfigurationsIfNeeded_MatchesLabelsWhenUIIsLocalized()
        {
            // Localize a Part's label to German (sufficient to cause a mismatched nodes crash if one config's labels are localized)
            var localizedPartLabels = new Dictionary <string, string>();

            localizedPartLabels["Main Entry"] = "Haupteintrag";
            var pathsToL10nStrings = (Dictionary <string, Dictionary <string, string> >)ReflectionHelper.GetField(m_mediator.StringTbl, "m_pathsToStrings");

            pathsToL10nStrings["group[@id = 'LocalizedAttributes']/"] = localizedPartLabels;

            var configSettingsDir = FdoFileHelper.GetConfigSettingsDir(Path.GetDirectoryName(Cache.ProjectId.Path));
            var newConfigFilePath = Path.Combine(configSettingsDir, DictionaryConfigurationListener.DictionaryConfigurationDirectoryName,
                                                 "Lexeme" + DictionaryConfigurationModel.FileExtension);

            Assert.False(File.Exists(newConfigFilePath), "should not yet be migrated");
            Directory.CreateDirectory(configSettingsDir);
            File.WriteAllLines(Path.Combine(configSettingsDir, "Test.fwlayout"), new[] {
                @"<layoutType label='Lexeme-based (complex forms as main entries)' layout='publishStem'><configure class='LexEntry' label='Main Entry' layout='publishStemEntry' />",
                @"<configure class='LexEntry' label='Minor Entry' layout='publishStemMinorEntry' hideConfig='true' /></layoutType>'"
            });
            var migrator = new DictionaryConfigurationMigrator(m_mediator);

            Assert.DoesNotThrow(() => migrator.MigrateOldConfigurationsIfNeeded(), "ArgumentException indicates localized labels.");             // SUT
            var updatedConfigModel = new DictionaryConfigurationModel(newConfigFilePath, Cache);

            Assert.AreEqual(2, updatedConfigModel.Parts.Count, "Should have 2 top-level nodes");
            Assert.AreEqual("Main Entry", updatedConfigModel.Parts[0].Label);
            DirectoryUtilities.DeleteDirectoryRobust(configSettingsDir);
        }
コード例 #5
0
        private static void MigratePartFromOldVersionToCurrent(ISimpleLogger logger, DictionaryConfigurationModel oldConfig,
                                                               ConfigurableDictionaryNode oldConfigPart, ConfigurableDictionaryNode currentDefaultConfigPart)
        {
            var oldVersion = oldConfig.Version;

            if (oldVersion < FirstAlphaMigrator.VersionAlpha3)
            {
                throw new ApplicationException("Beta migration starts at VersionAlpha3 (8)");
            }
            switch (oldVersion)
            {
            case FirstAlphaMigrator.VersionAlpha3:
                MoveNodesIntoNewGroups(oldConfigPart, currentDefaultConfigPart);
                MigrateNewChildNodesAndOptionsInto(oldConfigPart, currentDefaultConfigPart);
                goto case 9;

            case 9:
                UpgradeEtymologyCluster(oldConfigPart, oldConfig);
                goto case 10;

            case 10:
            case 11:
            case 12:
            case 13:
                RemoveMostOfGramInfoUnderRefdComplexForms(oldConfigPart);
                goto case VersionBeta5;

            case VersionBeta5:
            case 15:
                MigrateNewChildNodesAndOptionsInto(oldConfigPart, currentDefaultConfigPart);
                goto case 16;

            case 16:
                RemoveHiddenChildren(oldConfigPart, logger);
                goto case VersionRC2;

            case VersionRC2:
                ChangeReferenceSenseHeadwordFieldName(oldConfigPart);
                goto case 18;

            case 18:
                RemoveReferencedHeadwordSubField(oldConfigPart);
                break;

            default:
                logger.WriteLine(string.Format(
                                     "Unable to migrate {0}: no migration instructions for version {1}", oldConfigPart.Label, oldVersion));
                break;
            }
        }
コード例 #6
0
        internal void MigrateFrom83Alpha(DictionaryConfigurationModel alphaModel)
        {
            // original migration neglected to update the version number; -1 (Pre83) is the same as 1 (Alpha1)
            if (alphaModel.Version == PreHistoricMigrator.VersionPre83 || alphaModel.Version == PreHistoricMigrator.VersionAlpha1)
            {
                RemoveNonLoadableData(alphaModel.PartsAndSharedItems);
            }
            // now that it's safe to specify them, it would be helpful to have parents in certain steps:
            DictionaryConfigurationModel.SpecifyParentsAndReferences(alphaModel.Parts, alphaModel.SharedItems);
            switch (alphaModel.Version)
            {
            case -1:
            case 1:
            case 2:
                HandleNodewiseChanges(alphaModel.PartsAndSharedItems, m_logger, 2, alphaModel.IsReversal);
                goto case 3;

            case 3:
                HandleNodewiseChanges(alphaModel.PartsAndSharedItems, m_logger, 3, alphaModel.IsReversal);
                DCM.SetWritingSystemForReversalModel(alphaModel, Cache);
                AddSharedNodesToAlphaConfigurations(alphaModel);
                goto case 4;

            case 4:
                HandleNodewiseChanges(alphaModel.PartsAndSharedItems, m_logger, 4, alphaModel.IsReversal);
                goto case VersionAlpha2;

            case VersionAlpha2:
                HandleNodewiseChanges(alphaModel.PartsAndSharedItems, m_logger, VersionAlpha2, alphaModel.IsReversal);
                goto case 6;

            case 6:
                HandleNodewiseChanges(alphaModel.PartsAndSharedItems, m_logger, 6, alphaModel.IsReversal);
                goto case 7;

            case 7:
                var fileName = Path.GetFileNameWithoutExtension(alphaModel.FilePath);
                if (!alphaModel.IsRootBased)
                {
                    alphaModel.IsRootBased = fileName == DCM.RootFileName;
                }
                break;

            default:
                m_logger.WriteLine(string.Format(
                                       "Unable to migrate {0}: no migration instructions for version {1}", alphaModel.Label, alphaModel.Version));
                break;
            }
            alphaModel.Version = VersionAlpha3;
        }
コード例 #7
0
        internal void MigrateFrom83Alpha(ISimpleLogger logger, DictionaryConfigurationModel oldConfig, DictionaryConfigurationModel currentDefaultModel)
        {
            // it may be helpful to have parents and current custom fields in the oldConfig (currentDefaultModel already has them):
            DictionaryConfigurationModel.SpecifyParentsAndReferences(oldConfig.Parts, oldConfig.SharedItems);
            DictionaryConfigurationController.MergeCustomFieldsIntoDictionaryModel(oldConfig, Cache);
            ChooseAppropriateComplexForms(oldConfig);             // 13->14, but needed before rearranging and adding new nodes
            ConflateMainEntriesIfNecessary(logger, oldConfig);    // 12->13, but needed before rearranging and adding new nodes
            var currentDefaultList = new List <ConfigurableDictionaryNode>(currentDefaultModel.PartsAndSharedItems);

            foreach (var part in oldConfig.PartsAndSharedItems)
            {
                MigratePartFromOldVersionToCurrent(logger, oldConfig, part, FindMatchingChildNode(part.Label, currentDefaultList));
            }
            oldConfig.Version = DCM.VersionCurrent;
            logger.WriteLine("Migrated to version " + DCM.VersionCurrent);
        }
コード例 #8
0
 /// <summary>
 /// Earlier versions of Hybrid mistakenly used VisibleComplexFormBackRefs instead of ComplexFormsNotSubentries. Correct this mistake.
 /// Referenced Complex Forms should be *Other* Referenced Complex Forms whenever they are siblings of Subentries
 /// </summary>
 private static void ChooseAppropriateComplexForms(DictionaryConfigurationModel migratingModel)
 {
     if (!migratingModel.IsHybrid)
     {
         return;
     }
     DCM.PerformActionOnNodes(migratingModel.Parts, parentNode =>
     {
         if (parentNode.ReferencedOrDirectChildren != null && parentNode.ReferencedOrDirectChildren.Any(node => node.FieldDescription == "Subentries"))
         {
             parentNode.ReferencedOrDirectChildren.Where(sib => sib.FieldDescription == "VisibleComplexFormBackRefs").ForEach(sib =>
             {
                 sib.Label            = "Other Referenced Complex Forms";
                 sib.FieldDescription = "ComplexFormsNotSubentries";
             });
         }
     });
 }
コード例 #9
0
        public void MigrateOldConfigurationsIfNeeded_BringsPreHistoricFileToCurrentVersion()
        {
            var configSettingsDir = FdoFileHelper.GetConfigSettingsDir(Path.GetDirectoryName(Cache.ProjectId.Path));
            var newConfigFilePath = Path.Combine(configSettingsDir, DictionaryConfigurationListener.DictionaryConfigurationDirectoryName,
                                                 "Lexeme" + DictionaryConfigurationModel.FileExtension);

            Assert.False(File.Exists(newConfigFilePath), "should not yet be migrated");
            Directory.CreateDirectory(configSettingsDir);
            File.WriteAllLines(Path.Combine(configSettingsDir, "Test.fwlayout"), new[] {
                @"<layoutType label='Lexeme-based (complex forms as main entries)' layout='publishStem'><configure class='LexEntry' label='Main Entry' layout='publishStemEntry' />",
                @"<configure class='LexEntry' label='Minor Entry' layout='publishStemMinorEntry' hideConfig='true' /></layoutType>'"
            });
            var migrator = new DictionaryConfigurationMigrator(m_mediator);

            migrator.MigrateOldConfigurationsIfNeeded();             // SUT
            var updatedConfigModel = new DictionaryConfigurationModel(newConfigFilePath, Cache);

            Assert.AreEqual(DictionaryConfigurationMigrator.VersionCurrent, updatedConfigModel.Version);
            DirectoryUtilities.DeleteDirectoryRobust(configSettingsDir);
        }
コード例 #10
0
        internal void MigrateFrom83Alpha(ISimpleLogger logger, DictionaryConfigurationModel oldConfig, DictionaryConfigurationModel currentDefaultModel)
        {
            // it may be helpful to have parents and current custom fields in the oldConfig (currentDefaultModel already has them):
            DictionaryConfigurationModel.SpecifyParentsAndReferences(oldConfig.Parts, oldConfig.SharedItems);
            DictionaryConfigurationController.MergeCustomFieldsIntoDictionaryModel(oldConfig, Cache);
            ChooseAppropriateComplexForms(oldConfig);             // 13->14, but needed before rearranging and adding new nodes
            ConflateMainEntriesIfNecessary(logger, oldConfig);    // 12->13, but needed before rearranging and adding new nodes
            var currentDefaultList = new List <ConfigurableDictionaryNode>(currentDefaultModel.PartsAndSharedItems);

            foreach (var part in oldConfig.PartsAndSharedItems)
            {
                var defaultPart = FindMatchingChildNode(part.Label, currentDefaultList);
                if (defaultPart == null)
                {
                    throw new NullReferenceException(string.Format(
                                                         "{0} is corrupt. {1} has no corresponding part in the defaults (perhaps it missed a rename migration step).",
                                                         oldConfig.FilePath, part.Label));
                }
                MigratePartFromOldVersionToCurrent(logger, oldConfig, part, defaultPart);
            }
            oldConfig.Version = DCM.VersionCurrent;
            logger.WriteLine("Migrated to version " + DCM.VersionCurrent);
        }
コード例 #11
0
        private static void ConflateMainEntriesIfNecessary(ISimpleLogger logger, DictionaryConfigurationModel config)
        {
            if (config.Version >= VersionBeta5 || config.IsRootBased || config.IsReversal)
            {
                return;
            }
            var mainEntriesComplexForms = config.Parts.FirstOrDefault(n => IsComplexFormsNode(n) && n.IsEnabled)
                                          ?? config.Parts.FirstOrDefault(IsComplexFormsNode);

            if (mainEntriesComplexForms == null)
            {
                logger.WriteLine(string.Format("Unable to conflate main entries for config '{0}' (version {1})", config.Label, config.Version));
                return;
            }
            MigrateNewChildNodesAndOptionsInto(config.Parts[0], mainEntriesComplexForms);
            // Remove all complex form nodes *except* Main Entry
            for (var i = config.Parts.Count - 1; i >= 1; --i)
            {
                if (IsComplexFormsNode(config.Parts[i]))
                {
                    config.Parts.RemoveAt(i);
                }
            }
        }
コード例 #12
0
        public void MigrateOldConfigurationsIfNeeded_PreservesOrderOfBibliographies()
        {
            var configSettingsDir = FdoFileHelper.GetConfigSettingsDir(Path.GetDirectoryName(Cache.ProjectId.Path));
            var newConfigFilePath = Path.Combine(configSettingsDir, DictionaryConfigurationListener.ReversalIndexConfigurationDirectoryName,
                                                 "AllReversalIndexes" + DictionaryConfigurationModel.FileExtension);

            Assert.False(File.Exists(newConfigFilePath), "should not yet be migrated");
            Directory.CreateDirectory(configSettingsDir);
            File.WriteAllLines(Path.Combine(configSettingsDir, "Test.fwlayout"), new[] {
                @"<layoutType label='All Reversal Indexes' layout='publishReversal'>",
                @"<configure class='ReversalIndexEntry' label='Reversal Entry' layout='publishReversalEntry' /></layoutType>'"
            });
            var migrator = new DictionaryConfigurationMigrator(m_mediator);

            migrator.MigrateOldConfigurationsIfNeeded();             // SUT
            var updatedConfigModel = new DictionaryConfigurationModel(newConfigFilePath, Cache);
            var refdSenseChildren  = updatedConfigModel.Parts[0].Children.Find(n => n.Label == "Referenced Senses").Children;
            var bibCount           = 0;

            for (var i = 0; i < refdSenseChildren.Count; i++)
            {
                var bibNode = refdSenseChildren[i];
                if (!bibNode.Label.StartsWith("Bibliography"))
                {
                    continue;
                }
                StringAssert.StartsWith("Bibliography (", bibNode.Label, "Should specify (entry|sense), lest we never know");
                Assert.False(bibNode.IsCustomField, bibNode.Label + " should not be custom.");
                // Rough test to ensure Bibliography nodes aren't bumped to the end of the list. In the defaults, the later Bibliography
                // node is a little more than five nodes from the end
                Assert.LessOrEqual(i, refdSenseChildren.Count - 5, "Bibliography nodes should not have been bumped to the end of the list");
                ++bibCount;
            }
            Assert.AreEqual(2, bibCount, "Should be exactly two Bibliography nodes (sense and entry)");
            DirectoryUtilities.DeleteDirectoryRobust(configSettingsDir);
        }
コード例 #13
0
        /// <summary>
        /// Case FirstAlphaMigrator.VersionAlpha3 above will pull in all the new nodes in the Etymology cluster by Label.
        /// Gloss is the only pre-existing node that doesn't have a new name, so it won't be replaced.
        /// It needs to be marked Enabled. The main Etymology node needs several modifications.
        /// Three old nodes will need deleting: Etymological Form, Comment and Source
        /// </summary>
        /// <param name="oldConfigPart"></param>
        /// <param name="oldConfig"></param>
        private static void UpgradeEtymologyCluster(ConfigurableDictionaryNode oldConfigPart, DictionaryConfigurationModel oldConfig)
        {
            if (oldConfigPart.Children == null || oldConfigPart.Children.Count == 0)
            {
                return;                 // safety net
            }
            var etymNodes = new List <ConfigurableDictionaryNode>();

            DCM.PerformActionOnNodes(oldConfigPart.Children, node =>
            {
                if (node.Label == "Etymology")
                {
                    etymNodes.Add(node);                     // since we have to do some node deleting, just collect up the relevant nodes
                }
            });

            foreach (var node in etymNodes)
            {
                if (node.IsCustomField)           // Unfortunately there are some pathological users who have ancient custom fields named etymology
                {
                    continue;                     // Leave them be
                }
                // modify main node
                var etymSequence = "EtymologyOS";
                if (oldConfig.IsReversal)
                {
                    node.SubField         = etymSequence;
                    node.FieldDescription = "Entry";
                    node.IsEnabled        = true;
                }
                else
                {
                    node.FieldDescription = etymSequence;
                    node.IsEnabled        = !oldConfig.IsHybrid;
                }
                node.CSSClassNameOverride = "etymologies";
                node.Before  = "(";
                node.Between = " ";
                node.After   = ") ";

                if (node.Children == null)
                {
                    continue;
                }

                // enable Gloss node
                var glossNode = node.Children.Find(n => n.Label == "Gloss");
                if (glossNode != null)
                {
                    glossNode.IsEnabled = true;
                }

                // enable Source Language Notes
                var notesList = node.Children.Find(n => n.FieldDescription == "LanguageNotes");
                if (notesList != null)                // ran into some cases where this node didn't exist in reversal config!
                {
                    notesList.IsEnabled = true;
                }

                // remove old children
                var nodesToRemove = new[] { "Etymological Form", "Comment", "Source" };
                node.Children.RemoveAll(n => nodesToRemove.Contains(n.Label));
            }
            // Etymology changed too much to be matched in the PreHistoricMigration and was marked as custom
            DCM.PerformActionOnNodes(etymNodes, n => { n.IsCustomField = false; });
        }
コード例 #14
0
        public void StoredDefaultsUpdatedFromCurrentDefaults()
        {
            var subsenses = new ConfigurableDictionaryNode {
                Label = "Subsenses", FieldDescription = "SensesOS"
            };
            var inBoth = new ConfigurableDictionaryNode
            {
                Label            = "In Both",
                FieldDescription = "Both"
            };
            var inOld = new ConfigurableDictionaryNode
            {
                Label            = "inOld",
                FieldDescription = "OnlyOld",
                Children         = new List <ConfigurableDictionaryNode> {
                    subsenses
                }
            };
            var senses = new ConfigurableDictionaryNode {
                Label = "Senses", FieldDescription = "SensesOS", Children = new List <ConfigurableDictionaryNode> {
                    inOld, inBoth
                }
            };
            var mainEntry = new ConfigurableDictionaryNode
            {
                FieldDescription = "LexEntry",
                Children         = new List <ConfigurableDictionaryNode> {
                    senses
                }
            };
            var oldModel = new DictionaryConfigurationModel {
                Parts = new List <ConfigurableDictionaryNode> {
                    mainEntry
                }
            };

            CssGeneratorTests.PopulateFieldsForTesting(oldModel);             // PopulateFieldsForTesting populates each node's Label with its FieldDescription sets all isEnabled to true
            var newMain = mainEntry.DeepCloneUnderSameParent();

            newMain.Children[0].Before    = "{";
            newMain.Children[0].Between   = ",";
            newMain.Children[0].After     = "}";
            newMain.Children[0].Style     = "Stylish";
            newMain.Children[0].IsEnabled = false;
            newMain.Children[0].Children.RemoveAt(0);             // Remove inOld
            var newModel = new DictionaryConfigurationModel {
                Parts = new List <ConfigurableDictionaryNode> {
                    newMain
                }
            };

            // Verify valid starting point
            Assert.AreNotEqual("{", oldModel.Parts[0].Children[0].Before, "Invalid preconditions");
            Assert.AreNotEqual("}", oldModel.Parts[0].Children[0].After, "Invalid preconditions");
            Assert.AreNotEqual(",", oldModel.Parts[0].Children[0].Between, "Invalid preconditions");
            Assert.AreNotEqual("Stylish", oldModel.Parts[0].Children[0].Style, "Invalid preconditions");
            Assert.True(oldModel.Parts[0].Children[0].IsEnabled, "Invalid preconditions");

            DictionaryConfigurationMigrator.LoadConfigWithCurrentDefaults(oldModel, newModel);             // SUT
            Assert.AreEqual(2, oldModel.Parts[0].Children[0].Children.Count, "Old non-matching part was not retained");
            Assert.AreEqual("{", oldModel.Parts[0].Children[0].Before, "Before not copied from new defaults");
            Assert.AreEqual("}", oldModel.Parts[0].Children[0].After, "After not copied from new defaults");
            Assert.AreEqual(",", oldModel.Parts[0].Children[0].Between, "Between not copied from new defaults");
            Assert.AreEqual("Stylish", oldModel.Parts[0].Children[0].Style, "Style not copied from new defaults");
            Assert.False(oldModel.Parts[0].Children[0].IsEnabled, "IsEnabled value not copied from new defaults");
        }