From 407801c29573895ba5fd8bec9167eb7c40d82a76 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Thu, 21 Nov 2013 15:34:12 +0700 Subject: [PATCH 001/143] Remove unused references in FDO and FdoUi Change-Id: I542a71c7eacbf3c53b2b219cc024e734d3314435 --- Src/FDO/DomainImpl/ScrBook.cs | 1 - ...CantRestoreLinkedFilesToOriginalLocation.cs | 1 - .../BackupRestore/FilesToRestoreAreOlder.cs | 1 - .../RestoreLinkedFilesToProjectsFolder.cs | 1 - .../DataMigration/FWVersionTooOld.cs | 1 - Src/FDO/FDO.csproj | 18 ------------------ .../Infrastructure/Impl/ConflictingSaveDlg.cs | 1 - .../Infrastructure/Impl/ConnectionLostDlg.cs | 1 - Src/FdoUi/FdoUi.csproj | 9 --------- 9 files changed, 34 deletions(-) diff --git a/Src/FDO/DomainImpl/ScrBook.cs b/Src/FDO/DomainImpl/ScrBook.cs index 149132f21a..86c8051c53 100644 --- a/Src/FDO/DomainImpl/ScrBook.cs +++ b/Src/FDO/DomainImpl/ScrBook.cs @@ -23,7 +23,6 @@ using SILUBS.SharedScrUtils; using SIL.Utils; using System.Text; -using System.Data.SqlClient; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.Infrastructure; using SIL.CoreImpl; diff --git a/Src/FDO/DomainServices/BackupRestore/CantRestoreLinkedFilesToOriginalLocation.cs b/Src/FDO/DomainServices/BackupRestore/CantRestoreLinkedFilesToOriginalLocation.cs index 955bb2dbc8..40b237ec8a 100644 --- a/Src/FDO/DomainServices/BackupRestore/CantRestoreLinkedFilesToOriginalLocation.cs +++ b/Src/FDO/DomainServices/BackupRestore/CantRestoreLinkedFilesToOriginalLocation.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.Data; using System.Drawing; using System.Linq; using System.Text; diff --git a/Src/FDO/DomainServices/BackupRestore/FilesToRestoreAreOlder.cs b/Src/FDO/DomainServices/BackupRestore/FilesToRestoreAreOlder.cs index b59d583aae..90006d5744 100644 --- a/Src/FDO/DomainServices/BackupRestore/FilesToRestoreAreOlder.cs +++ b/Src/FDO/DomainServices/BackupRestore/FilesToRestoreAreOlder.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.Data; using System.Drawing; using System.Linq; using System.Text; diff --git a/Src/FDO/DomainServices/BackupRestore/RestoreLinkedFilesToProjectsFolder.cs b/Src/FDO/DomainServices/BackupRestore/RestoreLinkedFilesToProjectsFolder.cs index 6b58bd05bd..41e4980f5f 100644 --- a/Src/FDO/DomainServices/BackupRestore/RestoreLinkedFilesToProjectsFolder.cs +++ b/Src/FDO/DomainServices/BackupRestore/RestoreLinkedFilesToProjectsFolder.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.Data; using System.Drawing; using System.Linq; using System.Text; diff --git a/Src/FDO/DomainServices/DataMigration/FWVersionTooOld.cs b/Src/FDO/DomainServices/DataMigration/FWVersionTooOld.cs index 356ad1ee1f..c1b4aca533 100644 --- a/Src/FDO/DomainServices/DataMigration/FWVersionTooOld.cs +++ b/Src/FDO/DomainServices/DataMigration/FWVersionTooOld.cs @@ -14,7 +14,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; diff --git a/Src/FDO/FDO.csproj b/Src/FDO/FDO.csproj index c2167a033f..59d3c15ca1 100644 --- a/Src/FDO/FDO.csproj +++ b/Src/FDO/FDO.csproj @@ -106,17 +106,11 @@ COMInterfaces ..\..\Output\Debug\COMInterfaces.dll - - Microsoft.VisualBasic - PhonEnvValidator ..\..\Output\Debug\PhonEnvValidator.dll - - System.Data - System.Drawing @@ -146,9 +140,6 @@ ..\..\Output\Debug\Db4objects.Db4o.Linq.dll - - ..\..\Output\Debug\ECInterfaces.dll - ..\..\Output\Debug\FwUtils.dll @@ -176,9 +167,6 @@ ..\..\Output\Debug\SharedScrUtils.dll - - ..\..\Output\Debug\SilEncConverters40.dll - ..\..\DistFiles\StructureMap.dll @@ -188,15 +176,9 @@ ..\..\Output\Debug\SilUtils.dll - - ..\..\DistFiles\Tamir.SharpSSH.dll - ..\..\Output\Debug\xCoreInterfaces.dll - - ..\..\Output\Debug\ZipUtils.dll - diff --git a/Src/FDO/Infrastructure/Impl/ConflictingSaveDlg.cs b/Src/FDO/Infrastructure/Impl/ConflictingSaveDlg.cs index 2a56e0d603..0b9f42f03e 100644 --- a/Src/FDO/Infrastructure/Impl/ConflictingSaveDlg.cs +++ b/Src/FDO/Infrastructure/Impl/ConflictingSaveDlg.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.Data; using System.Drawing; using System.Linq; using System.Text; diff --git a/Src/FDO/Infrastructure/Impl/ConnectionLostDlg.cs b/Src/FDO/Infrastructure/Impl/ConnectionLostDlg.cs index 8cb33c8cd1..19ab502b7d 100644 --- a/Src/FDO/Infrastructure/Impl/ConnectionLostDlg.cs +++ b/Src/FDO/Infrastructure/Impl/ConnectionLostDlg.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.Data; using System.Drawing; using System.Linq; using System.Text; diff --git a/Src/FdoUi/FdoUi.csproj b/Src/FdoUi/FdoUi.csproj index 2b9cf24e40..7ece8f3046 100644 --- a/Src/FdoUi/FdoUi.csproj +++ b/Src/FdoUi/FdoUi.csproj @@ -103,8 +103,6 @@ x86 - - ..\..\Output\Debug\COMInterfaces.dll False @@ -137,10 +135,6 @@ False ..\..\DistFiles\Microsoft.Practices.ServiceLocation.dll - - ..\..\Output\Debug\Reporting.dll - False - ..\..\Output\Debug\RootSite.dll False @@ -154,10 +148,7 @@ - - - From 724d40265b1802e44b4d0ad18bc7238436723ba2 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Fri, 22 Nov 2013 09:45:21 +0700 Subject: [PATCH 002/143] Move some LexEntry domain logic from FdoUi into FDO FdoUi is not getting distributed with FDO, so we need the necessary domain logic in FDO. In this case, some of the lexical lookup logic was integrated with the UI code. Change-Id: I9d938db428d498d8011fb35ba81063ae55f5de86 --- Src/Common/Controls/XMLViews/XMLViews.csproj | 9 +- .../XMLViewsTests/XMLViewsTests.csproj | 6 +- Src/Common/Framework/Framework.csproj | 4 +- Src/FDO/FdoRepositoryInterfaceAdditions.cs | 20 ++ .../Impl/FdoRepositoryAdditions.cs | 185 ++++++++++++++++++ Src/FdoUi/LexEntryUi.cs | 164 ++-------------- .../FwCoreDlgControls.csproj | 8 +- 7 files changed, 233 insertions(+), 163 deletions(-) diff --git a/Src/Common/Controls/XMLViews/XMLViews.csproj b/Src/Common/Controls/XMLViews/XMLViews.csproj index a1512e3c5f..7c79fb6018 100644 --- a/Src/Common/Controls/XMLViews/XMLViews.csproj +++ b/Src/Common/Controls/XMLViews/XMLViews.csproj @@ -1,4 +1,4 @@ - + Local @@ -227,10 +227,10 @@ \usr\lib\cli\geckofx-14.0.1\geckofx-core-14.dll - + \usr\lib\cli\geckofx-14.0.1\Geckofx-Winforms-14.dll - + PreserveNewest @@ -424,11 +424,10 @@ - ../../../../DistFiles - + \ No newline at end of file diff --git a/Src/Common/Controls/XMLViews/XMLViewsTests/XMLViewsTests.csproj b/Src/Common/Controls/XMLViews/XMLViewsTests/XMLViewsTests.csproj index e8e2a399b7..b10234b971 100644 --- a/Src/Common/Controls/XMLViews/XMLViewsTests/XMLViewsTests.csproj +++ b/Src/Common/Controls/XMLViews/XMLViewsTests/XMLViewsTests.csproj @@ -1,4 +1,4 @@ - + Local @@ -233,7 +233,9 @@ - + + UserControl + diff --git a/Src/Common/Framework/Framework.csproj b/Src/Common/Framework/Framework.csproj index 1bd34cd8b7..7759329535 100644 --- a/Src/Common/Framework/Framework.csproj +++ b/Src/Common/Framework/Framework.csproj @@ -244,7 +244,9 @@ Code - + + UserControl + diff --git a/Src/FDO/FdoRepositoryInterfaceAdditions.cs b/Src/FDO/FdoRepositoryInterfaceAdditions.cs index 499af462d5..48b8ebf995 100644 --- a/Src/FDO/FdoRepositoryInterfaceAdditions.cs +++ b/Src/FDO/FdoRepositoryInterfaceAdditions.cs @@ -427,6 +427,26 @@ public partial interface ILexEntryRepository /// entries to see whether they are homographs. /// IMoMorphType HomographMorphType(FdoCache cache, IMoMorphType morphType); + + /// + /// Find the list of LexEntry objects which conceivably match the given wordform. + /// + /// + /// + /// + /// + /// + List FindEntriesForWordform(FdoCache cache, ITsString tssWf, IWfiAnalysis wfa, ref bool duplicates); + + /// ------------------------------------------------------------------------------------ + /// + /// Find wordform given a cache and the string. + /// + /// + /// + /// + /// ------------------------------------------------------------------------------------ + ILexEntry FindEntryForWordform(FdoCache cache, ITsString tssWf); } internal interface ILexEntryRepositoryInternal diff --git a/Src/FDO/Infrastructure/Impl/FdoRepositoryAdditions.cs b/Src/FDO/Infrastructure/Impl/FdoRepositoryAdditions.cs index da7a51b5b1..36594d2001 100644 --- a/Src/FDO/Infrastructure/Impl/FdoRepositoryAdditions.cs +++ b/Src/FDO/Infrastructure/Impl/FdoRepositoryAdditions.cs @@ -1444,6 +1444,191 @@ public IMoMorphType HomographMorphType(FdoCache cache, IMoMorphType morphType) } return morphType; } + + /// + /// Find the list of LexEntry objects which conceivably match the given wordform. + /// + /// + /// + /// + /// + /// + public List FindEntriesForWordform(FdoCache cache, ITsString tssWf, IWfiAnalysis wfa, ref bool duplicates) + { + var entries = FindEntriesForWordformWorker(cache, tssWf, wfa, ref duplicates); + + // if we do not find a match for the word then try converting it to lowercase and see if there + // is an entry in the lexicon for the Wordform in lowercase. This is needed for occurences of + // words which are capitalized at the beginning of sentences. LT-7444 RickM + if (entries == null || entries.Count == 0) + { + //We need to be careful when converting to lowercase therefore use Icu.ToLower() + //get the WS of the tsString + int wsWf = TsStringUtils.GetWsAtOffset(tssWf, 0); + //use that to get the locale for the WS, which is used for + string wsLocale = cache.ServiceLocator.WritingSystemManager.Get(wsWf).IcuLocale; + string sLower = Icu.ToLower(tssWf.Text, wsLocale); + ITsTextProps ttp = tssWf.get_PropertiesAt(0); + ITsStrFactory tsf = TsStrFactoryClass.Create(); + tssWf = tsf.MakeStringWithPropsRgch(sLower, sLower.Length, ttp); + entries = FindEntriesForWordformWorker(cache, tssWf, wfa, ref duplicates); + } + return entries; + } + + public List FindEntriesForWordformWorker(FdoCache cache, ITsString tssWf, IWfiAnalysis wfa, ref bool duplicates) + { + if (tssWf == null) + return new List(); + + var wf = tssWf.Text; + if (string.IsNullOrEmpty(wf)) + return new List(); + + var wsVern = TsStringUtils.GetWsAtOffset(tssWf, 0); + + var entries = new Set(); + + // Get the entries from the matching wordform. + // Get matching wordform. + var matchingWordforms = cache.ServiceLocator.GetInstance().AllInstances() + .Where(wrdfrm => wrdfrm.Form.get_String(wsVern).Text == wf); + + duplicates = matchingWordforms.Count() > 1; + + if (matchingWordforms.Count() > 0) + { + if (wfa != null && matchingWordforms.First().AnalysesOC.Contains(wfa)) + { + entries.AddRange(wfa.MorphBundlesOS + .Where(mb => mb.MsaRA != null) + .Select(mb => mb.MsaRA.Owner as ILexEntry)); + } + else + { + foreach (var analysis in matchingWordforms.First().AnalysesOC) + { + entries.AddRange(analysis.MorphBundlesOS + .Where(mb => mb.MsaRA != null) + .Select(mb => mb.MsaRA.Owner as ILexEntry)); + } + } + } + // Get the entries from the matching MoForms. + entries.AddRange( + cache.ServiceLocator.GetInstance().AllInstances() + .Cast() + .Where(mf => mf.Form.get_String(wsVern) != null && mf.Form.get_String(wsVern).Text == wf) + .Select(mf => mf.Owner as ILexEntry)); + + // Get the entries from the citation form + entries.AddRange( + cache.ServiceLocator.GetInstance().AllInstances() + .Cast() + .Where(entry => entry.CitationForm.get_String(wsVern) != null && entry.CitationForm.get_String(wsVern).Text == wf)); + + // Put the enrties in a List and sort it by the HomographNumber. + var retval = new List(entries.ToArray()); + retval.Sort(CompareEntriesByHomographNumber); + return retval; + } + + private int CompareEntriesByHomographNumber(ILexEntry x, ILexEntry y) + { + return x == null + ? (y == null ? 0 /* Both are null, so are equal */ : -1 /* x not being null is grater than y which is null */) + : (y == null + ? 1 /* y being null is greater than x which is not null */ + : (x.HomographNumber == y.HomographNumber + ? 0 /* Neither are null, and homograph numbers are the same, so they are equal */ + : (x.HomographNumber > y.HomographNumber + ? 1 /* x is greater than x */ + : -1 /* x is less than y */))); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Find wordform given a cache and the string. + /// + /// + /// + /// + /// ------------------------------------------------------------------------------------ + public ILexEntry FindEntryForWordform(FdoCache cache, ITsString tssWf) + { + if (tssWf == null || tssWf.Length == 0) + return null; + + var wsVern = TsStringUtils.GetWsAtOffset(tssWf, 0); + var icuEngine = cache.LanguageWritingSystemFactoryAccessor.get_CharPropEngine(wsVern); + var wf = icuEngine.ToLower(tssWf.Text); + ILexEntry matchingEntry = null; + + // Check for Lexeme form. + matchingEntry = ( + from e in cache.LanguageProject.LexDbOA.Entries + where e.LexemeFormOA != null && GetLowercaseStringFromMultiUnicodeSafely(icuEngine, e.LexemeFormOA.Form, wsVern) == wf + orderby e.HomographNumber + select e + ).FirstOrDefault(); + + // Check for Citation form. + if (matchingEntry == null) + matchingEntry = ( + from e in cache.LanguageProject.LexDbOA.Entries + where GetLowercaseStringFromMultiUnicodeSafely(icuEngine, e.CitationForm, wsVern) == wf + orderby e.HomographNumber + select e + ).FirstOrDefault(); + + // Check for Alternate forms. + if (matchingEntry == null) + matchingEntry = ( + from e in cache.LanguageProject.LexDbOA.Entries + where ( + from af in e.AlternateFormsOS + where GetLowercaseStringFromMultiUnicodeSafely(icuEngine, af.Form, wsVern) == wf + select af + ).FirstOrDefault() != null + orderby e.HomographNumber + select e + ).FirstOrDefault(); + + // Look for the most commonly used analysis of the wordform. + if (matchingEntry == null) + { + IWfiWordform wordform; + if (cache.ServiceLocator.GetInstance().TryGetObject(tssWf, out wordform)) + { + var guesser = new AnalysisGuessServices(cache); + var guess = guesser.GetBestGuess(wordform); + var analysis = guess as IWfiAnalysis; + if (guess is IWfiGloss) + analysis = guess.Owner as IWfiAnalysis; + if (analysis != null) + { + matchingEntry = + (from mb in analysis.MorphBundlesOS + where mb.MorphRA is IMoStemAllomorph + select mb.MorphRA.Owner).FirstOrDefault() as ILexEntry; + } + } + } + + return matchingEntry; + } + + private string GetLowercaseStringFromMultiUnicodeSafely(ILgCharacterPropertyEngine icuEngine, IMultiUnicode form, int ws) + { + if (form == null) + return string.Empty; + + var formTsstring = form.get_String(ws); + if (formTsstring == null || formTsstring.Length == 0) + return string.Empty; + + return icuEngine.ToLower(formTsstring.Text); + } } #endregion diff --git a/Src/FdoUi/LexEntryUi.cs b/Src/FdoUi/LexEntryUi.cs index eef84ebdae..5b4afa9f5c 100644 --- a/Src/FdoUi/LexEntryUi.cs +++ b/Src/FdoUi/LexEntryUi.cs @@ -103,78 +103,20 @@ public static LexEntryUi FindEntryForWordform(FdoCache cache, int hvoSrc, int ta /// /// /// - public static List FindEntriesForWordform(FdoCache cache, ITsString tssWf, IWfiAnalysis wfa) + public static List FindEntriesForWordformUI(FdoCache cache, ITsString tssWf, IWfiAnalysis wfa) { - if (tssWf == null) - return new List(); + bool duplicates = false; + List retval = cache.ServiceLocator.GetInstance().FindEntriesForWordform(cache, tssWf, wfa, ref duplicates); - var wf = tssWf.Text; - if (string.IsNullOrEmpty(wf)) - return new List(); - - var wsVern = TsStringUtils.GetWsAtOffset(tssWf, 0); - - var entries = new Set(); - - // Get the entries from the matching wordform. - // Get matching wordform. - var matchingWordforms = cache.ServiceLocator.GetInstance().AllInstances() - .Where(wrdfrm => wrdfrm.Form.get_String(wsVern).Text == wf); - if (matchingWordforms.Count() > 1) + if (duplicates) { MessageBox.Show(Form.ActiveForm, - string.Format(FdoUiStrings.ksDuplicateWordformsMsg, wf), + string.Format(FdoUiStrings.ksDuplicateWordformsMsg, tssWf.Text), FdoUiStrings.ksDuplicateWordformsCaption, MessageBoxButtons.OK, MessageBoxIcon.Warning); } - if (matchingWordforms.Count() > 0) - { - if (wfa != null && matchingWordforms.First().AnalysesOC.Contains(wfa)) - { - entries.AddRange(wfa.MorphBundlesOS - .Where(mb => mb.MsaRA != null) - .Select(mb => mb.MsaRA.Owner as ILexEntry)); - } - else - { - foreach (var analysis in matchingWordforms.First().AnalysesOC) - { - entries.AddRange(analysis.MorphBundlesOS - .Where(mb => mb.MsaRA != null) - .Select(mb => mb.MsaRA.Owner as ILexEntry)); - } - } - } - // Get the entries from the matching MoForms. - entries.AddRange( - cache.ServiceLocator.GetInstance().AllInstances() - .Cast() - .Where(mf => mf.Form.get_String(wsVern) != null && mf.Form.get_String(wsVern).Text == wf) - .Select(mf => mf.Owner as ILexEntry)); - - // Get the entries from the citation form - entries.AddRange( - cache.ServiceLocator.GetInstance().AllInstances() - .Cast() - .Where(entry => entry.CitationForm.get_String(wsVern) != null && entry.CitationForm.get_String(wsVern).Text == wf)); - - // Put the enrties in a List and sort it by the HomographNumber. - var retval = new List(entries.ToArray()); - retval.Sort(CompareEntriesByHomographNumber); return retval; } - private static string GetLowercaseStringFromMultiUnicodeSafely(ILgCharacterPropertyEngine icuEngine, IMultiUnicode form, int ws) - { - if (form == null) - return string.Empty; - - var formTsstring = form.get_String(ws); - if (formTsstring == null || formTsstring.Length == 0) - return string.Empty; - - return icuEngine.ToLower(formTsstring.Text); - } - /// ------------------------------------------------------------------------------------ /// /// Find wordform given a cache and the string. @@ -185,65 +127,7 @@ private static string GetLowercaseStringFromMultiUnicodeSafely(ILgCharacterPrope /// ------------------------------------------------------------------------------------ public static LexEntryUi FindEntryForWordform(FdoCache cache, ITsString tssWf) { - if (tssWf == null || tssWf.Length == 0) - return null; - - var wsVern = TsStringUtils.GetWsAtOffset(tssWf, 0); - var icuEngine = cache.LanguageWritingSystemFactoryAccessor.get_CharPropEngine(wsVern); - var wf = icuEngine.ToLower(tssWf.Text); - ILexEntry matchingEntry = null; - - // Check for Lexeme form. - matchingEntry = ( - from e in cache.LanguageProject.LexDbOA.Entries - where e.LexemeFormOA != null && GetLowercaseStringFromMultiUnicodeSafely(icuEngine, e.LexemeFormOA.Form, wsVern) == wf - orderby e.HomographNumber - select e - ).FirstOrDefault(); - - // Check for Citation form. - if (matchingEntry == null) - matchingEntry = ( - from e in cache.LanguageProject.LexDbOA.Entries - where GetLowercaseStringFromMultiUnicodeSafely(icuEngine, e.CitationForm, wsVern) == wf - orderby e.HomographNumber - select e - ).FirstOrDefault(); - - // Check for Alternate forms. - if (matchingEntry == null) - matchingEntry =( - from e in cache.LanguageProject.LexDbOA.Entries - where ( - from af in e.AlternateFormsOS - where GetLowercaseStringFromMultiUnicodeSafely(icuEngine, af.Form, wsVern) == wf - select af - ).FirstOrDefault() != null - orderby e.HomographNumber - select e - ).FirstOrDefault(); - - // Look for the most commonly used analysis of the wordform. - if (matchingEntry == null) - { - IWfiWordform wordform; - if (cache.ServiceLocator.GetInstance().TryGetObject(tssWf, out wordform)) - { - var guesser = new AnalysisGuessServices(cache); - var guess = guesser.GetBestGuess(wordform); - var analysis = guess as IWfiAnalysis; - if (guess is IWfiGloss) - analysis = guess.Owner as IWfiAnalysis; - if (analysis != null) - { - matchingEntry = - (from mb in analysis.MorphBundlesOS - where mb.MorphRA is IMoStemAllomorph - select mb.MorphRA.Owner).FirstOrDefault() as ILexEntry; - } - } - } - + ILexEntry matchingEntry = cache.ServiceLocator.GetInstance().FindEntryForWordform(cache, tssWf); return matchingEntry == null ? null : new LexEntryUi(matchingEntry); } @@ -418,6 +302,7 @@ internal static void DisplayEntry(FdoCache cache, IWin32Window owner, Mediator m } } + // Currently only called from WCF (11/21/2013 - AP) public static void DisplayEntry(FdoCache cache, Mediator mediatorIn, IHelpTopicProvider helpProvider, string helpFileKey, ITsString tssWfIn, IWfiAnalysis wfa) { @@ -428,24 +313,7 @@ internal static void DisplayEntries(FdoCache cache, IWin32Window owner, Mediator IHelpTopicProvider helpProvider, string helpFileKey, ITsString tssWfIn, IWfiAnalysis wfa) { ITsString tssWf = tssWfIn; - var entries = FindEntriesForWordform(cache, tssWf, wfa); - - // if we do not find a match for the word then try converting it to lowercase and see if there - // is an entry in the lexicon for the Wordform in lowercase. This is needed for occurences of - // words which are capitalized at the beginning of sentences. LT-7444 RickM - if (entries == null || entries.Count == 0) - { - //We need to be careful when converting to lowercase therefore use Icu.ToLower() - //get the WS of the tsString - int wsWf = TsStringUtils.GetWsAtOffset(tssWf, 0); - //use that to get the locale for the WS, which is used for - string wsLocale = cache.ServiceLocator.WritingSystemManager.Get(wsWf).IcuLocale; - string sLower = Icu.ToLower(tssWf.Text, wsLocale); - ITsTextProps ttp = tssWf.get_PropertiesAt(0); - ITsStrFactory tsf = TsStrFactoryClass.Create(); - tssWf = tsf.MakeStringWithPropsRgch(sLower, sLower.Length, ttp); - entries = FindEntriesForWordform(cache, tssWf, wfa); - } + var entries = FindEntriesForWordformUI(cache, tssWf, wfa); StringTable stOrig; Mediator mediator; @@ -601,6 +469,7 @@ private static void EnsureWindowConfiguration(Mediator mediator) } } + // Currently only called from WCF (11/21/2013 - AP) public static void DisplayRelatedEntries(FdoCache cache, Mediator mediatorIn, IHelpTopicProvider helpProvider, string helpFileKey, ITsString tss) { @@ -618,7 +487,9 @@ public static void DisplayRelatedEntries(FdoCache cache, Mediator mediatorIn, /// The help provider. /// The help file key. /// The ITsString for the word form. + /// /// ------------------------------------------------------------ + // Currently only called from WCF (11/21/2013 - AP) public static void DisplayRelatedEntries(FdoCache cache, IWin32Window owner, Mediator mediatorIn, IHelpTopicProvider helpProvider, string helpFileKey, ITsString tssWf, bool hideInsertButton) @@ -825,19 +696,6 @@ protected override bool ShouldDisplayMenuForClass(int specifiedClsid, return LexEntryTags.kClassId == specifiedClsid || base.ShouldDisplayMenuForClass(specifiedClsid, display); } - - private static int CompareEntriesByHomographNumber(ILexEntry x, ILexEntry y) - { - return x == null - ? (y == null ? 0 /* Both are null, so are equal */ : -1 /* x not being null is grater than y which is null */) - : (y == null - ? 1 /* y being null is greater than x which is not null */ - : (x.HomographNumber == y.HomographNumber - ? 0 /* Neither are null, and homograph numbers are the same, so they are equal */ - : (x.HomographNumber > y.HomographNumber - ? 1 /* x is greater than x */ - : -1 /* x is less than y */))); - } } /// ---------------------------------------------------------------------------------------- diff --git a/Src/FwCoreDlgs/FwCoreDlgControls/FwCoreDlgControls.csproj b/Src/FwCoreDlgs/FwCoreDlgControls/FwCoreDlgControls.csproj index 59d899fffd..b95e217162 100644 --- a/Src/FwCoreDlgs/FwCoreDlgControls/FwCoreDlgControls.csproj +++ b/Src/FwCoreDlgs/FwCoreDlgControls/FwCoreDlgControls.csproj @@ -203,7 +203,9 @@ ConfigSenseLayout.cs - + + UserControl + UserControl @@ -222,7 +224,9 @@ FwGeneralTab.cs - + + Component + From f85f7ff1da52247ab75b537e38e2ca165b0921cf Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Tue, 26 Nov 2013 10:31:59 +0700 Subject: [PATCH 003/143] Remove ProgressBar and ProgressBarStyle from FDO Create ProgressBarWrapper as a pass-through implementation of ProgressBar. Add non-Windows Forms ProgressBarStyle enum. Change-Id: Ia567e55b63768b725e3f3533af4f4348766c0d92 --- .../FwControls/FilterAllTextsDialog.cs | 1 + .../FwControls/ObtainProjectMethod.cs | 1 + .../Controls/FwControls/ProgressDialogImpl.cs | 5 +- .../FwControls/ProgressDialogWithTask.cs | 1 + Src/Common/Controls/Widgets/Widgets.csproj | 4 +- Src/Common/FieldWorks/FieldWorks.cs | 2 + .../Framework/StatusBarProgressHandler.cs | 5 +- .../FwPrintLayoutComponentsTests.csproj | 8 +- Src/Common/FwUtils/ConsoleProgress.cs | 4 +- Src/Common/FwUtils/FwUtils.csproj | 1 + Src/Common/FwUtils/IProgress.cs | 64 +++++++- Src/Common/FwUtils/ProgressBarWrapper.cs | 146 ++++++++++++++++++ .../PrintLayoutTests/PrintLayoutTests.csproj | 8 +- Src/Common/RootSite/RootSite.csproj | 5 +- .../SimpleRootSiteTests.csproj | 4 +- Src/FDO/DomainImpl/OverridesLing_Lex.cs | 21 +-- .../BackupRestore/ProjectBackupService.cs | 1 + .../DomainServices/ClientServerServices.cs | 1 + .../DataMigration/FdoDataMigrationManager.cs | 1 - .../DataMigration/ImportFrom6_0.cs | 1 + Src/FDO/DomainServices/WfiWordformServices.cs | 12 +- Src/FDO/FDOTests/DummyProgressDlg.cs | 1 + .../FDOTests/DuplicateAnalysisFixerTests.cs | 7 +- .../FDOTests/DuplicateWordformFixerTests.cs | 7 +- Src/FDO/FDOTests/LingTests.cs | 9 +- Src/FDO/FdoInterfaceAdditions.cs | 6 +- Src/FDO/FdoRepositoryInterfaceAdditions.cs | 4 +- .../Impl/FdoRepositoryAdditions.cs | 2 +- Src/FDO/fdoCache.cs | 1 + Src/FwCoreDlgs/FwCoreDlgs.csproj | 2 +- Src/FwCoreDlgs/FwSplashScreen.cs | 1 + Src/FwCoreDlgs/RealSplashScreen.cs | 1 + .../Interlinear/DuplicateAnalysisFixer.cs | 3 +- .../Interlinear/DuplicateWordformFixer.cs | 3 +- Src/LexText/Interlinear/ITextDll.csproj | 20 +-- .../ITextDllTests/ITextDllTests.csproj | 4 +- .../Interlinear/LinguaLinksImportDlg.cs | 1 + .../DataNotebook/NotebookImportWiz.cs | 1 + .../LexTextControls/LexTextControls.csproj | 6 +- Src/LexText/LexTextControls/LiftImportDlg.cs | 1 + Src/LexText/Lexicon/FLExBridgeListener.cs | 1 + Src/LexText/Lexicon/HomographResetter.cs | 3 +- .../Lexicon/LexEntryInflTypeConverter.cs | 5 +- Src/LexText/Morphology/ConcordanceDlg.cs | 3 +- .../Morphology/MorphologyEditorDll.csproj | 8 +- Src/LexText/ParserUI/ParserUI.csproj | 10 +- Src/TE/TeImportExport/TeImportManager.cs | 1 + Src/Utilities/FixFwData/Program.cs | 1 + Src/xWorks/ExportDialog.cs | 1 + Src/xWorks/xWorksTests/xWorksTests.csproj | 8 +- 50 files changed, 312 insertions(+), 105 deletions(-) create mode 100644 Src/Common/FwUtils/ProgressBarWrapper.cs diff --git a/Src/Common/Controls/FwControls/FilterAllTextsDialog.cs b/Src/Common/Controls/FwControls/FilterAllTextsDialog.cs index e4465c8c0e..837a1cc35c 100644 --- a/Src/Common/Controls/FwControls/FilterAllTextsDialog.cs +++ b/Src/Common/Controls/FwControls/FilterAllTextsDialog.cs @@ -18,6 +18,7 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Resources; using XCore; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.Common.Controls { diff --git a/Src/Common/Controls/FwControls/ObtainProjectMethod.cs b/Src/Common/Controls/FwControls/ObtainProjectMethod.cs index 122ed5dd1c..bef334cf67 100644 --- a/Src/Common/Controls/FwControls/ObtainProjectMethod.cs +++ b/Src/Common/Controls/FwControls/ObtainProjectMethod.cs @@ -9,6 +9,7 @@ using SIL.FieldWorks.FDO.Infrastructure.Impl; using SIL.Utils; using XCore; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.Common.Controls { diff --git a/Src/Common/Controls/FwControls/ProgressDialogImpl.cs b/Src/Common/Controls/FwControls/ProgressDialogImpl.cs index 4ec39b93e6..96823e642d 100644 --- a/Src/Common/Controls/FwControls/ProgressDialogImpl.cs +++ b/Src/Common/Controls/FwControls/ProgressDialogImpl.cs @@ -19,6 +19,7 @@ using System.Windows.Forms; using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.Common.Controls { @@ -297,8 +298,8 @@ public Form Form /// ------------------------------------------------------------------------------------ public ProgressBarStyle ProgressBarStyle { - get { return progressBar.Style; } - set { progressBar.Style = value; } + get { return ProgressBarStyleExtensions.Convert(progressBar.Style); } + set { progressBar.Style = ProgressBarStyleExtensions.Convert(value); } } #endregion diff --git a/Src/Common/Controls/FwControls/ProgressDialogWithTask.cs b/Src/Common/Controls/FwControls/ProgressDialogWithTask.cs index 1587b37960..2e05dc22ce 100644 --- a/Src/Common/Controls/FwControls/ProgressDialogWithTask.cs +++ b/Src/Common/Controls/FwControls/ProgressDialogWithTask.cs @@ -22,6 +22,7 @@ using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.Application.ApplicationServices; using System.IO; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.Common.Controls { diff --git a/Src/Common/Controls/Widgets/Widgets.csproj b/Src/Common/Controls/Widgets/Widgets.csproj index c549f26009..e338430f0d 100644 --- a/Src/Common/Controls/Widgets/Widgets.csproj +++ b/Src/Common/Controls/Widgets/Widgets.csproj @@ -1,4 +1,4 @@ - + Local @@ -318,4 +318,4 @@ ../../../../DistFiles - + \ No newline at end of file diff --git a/Src/Common/FieldWorks/FieldWorks.cs b/Src/Common/FieldWorks/FieldWorks.cs index 9f531be6e6..b7734f1050 100644 --- a/Src/Common/FieldWorks/FieldWorks.cs +++ b/Src/Common/FieldWorks/FieldWorks.cs @@ -59,6 +59,8 @@ using Gecko; #else using NetSparkle; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; + #endif [assembly:SuppressMessage("Gendarme.Rules.Portability", "ExitCodeIsLimitedOnUnixRule", diff --git a/Src/Common/Framework/StatusBarProgressHandler.cs b/Src/Common/Framework/StatusBarProgressHandler.cs index d131bb8e4e..c03b2529dc 100644 --- a/Src/Common/Framework/StatusBarProgressHandler.cs +++ b/Src/Common/Framework/StatusBarProgressHandler.cs @@ -21,6 +21,7 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.Common.Framework { @@ -213,8 +214,8 @@ public Form Form /// ------------------------------------------------------------------------------------ public ProgressBarStyle ProgressBarStyle { - get { return m_progressBar.Style; } - set { m_progressBar.Style = value; } + get { return ProgressBarStyleExtensions.Convert(m_progressBar.Style); } + set { m_progressBar.Style = ProgressBarStyleExtensions.Convert(value); } } /// ------------------------------------------------------------------------------------ diff --git a/Src/Common/FwPrintLayoutComponents/FwPrintLayoutComponentsTests/FwPrintLayoutComponentsTests.csproj b/Src/Common/FwPrintLayoutComponents/FwPrintLayoutComponentsTests/FwPrintLayoutComponentsTests.csproj index 5933f6a648..1616fe94d1 100644 --- a/Src/Common/FwPrintLayoutComponents/FwPrintLayoutComponentsTests/FwPrintLayoutComponentsTests.csproj +++ b/Src/Common/FwPrintLayoutComponents/FwPrintLayoutComponentsTests/FwPrintLayoutComponentsTests.csproj @@ -192,15 +192,11 @@ FwSetupFixtureClass.cs - - Form - + Code - - Form - + diff --git a/Src/Common/FwUtils/ConsoleProgress.cs b/Src/Common/FwUtils/ConsoleProgress.cs index 9a28214ac9..b9239c3659 100644 --- a/Src/Common/FwUtils/ConsoleProgress.cs +++ b/Src/Common/FwUtils/ConsoleProgress.cs @@ -173,9 +173,9 @@ public bool AllowCancel /// /// Gets or sets the progress bar style. /// - public System.Windows.Forms.ProgressBarStyle ProgressBarStyle + public ProgressBarStyle ProgressBarStyle { - get { return System.Windows.Forms.ProgressBarStyle.Continuous; } + get { return ProgressBarStyle.Continuous; } set { } } diff --git a/Src/Common/FwUtils/FwUtils.csproj b/Src/Common/FwUtils/FwUtils.csproj index 9b731f79d1..08c29cc68a 100644 --- a/Src/Common/FwUtils/FwUtils.csproj +++ b/Src/Common/FwUtils/FwUtils.csproj @@ -203,6 +203,7 @@ + Code diff --git a/Src/Common/FwUtils/IProgress.cs b/Src/Common/FwUtils/IProgress.cs index 607aabb46f..fce56ee342 100644 --- a/Src/Common/FwUtils/IProgress.cs +++ b/Src/Common/FwUtils/IProgress.cs @@ -11,7 +11,6 @@ // File: IProgress.cs // --------------------------------------------------------------------------------------------- using System.ComponentModel; -using System.Windows.Forms; namespace SIL.FieldWorks.Common.FwUtils { @@ -98,7 +97,7 @@ int Maximum /// Gets the form displaying the progress (used for message box owners, etc). If the progress /// is not associated with a visible Form, then this returns its owning form, if any. /// - Form Form + System.Windows.Forms.Form Form { get; } @@ -114,4 +113,65 @@ Form Form /// bool AllowCancel { get; set; } } + + /// + /// Specifies the style that a uses to indicate the progress of an operation. + /// + /// 2 + public enum ProgressBarStyle + { + /// + /// Blocks + /// + Blocks, + /// + /// Continuous + /// + Continuous, + /// + /// Marquee + /// + Marquee + } + + /// + /// Methods for the ProgressBarStyle enum + /// + public static class ProgressBarStyleExtensions + { + /// + /// Converts from Windows Forms ProgressBarStyle + /// + /// From. + /// + public static ProgressBarStyle Convert(System.Windows.Forms.ProgressBarStyle from) + { + switch (from) + { + case System.Windows.Forms.ProgressBarStyle.Blocks: + return ProgressBarStyle.Blocks; + case System.Windows.Forms.ProgressBarStyle.Continuous: + return ProgressBarStyle.Continuous; + default: + return ProgressBarStyle.Marquee; + } + } + /// + /// Converts to Windows Forms ProgressBarStyle + /// + /// From. + /// + public static System.Windows.Forms.ProgressBarStyle Convert(ProgressBarStyle from) + { + switch (from) + { + case ProgressBarStyle.Blocks: + return System.Windows.Forms.ProgressBarStyle.Blocks; + case ProgressBarStyle.Continuous: + return System.Windows.Forms.ProgressBarStyle.Continuous; + default: + return System.Windows.Forms.ProgressBarStyle.Marquee; + } + } + } } diff --git a/Src/Common/FwUtils/ProgressBarWrapper.cs b/Src/Common/FwUtils/ProgressBarWrapper.cs new file mode 100644 index 0000000000..282763d1f6 --- /dev/null +++ b/Src/Common/FwUtils/ProgressBarWrapper.cs @@ -0,0 +1,146 @@ +// --------------------------------------------------------------------------------------------- +#region // Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Distributable under the terms of either the Common Public License or the +// GNU Lesser General Public License, as specified in the LICENSING.txt file. +// +#endregion +// +// File: ProgressBarWrapper.cs +// --------------------------------------------------------------------------------------------- +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Windows.Forms; + +namespace SIL.FieldWorks.Common.FwUtils +{ + /// + /// Wrapper class to allow a ProgressBar to function as an IProgress + /// + [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", Justification="Disposable member is exposed for Dispose call if necessary")] + public class ProgressBarWrapper : IProgress + { + + private readonly ProgressBar m_progressBar; + /// + /// Gets the wrapped ProgressBar + /// + public ProgressBar ProgressBar + { + get { return m_progressBar; } + } + + /// + /// Constructor which passes in the progressBar to wrap + /// + /// + public ProgressBarWrapper(ProgressBar progressBar) + { + m_progressBar = progressBar; + } + + #region IProgress implementation + /// + /// Event handler for listening to whether or the cancel button is pressed. + /// + public event CancelEventHandler Canceling; + + /// + /// Cause the progress indicator to advance by the specified amount. + /// + /// Amount of progress. + public void Step(int amount) + { + int stepSizeHold = StepSize; + StepSize = amount; + m_progressBar.PerformStep(); + StepSize = stepSizeHold; + + if (Canceling != null) + { + // don't do anything -- this just shuts up the compiler about the + // event handler never being used. + } + } + + /// + /// Get the title of the progress display window. + /// + /// The title. + public string Title { get; set; } //ProgressBar.Text? + + /// + /// Get the message within the progress display window. + /// + /// The message. + public string Message { get; set; } //ProgressBar.Text? + + /// + /// Gets or sets the current position of the progress bar. This should be within the limits set by + /// SetRange, or returned by GetRange. + /// + /// The position. + public int Position + { + get { return m_progressBar.Value; } + set { m_progressBar.Value = value; } + } + + /// + /// Gets or sets the size of the step increment used by Step. + /// + /// The size of the step. + public int StepSize + { + get { return m_progressBar.Step; } + set { m_progressBar.Step = value; } + } + + /// + /// Gets or sets the minimum value of the progress bar. + /// + /// The minimum. + public int Minimum + { + get { return m_progressBar.Minimum; } + set { m_progressBar.Minimum = value; } + } + /// + /// Gets or sets the maximum value of the progress bar. + /// + /// The maximum. + public int Maximum + { + get { return m_progressBar.Maximum; } + set { m_progressBar.Maximum = value; } + } + + /// + /// Gets the form displaying the progress (used for message box owners, etc). If the progress + /// is not associated with a visible Form, then this returns its owning form, if any. + /// + public Form Form { get; set; } + + /// + /// Gets or sets the progress bar style. + /// + public ProgressBarStyle ProgressBarStyle + { + get { return ProgressBarStyleExtensions.Convert(m_progressBar.Style); } + set { m_progressBar.Style = ProgressBarStyleExtensions.Convert(value); } + } + + /// + /// Gets or sets a value indicating whether the opertation executing on the separate thread + /// can be cancelled by a different thread (typically the main UI thread). + /// + public bool AllowCancel + { + get { return false; } + set { } + } + #endregion + } +} diff --git a/Src/Common/PrintLayout/PrintLayoutTests/PrintLayoutTests.csproj b/Src/Common/PrintLayout/PrintLayoutTests/PrintLayoutTests.csproj index ff32720784..222ca933b0 100644 --- a/Src/Common/PrintLayout/PrintLayoutTests/PrintLayoutTests.csproj +++ b/Src/Common/PrintLayout/PrintLayoutTests/PrintLayoutTests.csproj @@ -192,13 +192,9 @@ - - UserControl - + - - UserControl - + diff --git a/Src/Common/RootSite/RootSite.csproj b/Src/Common/RootSite/RootSite.csproj index dde1120a7e..f6e6cc7d23 100644 --- a/Src/Common/RootSite/RootSite.csproj +++ b/Src/Common/RootSite/RootSite.csproj @@ -142,7 +142,7 @@ False - ..\..\..\Downloads\Palaso.dll + ..\..\..\Downloads\Palaso.dll False @@ -273,8 +273,7 @@ - ../../../DistFiles - + \ No newline at end of file diff --git a/Src/Common/SimpleRootSite/SimpleRootSiteTests/SimpleRootSiteTests.csproj b/Src/Common/SimpleRootSite/SimpleRootSiteTests/SimpleRootSiteTests.csproj index 2df1790f95..f2d169c0c2 100644 --- a/Src/Common/SimpleRootSite/SimpleRootSiteTests/SimpleRootSiteTests.csproj +++ b/Src/Common/SimpleRootSite/SimpleRootSiteTests/SimpleRootSiteTests.csproj @@ -206,9 +206,7 @@ - - UserControl - + diff --git a/Src/FDO/DomainImpl/OverridesLing_Lex.cs b/Src/FDO/DomainImpl/OverridesLing_Lex.cs index cef34219f7..bbded7a42f 100644 --- a/Src/FDO/DomainImpl/OverridesLing_Lex.cs +++ b/Src/FDO/DomainImpl/OverridesLing_Lex.cs @@ -28,6 +28,7 @@ using System.Drawing; using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Application; using SIL.FieldWorks.FDO.Infrastructure.Impl; using SIL.Utils; @@ -241,29 +242,29 @@ public ICmPossibilityList PublicationTypesOA /// /// Allows user to convert LexEntryType to LexEntryInflType. /// - public void ConvertLexEntryInflTypes(ProgressBar progressBar, IEnumerable list) + public void ConvertLexEntryInflTypes(IProgress progressBar, IEnumerable list) { progressBar.Minimum = 0; progressBar.Maximum = list.Count(); - progressBar.Step = 1; + progressBar.StepSize = 1; foreach (var lexEntryType in list) { var leitFactory = m_cache.ServiceLocator.GetInstance(); var leit = leitFactory.Create(); leit.ConvertLexEntryType(lexEntryType); lexEntryType.Delete(); - progressBar.PerformStep(); + progressBar.Step(1); } } /// /// Allows user to convert LexEntryInflType to LexEntryType. /// - public void ConvertLexEntryTypes(ProgressBar progressBar, IEnumerable list) + public void ConvertLexEntryTypes(IProgress progressBar, IEnumerable list) { progressBar.Minimum = 0; progressBar.Maximum = list.Count(); - progressBar.Step = 1; + progressBar.StepSize = 1; foreach (var lexEntryInflType in list) { var leit = lexEntryInflType as ILexEntryInflType; @@ -274,20 +275,20 @@ public void ConvertLexEntryTypes(ProgressBar progressBar, IEnumerable /// Resets the homograph numbers for all entries but can take a null progress bar. /// - public void ResetHomographNumbers(ProgressBar progressBar) + public void ResetHomographNumbers(IProgress progressBar) { if (progressBar != null) { progressBar.Minimum = 0; progressBar.Maximum = Entries.Count(); - progressBar.Step = 1; + progressBar.StepSize = 1; } var processedEntryIds = new List(); UndoableUnitOfWorkHelper.DoUsingNewOrCurrentUOW(Strings.ksUndoResetHomographs, Strings.ksRedoResetHomographs, Cache.ActionHandlerAccessor, @@ -298,7 +299,7 @@ public void ResetHomographNumbers(ProgressBar progressBar) if (processedEntryIds.Contains(le.Hvo)) { if (progressBar != null) - progressBar.PerformStep(); + progressBar.Step(1); continue; } @@ -316,7 +317,7 @@ public void ResetHomographNumbers(ProgressBar progressBar) { processedEntryIds.Add(homograph.Hvo); if (progressBar != null) - progressBar.PerformStep(); + progressBar.Step(1); } } }); diff --git a/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs b/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs index ef5c5b8176..7bdd98d6f6 100644 --- a/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs +++ b/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs @@ -21,6 +21,7 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Infrastructure; using SIL.Utils; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.FDO.DomainServices.BackupRestore { diff --git a/Src/FDO/DomainServices/ClientServerServices.cs b/Src/FDO/DomainServices/ClientServerServices.cs index a05a098540..3699ae73f0 100644 --- a/Src/FDO/DomainServices/ClientServerServices.cs +++ b/Src/FDO/DomainServices/ClientServerServices.cs @@ -28,6 +28,7 @@ using SIL.FieldWorks.FDO.Infrastructure.Impl; using SIL.FieldWorks.Resources; using SIL.Utils; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.FDO.DomainServices { diff --git a/Src/FDO/DomainServices/DataMigration/FdoDataMigrationManager.cs b/Src/FDO/DomainServices/DataMigration/FdoDataMigrationManager.cs index 7b1a00aa87..03a0348d15 100644 --- a/Src/FDO/DomainServices/DataMigration/FdoDataMigrationManager.cs +++ b/Src/FDO/DomainServices/DataMigration/FdoDataMigrationManager.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Windows.Forms; using SIL.FieldWorks.Common.FwUtils; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration diff --git a/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs b/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs index e5a8d208b5..6988e47116 100644 --- a/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs +++ b/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs @@ -20,6 +20,7 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Resources; using SIL.Utils; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration { diff --git a/Src/FDO/DomainServices/WfiWordformServices.cs b/Src/FDO/DomainServices/WfiWordformServices.cs index c7cc24f3b9..d6ce8cc1f4 100644 --- a/Src/FDO/DomainServices/WfiWordformServices.cs +++ b/Src/FDO/DomainServices/WfiWordformServices.cs @@ -208,7 +208,7 @@ public static IPunctuationForm FindOrCreatePunctuationform(FdoCache cache, ITsSt /// /// /// A string containing a list of wordforms that could not be merged because they have differing values for other WSs - public static string FixDuplicates(FdoCache cache, ProgressBar progressBar) + public static string FixDuplicates(FdoCache cache, IProgress progressBar) { var failures = new HashSet(); var wfRepo = cache.ServiceLocator.GetInstance(); @@ -216,10 +216,10 @@ public static string FixDuplicates(FdoCache cache, ProgressBar progressBar) var wfiWordforms = wfRepo.AllInstances().ToArray(); progressBar.Minimum = 0; progressBar.Maximum = wfiWordforms.Length; - progressBar.Step = 1; + progressBar.StepSize = 1; foreach (var wf in wfiWordforms) { - progressBar.PerformStep(); + progressBar.Step(1); var text = wf.Form.VernacularDefaultWritingSystem.Text; if (string.IsNullOrEmpty(text)) continue; @@ -290,15 +290,15 @@ public static string FixDuplicates(FdoCache cache, ProgressBar progressBar) /// Merge duplicate analyses on all wordforms. (Also merges duplicate WfiGlosses.) /// /// - public static void MergeDuplicateAnalyses(FdoCache cache, ProgressBar progressBar) + public static void MergeDuplicateAnalyses(FdoCache cache, IProgress progressBar) { var wfiWordforms = cache.ServiceLocator.GetInstance().AllInstances().ToList(); progressBar.Minimum = 0; progressBar.Maximum = wfiWordforms.Count; - progressBar.Step = 1; + progressBar.StepSize = 1; foreach (var wf in wfiWordforms) { - progressBar.PerformStep(); + progressBar.Step(1); var analyses = wf.AnalysesOC.ToList(); for (int i = 0; i < analyses.Count; i++) { diff --git a/Src/FDO/FDOTests/DummyProgressDlg.cs b/Src/FDO/FDOTests/DummyProgressDlg.cs index ff9cc4d41a..8706fbe6d8 100644 --- a/Src/FDO/FDOTests/DummyProgressDlg.cs +++ b/Src/FDO/FDOTests/DummyProgressDlg.cs @@ -16,6 +16,7 @@ using System.Windows.Forms; using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.FDO.FDOTests { diff --git a/Src/FDO/FDOTests/DuplicateAnalysisFixerTests.cs b/Src/FDO/FDOTests/DuplicateAnalysisFixerTests.cs index 1175bd9806..87cec96d10 100644 --- a/Src/FDO/FDOTests/DuplicateAnalysisFixerTests.cs +++ b/Src/FDO/FDOTests/DuplicateAnalysisFixerTests.cs @@ -7,6 +7,7 @@ using NUnit.Framework; using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices; namespace SIL.FieldWorks.FDO.FDOTests @@ -20,7 +21,7 @@ namespace SIL.FieldWorks.FDO.FDOTests public class DuplicateAnalysisFixerTests : MemoryOnlyBackendProviderRestoredForEachTestTestBase { private IWfiWordformFactory m_wfiFactory; - private ProgressBar m_progress; + private ProgressBarWrapper m_progress; /// /// Set up some common data @@ -29,13 +30,13 @@ public override void TestSetup() { base.TestSetup(); m_wfiFactory = Cache.ServiceLocator.GetInstance(); - m_progress = new ProgressBar(); + m_progress = new ProgressBarWrapper(new ProgressBar()); } /// public override void TestTearDown() { - m_progress.Dispose(); + m_progress.ProgressBar.Dispose(); m_progress = null; base.TestTearDown(); } diff --git a/Src/FDO/FDOTests/DuplicateWordformFixerTests.cs b/Src/FDO/FDOTests/DuplicateWordformFixerTests.cs index e3b88655f2..55b1ca6eb3 100644 --- a/Src/FDO/FDOTests/DuplicateWordformFixerTests.cs +++ b/Src/FDO/FDOTests/DuplicateWordformFixerTests.cs @@ -2,6 +2,7 @@ using System.Windows.Forms; using NUnit.Framework; using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices; namespace SIL.FieldWorks.FDO.FDOTests @@ -15,7 +16,7 @@ namespace SIL.FieldWorks.FDO.FDOTests public class DuplicateWordformFixerTests : MemoryOnlyBackendProviderRestoredForEachTestTestBase { private IWfiWordformFactory m_wfiFactory; - private ProgressBar m_progress; + private ProgressBarWrapper m_progress; /// /// Set up some common data @@ -24,13 +25,13 @@ public override void TestSetup() { base.TestSetup(); m_wfiFactory = Cache.ServiceLocator.GetInstance(); - m_progress = new ProgressBar(); + m_progress = new ProgressBarWrapper(new ProgressBar()); } /// public override void TestTearDown() { - m_progress.Dispose(); + m_progress.ProgressBar.Dispose(); m_progress = null; base.TestTearDown(); } diff --git a/Src/FDO/FDOTests/LingTests.cs b/Src/FDO/FDOTests/LingTests.cs index ba7bbcd006..16057fe5fe 100644 --- a/Src/FDO/FDOTests/LingTests.cs +++ b/Src/FDO/FDOTests/LingTests.cs @@ -22,6 +22,7 @@ using System.Xml; using NUnit.Framework; using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainImpl; using SIL.FieldWorks.FDO.FDOTests.CellarTests; using SIL.FieldWorks.FDO.Validation; @@ -2410,11 +2411,13 @@ public void ConvertLexEntryInflTypes() using (var progressBar = new ProgressBar()) { + IProgress progressBarWrapper = new ProgressBarWrapper(progressBar); + var itemsToChange = new List(); itemsToChange.Add(lexEntryType1); itemsToChange.Add(lexEntryType1Sub1); - Cache.LangProject.LexDbOA.ConvertLexEntryInflTypes(progressBar, itemsToChange); + Cache.LangProject.LexDbOA.ConvertLexEntryInflTypes(progressBarWrapper, itemsToChange); var leit1 = ler1.VariantEntryTypesRS[0]; Assert.AreEqual(LexEntryInflTypeTags.kClassId, leit1.ClassID, "first lex entry type of first entry should be irregularly inflected form"); leit1 = ler1.VariantEntryTypesRS[1]; @@ -2465,11 +2468,13 @@ public void ConvertLexEntryTypes() using (var progressBar = new ProgressBar()) { + IProgress progressBarWrapper = new ProgressBarWrapper(progressBar); + var itemsToChange = new List(); itemsToChange.Add(lexEntryInflType1); itemsToChange.Add(lexEntryInflType1Sub1); - Cache.LangProject.LexDbOA.ConvertLexEntryTypes(progressBar, itemsToChange); + Cache.LangProject.LexDbOA.ConvertLexEntryTypes(progressBarWrapper, itemsToChange); var let1 = ler1.VariantEntryTypesRS[0]; Assert.AreEqual(LexEntryTypeTags.kClassId, let1.ClassID, "first lex entry type of first entry should be variant"); let1 = ler1.VariantEntryTypesRS[1]; diff --git a/Src/FDO/FdoInterfaceAdditions.cs b/Src/FDO/FdoInterfaceAdditions.cs index f62e765d4d..4e76c017a3 100644 --- a/Src/FDO/FdoInterfaceAdditions.cs +++ b/Src/FDO/FdoInterfaceAdditions.cs @@ -869,17 +869,17 @@ IEnumerable AllAllomorphs /// /// Resets the homograph numbers for all entries. /// - void ResetHomographNumbers(ProgressBar progressBar); + void ResetHomographNumbers(IProgress progressBar); /// /// Allows user to convert LexEntryType to LexEntryInflType. /// - void ConvertLexEntryInflTypes(ProgressBar progressBar, IEnumerable list); + void ConvertLexEntryInflTypes(IProgress progressBar, IEnumerable list); /// /// Allows user to convert LexEntryInflType to LexEntryType. /// - void ConvertLexEntryTypes(ProgressBar progressBar, IEnumerable list); + void ConvertLexEntryTypes(IProgress progressBar, IEnumerable list); /// /// used when dumping the lexical database for the automated Parser /// diff --git a/Src/FDO/FdoRepositoryInterfaceAdditions.cs b/Src/FDO/FdoRepositoryInterfaceAdditions.cs index 48b8ebf995..36b6511901 100644 --- a/Src/FDO/FdoRepositoryInterfaceAdditions.cs +++ b/Src/FDO/FdoRepositoryInterfaceAdditions.cs @@ -14,8 +14,8 @@ // -------------------------------------------------------------------------------------------- using System; using System.Collections.Generic; -using System.Windows.Forms; using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.DomainServices.SemanticDomainSearch; @@ -409,7 +409,7 @@ public partial interface ILexEntryRepository /// /// Clear the list of homograph information /// - void ResetHomographs(ProgressBar progressBar); + void ResetHomographs(IProgress progressBar); /// /// Return a list of all the homographs of the specified form. diff --git a/Src/FDO/Infrastructure/Impl/FdoRepositoryAdditions.cs b/Src/FDO/Infrastructure/Impl/FdoRepositoryAdditions.cs index 36594d2001..69cb047221 100644 --- a/Src/FDO/Infrastructure/Impl/FdoRepositoryAdditions.cs +++ b/Src/FDO/Infrastructure/Impl/FdoRepositoryAdditions.cs @@ -1248,7 +1248,7 @@ public IEnumerable GetVariantFormEntries(ICmObject mainEntryOrSense) /// /// Clear the list of homograph information /// - public void ResetHomographs(ProgressBar progressBar) + public void ResetHomographs(IProgress progressBar) { m_homographInfo = null; // GetHomographs() will rebuild the homograph list Cache.LanguageProject.LexDbOA.ResetHomographNumbers(progressBar); diff --git a/Src/FDO/fdoCache.cs b/Src/FDO/fdoCache.cs index 34d115dac2..b05086bf5a 100644 --- a/Src/FDO/fdoCache.cs +++ b/Src/FDO/fdoCache.cs @@ -36,6 +36,7 @@ using SIL.CoreImpl; using SIL.FieldWorks.FDO.Infrastructure.Impl; using SIL.Utils.FileDialog; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.FDO { diff --git a/Src/FwCoreDlgs/FwCoreDlgs.csproj b/Src/FwCoreDlgs/FwCoreDlgs.csproj index 6178906c2d..0b47007489 100644 --- a/Src/FwCoreDlgs/FwCoreDlgs.csproj +++ b/Src/FwCoreDlgs/FwCoreDlgs.csproj @@ -678,4 +678,4 @@ ../../DistFiles - + \ No newline at end of file diff --git a/Src/FwCoreDlgs/FwSplashScreen.cs b/Src/FwCoreDlgs/FwSplashScreen.cs index b45631616c..a5bb9052e3 100644 --- a/Src/FwCoreDlgs/FwSplashScreen.cs +++ b/Src/FwCoreDlgs/FwSplashScreen.cs @@ -20,6 +20,7 @@ using System.Windows.Forms; using SIL.FieldWorks.Common.FwUtils; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.FwCoreDlgs { diff --git a/Src/FwCoreDlgs/RealSplashScreen.cs b/Src/FwCoreDlgs/RealSplashScreen.cs index 9263564853..86ef398445 100644 --- a/Src/FwCoreDlgs/RealSplashScreen.cs +++ b/Src/FwCoreDlgs/RealSplashScreen.cs @@ -20,6 +20,7 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; using SIL.FieldWorks.Common.Controls; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.FwCoreDlgs { diff --git a/Src/LexText/Interlinear/DuplicateAnalysisFixer.cs b/Src/LexText/Interlinear/DuplicateAnalysisFixer.cs index ccc783dfcc..f6585be725 100644 --- a/Src/LexText/Interlinear/DuplicateAnalysisFixer.cs +++ b/Src/LexText/Interlinear/DuplicateAnalysisFixer.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text; using System.Windows.Forms; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.Infrastructure; @@ -68,7 +69,7 @@ public void Process() var cache = (FdoCache) m_dlg.Mediator.PropertyTable.GetValue("cache"); UndoableUnitOfWorkHelper.Do(ITextStrings.ksUndoMergeAnalyses, ITextStrings.ksRedoMergeAnalyses, cache.ActionHandlerAccessor, - () => WfiWordformServices.MergeDuplicateAnalyses(cache, m_dlg.ProgressBar)); + () => WfiWordformServices.MergeDuplicateAnalyses(cache, new ProgressBarWrapper(m_dlg.ProgressBar))); } } } diff --git a/Src/LexText/Interlinear/DuplicateWordformFixer.cs b/Src/LexText/Interlinear/DuplicateWordformFixer.cs index 3c8e5d2184..699361e858 100644 --- a/Src/LexText/Interlinear/DuplicateWordformFixer.cs +++ b/Src/LexText/Interlinear/DuplicateWordformFixer.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text; using System.Windows.Forms; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.Infrastructure; @@ -62,7 +63,7 @@ public void Process() var cache = (FdoCache)m_dlg.Mediator.PropertyTable.GetValue("cache"); string failures = null; UndoableUnitOfWorkHelper.Do(ITextStrings.ksUndoMergeWordforms, ITextStrings.ksRedoMergeWordforms, cache.ActionHandlerAccessor, - () => failures = WfiWordformServices.FixDuplicates(cache, m_dlg.ProgressBar)); + () => failures = WfiWordformServices.FixDuplicates(cache, new ProgressBarWrapper(m_dlg.ProgressBar))); if (!string.IsNullOrEmpty(failures)) { MessageBox.Show(m_dlg, string.Format(ITextStrings.ksWordformMergeFailures, failures), ITextStrings.ksWarning, diff --git a/Src/LexText/Interlinear/ITextDll.csproj b/Src/LexText/Interlinear/ITextDll.csproj index d737acb469..59f7f74bee 100644 --- a/Src/LexText/Interlinear/ITextDll.csproj +++ b/Src/LexText/Interlinear/ITextDll.csproj @@ -350,9 +350,7 @@ UserControl - - Form - + Form @@ -382,15 +380,9 @@ InterlinDocRootSiteBase.cs - - UserControl - - - UserControl - - - UserControl - + + + UserControl @@ -409,9 +401,7 @@ InterlinMaster.cs - - UserControl - + True diff --git a/Src/LexText/Interlinear/ITextDllTests/ITextDllTests.csproj b/Src/LexText/Interlinear/ITextDllTests/ITextDllTests.csproj index c07365b7e5..88c0059272 100644 --- a/Src/LexText/Interlinear/ITextDllTests/ITextDllTests.csproj +++ b/Src/LexText/Interlinear/ITextDllTests/ITextDllTests.csproj @@ -256,9 +256,7 @@ - - UserControl - + diff --git a/Src/LexText/Interlinear/LinguaLinksImportDlg.cs b/Src/LexText/Interlinear/LinguaLinksImportDlg.cs index 7f48985a16..12a3624f11 100644 --- a/Src/LexText/Interlinear/LinguaLinksImportDlg.cs +++ b/Src/LexText/Interlinear/LinguaLinksImportDlg.cs @@ -19,6 +19,7 @@ using SIL.FieldWorks.Common.RootSites; using SIL.FieldWorks.XWorks; using SilEncConverters40; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.IText { diff --git a/Src/LexText/LexTextControls/DataNotebook/NotebookImportWiz.cs b/Src/LexText/LexTextControls/DataNotebook/NotebookImportWiz.cs index 64439f3490..0211c6414c 100644 --- a/Src/LexText/LexTextControls/DataNotebook/NotebookImportWiz.cs +++ b/Src/LexText/LexTextControls/DataNotebook/NotebookImportWiz.cs @@ -40,6 +40,7 @@ using System.Globalization; using SIL.FieldWorks.Common.RootSites; using SilEncConverters40; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.LexText.Controls.DataNotebook { diff --git a/Src/LexText/LexTextControls/LexTextControls.csproj b/Src/LexText/LexTextControls/LexTextControls.csproj index f942426ca5..9b87fff159 100644 --- a/Src/LexText/LexTextControls/LexTextControls.csproj +++ b/Src/LexText/LexTextControls/LexTextControls.csproj @@ -241,10 +241,10 @@ \usr\lib\cli\geckofx-14.0.1\geckofx-core-14.dll - + \usr\lib\cli\geckofx-14.0.1\Geckofx-Winforms-14.dll - + PreserveNewest @@ -697,4 +697,4 @@ - + \ No newline at end of file diff --git a/Src/LexText/LexTextControls/LiftImportDlg.cs b/Src/LexText/LexTextControls/LiftImportDlg.cs index ce39f5270b..88444ba0d4 100644 --- a/Src/LexText/LexTextControls/LiftImportDlg.cs +++ b/Src/LexText/LexTextControls/LiftImportDlg.cs @@ -35,6 +35,7 @@ using SIL.Utils; using SIL.Utils.FileDialog; using SIL.FieldWorks.Resources; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.LexText.Controls { diff --git a/Src/LexText/Lexicon/FLExBridgeListener.cs b/Src/LexText/Lexicon/FLExBridgeListener.cs index ea63ece9cc..7ae11202ac 100644 --- a/Src/LexText/Lexicon/FLExBridgeListener.cs +++ b/Src/LexText/Lexicon/FLExBridgeListener.cs @@ -24,6 +24,7 @@ using SIL.FieldWorks.XWorks.LexText; using SIL.Utils; using XCore; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.XWorks.LexEd { diff --git a/Src/LexText/Lexicon/HomographResetter.cs b/Src/LexText/Lexicon/HomographResetter.cs index ae3ce57e33..b31ac37690 100644 --- a/Src/LexText/Lexicon/HomographResetter.cs +++ b/Src/LexText/Lexicon/HomographResetter.cs @@ -1,5 +1,6 @@ using System.Diagnostics; using System.Linq; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.FwCoreDlgs; @@ -94,7 +95,7 @@ public void Process() cache.LanguageProject.HomographWs = defaultVernacularWsId; }); } - cache.LanguageProject.LexDbOA.ResetHomographNumbers(m_dlg.ProgressBar); + cache.LanguageProject.LexDbOA.ResetHomographNumbers(new ProgressBarWrapper(m_dlg.ProgressBar)); } /// diff --git a/Src/LexText/Lexicon/LexEntryInflTypeConverter.cs b/Src/LexText/Lexicon/LexEntryInflTypeConverter.cs index 13c59abe80..bf0267f6e3 100644 --- a/Src/LexText/Lexicon/LexEntryInflTypeConverter.cs +++ b/Src/LexText/Lexicon/LexEntryInflTypeConverter.cs @@ -7,6 +7,7 @@ using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.Common.Controls; using SIL.FieldWorks.Common.Framework.DetailControls; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.Application; using SIL.FieldWorks.FDO.Infrastructure; @@ -205,7 +206,7 @@ public override void Process() protected override void Convert(IEnumerable itemsToChange) { - m_cache.LanguageProject.LexDbOA.ConvertLexEntryInflTypes(m_dlg.ProgressBar, itemsToChange); + m_cache.LanguageProject.LexDbOA.ConvertLexEntryInflTypes(new SIL.FieldWorks.Common.FwUtils.ProgressBarWrapper(m_dlg.ProgressBar), itemsToChange); } } @@ -257,7 +258,7 @@ public override void Process() protected override void Convert(IEnumerable itemsToChange) { - m_cache.LanguageProject.LexDbOA.ConvertLexEntryTypes(m_dlg.ProgressBar, itemsToChange); + m_cache.LanguageProject.LexDbOA.ConvertLexEntryTypes(new SIL.FieldWorks.Common.FwUtils.ProgressBarWrapper(m_dlg.ProgressBar), itemsToChange); } #endregion IUtility implementation diff --git a/Src/LexText/Morphology/ConcordanceDlg.cs b/Src/LexText/Morphology/ConcordanceDlg.cs index 8ec4435395..8dc860a4f8 100644 --- a/Src/LexText/Morphology/ConcordanceDlg.cs +++ b/Src/LexText/Morphology/ConcordanceDlg.cs @@ -17,6 +17,7 @@ using XCore; using SIL.FieldWorks.Common.Controls; using SIL.CoreImpl; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.XWorks.MorphologyEditor { @@ -169,7 +170,7 @@ public ProgressReporting(ToolStripProgressBar bar) m_progressBar.Minimum = 0; m_progressBar.Maximum = 100; m_progressBar.Value = 0; - m_progressBar.ProgressBar.Style = ProgressBarStyle.Continuous; + m_progressBar.ProgressBar.Style = ProgressBarStyleExtensions.Convert(ProgressBarStyle.Continuous); } #region IProgress Members diff --git a/Src/LexText/Morphology/MorphologyEditorDll.csproj b/Src/LexText/Morphology/MorphologyEditorDll.csproj index 131d5a4d82..73891480dc 100644 --- a/Src/LexText/Morphology/MorphologyEditorDll.csproj +++ b/Src/LexText/Morphology/MorphologyEditorDll.csproj @@ -270,9 +270,7 @@ UserControl - - UserControl - + AssignFeaturesToPhonemes.cs @@ -320,9 +318,7 @@ Code - - UserControl - + OneAnalysisSandbox.cs diff --git a/Src/LexText/ParserUI/ParserUI.csproj b/Src/LexText/ParserUI/ParserUI.csproj index 46d81a8c03..e3287f918b 100644 --- a/Src/LexText/ParserUI/ParserUI.csproj +++ b/Src/LexText/ParserUI/ParserUI.csproj @@ -1,4 +1,4 @@ - + Local @@ -159,10 +159,10 @@ \usr\lib\cli\geckofx-14.0.1\geckofx-core-14.dll - + \usr\lib\cli\geckofx-14.0.1\Geckofx-Winforms-14.dll - + PreserveNewest @@ -247,9 +247,7 @@ UserControl - - UserControl - + diff --git a/Src/TE/TeImportExport/TeImportManager.cs b/Src/TE/TeImportExport/TeImportManager.cs index 9aa07d8b4d..9e75e8c4f0 100644 --- a/Src/TE/TeImportExport/TeImportManager.cs +++ b/Src/TE/TeImportExport/TeImportManager.cs @@ -32,6 +32,7 @@ using SIL.FieldWorks.FDO.Infrastructure; using SILUBS.SharedScrUtils; using XCore; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.TE { diff --git a/Src/Utilities/FixFwData/Program.cs b/Src/Utilities/FixFwData/Program.cs index 2e74be978b..a6d62ecfc1 100644 --- a/Src/Utilities/FixFwData/Program.cs +++ b/Src/Utilities/FixFwData/Program.cs @@ -19,6 +19,7 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FixData; using Palaso.UI.WindowsForms.HotSpot; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace FixFwData { diff --git a/Src/xWorks/ExportDialog.cs b/Src/xWorks/ExportDialog.cs index 1176b0b121..61133f473d 100644 --- a/Src/xWorks/ExportDialog.cs +++ b/Src/xWorks/ExportDialog.cs @@ -45,6 +45,7 @@ using SIL.FieldWorks.Common.RootSites; using SIL.FieldWorks.LexText.Controls; using XCore; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.XWorks { diff --git a/Src/xWorks/xWorksTests/xWorksTests.csproj b/Src/xWorks/xWorksTests/xWorksTests.csproj index 5668714181..dbc418d9d0 100644 --- a/Src/xWorks/xWorksTests/xWorksTests.csproj +++ b/Src/xWorks/xWorksTests/xWorksTests.csproj @@ -240,9 +240,7 @@ - - Form - + @@ -258,9 +256,7 @@ - - Form - + AssemblyInfo.cs From 03f428c0fe9700db44dea37d3eabcf9972c8b853 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Wed, 27 Nov 2013 11:37:39 +0700 Subject: [PATCH 004/143] Remove all dialogs from FDO User actions are passed through an interface. Original Windows Forms implementation is provided for Fieldworks. Change-Id: I47450ce5735b538058eb6d35bbb0e2c6c7af6fd5 --- .../FwControls/ObtainProjectMethod.cs | 15 +- .../TestColumnConfigureDialog.cs | 2 +- Src/Common/FieldWorks/FieldWorks.cs | 22 +- .../FwPrintLayoutComponentsTests.csproj | 8 +- Src/Common/FwUtils/FwUtils.csproj | 1 + .../FwUtilsTests/DummyFdoUserAction.cs | 51 ++ .../FwUtils/FwUtilsTests/FwUtilsTests.csproj | 1 + Src/Common/FwUtils/IFdoUserAction.cs | 40 ++ .../PrintLayoutTests/PrintLayoutTests.csproj | 8 +- .../BackupRestore/ProjectBackupService.cs | 4 +- .../BackupRestore/ProjectRestoreService.cs | 5 +- .../DomainServices/ClientServerServices.cs | 48 +- Src/FDO/FDO.csproj | 20 - .../BackupRestoreSettingsTests.cs | 4 +- .../ProjectRestoreServiceTests.cs | 17 +- Src/FDO/FDOTests/ClientServerServicesTests.cs | 16 +- Src/FDO/FDOTests/FdoCacheTests.cs | 29 +- Src/FDO/FDOTests/FdoTestBase.cs | 4 +- .../PersistingBackendProviderTests.cs | 4 +- .../PersistingLayerTests.BEPPortTests.cs | 8 +- Src/FDO/FDOTests/XmlImportDataTests.cs | 2 +- Src/FDO/FDOTests/XmlListTests.cs | 2 +- Src/FDO/FDOTests/XmlTranslatedListsTests.cs | 2 +- Src/FDO/IOC/FdoServiceLocatorFactory.cs | 10 +- .../Impl/ClientServerBackendProvider.cs | 4 +- .../Infrastructure/Impl/ConflictingSaveDlg.cs | 27 - .../Infrastructure/Impl/ConnectionLostDlg.cs | 24 - .../Impl/Db4oClientServerBackendProvider.cs | 30 +- .../Infrastructure/Impl/FDOBackendProvider.cs | 8 +- .../Impl/MemoryOnlyBackendProvider.cs | 6 +- .../Infrastructure/Impl/UnitOfWorkService.cs | 22 +- .../Infrastructure/Impl/XMLBackendProvider.cs | 4 +- Src/FDO/fdoCache.cs | 47 +- Src/FDOBrowser/FDOBrowser.csproj | 477 +++++++++--------- Src/FDOBrowser/FDOBrowserForm.cs | 4 +- Src/FDOBrowser/FDOClassList.cs | 2 +- Src/FDOBrowser/FdoUserAction.cs | 47 ++ Src/FDOBrowser/ModelWnd.cs | 2 +- .../ConflictingSaveDlg.Designer.cs | 2 +- Src/FdoUi/ConflictingSaveDlg.cs | 33 ++ .../Impl => FdoUi}/ConflictingSaveDlg.resx | 2 +- .../ConnectionLostDlg.Designer.cs | 2 +- Src/FdoUi/ConnectionLostDlg.cs | 28 + .../Impl => FdoUi}/ConnectionLostDlg.resx | 2 +- Src/FdoUi/FdoUi.csproj | 21 + Src/FdoUi/FdoUserActionWindowsForms.cs | 54 ++ .../BackupRestore/BackupProjectDlg.cs | 2 +- .../BackupRestore/BackupProjectPresenter.cs | 4 +- Src/FwCoreDlgs/ChooseLangProjectDialog.cs | 11 +- .../FwCoreDlgsTests/FwNewLangProjectTests.cs | 11 +- Src/FwCoreDlgs/FwNewLangProject.cs | 15 +- Src/LexText/Interlinear/ITextDll.csproj | 20 +- .../ITextDllTests/ITextDllTests.csproj | 4 +- .../LexTextControlsTests/LiftExportTests.cs | 2 +- Src/LexText/Lexicon/FLExBridgeListener.cs | 4 +- .../Morphology/MorphologyEditorDll.csproj | 8 +- Src/LexText/ParserUI/ParserUI.csproj | 4 +- Src/xWorks/xWorksTests/ExportDialogTests.cs | 2 +- Src/xWorks/xWorksTests/xWorksTests.csproj | 8 +- 59 files changed, 784 insertions(+), 482 deletions(-) create mode 100644 Src/Common/FwUtils/FwUtilsTests/DummyFdoUserAction.cs create mode 100644 Src/Common/FwUtils/IFdoUserAction.cs delete mode 100644 Src/FDO/Infrastructure/Impl/ConflictingSaveDlg.cs delete mode 100644 Src/FDO/Infrastructure/Impl/ConnectionLostDlg.cs create mode 100644 Src/FDOBrowser/FdoUserAction.cs rename Src/{FDO/Infrastructure/Impl => FdoUi}/ConflictingSaveDlg.Designer.cs (98%) create mode 100644 Src/FdoUi/ConflictingSaveDlg.cs rename Src/{FDO/Infrastructure/Impl => FdoUi}/ConflictingSaveDlg.resx (99%) rename Src/{FDO/Infrastructure/Impl => FdoUi}/ConnectionLostDlg.Designer.cs (98%) create mode 100644 Src/FdoUi/ConnectionLostDlg.cs rename Src/{FDO/Infrastructure/Impl => FdoUi}/ConnectionLostDlg.resx (99%) create mode 100644 Src/FdoUi/FdoUserActionWindowsForms.cs diff --git a/Src/Common/Controls/FwControls/ObtainProjectMethod.cs b/Src/Common/Controls/FwControls/ObtainProjectMethod.cs index bef334cf67..e4e0ae7b14 100644 --- a/Src/Common/Controls/FwControls/ObtainProjectMethod.cs +++ b/Src/Common/Controls/FwControls/ObtainProjectMethod.cs @@ -25,7 +25,7 @@ public static class ObtainProjectMethod /// /// Null if the operation was cancelled or otherwise did not work. The full pathname of an fwdata file, if it did work. public static string ObtainProjectFromAnySource(Form parent, IHelpTopicProvider helpTopicProvider, - out ObtainedProjectType obtainedProjectType) + out ObtainedProjectType obtainedProjectType, IFdoUserAction userAction) { bool dummy; string fwdataFileFullPathname; @@ -46,7 +46,7 @@ public static string ObtainProjectFromAnySource(Form parent, IHelpTopicProvider if (fwdataFileFullPathname.EndsWith("lift")) { - fwdataFileFullPathname = CreateProjectFromLift(parent, helpTopicProvider, fwdataFileFullPathname); + fwdataFileFullPathname = CreateProjectFromLift(parent, helpTopicProvider, fwdataFileFullPathname, userAction); obtainedProjectType = ObtainedProjectType.Lift; } @@ -56,7 +56,7 @@ public static string ObtainProjectFromAnySource(Form parent, IHelpTopicProvider /// /// Create a new Fieldworks project and import a lift file into it. Return the .fwdata path. /// - private static string CreateProjectFromLift(Form parent, IHelpTopicProvider helpTopicProvider, string liftPath) + private static string CreateProjectFromLift(Form parent, IHelpTopicProvider helpTopicProvider, string liftPath, IFdoUserAction userAction) { string projectPath; FdoCache cache; @@ -80,7 +80,7 @@ private static string CreateProjectFromLift(Form parent, IHelpTopicProvider help progressDlg.ProgressBarStyle = ProgressBarStyle.Continuous; progressDlg.Title = FwControls.ksCreatingLiftProject; var cacheReceiver = new FdoCache[1]; // a clumsy way of handling an out parameter, consistent with RunTask - projectPath = (string)progressDlg.RunTask(true, CreateProjectTask, + projectPath = (string)progressDlg.RunTask(true, (progress, parameters) => CreateProjectTask(progress, userAction, parameters), new object[] { liftPath, helper, anthroListFile, cacheReceiver }); cache = cacheReceiver[0]; } @@ -105,9 +105,10 @@ private static string CreateProjectFromLift(Form parent, IHelpTopicProvider help /// as a background task while showing the dialog. /// /// + /// /// A specific list is required...see the first few lines of the method. /// - private static object CreateProjectTask(IThreadedProgress progress, object[] parameters) + private static object CreateProjectTask(IThreadedProgress progress, IFdoUserAction userAction, object[] parameters) { // Get required parameters. Ideally these would just be the signature of the method, but RunTask requires object[]. var liftPathname = (string)parameters[0]; @@ -118,13 +119,13 @@ private static object CreateProjectTask(IThreadedProgress progress, object[] par IWritingSystem wsVern, wsAnalysis; RetrieveDefaultWritingSystemsFromLift(liftPathname, out wsVern, out wsAnalysis); - string projectPath = FdoCache.CreateNewLangProj(progress, + string projectPath = FdoCache.CreateNewLangProj(progress, userAction, Directory.GetParent(Path.GetDirectoryName(liftPathname)).Parent.Name, // Get the new Flex project name from the Lift pathname. helper, wsAnalysis, wsVern, null, null, null, anthroFile); // This is a temporary cache, just to do the import, and AFAIK we have no access to the current // user WS. So create it as "English". Put it in the array to return to the caller. - cacheReceiver[0] = FdoCache.CreateCacheFromLocalProjectFile(projectPath, "en", progress); + cacheReceiver[0] = FdoCache.CreateCacheFromLocalProjectFile(projectPath, "en", progress, userAction); return projectPath; } diff --git a/Src/Common/Controls/XMLViews/XMLViewsTests/TestColumnConfigureDialog.cs b/Src/Common/Controls/XMLViews/XMLViewsTests/TestColumnConfigureDialog.cs index 3a8e4fe62d..9ec9ee7d8c 100644 --- a/Src/Common/Controls/XMLViews/XMLViewsTests/TestColumnConfigureDialog.cs +++ b/Src/Common/Controls/XMLViews/XMLViewsTests/TestColumnConfigureDialog.cs @@ -35,7 +35,7 @@ public void SetUp() m_mediator = new Mediator(); m_mediator.StringTbl = new StringTable("../../DistFiles/Language Explorer/Configuration"); m_cache = FdoCache.CreateCacheWithNewBlankLangProj( - new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "en", "en", new ThreadHelper()); + new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "en", "en", new ThreadHelper(), new DummyFdoUserAction()); m_mediator.PropertyTable.SetProperty("cache", m_cache); } diff --git a/Src/Common/FieldWorks/FieldWorks.cs b/Src/Common/FieldWorks/FieldWorks.cs index b7734f1050..b377b20951 100644 --- a/Src/Common/FieldWorks/FieldWorks.cs +++ b/Src/Common/FieldWorks/FieldWorks.cs @@ -42,6 +42,7 @@ using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.DomainServices.BackupRestore; using SIL.FieldWorks.FDO.Infrastructure; +using SIL.FieldWorks.FdoUi; using SIL.FieldWorks.FwCoreDlgs; using SIL.FieldWorks.FwCoreDlgs.BackupRestore; using SIL.FieldWorks.PaObjects; @@ -130,6 +131,7 @@ private enum StartupStatus // true if we have no previous reporting settings, typically the first time a version of FLEx that // supports usage reporting has been run. private static bool s_noPreviousReportingSettings; + private static IFdoUserAction s_userAction; #endregion #region Main Method and Initialization Methods @@ -189,6 +191,8 @@ static int Main(string[] rgArgs) #endif s_threadHelper = new ThreadHelper(); + s_userAction = new FdoUserActionWindowsForms(); + // ENHANCE (TimS): Another idea for ensuring that we have only one process started for // this project is to use a Mutex. They can be used for cross-process resource access // and would probably be less error-prone then our current implementation since it @@ -769,7 +773,7 @@ private static FdoCache CreateCache(ProjectId projectId) Form owner = s_splashScreen != null ? s_splashScreen.Form : Form.ActiveForm; using (var progressDlg = new ProgressDialogWithTask(owner, s_threadHelper)) { - FdoCache cache = FdoCache.CreateCacheFromExistingData(projectId, s_sWsUser, progressDlg); + FdoCache cache = FdoCache.CreateCacheFromExistingData(projectId, s_sWsUser, progressDlg, s_userAction); cache.ProjectNameChanged += ProjectNameChanged; cache.ServiceLocator.GetInstance().OnSave += FieldWorks_OnSave; @@ -1616,7 +1620,7 @@ private static ProjectId ShowWelcomeDialog(FwAppArgs args, FwApp startingApp, Pr projectToTry = null; // If the user cancels the send/receive, this null will result in a return to the welcome dialog. // Hard to say what Form.ActiveForm is here. The splash and welcome dlgs are both gone. var projectDataPathname = ObtainProjectMethod.ObtainProjectFromAnySource(Form.ActiveForm, - helpTopicProvider, out obtainedProjectType); + helpTopicProvider, out obtainedProjectType, s_userAction); if (!string.IsNullOrEmpty(projectDataPathname)) { projectToTry = new ProjectId(FDOBackendProviderType.kXML, projectDataPathname, null); @@ -1688,7 +1692,7 @@ internal static ProjectId ChooseLangProject(Form dialogOwner, IHelpTopicProvider { return null; } - using (var dlg = new ChooseLangProjectDialog(helpTopicProvider, false)) + using (var dlg = new ChooseLangProjectDialog(helpTopicProvider, false, s_userAction)) { dlg.ShowDialog(dialogOwner); var app = helpTopicProvider as IApp; @@ -1720,7 +1724,7 @@ internal static ProjectId ChooseLangProject(Form dialogOwner, IHelpTopicProvider /// ------------------------------------------------------------------------------------ internal static ProjectId CreateNewProject(Form dialogOwner, FwApp app, IHelpTopicProvider helpTopicProvider) { - using (var dlg = new FwNewLangProject()) + using (var dlg = new FwNewLangProject(s_userAction)) { dlg.SetDialogProperties(helpTopicProvider); switch (dlg.DisplayDialog(dialogOwner)) @@ -1950,7 +1954,7 @@ private static bool UpdateProjectsSharing(bool fShareProjects, Form dialogOwner // Both these setters check and do nothing if not changed. using (var progressDlg = new ProgressDialogWithTask(null, s_threadHelper)) { - return ClientServerServices.Current.Local.SetProjectSharing(fShareProjects, progressDlg); + return ClientServerServices.Current.Local.SetProjectSharing(fShareProjects, progressDlg, s_userAction); } } @@ -1959,7 +1963,7 @@ private static bool UpdateProjectsSharing(bool fShareProjects, Form dialogOwner { using (var progressDlg = new ProgressDialogWithTask(null, s_threadHelper)) { - fSuccess = ClientServerServices.Current.Local.SetProjectSharing(fShareProjects, progressDlg); + fSuccess = ClientServerServices.Current.Local.SetProjectSharing(fShareProjects, progressDlg, s_userAction); } return new ProjectId(ClientServerServices.Current.Local.IdForLocalProject(Path.GetFileNameWithoutExtension(projectPath)), null); }); @@ -2460,7 +2464,7 @@ private static void RestoreCurrentProject(FwRestoreProjectSettings restoreSettin private static void DoRestore(ProjectRestoreService restoreService) { using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(null, s_threadHelper)) - restoreService.RestoreProject(progressDlg); + restoreService.RestoreProject(progressDlg, s_userAction); } /// ------------------------------------------------------------------------------------ @@ -2484,7 +2488,7 @@ private static bool BackupProjectForRestore(FwRestoreProjectSettings restoreSett { FdoCache cache = existingCache ?? FdoCache.CreateCacheFromExistingData( new ProjectId(restoreSettings.Settings.FullProjectPath, null), - s_sWsUser, progressDlg); + s_sWsUser, progressDlg, s_userAction); try { @@ -2493,7 +2497,7 @@ private static bool BackupProjectForRestore(FwRestoreProjectSettings restoreSett settings.AppAbbrev = restoreSettings.FwAppCommandLineAbbrev; ProjectBackupService backupService = new ProjectBackupService(cache, settings); - backupService.BackupProject(progressDlg); + backupService.BackupProject(progressDlg, s_userAction); } catch (FwBackupException e) { diff --git a/Src/Common/FwPrintLayoutComponents/FwPrintLayoutComponentsTests/FwPrintLayoutComponentsTests.csproj b/Src/Common/FwPrintLayoutComponents/FwPrintLayoutComponentsTests/FwPrintLayoutComponentsTests.csproj index 1616fe94d1..5933f6a648 100644 --- a/Src/Common/FwPrintLayoutComponents/FwPrintLayoutComponentsTests/FwPrintLayoutComponentsTests.csproj +++ b/Src/Common/FwPrintLayoutComponents/FwPrintLayoutComponentsTests/FwPrintLayoutComponentsTests.csproj @@ -192,11 +192,15 @@ FwSetupFixtureClass.cs - + + Form + Code - + + Form + diff --git a/Src/Common/FwUtils/FwUtils.csproj b/Src/Common/FwUtils/FwUtils.csproj index 08c29cc68a..a9abb03425 100644 --- a/Src/Common/FwUtils/FwUtils.csproj +++ b/Src/Common/FwUtils/FwUtils.csproj @@ -176,6 +176,7 @@ + diff --git a/Src/Common/FwUtils/FwUtilsTests/DummyFdoUserAction.cs b/Src/Common/FwUtils/FwUtilsTests/DummyFdoUserAction.cs new file mode 100644 index 0000000000..d01382f5f3 --- /dev/null +++ b/Src/Common/FwUtils/FwUtilsTests/DummyFdoUserAction.cs @@ -0,0 +1,51 @@ +// --------------------------------------------------------------------------------------------- +#region // Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Distributable under the terms of either the Common Public License or the +// GNU Lesser General Public License, as specified in the LICENSING.txt file. +// +#endregion +// --------------------------------------------------------------------------------------------- +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SIL.FieldWorks.Common.FwUtils +{ + /// + /// Dummy implementation of FdoUserAction for unit tests + /// + public class DummyFdoUserAction : IFdoUserAction + { + /// + /// Check with user regarding conflicting changes + /// + /// True if user wishes to revert to saved state. False otherwise. + public bool ConflictingSave() + { + throw new NotImplementedException(); + //return false; + } + + /// + /// Inform the user of a lost connection + /// + /// True if user wishes to attempt reconnect. False otherwise. + public bool ConnectionLost() + { + throw new NotImplementedException(); + //return false; + } + + /// + /// Displays information to the user + /// + public void MessageBox() + { + throw new NotImplementedException(); + } + } +} diff --git a/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj b/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj index 0b8a84df8c..91de873255 100644 --- a/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj +++ b/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj @@ -148,6 +148,7 @@ + diff --git a/Src/Common/FwUtils/IFdoUserAction.cs b/Src/Common/FwUtils/IFdoUserAction.cs new file mode 100644 index 0000000000..4a2ed2bba7 --- /dev/null +++ b/Src/Common/FwUtils/IFdoUserAction.cs @@ -0,0 +1,40 @@ +// --------------------------------------------------------------------------------------------- +#region // Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Distributable under the terms of either the Common Public License or the +// GNU Lesser General Public License, as specified in the LICENSING.txt file. +// +#endregion +// --------------------------------------------------------------------------------------------- +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SIL.FieldWorks.Common.FwUtils +{ + /// + /// Used for getting user feedback while processing FDO requests + /// + public interface IFdoUserAction + { + /// + /// Check with user regarding conflicting changes + /// + /// True if user wishes to revert to saved state. False otherwise. + bool ConflictingSave(); + + /// + /// Inform the user of a lost connection + /// + /// True if user wishes to attempt reconnect. False otherwise. + bool ConnectionLost(); + + /// + /// Displays information to the user + /// + void MessageBox(); + } +} diff --git a/Src/Common/PrintLayout/PrintLayoutTests/PrintLayoutTests.csproj b/Src/Common/PrintLayout/PrintLayoutTests/PrintLayoutTests.csproj index 222ca933b0..ff32720784 100644 --- a/Src/Common/PrintLayout/PrintLayoutTests/PrintLayoutTests.csproj +++ b/Src/Common/PrintLayout/PrintLayoutTests/PrintLayoutTests.csproj @@ -192,9 +192,13 @@ - + + UserControl + - + + UserControl + diff --git a/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs b/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs index 7bdd98d6f6..640516c419 100644 --- a/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs +++ b/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs @@ -47,7 +47,7 @@ public ProjectBackupService(FdoCache cache, BackupProjectSettings settings) /// Perform a backup of the current project, using specified settings. /// /// The backup file or null if something went wrong. - public string BackupProject(IThreadedProgress progressDlg) + public string BackupProject(IThreadedProgress progressDlg, IFdoUserAction userAction) { PersistBackupFileSettings(); @@ -58,7 +58,7 @@ public string BackupProject(IThreadedProgress progressDlg) m_cache.ServiceLocator.GetInstance().Save(); m_cache.ServiceLocator.GetInstance().CompleteAllCommits(); - string tempFilePath = ClientServerServices.Current.Local.CopyToXmlFile(m_cache, m_settings.DatabaseFolder); + string tempFilePath = ClientServerServices.Current.Local.CopyToXmlFile(m_cache, m_settings.DatabaseFolder, userAction); var filesToZip = CreateListOfFilesToZip(); progressDlg.Title = Strings.ksBackupProgressCaption; diff --git a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs index fd08dbe982..14e11cfab2 100644 --- a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs +++ b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs @@ -73,11 +73,12 @@ public ProjectRestoreService(RestoreProjectSettings settings) /// Perform a restore of the project specified in the settings. /// /// The progress dialog. + /// /// File does not exist, or some such problem /// XML deserialization problem or required /// files not found in zip file /// ------------------------------------------------------------------------------------ - public void RestoreProject(IThreadedProgress progressDlg) + public void RestoreProject(IThreadedProgress progressDlg, IFdoUserAction userAction) { BackupFileSettings fileSettings = m_restoreSettings.Backup; fileSettings.Validate(); // Normally, this will already have been done, so this will do nothing. @@ -126,7 +127,7 @@ public void RestoreProject(IThreadedProgress progressDlg) // switch to the desired backend (if it's in the projects directory...anything else stays XML for now). if (DirectoryFinder.IsSubFolderOfProjectsDirectory(m_restoreSettings.ProjectPath) && !suppressConversion) - ClientServerServices.Current.Local.ConvertToDb4oBackendIfNeeded(progressDlg, m_restoreSettings.FullProjectPath); + ClientServerServices.Current.Local.ConvertToDb4oBackendIfNeeded(progressDlg, m_restoreSettings.FullProjectPath, userAction); CleanupAfterRestore(true); } diff --git a/Src/FDO/DomainServices/ClientServerServices.cs b/Src/FDO/DomainServices/ClientServerServices.cs index 3699ae73f0..9d09fd2ce7 100644 --- a/Src/FDO/DomainServices/ClientServerServices.cs +++ b/Src/FDO/DomainServices/ClientServerServices.cs @@ -219,8 +219,9 @@ public interface ILocalClientServerServices /// /// if set to true, turn sharing on. /// The progress dialog. + /// /// Indication of whether the request was performed successfully. - bool SetProjectSharing(bool fShare, IThreadedProgress progress); + bool SetProjectSharing(bool fShare, IThreadedProgress progress, IFdoUserAction userAction); /// /// Return true if the specified project (in the specified parent directory) will be @@ -238,10 +239,11 @@ public interface ILocalClientServerServices /// The progress dialog for getting a message box owner and/or /// ensuring we're invoking on the uI thread. /// The full path of the existing XML file for the project + /// /// The project identifier, typically the path to the converted file (or the /// original, if not configured for the client-server backend) /// ------------------------------------------------------------------------------------ - string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string filename); + string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string filename, IFdoUserAction userAction); /// /// Copies the specified project (assumed to be in the current Projects directory) @@ -251,7 +253,8 @@ public interface ILocalClientServerServices /// The source cache /// The destination directory for the converted copy if a /// conversion needs to be done. - string CopyToXmlFile(FdoCache source, string destDir); + /// + string CopyToXmlFile(FdoCache source, string destDir, IFdoUserAction userAction); /// /// Return the full ID that should be used to open the specified project, which is in the @@ -615,8 +618,9 @@ public bool ShareMyProjects /// /// if set to true, turn sharing on. /// The progress dialog. + /// /// ------------------------------------------------------------------------------------ - public bool SetProjectSharing(bool fShare, IThreadedProgress progress) + public bool SetProjectSharing(bool fShare, IThreadedProgress progress, IFdoUserAction userAction) { Db4oServerInfo serverInfo = null; do @@ -643,7 +647,7 @@ public bool SetProjectSharing(bool fShare, IThreadedProgress progress) if (fShare) { // Turning sharing on. - if (!ConvertAllProjectsToDb4o(progress)) + if (!ConvertAllProjectsToDb4o(progress, userAction)) { LocalDb4OServerInfoConnection.ShareProjects(false); // could not switch return false; @@ -651,7 +655,7 @@ public bool SetProjectSharing(bool fShare, IThreadedProgress progress) } else { - if (!ConvertAllProjectsToXml(progress)) + if (!ConvertAllProjectsToXml(progress, userAction)) { // If ConvertAllProjectsToXml failed then leave sharing on. LocalDb4OServerInfoConnection.ShareProjects(true); @@ -769,7 +773,7 @@ private static DialogResult WarnOfOtherConnectedClients(Form messageBoxOwner, /// true if successful; false if other clients are connected, /// which prevents conversion of shared projects. /// ------------------------------------------------------------------------------------ - private bool ConvertAllProjectsToXml(IThreadedProgress progressDlg) + private bool ConvertAllProjectsToXml(IThreadedProgress progressDlg, IFdoUserAction userAction) { if (!EnsureNoClientsAreConnected()) return false; @@ -778,12 +782,11 @@ private bool ConvertAllProjectsToXml(IThreadedProgress progressDlg) progressDlg.AllowCancel = false; progressDlg.ProgressBarStyle = ProgressBarStyle.Continuous; progressDlg.Maximum = Directory.GetDirectories(DirectoryFinder.ProjectsDirectory).Count(); - progressDlg.RunTask(true, ConvertAllProjectsToXmlTask); - + progressDlg.RunTask(true, (progress, args) => ConvertAllProjectsToXmlTask(progress, userAction, args)); return true; } - private object ConvertAllProjectsToXmlTask(IThreadedProgress progress, object[] args) + private object ConvertAllProjectsToXmlTask(IThreadedProgress progress, IFdoUserAction userAction, object[] args) { foreach (var projectFolder in Directory.GetDirectories(DirectoryFinder.ProjectsDirectory)) { @@ -798,9 +801,9 @@ private object ConvertAllProjectsToXmlTask(IThreadedProgress progress, object[] // This is fine since we aren't yet trying to start up on this restored database. // The null says we are creating the file on the local host. using (var tempCache = FdoCache.CreateCacheFromExistingData( - new SimpleProjectId(FDOBackendProviderType.kDb4oClientServer, projectPath), "en", progress)) + new SimpleProjectId(FDOBackendProviderType.kDb4oClientServer, projectPath), "en", progress, userAction)) { - CopyToXmlFile(tempCache, tempCache.ProjectId.ProjectFolder); + CopyToXmlFile(tempCache, tempCache.ProjectId.ProjectFolder, userAction); // Enhance JohnT: how can we tell this succeeded? } File.Delete(projectPath); // only if we converted successfully; otherwise will throw. @@ -820,17 +823,18 @@ private object ConvertAllProjectsToXmlTask(IThreadedProgress progress, object[] /// Converts all projects to db4o. /// /// The progress dialog box. + /// /// ------------------------------------------------------------------------------------ - private bool ConvertAllProjectsToDb4o(IThreadedProgress progressDlg) + private bool ConvertAllProjectsToDb4o(IThreadedProgress progressDlg, IFdoUserAction userAction) { progressDlg.Title = Strings.ksConvertingToShared; progressDlg.AllowCancel = false; progressDlg.ProgressBarStyle = ProgressBarStyle.Continuous; progressDlg.Maximum = Directory.GetDirectories(DirectoryFinder.ProjectsDirectory).Count(); - return (bool)progressDlg.RunTask(true, ConvertAllProjectsToDb4o); + return (bool)progressDlg.RunTask(true, (progress, args) => ConvertAllProjectsToDb4o(progress, userAction, args)); } - private object ConvertAllProjectsToDb4o(IThreadedProgress progress, object[] args) + private object ConvertAllProjectsToDb4o(IThreadedProgress progress, IFdoUserAction userAction, object[] args) { for (; ; ) { @@ -863,7 +867,7 @@ private object ConvertAllProjectsToDb4o(IThreadedProgress progress, object[] arg { try { - ConvertToDb4oBackendIfNeeded(progress, projectPath); + ConvertToDb4oBackendIfNeeded(progress, projectPath, userAction); } catch (Exception e) { @@ -901,10 +905,11 @@ private static void ReportConversionError(Form messageBoxOwner, string projectPa /// The progress dialog (for getting a message box owner and/or /// ensuring we're invoking on the UI thread). /// The full path of the existing XML file for the project + /// /// The project identifier, typically the path to the converted file (or the /// original, if not configured for the client-server backend) /// ------------------------------------------------------------------------------------ - public string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string xmlFilename) + public string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string xmlFilename, IFdoUserAction userAction) { if (!ShareMyProjects) return xmlFilename; // no conversion needed. @@ -915,14 +920,14 @@ public string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string try { using (var tempCache = FdoCache.CreateCacheFromExistingData( - new SimpleProjectId(FDOBackendProviderType.kXML, xmlFilename), "en", progressDlg)) + new SimpleProjectId(FDOBackendProviderType.kXML, xmlFilename), "en", progressDlg, userAction)) { // The zero in the object array is for db4o and causes it not to open a port. // This is fine since we aren't yet trying to start up on this restored database. // The null says we are creating the file on the local host. using (var copyCache = FdoCache.CreateCacheCopy( - new SimpleProjectId(FDOBackendProviderType.kDb4oClientServer, desiredPath), "en", tempCache, progressDlg.ThreadHelper)) + new SimpleProjectId(FDOBackendProviderType.kDb4oClientServer, desiredPath), "en", tempCache, progressDlg.ThreadHelper, userAction)) { copyCache.ServiceLocator.GetInstance().Commit(new HashSet(), new HashSet(), new HashSet()); @@ -951,8 +956,9 @@ public string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string /// The source cache /// The destination directory for the converted copy if a /// conversion needs to be done. + /// /// ------------------------------------------------------------------------------------ - public string CopyToXmlFile(FdoCache source, string destDir) + public string CopyToXmlFile(FdoCache source, string destDir, IFdoUserAction userAction) { IDataStorer dataStorer = source.ServiceLocator.GetInstance(); if (dataStorer is XMLBackendProvider) @@ -964,7 +970,7 @@ public string CopyToXmlFile(FdoCache source, string destDir) try { using (var copyCache = FdoCache.CreateCacheCopy( - new SimpleProjectId(FDOBackendProviderType.kXML, newFilePath), "en", source, source.ThreadHelper)) + new SimpleProjectId(FDOBackendProviderType.kXML, newFilePath), "en", source, source.ThreadHelper, userAction)) { copyCache.ServiceLocator.GetInstance().Commit( new HashSet(), diff --git a/Src/FDO/FDO.csproj b/Src/FDO/FDO.csproj index 59d3c15ca1..d219e36250 100644 --- a/Src/FDO/FDO.csproj +++ b/Src/FDO/FDO.csproj @@ -407,18 +407,6 @@ - - Form - - - ConflictingSaveDlg.cs - - - Form - - - ConnectionLostDlg.cs - @@ -560,14 +548,6 @@ ScrFdoResources.Designer.cs Designer - - ConflictingSaveDlg.cs - Designer - - - ConnectionLostDlg.cs - Designer - ResXFileCodeGenerator Resources.Designer.cs diff --git a/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs b/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs index 048e72550d..414c5f391f 100644 --- a/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs +++ b/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs @@ -102,7 +102,7 @@ public void RestoreProjectSettings_VerifyExistenceOfProject() try { // Restore the project and check to ensure that it exists. - restoreProjectService.RestoreProject(new DummyProgressDlg()); + restoreProjectService.RestoreProject(new DummyProgressDlg(), new DummyFdoUserAction()); Assert.True(restoreSettings.ProjectExists, "Project does not exist but it should."); } finally @@ -139,7 +139,7 @@ public void RestoreProjectSettings_VerifyExistenceOfHgRepo() try { // Restore the project and check to ensure that it exists, but is not using Send/Receive. - restoreProjectService.RestoreProject(new DummyProgressDlg()); + restoreProjectService.RestoreProject(new DummyProgressDlg(), new DummyFdoUserAction()); Assert.True(restoreSettings.ProjectExists, "Project does not exist but it should."); Assert.False(restoreSettings.UsingSendReceive, "Project is using S/R but it should not be."); diff --git a/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs b/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs index f263830f3f..c43b7c98fb 100644 --- a/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs +++ b/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs @@ -34,6 +34,7 @@ public class ProjectRestoreServiceTests : MemoryOnlyBackendProviderBasicTestBase { private ProjectRestoreService m_restoreProjectService; private RestoreProjectSettings m_restoreSettings; + private IFdoUserAction m_userAction; private bool m_fResetSharedProjectValue; /// Setup for db4o client server tests. [TestFixtureSetUp] @@ -77,6 +78,8 @@ public void Initialize() ProjectName = "TestRestoreFWProject", BackupOfExistingProjectRequested = false, }; + + m_userAction = new DummyFdoUserAction(); } /// @@ -99,7 +102,7 @@ public void RestoreProject_CreateNew_OnlyDataFileAndWsFiles() m_restoreProjectService = new ProjectRestoreService(m_restoreSettings); - m_restoreProjectService.RestoreProject(new DummyProgressDlg()); + m_restoreProjectService.RestoreProject(new DummyProgressDlg(), m_userAction); VerifyManditoryFilesUnzippedAndDeleteThem(); } @@ -115,7 +118,7 @@ public void RestoreProject_CreateNew_DataFileAndConfigurationSettings() m_restoreSettings.IncludeConfigurationSettings = true; m_restoreProjectService = new ProjectRestoreService(m_restoreSettings); - m_restoreProjectService.RestoreProject(new DummyProgressDlg()); + m_restoreProjectService.RestoreProject(new DummyProgressDlg(), m_userAction); VerifyManditoryFilesUnzippedAndDeleteThem(); @@ -135,7 +138,7 @@ public void RestoreProject_PutLinkedFilesInDefaultLocation() m_restoreProjectService = new ProjectRestoreTestService(m_restoreSettings); ((ProjectRestoreTestService)m_restoreProjectService).PutFilesInProject = true; - m_restoreProjectService.RestoreProject(new DummyProgressDlg()); + m_restoreProjectService.RestoreProject(new DummyProgressDlg(), m_userAction); VerifyManditoryFilesUnzippedAndDeleteThem(); @@ -164,7 +167,7 @@ public void RestoreProject_PutLinkedFilesInOldLocation() var fullVersionOfRelativeNonStdDir = GetFullVersionOfRelativeNonStdDir(nonStdLinkedFilesDir); try { - m_restoreProjectService.RestoreProject(new DummyProgressDlg()); + m_restoreProjectService.RestoreProject(new DummyProgressDlg(), m_userAction); VerifyManditoryFilesUnzippedAndDeleteThem(); @@ -200,7 +203,7 @@ public void RestoreProject_PutLinkedFilesInOldLocation_CancelSelected() var fullVersionOfRelativeNonStdDir = GetFullVersionOfRelativeNonStdDir(nonStdLinkedFilesDir); try { - m_restoreProjectService.RestoreProject(new DummyProgressDlg()); + m_restoreProjectService.RestoreProject(new DummyProgressDlg(), m_userAction); VerifyManditoryFilesUnzippedAndDeleteThem(); @@ -237,7 +240,7 @@ public void RestoreProject_OverwriteOnlyDataRestored() m_restoreProjectService = new ProjectRestoreService(m_restoreSettings); //Restore the project once and do not delete it so that we can restore the project over the previous one. - m_restoreProjectService.RestoreProject(progressDlg); + m_restoreProjectService.RestoreProject(progressDlg, m_userAction); string restoreProjectDirectory = m_restoreSettings.ProjectPath; VerifyFileExists(restoreProjectDirectory, DirectoryFinder.GetXmlDataFileName("TestRestoreFWProject")); @@ -253,7 +256,7 @@ public void RestoreProject_OverwriteOnlyDataRestored() Assert.True(m_restoreSettings.ProjectExists, "Project does not exist but it should."); //Now do another restore then verify that the two files are not the same by comparing the LastWriteTime values. - m_restoreProjectService.RestoreProject(progressDlg); + m_restoreProjectService.RestoreProject(progressDlg, m_userAction); var dateTimeTicksOfSecondFile = GetLastWriteTimeOfRestoredFile(restoreProjectDirectory, DirectoryFinder.GetXmlDataFileName("TestRestoreFWProject")); Assert.True(dateTimeTicksOfSecondFile.Equals(dateTimeTicksOfFirstFile), "The dates and times of the files should be the same since they are set to the timestamp of the file in the zip file."); diff --git a/Src/FDO/FDOTests/ClientServerServicesTests.cs b/Src/FDO/FDOTests/ClientServerServicesTests.cs index 2c90c2da07..78e8f3d47e 100644 --- a/Src/FDO/FDOTests/ClientServerServicesTests.cs +++ b/Src/FDO/FDOTests/ClientServerServicesTests.cs @@ -25,6 +25,8 @@ public class ClientServerServicesTests : BaseTest private IThreadedProgress m_progress; + private IFdoUserAction m_userAction; + /// [SetUp] public void StartFwRemoteDatabaseConnector() @@ -45,6 +47,8 @@ public void StartFwRemoteDatabaseConnector() m_db4OServerInfo.AreProjectShared(); m_progress = new DummyProgressDlg(); + + m_userAction = new DummyFdoUserAction(); } /// @@ -78,7 +82,7 @@ public void ProjectNames_NullServer_ThrowsArgumentExeception() [Test] public void ProjectNames_LocalhostServiceIsRunning_ProjectsReturned() { - ClientServerServices.Current.Local.SetProjectSharing(true, m_progress); + ClientServerServices.Current.Local.SetProjectSharing(true, m_progress, m_userAction); using (var db4OServerFile = new TemporaryDb4OServerFile(m_db4OServerInfo)) { @@ -95,9 +99,9 @@ public void ProjectNames_LocalhostServiceIsRunning_ProjectsReturned() [Test] public void ShareMyProjects_TurningShareMyProjectOff_ShareMyProjectsReturnedFalse() { - ClientServerServices.Current.Local.SetProjectSharing(true, m_progress); + ClientServerServices.Current.Local.SetProjectSharing(true, m_progress, m_userAction); - Assert.IsTrue(ClientServerServices.Current.Local.SetProjectSharing(false, m_progress)); + Assert.IsTrue(ClientServerServices.Current.Local.SetProjectSharing(false, m_progress, m_userAction)); Assert.AreEqual(false, ClientServerServices.Current.Local.ShareMyProjects); } @@ -105,9 +109,9 @@ public void ShareMyProjects_TurningShareMyProjectOff_ShareMyProjectsReturnedFals [Test] public void ShareMyProjects_TurningShareMyProjectOn_ShareMyProjectsReturnedTrue() { - ClientServerServices.Current.Local.SetProjectSharing(false, m_progress); + ClientServerServices.Current.Local.SetProjectSharing(false, m_progress, m_userAction); - Assert.IsTrue(ClientServerServices.Current.Local.SetProjectSharing(true, m_progress)); + Assert.IsTrue(ClientServerServices.Current.Local.SetProjectSharing(true, m_progress, m_userAction)); Assert.IsTrue(Db4OLocalClientServerServices.LocalDb4OServerInfoConnection.AreProjectShared()); Assert.IsFalse(ClientServerServices.Current.Local.ShareMyProjects, "ShareMyProjects should not be true unless HKCU projects dir same as HKLM"); var temp = DirectoryFinder.ProjectsDirectory; @@ -127,7 +131,7 @@ public void ConvertToCurrentBackend_ConvertFromFwDataToClientServer_ValidFwDataF [Test] public void IdForLocalProject_SimpleNameProjectsAreNotShared_ReturnedFilenameHasFwdataExtenstionAndExistsInProjectDirectory() { - ClientServerServices.Current.Local.SetProjectSharing(false, m_progress); + ClientServerServices.Current.Local.SetProjectSharing(false, m_progress, m_userAction); string filename = ClientServerServices.Current.Local.IdForLocalProject("tom"); // Assert ends with .fwdata diff --git a/Src/FDO/FDOTests/FdoCacheTests.cs b/Src/FDO/FDOTests/FdoCacheTests.cs index aa4bb77fcd..d3779dd806 100644 --- a/Src/FDO/FDOTests/FdoCacheTests.cs +++ b/Src/FDO/FDOTests/FdoCacheTests.cs @@ -35,6 +35,7 @@ namespace SIL.FieldWorks.FDO.CoreTests.FdoCacheTests public class FdoCacheTests : MemoryOnlyBackendProviderTestBase { private string m_oldProjectDirectory; + private IFdoUserAction m_userAction; /// Setup for db4o client server tests. public override void FixtureSetup() @@ -45,6 +46,8 @@ public override void FixtureSetup() DirectoryFinder.ProjectsDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); Directory.CreateDirectory(DirectoryFinder.ProjectsDirectory); + m_userAction = new DummyFdoUserAction(); + try { // Allow db4o client server unit test to work without running the window service. @@ -84,7 +87,7 @@ public void CreateNewLangProject_DbFilesExist() using (new DummyFileMaker(Path.Combine(DirectoryFinder.ProjectsDirectory, "Gumby", DirectoryFinder.GetXmlDataFileName("Gumby")))) { using (var threadHelper = new ThreadHelper()) - FdoCache.CreateNewLangProj(new DummyProgressDlg(), "Gumby", threadHelper); + FdoCache.CreateNewLangProj(new DummyProgressDlg(), new DummyFdoUserAction(), "Gumby", threadHelper); } } finally @@ -114,7 +117,7 @@ public void CreateNewLangProject_NameWithSingleQuote() { string dbFileName; using (var threadHelper = new ThreadHelper()) - dbFileName = FdoCache.CreateNewLangProj(new DummyProgressDlg(), dbName, threadHelper); + dbFileName = FdoCache.CreateNewLangProj(new DummyProgressDlg(), new DummyFdoUserAction(), dbName, threadHelper); currentDirs = new List(Directory.GetDirectories(DirectoryFinder.ProjectsDirectory)); if (currentDirs.Contains(writingSystemsCommonDir) && !expectedDirs.Contains(writingSystemsCommonDir)) @@ -145,9 +148,9 @@ public void CreateNewLangProject_AnthropologyCategoriesExist() // create project string dbFileName; using (var threadHelper = new ThreadHelper()) - dbFileName = FdoCache.CreateNewLangProj(new DummyProgressDlg(), dbName, threadHelper); + dbFileName = FdoCache.CreateNewLangProj(new DummyProgressDlg(), new DummyFdoUserAction(), dbName, threadHelper); - using (var cache = FdoCache.CreateCacheFromLocalProjectFile(dbFileName, "en", new DummyProgressDlg())) + using (var cache = FdoCache.CreateCacheFromLocalProjectFile(dbFileName, "en", new DummyProgressDlg(), m_userAction)) { Assert.AreEqual(Strings.ksAnthropologyCategories, cache.LangProject.AnthroListOA.Name.UiString, "Anthropology Categories list was not properly initialized."); @@ -218,7 +221,7 @@ public void ChangingLangProjDefaultVernWs_ChangesCacheDefaultVernWs() using (var threadHelper = new ThreadHelper()) using ( var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", threadHelper)) + "en", "fr", "en", threadHelper, m_userAction)) { var wsFr = cache.DefaultVernWs; Assert.That(cache.LangProject.DefaultVernacularWritingSystem.Handle, Is.EqualTo(wsFr)); @@ -252,7 +255,7 @@ public void ChangingLangProjDefaultAnalysisWs_ChangesCacheDefaultAnalWs() using (var threadHelper = new ThreadHelper()) using ( var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", threadHelper)) + "en", "fr", "en", threadHelper, m_userAction)) { var wsEn = cache.DefaultAnalWs; Assert.That(cache.LangProject.DefaultAnalysisWritingSystem.Handle, Is.EqualTo(wsEn)); @@ -287,7 +290,7 @@ public void ChangingLangProjDefaultPronunciationWs_ChangesCacheDefaultPronunciat using (var threadHelper = new ThreadHelper()) using ( var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", threadHelper)) + "en", "fr", "en", threadHelper, m_userAction)) { var wsFr = cache.DefaultPronunciationWs; Assert.That(cache.LangProject.DefaultPronunciationWritingSystem.Handle, Is.EqualTo(wsFr)); @@ -422,6 +425,8 @@ public void EnsureValidLinkedFilesFolderCore_NonDefaultLocationAndExists_DoesntC [TestFixture] public class FdoCacheDisposedTests: BaseTest { + private readonly IFdoUserAction m_userAction = new DummyFdoUserAction(); + /// /// Make sure the CheckDisposed method works. /// @@ -433,7 +438,7 @@ public void CacheCheckDisposedTest() using (var threadHelper = new ThreadHelper()) { var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", threadHelper); + "en", "fr", "en", threadHelper, m_userAction); // Init backend data provider var dataSetup = cache.ServiceLocator.GetInstance(); dataSetup.LoadDomain(BackendBulkLoadDomain.All); @@ -452,7 +457,7 @@ public void CacheIsDisposedTest() { // This can't be in the minimalist class, because it disposes the cache. var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", threadHelper); + "en", "fr", "en", threadHelper, m_userAction); // Init backend data provider var dataSetup = cache.ServiceLocator.GetInstance(); dataSetup.LoadDomain(BackendBulkLoadDomain.All); @@ -471,7 +476,7 @@ public void CacheDisposedForFDOObject() using (var threadHelper = new ThreadHelper()) { var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", threadHelper); + "en", "fr", "en", threadHelper, m_userAction); // Init backend data provider var dataSetup = cache.ServiceLocator.GetInstance(); dataSetup.LoadDomain(BackendBulkLoadDomain.All); @@ -489,7 +494,7 @@ public void FDOObjectDeleted() { using (var threadHelper = new ThreadHelper()) using (var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", threadHelper)) + "en", "fr", "en", threadHelper, m_userAction)) { // Init backend data provider var dataSetup = cache.ServiceLocator.GetInstance(); @@ -513,7 +518,7 @@ public void NumberOfRemoteClients_NotClientServer_ReturnsZero() using (var threadHelper = new ThreadHelper()) using ( var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", threadHelper)) + "en", "fr", "en", threadHelper, m_userAction)) { Assert.AreEqual(0, cache.NumberOfRemoteClients); } diff --git a/Src/FDO/FDOTests/FdoTestBase.cs b/Src/FDO/FDOTests/FdoTestBase.cs index 4c5c2c465a..19aa8ddcf4 100644 --- a/Src/FDO/FDOTests/FdoTestBase.cs +++ b/Src/FDO/FDOTests/FdoTestBase.cs @@ -183,8 +183,8 @@ public virtual void TestTearDown() protected FdoCache BootstrapSystem(IProjectIdentifier projectId, BackendBulkLoadDomain loadType) { // This thread helper will be disposed in FixtureTeardown along with the cache. - var retval = m_internalRestart ? FdoCache.CreateCacheFromExistingData(projectId, "en", new DummyProgressDlg()) : - FdoCache.CreateCacheWithNewBlankLangProj(projectId, "en", "fr", "en", new ThreadHelper()); + var retval = m_internalRestart ? FdoCache.CreateCacheFromExistingData(projectId, "en", new DummyProgressDlg(), new DummyFdoUserAction()) : + FdoCache.CreateCacheWithNewBlankLangProj(projectId, "en", "fr", "en", new ThreadHelper(), new DummyFdoUserAction()); var dataSetup = retval.ServiceLocator.GetInstance(); dataSetup.LoadDomain(loadType); return retval; diff --git a/Src/FDO/FDOTests/PersistingBackendProviderTests.cs b/Src/FDO/FDOTests/PersistingBackendProviderTests.cs index 6e0879299c..c303286c09 100644 --- a/Src/FDO/FDOTests/PersistingBackendProviderTests.cs +++ b/Src/FDO/FDOTests/PersistingBackendProviderTests.cs @@ -614,7 +614,7 @@ public void OnlyOneCacheAllowed() private FdoCache OpenExistingFile(string filename) { return FdoCache.CreateCacheFromExistingData( - new TestProjectId(FDOBackendProviderType.kXMLWithMemoryOnlyWsMgr, filename), "en", new DummyProgressDlg()); + new TestProjectId(FDOBackendProviderType.kXMLWithMemoryOnlyWsMgr, filename), "en", new DummyProgressDlg(), new DummyFdoUserAction()); } /// ------------------------------------------------------------------------------------ @@ -750,7 +750,7 @@ internal class MockXMLBackendProvider : XMLBackendProvider public MockXMLBackendProvider(FdoCache cache, string projName): base(cache, new IdentityMap((IFwMetaDataCacheManaged)cache.MetaDataCache), new CmObjectSurrogateFactory(cache), (IFwMetaDataCacheManagedInternal)cache.MetaDataCache, - new FdoDataMigrationManager()) + new FdoDataMigrationManager(), new DummyFdoUserAction()) { Project = projName; Cache = cache; diff --git a/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs b/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs index 4f368800e4..1ac5939336 100644 --- a/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs +++ b/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs @@ -211,7 +211,7 @@ public void PortAllBEPsTestsUsingAnAlreadyOpenedSource( using (var threadHelper = new ThreadHelper()) using (var sourceCache = FdoCache.CreateCacheWithNewBlankLangProj( new TestProjectId(sourceBackendStartupParameters.ProjectId.Type, - sourceBackendStartupParameters.ProjectId.Path), "en", "fr", "en", threadHelper)) + sourceBackendStartupParameters.ProjectId.Path), "en", "fr", "en", threadHelper, new DummyFdoUserAction())) { // BEP is a singleton, so we shouldn't call Dispose on it. This will be done // by service locator. @@ -227,7 +227,7 @@ public void PortAllBEPsTestsUsingAnAlreadyOpenedSource( using (var otherThreadHelper = new ThreadHelper()) using (var targetCache = FdoCache.CreateCacheCopy( new TestProjectId(targetBackendStartupParameters.ProjectId.Type, - targetBackendStartupParameters.ProjectId.Path), "en", sourceCache, otherThreadHelper)) + targetBackendStartupParameters.ProjectId.Path), "en", sourceCache, otherThreadHelper, new DummyFdoUserAction())) { // BEP is a singleton, so we shouldn't call Dispose on it. This will be done // by service locator. @@ -276,7 +276,7 @@ public void PortAllBEPsTestsUsingAnUnopenedSource( sourceBackendStartupParameters.ProjectId.Path); IThreadedProgress progressDlg = new DummyProgressDlg(); using (FdoCache sourceCache = FdoCache.CreateCacheWithNewBlankLangProj( - projId, "en", "fr", "en", progressDlg.ThreadHelper)) + projId, "en", "fr", "en", progressDlg.ThreadHelper, new DummyFdoUserAction())) { // BEP is a singleton, so we shouldn't call Dispose on it. This will be done // by service locator. @@ -290,7 +290,7 @@ public void PortAllBEPsTestsUsingAnUnopenedSource( // Migrate source data to new BEP. progressDlg = new DummyProgressDlg(); using (var targetCache = FdoCache.CreateCacheWithNoLangProj( - new TestProjectId(targetBackendStartupParameters.ProjectId.Type, null), "en", progressDlg.ThreadHelper)) + new TestProjectId(targetBackendStartupParameters.ProjectId.Type, null), "en", progressDlg.ThreadHelper, new DummyFdoUserAction())) { // BEP is a singleton, so we shouldn't call Dispose on it. This will be done // by service locator. diff --git a/Src/FDO/FDOTests/XmlImportDataTests.cs b/Src/FDO/FDOTests/XmlImportDataTests.cs index e1ca0dad93..67af2a691a 100644 --- a/Src/FDO/FDOTests/XmlImportDataTests.cs +++ b/Src/FDO/FDOTests/XmlImportDataTests.cs @@ -54,7 +54,7 @@ public void CreateTestCache() { m_now = DateTime.Now; m_cache = FdoCache.CreateCacheWithNewBlankLangProj( - new TestProjectId(FDOBackendProviderType.kMemoryOnly, "MemoryOnly.mem"), "en", "fr", "en", new ThreadHelper()); + new TestProjectId(FDOBackendProviderType.kMemoryOnly, "MemoryOnly.mem"), "en", "fr", "en", new ThreadHelper(), new DummyFdoUserAction()); IDataSetup dataSetup = m_cache.ServiceLocator.GetInstance(); dataSetup.LoadDomain(BackendBulkLoadDomain.All); if (m_cache.LangProject != null) diff --git a/Src/FDO/FDOTests/XmlListTests.cs b/Src/FDO/FDOTests/XmlListTests.cs index 57c4abc25c..08199c39d2 100644 --- a/Src/FDO/FDOTests/XmlListTests.cs +++ b/Src/FDO/FDOTests/XmlListTests.cs @@ -600,7 +600,7 @@ public class XmlListTests : BaseTest public void CreateMockCache() { m_cache = FdoCache.CreateCacheWithNewBlankLangProj( - new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "es", "en", new ThreadHelper()); + new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "es", "en", new ThreadHelper(), new DummyFdoUserAction()); } /// diff --git a/Src/FDO/FDOTests/XmlTranslatedListsTests.cs b/Src/FDO/FDOTests/XmlTranslatedListsTests.cs index 9dd59efc0b..0fe2e4a93b 100644 --- a/Src/FDO/FDOTests/XmlTranslatedListsTests.cs +++ b/Src/FDO/FDOTests/XmlTranslatedListsTests.cs @@ -644,7 +644,7 @@ public class XmlTranslatedListsTests : BaseTest public void CreateMockCache() { m_cache = FdoCache.CreateCacheWithNewBlankLangProj( - new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "es", "en", new ThreadHelper()); + new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "es", "en", new ThreadHelper(), new DummyFdoUserAction()); var xl = new XmlList(); using (var reader = new StringReader(XmlListTests.s_ksPartsOfSpeechXml)) diff --git a/Src/FDO/IOC/FdoServiceLocatorFactory.cs b/Src/FDO/IOC/FdoServiceLocatorFactory.cs index d6c9c7d9f3..537ab403e3 100644 --- a/Src/FDO/IOC/FdoServiceLocatorFactory.cs +++ b/Src/FDO/IOC/FdoServiceLocatorFactory.cs @@ -36,16 +36,18 @@ namespace SIL.FieldWorks.FDO.IOC internal sealed partial class FdoServiceLocatorFactory : IServiceLocatorBootstrapper { private readonly FDOBackendProviderType m_backendProviderType; + private readonly IFdoUserAction m_userAction; - /// ------------------------------------------------------------------------------------ /// /// Constructor /// /// Type of backend provider to create. + /// The user action implementation /// ------------------------------------------------------------------------------------ - internal FdoServiceLocatorFactory(FDOBackendProviderType backendProviderType) + internal FdoServiceLocatorFactory(FDOBackendProviderType backendProviderType, IFdoUserAction userAction) { m_backendProviderType = backendProviderType; + m_userAction = userAction; } #region Implementation of IServiceLocatorBootstrapper @@ -242,6 +244,10 @@ public IServiceLocator CreateServiceLocator() .For() .Use(c => c.GetInstance().Singleton); + registry + .For() + .Use(m_userAction); + // ================================================================================= // Don't add COM object to the registry. StructureMap does not properly release COM // objects when the container is disposed, it will crash when the container is diff --git a/Src/FDO/Infrastructure/Impl/ClientServerBackendProvider.cs b/Src/FDO/Infrastructure/Impl/ClientServerBackendProvider.cs index ac26751582..797a635184 100644 --- a/Src/FDO/Infrastructure/Impl/ClientServerBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/ClientServerBackendProvider.cs @@ -12,6 +12,7 @@ /* This class may well replace ClientServerBackend, which currently is used only by the MySQL classes */ using System.Collections.Generic; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.Infrastructure.Impl @@ -22,7 +23,8 @@ protected ClientServerBackendProvider(FdoCache cache, IdentityMap identityMap, ICmObjectSurrogateFactory surrogateFactory, IFwMetaDataCacheManagedInternal mdc, - IDataMigrationManager dataMigrationManager) : base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager) + IDataMigrationManager dataMigrationManager, + IFdoUserAction userAction) : base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager, userAction) { } diff --git a/Src/FDO/Infrastructure/Impl/ConflictingSaveDlg.cs b/Src/FDO/Infrastructure/Impl/ConflictingSaveDlg.cs deleted file mode 100644 index 0b9f42f03e..0000000000 --- a/Src/FDO/Infrastructure/Impl/ConflictingSaveDlg.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Windows.Forms; - -namespace SIL.FieldWorks.FDO.Infrastructure.Impl -{ - /// - /// This dialog is like a message box, but offers two buttons, OK and "Refresh Now", which - /// when clicked produces a DialogResult of 'Yes'. - /// - public partial class ConflictingSaveDlg : Form - { - /// - /// Make one. - /// - public ConflictingSaveDlg() - { - InitializeComponent(); - pictureBox1.BackgroundImage = SystemIcons.Warning.ToBitmap(); - pictureBox1.Size = SystemIcons.Warning.Size; - } - } -} diff --git a/Src/FDO/Infrastructure/Impl/ConnectionLostDlg.cs b/Src/FDO/Infrastructure/Impl/ConnectionLostDlg.cs deleted file mode 100644 index 19ab502b7d..0000000000 --- a/Src/FDO/Infrastructure/Impl/ConnectionLostDlg.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Windows.Forms; - -namespace SIL.FieldWorks.FDO.Infrastructure.Impl -{ - /// - /// Dialog shown in place of MessageBox when connection lost, so it can have an Exit button. - /// - public partial class ConnectionLostDlg : Form - { - /// - /// Make one. Grrr. - /// - public ConnectionLostDlg() - { - InitializeComponent(); - } - } -} diff --git a/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs b/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs index 9e4884e692..a37dd19f3c 100644 --- a/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs @@ -87,13 +87,15 @@ internal class Db4oClientServerBackendProvider : ClientServerBackendProvider /// /// /// + /// public Db4oClientServerBackendProvider( FdoCache cache, IdentityMap identityMap, ICmObjectSurrogateFactory surrogateFactory, IFwMetaDataCacheManagedInternal mdc, - IDataMigrationManager dataMigrationManager) - : base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager) + IDataMigrationManager dataMigrationManager, + IFdoUserAction userAction) + : base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager, userAction) { } @@ -743,24 +745,18 @@ private bool ResumeDb4oConnectionAskingUser() return true; } - // It's useful to have this MessageBox handling here, as it allows reconnecting a dropped connection. - // Handling this at the application layer would require either recreating FdoCache or - // adding interface methods to expose resuming a dropped connection. - using (var dlg = new ConnectionLostDlg()) + while (m_userAction.ConnectionLost()) { - while (dlg.ShowDialog() == DialogResult.Yes) - { - // if re-connection failed allow user to keep retrying as many times as they want. - if (ResumeDb4oConnection()) - break; - } + // if re-connection failed allow user to keep retrying as many times as they want. + if (ResumeDb4oConnection()) + break; + } - if (m_dbStore == null) - System.Windows.Forms.Application.Exit(); + if (m_dbStore == null) + System.Windows.Forms.Application.Exit(); - // return true if connection re-established - return (m_dbStore != null); - } + // return true if connection re-established + return (m_dbStore != null); } internal static Db4oServerInfo GetDb4OServerInfo(string host, int port) diff --git a/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs b/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs index 0cbb56bdfa..85bbf6b898 100644 --- a/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs @@ -38,6 +38,7 @@ internal abstract partial class FDOBackendProvider : IDataSetup, IDataReader, ID protected readonly FdoCache m_cache; protected readonly IFwMetaDataCacheManagedInternal m_mdcInternal; private readonly IDataMigrationManager m_dataMigrationManager; + protected readonly IFdoUserAction m_userAction; protected readonly Dictionary m_extantCustomFields = new Dictionary(); protected int m_modelVersionOverride = ModelVersion; private readonly List m_loadDomainThreads = new List(); @@ -48,12 +49,14 @@ internal abstract partial class FDOBackendProvider : IDataSetup, IDataReader, ID /// /// protected FDOBackendProvider(FdoCache cache, IdentityMap identityMap, - ICmObjectSurrogateFactory surrogateFactory, IFwMetaDataCacheManagedInternal mdc, IDataMigrationManager dataMigrationManager) + ICmObjectSurrogateFactory surrogateFactory, IFwMetaDataCacheManagedInternal mdc, IDataMigrationManager dataMigrationManager, + IFdoUserAction userAction) { if (cache == null) throw new ArgumentNullException("cache"); if (identityMap == null) throw new ArgumentNullException("identityMap"); if (surrogateFactory == null) throw new ArgumentNullException("surrogateFactory"); if (dataMigrationManager == null) throw new ArgumentNullException("dataMigrationManager"); + if (userAction == null) throw new ArgumentNullException("userAction"); m_cache = cache; m_cache.Disposing += OnCacheDisposing; @@ -61,6 +64,7 @@ protected FDOBackendProvider(FdoCache cache, IdentityMap identityMap, m_surrogateFactory = surrogateFactory; m_mdcInternal = mdc; m_dataMigrationManager = dataMigrationManager; + m_userAction = userAction; } @@ -816,7 +820,7 @@ public void InitializeFromSource(IProjectIdentifier projectId, // 3. Startup source BEP, but without instantiating any FDO objects (surrogates, are loaded). using (var sourceCache = FdoCache.CreateCacheFromExistingData(sourceDataStore.ProjectId, - userWsIcuLocale, progressDlg)) + userWsIcuLocale, progressDlg, m_userAction)) { // 4. Do the port. var sourceCacheServLoc = sourceCache.ServiceLocator; diff --git a/Src/FDO/Infrastructure/Impl/MemoryOnlyBackendProvider.cs b/Src/FDO/Infrastructure/Impl/MemoryOnlyBackendProvider.cs index 645c9af47f..defa13179e 100644 --- a/Src/FDO/Infrastructure/Impl/MemoryOnlyBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/MemoryOnlyBackendProvider.cs @@ -11,6 +11,7 @@ using System; using System.Collections.Generic; using System.IO; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; using SIL.Utils; @@ -25,8 +26,9 @@ internal sealed class MemoryOnlyBackendProvider : FDOBackendProvider /// /// Constructor. /// - internal MemoryOnlyBackendProvider(FdoCache cache, IdentityMap identityMap, ICmObjectSurrogateFactory surrogateFactory, IFwMetaDataCacheManagedInternal mdc, IDataMigrationManager dataMigrationManager) - : base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager) + internal MemoryOnlyBackendProvider(FdoCache cache, IdentityMap identityMap, ICmObjectSurrogateFactory surrogateFactory, + IFwMetaDataCacheManagedInternal mdc, IDataMigrationManager dataMigrationManager, IFdoUserAction userAction) + : base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager, userAction) { } diff --git a/Src/FDO/Infrastructure/Impl/UnitOfWorkService.cs b/Src/FDO/Infrastructure/Impl/UnitOfWorkService.cs index 31ce89825d..d93549a0a3 100644 --- a/Src/FDO/Infrastructure/Impl/UnitOfWorkService.cs +++ b/Src/FDO/Infrastructure/Impl/UnitOfWorkService.cs @@ -108,6 +108,7 @@ internal enum FdoBusinessTransactionState private readonly IDataStorer m_dataStorer; private readonly IdentityMap m_identityMap; + private readonly IFdoUserAction m_userAction; internal ICmObjectRepositoryInternal ObjectRepository { get; @@ -156,15 +157,17 @@ internal FdoBusinessTransactionState CurrentProcessingState { /// /// Constructor. /// - internal UnitOfWorkService(IDataStorer dataStorer, IdentityMap identityMap, ICmObjectRepositoryInternal objectRepository) + internal UnitOfWorkService(IDataStorer dataStorer, IdentityMap identityMap, ICmObjectRepositoryInternal objectRepository, IFdoUserAction userAction) { if (dataStorer == null) throw new ArgumentNullException("dataStorer"); if (identityMap == null) throw new ArgumentNullException("identityMap"); if (objectRepository == null) throw new ArgumentNullException("objectRepository"); + if (userAction == null) throw new ArgumentNullException("userAction"); m_dataStorer = dataStorer; m_identityMap = identityMap; ObjectRepository = objectRepository; + m_userAction = userAction; CurrentProcessingState = FdoBusinessTransactionState.ReadyForBeginTask; NonUndoableStack = (UndoStack)CreateUndoStack(); // Make a separate stack as the initial default. This should be mainly used in tests. @@ -325,7 +328,7 @@ private void SaveInternal() { if (m_pendingReconciliation != null) { - ShowConflictingSaveDialogBox(); + GetUserInputOnConflictingSave(); return; // Don't try to save the changes we just reverted! } List foreignNewbies; @@ -343,7 +346,7 @@ private void SaveInternal() else { m_pendingReconciliation = reconciler; - ShowConflictingSaveDialogBox(); + GetUserInputOnConflictingSave(); return; } } @@ -366,19 +369,14 @@ private void SaveInternal() /// ------------------------------------------------------------------------------------ /// - /// Shows the conflicting save dialog box. - /// ENHANCE (TimS): We should not be showing a dialog box at this level. If we - /// really need to show it here, we should pass in the owning form instead of relying on - /// Form.ActiveForm since it can return null if no .Net forms have focus. + /// Gets user input on conflicting save /// /// ------------------------------------------------------------------------------------ - private void ShowConflictingSaveDialogBox() + private void GetUserInputOnConflictingSave() { - using (ConflictingSaveDlg dlg = new ConflictingSaveDlg()) + if (m_userAction.ConflictingSave()) { - DialogResult result = dlg.ShowDialog(Form.ActiveForm); - if (result != DialogResult.OK) - RevertToSavedState(); + RevertToSavedState(); } } diff --git a/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs b/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs index 22f74ea338..e625c3a366 100644 --- a/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs @@ -125,8 +125,8 @@ public void Combine(CommitWork work) /// internal XMLBackendProvider(FdoCache cache, IdentityMap identityMap, ICmObjectSurrogateFactory surrogateFactory, IFwMetaDataCacheManagedInternal mdc, - IDataMigrationManager dataMigrationManager) : - base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager) + IDataMigrationManager dataMigrationManager, IFdoUserAction userAction) : + base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager, userAction) { } diff --git a/Src/FDO/fdoCache.cs b/Src/FDO/fdoCache.cs index b05086bf5a..b86d25b8a5 100644 --- a/Src/FDO/fdoCache.cs +++ b/Src/FDO/fdoCache.cs @@ -101,11 +101,12 @@ public sealed partial class FdoCache /// The ICU locale of the default user WS. /// The thread helper used for invoking actions on the main /// UI thread. + /// /// ------------------------------------------------------------------------------------ public static FdoCache CreateCacheWithNoLangProj(IProjectIdentifier projectId, - string userWsIcuLocale, ThreadHelper threadHelper) + string userWsIcuLocale, ThreadHelper threadHelper, IFdoUserAction userAction) { - FdoCache createdCache = CreateCacheInternal(projectId, threadHelper); + FdoCache createdCache = CreateCacheInternal(projectId, threadHelper, userAction); createdCache.FullyInitializedAndReadyToRock = true; return createdCache; } @@ -127,13 +128,14 @@ public static FdoCache CreateCacheWithNoLangProj(IProjectIdentifier projectId, /// system. /// The thread helper used for invoking actions on the main /// UI thread. + /// /// ------------------------------------------------------------------------------------ public static FdoCache CreateCacheWithNewBlankLangProj(IProjectIdentifier projectId, string analWsIcuLocale, string vernWsIcuLocale, string userWsIcuLocale, - ThreadHelper threadHelper) + ThreadHelper threadHelper, IFdoUserAction userAction) { FdoCache createdCache = CreateCacheInternal(projectId, userWsIcuLocale, threadHelper, - dataSetup => dataSetup.CreateNewLanguageProject(projectId)); + dataSetup => dataSetup.CreateNewLanguageProject(projectId), userAction); NonUndoableUnitOfWorkHelper.Do(createdCache.ActionHandlerAccessor, () => { createdCache.ServiceLocator.WritingSystems.DefaultAnalysisWritingSystem = @@ -152,13 +154,14 @@ public static FdoCache CreateCacheWithNewBlankLangProj(IProjectIdentifier projec /// Identifies the project to load. /// The ICU locale of the default user WS. /// The progress dialog box + /// /// ------------------------------------------------------------------------------------ public static FdoCache CreateCacheFromExistingData(IProjectIdentifier projectId, - string userWsIcuLocale, IThreadedProgress progressDlg) + string userWsIcuLocale, IThreadedProgress progressDlg, IFdoUserAction userAction) { return CreateCacheInternal(projectId, userWsIcuLocale, progressDlg.ThreadHelper, dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg), - cache => cache.Initialize(userWsIcuLocale, progressDlg)); + cache => cache.Initialize(userWsIcuLocale, progressDlg), userAction); } /// ------------------------------------------------------------------------------------ @@ -169,14 +172,15 @@ public static FdoCache CreateCacheFromExistingData(IProjectIdentifier projectId, /// /// /// The progress dialog box + /// /// ------------------------------------------------------------------------------------ public static FdoCache CreateCacheFromLocalProjectFile(string projectPath, - string userWsIcuLocale, IThreadedProgress progressDlg) + string userWsIcuLocale, IThreadedProgress progressDlg, IFdoUserAction userAction) { var projectId = new SimpleProjectId(FDOBackendProviderType.kXML, projectPath); return CreateCacheInternal(projectId, userWsIcuLocale, progressDlg.ThreadHelper, dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg), - cache => cache.Initialize(userWsIcuLocale, progressDlg)); + cache => cache.Initialize(userWsIcuLocale, progressDlg), userAction); } /// ------------------------------------------------------------------------------------ @@ -189,12 +193,13 @@ public static FdoCache CreateCacheFromLocalProjectFile(string projectPath, /// The FdoCache to copy /// The thread helper used for invoking actions on the main /// UI thread. + /// /// ------------------------------------------------------------------------------------ public static FdoCache CreateCacheCopy(IProjectIdentifier projectId, - string userWsIcuLocale, FdoCache sourceCache, ThreadHelper threadHelper) + string userWsIcuLocale, FdoCache sourceCache, ThreadHelper threadHelper, IFdoUserAction userAction) { return CreateCacheInternal(projectId, userWsIcuLocale, threadHelper, - dataSetup => dataSetup.InitializeFromSource(projectId, sourceCache)); + dataSetup => dataSetup.InitializeFromSource(projectId, sourceCache), userAction); } /// ------------------------------------------------------------------------------------ @@ -204,15 +209,16 @@ public static FdoCache CreateCacheCopy(IProjectIdentifier projectId, /// Identifies the project to create or load. /// The thread helper used for invoking actions on the main /// UI thread. + /// /// ------------------------------------------------------------------------------------ private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, - ThreadHelper threadHelper) + ThreadHelper threadHelper, IFdoUserAction userAction) { FDOBackendProviderType providerType = projectId.Type; if (providerType == FDOBackendProviderType.kXMLWithMemoryOnlyWsMgr) providerType = FDOBackendProviderType.kXML; - var iocFactory = new FdoServiceLocatorFactory(providerType); + var iocFactory = new FdoServiceLocatorFactory(providerType, userAction); var servLoc = (IFdoServiceLocator)iocFactory.CreateServiceLocator(); var createdCache = servLoc.GetInstance(); createdCache.m_serviceLocator = servLoc; @@ -230,11 +236,12 @@ private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, /// The thread helper used for invoking actions on the main /// UI thread. /// The data setup action to perform. + /// /// ------------------------------------------------------------------------------------ private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, - string userWsIcuLocale, ThreadHelper threadHelper, Action doThe) + string userWsIcuLocale, ThreadHelper threadHelper, Action doThe, IFdoUserAction userAction) { - return CreateCacheInternal(projectId, userWsIcuLocale, threadHelper, doThe, null); + return CreateCacheInternal(projectId, userWsIcuLocale, threadHelper, doThe, null, userAction); } /// ------------------------------------------------------------------------------------ @@ -247,16 +254,17 @@ private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, /// UI thread. /// The data setup action to perform. /// The initialization step to perfrom (can be null). + /// /// The newly created cache /// ------------------------------------------------------------------------------------ private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, string userWsIcuLocale, ThreadHelper threadHelper, Action doThe, - Action initialize) + Action initialize, IFdoUserAction userAction) { FDOBackendProviderType providerType = projectId.Type; bool useMemoryWsManager = (providerType == FDOBackendProviderType.kMemoryOnly || providerType == FDOBackendProviderType.kXMLWithMemoryOnlyWsMgr); - FdoCache createdCache = CreateCacheInternal(projectId, threadHelper); + FdoCache createdCache = CreateCacheInternal(projectId, threadHelper, userAction); // Init backend data provider IDataSetup dataSetup = createdCache.ServiceLocator.GetInstance(); @@ -369,6 +377,7 @@ private static bool IsUpdatedWsInUse(StringBuilder updatedWssInUseBuilder) /// Create a new language project for the new language name /// /// The progress dialog. + /// /// One or more parameters, supplied in this order: /// 0. A string containing the name of the project (required); /// 1. A ThreadHelper used for invoking actions on the main UI thread (required); @@ -381,7 +390,7 @@ private static bool IsUpdatedWsInUse(StringBuilder updatedWssInUseBuilder) /// Path of the newly created project file. /// Override DisplayUi to prevent progress dialog from showing. /// ------------------------------------------------------------------------------------ - public static string CreateNewLangProj(IThreadedProgress progressDlg, params object[] parameters) + public static string CreateNewLangProj(IThreadedProgress progressDlg, IFdoUserAction userAction, params object[] parameters) { if (parameters == null || parameters.Length < 2) throw new ArgumentException("Parameters must include at least a project name and the ThreadHelper"); @@ -412,7 +421,7 @@ public static string CreateNewLangProj(IThreadedProgress progressDlg, params obj var projectId = new SimpleProjectId(FDOBackendProviderType.kXML, dbFileName); using (var cache = CreateCacheInternal(projectId, - userIcuLocale, threadHelper, dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg))) + userIcuLocale, threadHelper, dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg), userAction)) { if (progressDlg != null) { @@ -525,7 +534,7 @@ public static string CreateNewLangProj(IThreadedProgress progressDlg, params obj cache.SaveAndForceNewestXmlForCmObjectWithoutUnitOfWork(null, cache.m_serviceLocator.ObjectRepository.AllInstances().ToList()); } } - return ClientServerServices.Current.Local.ConvertToDb4oBackendIfNeeded(progressDlg, dbFileName); + return ClientServerServices.Current.Local.ConvertToDb4oBackendIfNeeded(progressDlg, dbFileName, userAction); } /// diff --git a/Src/FDOBrowser/FDOBrowser.csproj b/Src/FDOBrowser/FDOBrowser.csproj index e5f152593d..2f39ae7546 100644 --- a/Src/FDOBrowser/FDOBrowser.csproj +++ b/Src/FDOBrowser/FDOBrowser.csproj @@ -1,257 +1,258 @@ - + - Debug - AnyCPU - 9.0.30729 - 2.0 - {C194A88D-5F50-4B2A-988D-E3690FA7384D} - WinExe - Properties - FDOBrowser - FDOBrowser - - - 3.5 - - - v4.0 - false - true - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - true - + Debug + AnyCPU + 9.0.30729 + 2.0 + {C194A88D-5F50-4B2A-988D-E3690FA7384D} + WinExe + Properties + FDOBrowser + FDOBrowser + + + 3.5 + + + v4.0 + false + true + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + - true - full - false - 168,169,219,414,649,1635,1702,1701 - ..\..\Output\Debug\ - DEBUG;TRACE - prompt - 4 - ..\..\Output\Debug\FDOBrowser.xml - false - x86 - AllRules.ruleset + true + full + false + 168,169,219,414,649,1635,1702,1701 + ..\..\Output\Debug\ + DEBUG;TRACE + prompt + 4 + ..\..\Output\Debug\FDOBrowser.xml + false + x86 + AllRules.ruleset - pdbonly - true - 168,169,219,414,649,1635,1702,1701 - ..\..\Output\Release\ - TRACE - prompt - 4 - ..\..\Output\Release\FDOBrowser.XML - x86 - AllRules.ruleset + pdbonly + true + 168,169,219,414,649,1635,1702,1701 + ..\..\Output\Release\ + TRACE + prompt + 4 + ..\..\Output\Release\FDOBrowser.XML + x86 + AllRules.ruleset - - False - ..\..\Output\Debug\CoreImpl.dll - - - False - ..\..\Output\Debug\Db4objects.Db4o.dll - - - False - ..\..\Output\Debug\Db4objects.Db4o.CS.dll - - - False - ..\..\Output\Debug\Db4objects.Db4o.Linq.dll - - - ..\..\Output\Debug\DetailControls.dll - False - - - False - ..\..\Output\Debug\FDO.dll - - - False - - - False - ..\..\Output\Debug\FwResources.dll - - - False - ..\..\Output\Debug\FwUtils.dll - - - False - ..\..\DistFiles\Microsoft.Practices.ServiceLocation.dll - - - False - ..\..\Output\Debug\ObjectBrowser.dll - - - ..\..\Output\Debug\SilUtils.dll - False - - - - - - - - - BasicUtils - ..\..\Output\Debug\BasicUtils.dll - - - COMInterfaces - ..\..\Output\Debug\COMInterfaces.dll - - - False - .\WeifenLuo.WinFormsUI.Docking.dll - - - False - ..\..\Output\Debug\Widgets.dll - - - False - ..\..\Output\Debug\xCoreInterfaces.dll - - - False - ..\..\Output\Debug\XMLViews.dll - + + False + ..\..\Output\Debug\CoreImpl.dll + + + False + ..\..\Output\Debug\Db4objects.Db4o.dll + + + False + ..\..\Output\Debug\Db4objects.Db4o.CS.dll + + + False + ..\..\Output\Debug\Db4objects.Db4o.Linq.dll + + + ..\..\Output\Debug\DetailControls.dll + False + + + False + ..\..\Output\Debug\FDO.dll + + + False + + + False + ..\..\Output\Debug\FwResources.dll + + + False + ..\..\Output\Debug\FwUtils.dll + + + False + ..\..\DistFiles\Microsoft.Practices.ServiceLocation.dll + + + False + ..\..\Output\Debug\ObjectBrowser.dll + + + ..\..\Output\Debug\SilUtils.dll + False + + + + + + + + + BasicUtils + ..\..\Output\Debug\BasicUtils.dll + + + COMInterfaces + ..\..\Output\Debug\COMInterfaces.dll + + + False + .\WeifenLuo.WinFormsUI.Docking.dll + + + False + ..\..\Output\Debug\Widgets.dll + + + False + ..\..\Output\Debug\xCoreInterfaces.dll + + + False + ..\..\Output\Debug\XMLViews.dll + - - CommonAssemblyInfo.cs - - - - - - Form - - - FDOBrowserForm.cs - - - - - Form - - - FileInOutChooser.cs - - - Form - - - ModelWnd.cs - - - Form - - - ClassPropertySelector.cs - - - - - ClassPropertySelector.cs - Designer - - - FDOBrowserForm.cs - Designer - - - FileInOutChooser.cs - - - ModelWnd.cs - Designer - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - RealListChooser.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - Form - - - RealListChooser.cs - + + CommonAssemblyInfo.cs + + + + + + Form + + + FDOBrowserForm.cs + + + + + + Form + + + FileInOutChooser.cs + + + Form + + + ModelWnd.cs + + + Form + + + ClassPropertySelector.cs + + + + + ClassPropertySelector.cs + Designer + + + FDOBrowserForm.cs + Designer + + + FileInOutChooser.cs + + + ModelWnd.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + RealListChooser.cs + Designer + + + True + Resources.resx + True + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + Form + + + RealListChooser.cs + - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 2.0 %28x86%29 - true - - - False - .NET Framework 3.0 %28x86%29 - false - - - False - .NET Framework 3.5 - false - - - False - .NET Framework 3.5 SP1 - false - + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + true + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + False + .NET Framework 3.5 SP1 + false + - + - + diff --git a/Src/FDOBrowser/FDOBrowserForm.cs b/Src/FDOBrowser/FDOBrowserForm.cs index 2933047523..5515cb9ab5 100644 --- a/Src/FDOBrowser/FDOBrowserForm.cs +++ b/Src/FDOBrowser/FDOBrowserForm.cs @@ -382,12 +382,12 @@ protected override void OpenFile(string fileName) m_ThreadHelper = new ThreadHelper(); if (isMemoryBEP) - m_cache = FdoCache.CreateCacheWithNewBlankLangProj(new BrowserProjectId(bepType, null), "en", "en", "en", m_ThreadHelper); + m_cache = FdoCache.CreateCacheWithNewBlankLangProj(new BrowserProjectId(bepType, null), "en", "en", "en", m_ThreadHelper, new FdoUserAction()); else { using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(this, m_ThreadHelper)) { - m_cache = FdoCache.CreateCacheFromExistingData(new BrowserProjectId(bepType, fileName), "en", progressDlg); + m_cache = FdoCache.CreateCacheFromExistingData(new BrowserProjectId(bepType, fileName), "en", progressDlg, new FdoUserAction()); } } // var v = m_cache. diff --git a/Src/FDOBrowser/FDOClassList.cs b/Src/FDOBrowser/FDOClassList.cs index 431c2227c4..888c2bf83c 100644 --- a/Src/FDOBrowser/FDOClassList.cs +++ b/Src/FDOBrowser/FDOClassList.cs @@ -139,7 +139,7 @@ private static void LoadFDOClassNames() if (s_allFDOClassNames != null) return; - using (FdoCache cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", null)) + using (FdoCache cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", null, new FdoUserAction())) { IFwMetaDataCacheManaged mdc = (IFwMetaDataCacheManaged)cache.MainCacheAccessor.MetaDataCache; s_allFDOClassNames = new List(); diff --git a/Src/FDOBrowser/FdoUserAction.cs b/Src/FDOBrowser/FdoUserAction.cs new file mode 100644 index 0000000000..6f4062b28f --- /dev/null +++ b/Src/FDOBrowser/FdoUserAction.cs @@ -0,0 +1,47 @@ +// --------------------------------------------------------------------------------------------- +#region // Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Distributable under the terms of either the Common Public License or the +// GNU Lesser General Public License, as specified in the LICENSING.txt file. +// +#endregion +// --------------------------------------------------------------------------------------------- +using System; +using System.Windows.Forms; +using SIL.FieldWorks.Common.FwUtils; + +namespace FDOBrowser +{ + class FdoUserAction : IFdoUserAction + { + /// + /// Check with user regarding conflicting changes + /// + /// True if user wishes to revert to saved state. False otherwise. + public bool ConflictingSave() + { + DialogResult dialogResult = System.Windows.Forms.MessageBox.Show("There are conflicting changes from another user. Do you want to load the latest saved version?", "Conflicting Changes", MessageBoxButtons.YesNo); + return dialogResult == DialogResult.Yes; + } + + /// + /// Inform the user of a lost connection + /// + /// True if user wishes to attempt reconnect. False otherwise. + public bool ConnectionLost() + { + DialogResult dialogResult = System.Windows.Forms.MessageBox.Show("The connection has been lost. Do you wish to attempt a reconnect?", "Connection Lost", MessageBoxButtons.YesNo); + return dialogResult == DialogResult.Yes; + } + + /// + /// Displays information to the user + /// + public void MessageBox() + { + throw new NotImplementedException(); + } + } +} diff --git a/Src/FDOBrowser/ModelWnd.cs b/Src/FDOBrowser/ModelWnd.cs index 6e5c813d57..485986ab02 100644 --- a/Src/FDOBrowser/ModelWnd.cs +++ b/Src/FDOBrowser/ModelWnd.cs @@ -40,7 +40,7 @@ public ModelWnd() m_lvModel.Font = SystemFonts.MenuFont; // Add model browsing cache (no data, just model browsing). - m_cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", new ThreadHelper()); + m_cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", new ThreadHelper(), new FdoUserAction()); m_mdc = (IFwMetaDataCacheManaged)m_cache.MainCacheAccessor.MetaDataCache; PopulateModelTree(); diff --git a/Src/FDO/Infrastructure/Impl/ConflictingSaveDlg.Designer.cs b/Src/FdoUi/ConflictingSaveDlg.Designer.cs similarity index 98% rename from Src/FDO/Infrastructure/Impl/ConflictingSaveDlg.Designer.cs rename to Src/FdoUi/ConflictingSaveDlg.Designer.cs index 9bf4d2d62c..948ffa55ab 100644 --- a/Src/FDO/Infrastructure/Impl/ConflictingSaveDlg.Designer.cs +++ b/Src/FdoUi/ConflictingSaveDlg.Designer.cs @@ -1,4 +1,4 @@ -namespace SIL.FieldWorks.FDO.Infrastructure.Impl +namespace SIL.FieldWorks.FdoUi { partial class ConflictingSaveDlg { diff --git a/Src/FdoUi/ConflictingSaveDlg.cs b/Src/FdoUi/ConflictingSaveDlg.cs new file mode 100644 index 0000000000..aae6a59ff1 --- /dev/null +++ b/Src/FdoUi/ConflictingSaveDlg.cs @@ -0,0 +1,33 @@ +// --------------------------------------------------------------------------------------------- +#region // Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Distributable under the terms of either the Common Public License or the +// GNU Lesser General Public License, as specified in the LICENSING.txt file. +// +#endregion +// --------------------------------------------------------------------------------------------- +using System.Drawing; +using System.Windows.Forms; +using SIL.FieldWorks.Common.FwUtils; + +namespace SIL.FieldWorks.FdoUi +{ + /// + /// This dialog is like a message box, but offers two buttons, OK and "Refresh Now", which + /// when clicked produces a DialogResult of 'Yes'. + /// + public partial class ConflictingSaveDlg : Form + { + /// + /// Make one. + /// + public ConflictingSaveDlg() + { + InitializeComponent(); + pictureBox1.BackgroundImage = SystemIcons.Warning.ToBitmap(); + pictureBox1.Size = SystemIcons.Warning.Size; + } + } +} diff --git a/Src/FDO/Infrastructure/Impl/ConflictingSaveDlg.resx b/Src/FdoUi/ConflictingSaveDlg.resx similarity index 99% rename from Src/FDO/Infrastructure/Impl/ConflictingSaveDlg.resx rename to Src/FdoUi/ConflictingSaveDlg.resx index 3377cb6229..fa19ee177d 100644 --- a/Src/FDO/Infrastructure/Impl/ConflictingSaveDlg.resx +++ b/Src/FdoUi/ConflictingSaveDlg.resx @@ -1,4 +1,4 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - 60, 12 - - - 488, 52 - - - - 3 - - - Some files in the Linked Files folder are newer than the ones which will be restored, and these may not be files that this FieldWorks project links to yet. - - - label_message - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 7 - - - 60, 64 - - - 488, 41 - - - 4 - - - Would you like to keep the newer files in the folder or replace them with the older ones from the backup? - - - label_Question - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 6 - - - 12, 12 - - - 42, 38 - - - 5 - - - pictureBox1 - - - System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 5 - - - True - - - - NoControl - - - 64, 132 - - - 192, 17 - - - 13 - - - Use the older files from the backup. - - - radio_Overwrite - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 0 - - - True - - - NoControl - - - 64, 109 - - - 164, 17 - - - 12 - - - Keep newer files in the folder. - - - radio_Keep - - - System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 1 - - - NoControl - - - 474, 157 - - - 75, 23 - - - 11 - - - Help - - - button_Help - - - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 2 - - - NoControl - - - 393, 157 - - - 75, 23 - - - 10 - - - Cancel - - - button_Cancel - - - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 3 - - - NoControl - - - 312, 157 - - - 75, 23 - - - 9 - - - OK - - - button_OK - - - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 4 - - - True - - - 6, 13 - - - 561, 192 - - - Linked files in backup are older - - - FilesToRestoreAreOlder - - - System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs b/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs index 640516c419..7bdd98d6f6 100644 --- a/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs +++ b/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs @@ -47,7 +47,7 @@ public ProjectBackupService(FdoCache cache, BackupProjectSettings settings) /// Perform a backup of the current project, using specified settings. /// /// The backup file or null if something went wrong. - public string BackupProject(IThreadedProgress progressDlg, IFdoUserAction userAction) + public string BackupProject(IThreadedProgress progressDlg) { PersistBackupFileSettings(); @@ -58,7 +58,7 @@ public string BackupProject(IThreadedProgress progressDlg, IFdoUserAction userAc m_cache.ServiceLocator.GetInstance().Save(); m_cache.ServiceLocator.GetInstance().CompleteAllCommits(); - string tempFilePath = ClientServerServices.Current.Local.CopyToXmlFile(m_cache, m_settings.DatabaseFolder, userAction); + string tempFilePath = ClientServerServices.Current.Local.CopyToXmlFile(m_cache, m_settings.DatabaseFolder); var filesToZip = CreateListOfFilesToZip(); progressDlg.Title = Strings.ksBackupProgressCaption; diff --git a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs index 14e11cfab2..e49db51bb4 100644 --- a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs +++ b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs @@ -39,6 +39,7 @@ public class ProjectRestoreService private bool m_fRestoreOverProject; private readonly IHelpTopicProvider m_helpTopicProvider; private string m_sLinkDirChangedTo; + private readonly IFdoUserAction m_userAction; #endregion #region Constructor @@ -48,11 +49,13 @@ public class ProjectRestoreService /// /// The restore settings. /// + /// /// ------------------------------------------------------------------------------------ - public ProjectRestoreService(RestoreProjectSettings settings, IHelpTopicProvider helpTopicProvider) + public ProjectRestoreService(RestoreProjectSettings settings, IHelpTopicProvider helpTopicProvider, IFdoUserAction userAction) { m_restoreSettings = settings; m_helpTopicProvider = helpTopicProvider; + m_userAction = userAction; } /// ------------------------------------------------------------------------------------ @@ -73,12 +76,11 @@ public ProjectRestoreService(RestoreProjectSettings settings) /// Perform a restore of the project specified in the settings. /// /// The progress dialog. - /// /// File does not exist, or some such problem /// XML deserialization problem or required /// files not found in zip file /// ------------------------------------------------------------------------------------ - public void RestoreProject(IThreadedProgress progressDlg, IFdoUserAction userAction) + public void RestoreProject(IThreadedProgress progressDlg) { BackupFileSettings fileSettings = m_restoreSettings.Backup; fileSettings.Validate(); // Normally, this will already have been done, so this will do nothing. @@ -127,7 +129,7 @@ public void RestoreProject(IThreadedProgress progressDlg, IFdoUserAction userAct // switch to the desired backend (if it's in the projects directory...anything else stays XML for now). if (DirectoryFinder.IsSubFolderOfProjectsDirectory(m_restoreSettings.ProjectPath) && !suppressConversion) - ClientServerServices.Current.Local.ConvertToDb4oBackendIfNeeded(progressDlg, m_restoreSettings.FullProjectPath, userAction); + ClientServerServices.Current.Local.ConvertToDb4oBackendIfNeeded(progressDlg, m_restoreSettings.FullProjectPath); CleanupAfterRestore(true); } @@ -377,11 +379,7 @@ private void RestoreLinkedFiles(BackupFileSettings fileSettings) /// Protected so we can subclass in tests. protected virtual bool CanRestoreLinkedFilesToProjectsFolder() { - using (var dlg = new RestoreLinkedFilesToProjectsFolder(m_helpTopicProvider)) - { - // Let a Cancel result mean "Keep my old non-standard location" - return dlg.ShowDialog() == DialogResult.OK && dlg.fRestoreLinkedFilesToProjectFolder; - } + return m_userAction.RestoreLinkedFilesInProjectFolder(); } /// @@ -440,22 +438,17 @@ private void ExternalLinksDirectoryExits(string linkedFilesPathPersisted, string { //Some files in the zip file are older than the ones on disk. Therefore find out if the user wants //to keep the newer files on disk. - using (var dlg = new FilesToRestoreAreOlder(m_helpTopicProvider)) + FileSelection fileSelection = m_userAction.ChooseFilesToUse(); + if (fileSelection == FileSelection.OkKeepNewer) { - if (dlg.ShowDialog() == DialogResult.OK) - { - if (dlg.fKeepFilesThatAreNewer) - { - var newList = RemoveFilesThatAreOlderThanThoseOnDisk(filesContainedInLinkdFilesFolder, - proposedDestinationLinkedFilesPath, linkedFilesPathPersisted); - UncompressLinkedFiles(newList, proposedDestinationLinkedFilesPath, linkedFilesPathPersisted); - } - if (dlg.fOverWriteThatAreNewer) - { - UncompressLinkedFiles(filesContainedInLinkdFilesFolder, proposedDestinationLinkedFilesPath, - linkedFilesPathPersisted); - } - } + var newList = RemoveFilesThatAreOlderThanThoseOnDisk(filesContainedInLinkdFilesFolder, + proposedDestinationLinkedFilesPath, linkedFilesPathPersisted); + UncompressLinkedFiles(newList, proposedDestinationLinkedFilesPath, linkedFilesPathPersisted); + } + if (fileSelection == FileSelection.OkUseOlder) + { + UncompressLinkedFiles(filesContainedInLinkdFilesFolder, proposedDestinationLinkedFilesPath, + linkedFilesPathPersisted); } } else //no files to be restored are older than those on disk so restore them all. @@ -476,21 +469,16 @@ private void ExternalLinksDirectoryExits(string linkedFilesPathPersisted, string /// protected virtual void CouldNotRestoreLinkedFilesToOriginalLocation(string linkedFilesPathPersisted, Dictionary filesContainedInLinkdFilesFolder) { - using (var dlgCantWriteFiles = new CantRestoreLinkedFilesToOriginalLocation(m_helpTopicProvider)) + YesNoCancel userSelection = m_userAction.CannotRestoreLinkedFilesToOriginalLocation(); + if (userSelection == YesNoCancel.OkYes) { - if (dlgCantWriteFiles.ShowDialog() == DialogResult.OK) - { - if (dlgCantWriteFiles.fRestoreLinkedFilesToProjectFolder) - { - m_sLinkDirChangedTo = DirectoryFinder.GetDefaultLinkedFilesDir(m_restoreSettings.ProjectPath); - //Restore the files to the project folder. - UncompressLinkedFiles(filesContainedInLinkdFilesFolder, m_sLinkDirChangedTo, linkedFilesPathPersisted); - } - if (dlgCantWriteFiles.fDoNotRestoreLinkedFiles) - { - //Do nothing. Do not restore any LinkedFiles. - } - } + m_sLinkDirChangedTo = DirectoryFinder.GetDefaultLinkedFilesDir(m_restoreSettings.ProjectPath); + //Restore the files to the project folder. + UncompressLinkedFiles(filesContainedInLinkdFilesFolder, m_sLinkDirChangedTo, linkedFilesPathPersisted); + } + else if (userSelection == YesNoCancel.OkNo) + { + //Do nothing. Do not restore any LinkedFiles. } } diff --git a/Src/FDO/DomainServices/ClientServerServices.cs b/Src/FDO/DomainServices/ClientServerServices.cs index 9d09fd2ce7..dd79f637d7 100644 --- a/Src/FDO/DomainServices/ClientServerServices.cs +++ b/Src/FDO/DomainServices/ClientServerServices.cs @@ -239,11 +239,10 @@ public interface ILocalClientServerServices /// The progress dialog for getting a message box owner and/or /// ensuring we're invoking on the uI thread. /// The full path of the existing XML file for the project - /// /// The project identifier, typically the path to the converted file (or the /// original, if not configured for the client-server backend) /// ------------------------------------------------------------------------------------ - string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string filename, IFdoUserAction userAction); + string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string filename); /// /// Copies the specified project (assumed to be in the current Projects directory) @@ -253,8 +252,7 @@ public interface ILocalClientServerServices /// The source cache /// The destination directory for the converted copy if a /// conversion needs to be done. - /// - string CopyToXmlFile(FdoCache source, string destDir, IFdoUserAction userAction); + string CopyToXmlFile(FdoCache source, string destDir); /// /// Return the full ID that should be used to open the specified project, which is in the @@ -647,7 +645,7 @@ public bool SetProjectSharing(bool fShare, IThreadedProgress progress, IFdoUserA if (fShare) { // Turning sharing on. - if (!ConvertAllProjectsToDb4o(progress, userAction)) + if (!ConvertAllProjectsToDb4o(progress)) { LocalDb4OServerInfoConnection.ShareProjects(false); // could not switch return false; @@ -803,7 +801,7 @@ private object ConvertAllProjectsToXmlTask(IThreadedProgress progress, IFdoUserA using (var tempCache = FdoCache.CreateCacheFromExistingData( new SimpleProjectId(FDOBackendProviderType.kDb4oClientServer, projectPath), "en", progress, userAction)) { - CopyToXmlFile(tempCache, tempCache.ProjectId.ProjectFolder, userAction); + CopyToXmlFile(tempCache, tempCache.ProjectId.ProjectFolder); // Enhance JohnT: how can we tell this succeeded? } File.Delete(projectPath); // only if we converted successfully; otherwise will throw. @@ -823,18 +821,17 @@ private object ConvertAllProjectsToXmlTask(IThreadedProgress progress, IFdoUserA /// Converts all projects to db4o. /// /// The progress dialog box. - /// /// ------------------------------------------------------------------------------------ - private bool ConvertAllProjectsToDb4o(IThreadedProgress progressDlg, IFdoUserAction userAction) + private bool ConvertAllProjectsToDb4o(IThreadedProgress progressDlg) { progressDlg.Title = Strings.ksConvertingToShared; progressDlg.AllowCancel = false; progressDlg.ProgressBarStyle = ProgressBarStyle.Continuous; progressDlg.Maximum = Directory.GetDirectories(DirectoryFinder.ProjectsDirectory).Count(); - return (bool)progressDlg.RunTask(true, (progress, args) => ConvertAllProjectsToDb4o(progress, userAction, args)); + return (bool)progressDlg.RunTask(true, ConvertAllProjectsToDb4o); } - private object ConvertAllProjectsToDb4o(IThreadedProgress progress, IFdoUserAction userAction, object[] args) + private object ConvertAllProjectsToDb4o(IThreadedProgress progress, object[] args) { for (; ; ) { @@ -867,7 +864,7 @@ private object ConvertAllProjectsToDb4o(IThreadedProgress progress, IFdoUserActi { try { - ConvertToDb4oBackendIfNeeded(progress, projectPath, userAction); + ConvertToDb4oBackendIfNeeded(progress, projectPath); } catch (Exception e) { @@ -905,11 +902,10 @@ private static void ReportConversionError(Form messageBoxOwner, string projectPa /// The progress dialog (for getting a message box owner and/or /// ensuring we're invoking on the UI thread). /// The full path of the existing XML file for the project - /// /// The project identifier, typically the path to the converted file (or the /// original, if not configured for the client-server backend) /// ------------------------------------------------------------------------------------ - public string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string xmlFilename, IFdoUserAction userAction) + public string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string xmlFilename) { if (!ShareMyProjects) return xmlFilename; // no conversion needed. @@ -920,14 +916,14 @@ public string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string try { using (var tempCache = FdoCache.CreateCacheFromExistingData( - new SimpleProjectId(FDOBackendProviderType.kXML, xmlFilename), "en", progressDlg, userAction)) + new SimpleProjectId(FDOBackendProviderType.kXML, xmlFilename), "en", progressDlg, new SilentFdoUserAction())) { // The zero in the object array is for db4o and causes it not to open a port. // This is fine since we aren't yet trying to start up on this restored database. // The null says we are creating the file on the local host. using (var copyCache = FdoCache.CreateCacheCopy( - new SimpleProjectId(FDOBackendProviderType.kDb4oClientServer, desiredPath), "en", tempCache, progressDlg.ThreadHelper, userAction)) + new SimpleProjectId(FDOBackendProviderType.kDb4oClientServer, desiredPath), "en", tempCache, progressDlg.ThreadHelper, new SilentFdoUserAction())) { copyCache.ServiceLocator.GetInstance().Commit(new HashSet(), new HashSet(), new HashSet()); @@ -956,9 +952,8 @@ public string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string /// The source cache /// The destination directory for the converted copy if a /// conversion needs to be done. - /// /// ------------------------------------------------------------------------------------ - public string CopyToXmlFile(FdoCache source, string destDir, IFdoUserAction userAction) + public string CopyToXmlFile(FdoCache source, string destDir) { IDataStorer dataStorer = source.ServiceLocator.GetInstance(); if (dataStorer is XMLBackendProvider) @@ -970,7 +965,7 @@ public string CopyToXmlFile(FdoCache source, string destDir, IFdoUserAction user try { using (var copyCache = FdoCache.CreateCacheCopy( - new SimpleProjectId(FDOBackendProviderType.kXML, newFilePath), "en", source, source.ThreadHelper, userAction)) + new SimpleProjectId(FDOBackendProviderType.kXML, newFilePath), "en", source, source.ThreadHelper, source.ServiceLocator.GetInstance())) { copyCache.ServiceLocator.GetInstance().Commit( new HashSet(), diff --git a/Src/FDO/FDO.csproj b/Src/FDO/FDO.csproj index d219e36250..e263104fa2 100644 --- a/Src/FDO/FDO.csproj +++ b/Src/FDO/FDO.csproj @@ -216,30 +216,12 @@ - - Form - - - CantRestoreLinkedFilesToOriginalLocation.cs - - - Form - - - FilesToRestoreAreOlder.cs - Code - - Form - - - RestoreLinkedFilesToProjectsFolder.cs - @@ -399,6 +381,7 @@ + @@ -527,18 +510,6 @@ AppStrings.Designer.cs Designer - - CantRestoreLinkedFilesToOriginalLocation.cs - Designer - - - FilesToRestoreAreOlder.cs - Designer - - - RestoreLinkedFilesToProjectsFolder.cs - Designer - FWVersionTooOld.cs Designer @@ -589,7 +560,6 @@ - diff --git a/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs b/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs index 414c5f391f..048e72550d 100644 --- a/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs +++ b/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs @@ -102,7 +102,7 @@ public void RestoreProjectSettings_VerifyExistenceOfProject() try { // Restore the project and check to ensure that it exists. - restoreProjectService.RestoreProject(new DummyProgressDlg(), new DummyFdoUserAction()); + restoreProjectService.RestoreProject(new DummyProgressDlg()); Assert.True(restoreSettings.ProjectExists, "Project does not exist but it should."); } finally @@ -139,7 +139,7 @@ public void RestoreProjectSettings_VerifyExistenceOfHgRepo() try { // Restore the project and check to ensure that it exists, but is not using Send/Receive. - restoreProjectService.RestoreProject(new DummyProgressDlg(), new DummyFdoUserAction()); + restoreProjectService.RestoreProject(new DummyProgressDlg()); Assert.True(restoreSettings.ProjectExists, "Project does not exist but it should."); Assert.False(restoreSettings.UsingSendReceive, "Project is using S/R but it should not be."); diff --git a/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs b/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs index c43b7c98fb..f263830f3f 100644 --- a/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs +++ b/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs @@ -34,7 +34,6 @@ public class ProjectRestoreServiceTests : MemoryOnlyBackendProviderBasicTestBase { private ProjectRestoreService m_restoreProjectService; private RestoreProjectSettings m_restoreSettings; - private IFdoUserAction m_userAction; private bool m_fResetSharedProjectValue; /// Setup for db4o client server tests. [TestFixtureSetUp] @@ -78,8 +77,6 @@ public void Initialize() ProjectName = "TestRestoreFWProject", BackupOfExistingProjectRequested = false, }; - - m_userAction = new DummyFdoUserAction(); } /// @@ -102,7 +99,7 @@ public void RestoreProject_CreateNew_OnlyDataFileAndWsFiles() m_restoreProjectService = new ProjectRestoreService(m_restoreSettings); - m_restoreProjectService.RestoreProject(new DummyProgressDlg(), m_userAction); + m_restoreProjectService.RestoreProject(new DummyProgressDlg()); VerifyManditoryFilesUnzippedAndDeleteThem(); } @@ -118,7 +115,7 @@ public void RestoreProject_CreateNew_DataFileAndConfigurationSettings() m_restoreSettings.IncludeConfigurationSettings = true; m_restoreProjectService = new ProjectRestoreService(m_restoreSettings); - m_restoreProjectService.RestoreProject(new DummyProgressDlg(), m_userAction); + m_restoreProjectService.RestoreProject(new DummyProgressDlg()); VerifyManditoryFilesUnzippedAndDeleteThem(); @@ -138,7 +135,7 @@ public void RestoreProject_PutLinkedFilesInDefaultLocation() m_restoreProjectService = new ProjectRestoreTestService(m_restoreSettings); ((ProjectRestoreTestService)m_restoreProjectService).PutFilesInProject = true; - m_restoreProjectService.RestoreProject(new DummyProgressDlg(), m_userAction); + m_restoreProjectService.RestoreProject(new DummyProgressDlg()); VerifyManditoryFilesUnzippedAndDeleteThem(); @@ -167,7 +164,7 @@ public void RestoreProject_PutLinkedFilesInOldLocation() var fullVersionOfRelativeNonStdDir = GetFullVersionOfRelativeNonStdDir(nonStdLinkedFilesDir); try { - m_restoreProjectService.RestoreProject(new DummyProgressDlg(), m_userAction); + m_restoreProjectService.RestoreProject(new DummyProgressDlg()); VerifyManditoryFilesUnzippedAndDeleteThem(); @@ -203,7 +200,7 @@ public void RestoreProject_PutLinkedFilesInOldLocation_CancelSelected() var fullVersionOfRelativeNonStdDir = GetFullVersionOfRelativeNonStdDir(nonStdLinkedFilesDir); try { - m_restoreProjectService.RestoreProject(new DummyProgressDlg(), m_userAction); + m_restoreProjectService.RestoreProject(new DummyProgressDlg()); VerifyManditoryFilesUnzippedAndDeleteThem(); @@ -240,7 +237,7 @@ public void RestoreProject_OverwriteOnlyDataRestored() m_restoreProjectService = new ProjectRestoreService(m_restoreSettings); //Restore the project once and do not delete it so that we can restore the project over the previous one. - m_restoreProjectService.RestoreProject(progressDlg, m_userAction); + m_restoreProjectService.RestoreProject(progressDlg); string restoreProjectDirectory = m_restoreSettings.ProjectPath; VerifyFileExists(restoreProjectDirectory, DirectoryFinder.GetXmlDataFileName("TestRestoreFWProject")); @@ -256,7 +253,7 @@ public void RestoreProject_OverwriteOnlyDataRestored() Assert.True(m_restoreSettings.ProjectExists, "Project does not exist but it should."); //Now do another restore then verify that the two files are not the same by comparing the LastWriteTime values. - m_restoreProjectService.RestoreProject(progressDlg, m_userAction); + m_restoreProjectService.RestoreProject(progressDlg); var dateTimeTicksOfSecondFile = GetLastWriteTimeOfRestoredFile(restoreProjectDirectory, DirectoryFinder.GetXmlDataFileName("TestRestoreFWProject")); Assert.True(dateTimeTicksOfSecondFile.Equals(dateTimeTicksOfFirstFile), "The dates and times of the files should be the same since they are set to the timestamp of the file in the zip file."); diff --git a/Src/FDO/FDOTests/FdoCacheTests.cs b/Src/FDO/FDOTests/FdoCacheTests.cs index d3779dd806..29c9656e19 100644 --- a/Src/FDO/FDOTests/FdoCacheTests.cs +++ b/Src/FDO/FDOTests/FdoCacheTests.cs @@ -87,7 +87,7 @@ public void CreateNewLangProject_DbFilesExist() using (new DummyFileMaker(Path.Combine(DirectoryFinder.ProjectsDirectory, "Gumby", DirectoryFinder.GetXmlDataFileName("Gumby")))) { using (var threadHelper = new ThreadHelper()) - FdoCache.CreateNewLangProj(new DummyProgressDlg(), new DummyFdoUserAction(), "Gumby", threadHelper); + FdoCache.CreateNewLangProj(new DummyProgressDlg(), "Gumby", threadHelper); } } finally @@ -117,7 +117,7 @@ public void CreateNewLangProject_NameWithSingleQuote() { string dbFileName; using (var threadHelper = new ThreadHelper()) - dbFileName = FdoCache.CreateNewLangProj(new DummyProgressDlg(), new DummyFdoUserAction(), dbName, threadHelper); + dbFileName = FdoCache.CreateNewLangProj(new DummyProgressDlg(), dbName, threadHelper); currentDirs = new List(Directory.GetDirectories(DirectoryFinder.ProjectsDirectory)); if (currentDirs.Contains(writingSystemsCommonDir) && !expectedDirs.Contains(writingSystemsCommonDir)) @@ -148,7 +148,7 @@ public void CreateNewLangProject_AnthropologyCategoriesExist() // create project string dbFileName; using (var threadHelper = new ThreadHelper()) - dbFileName = FdoCache.CreateNewLangProj(new DummyProgressDlg(), new DummyFdoUserAction(), dbName, threadHelper); + dbFileName = FdoCache.CreateNewLangProj(new DummyProgressDlg(), dbName, threadHelper); using (var cache = FdoCache.CreateCacheFromLocalProjectFile(dbFileName, "en", new DummyProgressDlg(), m_userAction)) { diff --git a/Src/FDO/Properties/Resources.Designer.cs b/Src/FDO/Properties/Resources.Designer.cs index 0bd9356c3b..e9a934a37d 100644 --- a/Src/FDO/Properties/Resources.Designer.cs +++ b/Src/FDO/Properties/Resources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.239 +// Runtime Version:4.0.30319.1008 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -9,173 +9,166 @@ //------------------------------------------------------------------------------ namespace SIL.FieldWorks.FDO.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SIL.FieldWorks.FDO.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to Loading the initial Parts of Speech. - /// - internal static string ksLoadingPartsOfSpeech { - get { - return ResourceManager.GetString("ksLoadingPartsOfSpeech", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Loading the Semantic Domain List. - /// - internal static string ksLoadingSemanticDomains { - get { - return ResourceManager.GetString("ksLoadingSemanticDomains", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Creating new database.... - /// - internal static string kstidCreatingDB { - get { - return ResourceManager.GetString("kstidCreatingDB", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to FieldWorks 6.0 (or earlier) backup. - /// - internal static string kstidFw60OrEarlierBackupComment { - get { - return ResourceManager.GetString("kstidFw60OrEarlierBackupComment", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to FieldWorks 6.0 XML file. - /// - internal static string kstidFw60XmlBackupComment { - get { - return ResourceManager.GetString("kstidFw60XmlBackupComment", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Initializing new database.... - /// - internal static string kstidInitializingDB { - get { - return ResourceManager.GetString("kstidInitializingDB", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to File is not a valid FieldWorks project file.. - /// - internal static string kstidInvalidFieldWorksXMLFile { - get { - return ResourceManager.GetString("kstidInvalidFieldWorksXMLFile", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to FieldWorks cannot open the project {0} because another program is using it. Please close the other program and try again. Note: this can sometimes occur when there appears to be no other program using the file. The simplest way to fix this is to log off and on again. Other options are discussed in Help.. - /// - internal static string kstidLockFileLocked { - get { - return ResourceManager.GetString("kstidLockFileLocked", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There was a problem opening the current version of the file {0}, dated {1}. Would you like to open the automatic backup, {2}, dated {3}?. - /// - internal static string kstidOfferToRestore { - get { - return ResourceManager.GetString("kstidOfferToRestore", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Problem opening file. - /// - internal static string kstidProblemOpeningFile { - get { - return ResourceManager.GetString("kstidProblemOpeningFile", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to This project is for a newer version of FieldWorks. - /// - ///To open this project, click Close, and then install the newer version of FieldWorks. - ///To revert to a version of this project which is compatible with this version of FieldWorks, click Restore a Project.. - /// - internal static string kstidProjectIsForNewerVersionOfFw { - get { - return ResourceManager.GetString("kstidProjectIsForNewerVersionOfFw", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to {0} has {1} entries referenced by {2} senses.. - /// - internal static string kstidReversalIndexDeletionText { - get { - return ResourceManager.GetString("kstidReversalIndexDeletionText", resourceCulture); - } - } - - internal static System.Drawing.Bitmap question { - get { - object obj = ResourceManager.GetObject("question", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - } + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SIL.FieldWorks.FDO.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Loading the initial Grammatical Categories. + /// + internal static string ksLoadingPartsOfSpeech { + get { + return ResourceManager.GetString("ksLoadingPartsOfSpeech", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Loading the Semantic Domain List. + /// + internal static string ksLoadingSemanticDomains { + get { + return ResourceManager.GetString("ksLoadingSemanticDomains", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Creating new database.... + /// + internal static string kstidCreatingDB { + get { + return ResourceManager.GetString("kstidCreatingDB", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to FieldWorks 6.0 (or earlier) backup. + /// + internal static string kstidFw60OrEarlierBackupComment { + get { + return ResourceManager.GetString("kstidFw60OrEarlierBackupComment", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to FieldWorks 6.0 XML file. + /// + internal static string kstidFw60XmlBackupComment { + get { + return ResourceManager.GetString("kstidFw60XmlBackupComment", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Initializing new database.... + /// + internal static string kstidInitializingDB { + get { + return ResourceManager.GetString("kstidInitializingDB", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to File is not a valid FieldWorks project file.. + /// + internal static string kstidInvalidFieldWorksXMLFile { + get { + return ResourceManager.GetString("kstidInvalidFieldWorksXMLFile", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to FieldWorks cannot open the project {0} because another program is using it. Please close the other program and try again. Note: this can sometimes occur when there appears to be no other program using the file. The simplest way to fix this is to log off and on again. Other options are discussed in Help.. + /// + internal static string kstidLockFileLocked { + get { + return ResourceManager.GetString("kstidLockFileLocked", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There was a problem opening the current version of the file {0}, dated {1}. Would you like to open the automatic backup, {2}, dated {3}?. + /// + internal static string kstidOfferToRestore { + get { + return ResourceManager.GetString("kstidOfferToRestore", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Problem opening file. + /// + internal static string kstidProblemOpeningFile { + get { + return ResourceManager.GetString("kstidProblemOpeningFile", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This project is for a newer version of FieldWorks. + /// + ///To open this project, click Close, and then install the newer version of FieldWorks. + ///To revert to a version of this project which is compatible with this version of FieldWorks, click Restore a Project.. + /// + internal static string kstidProjectIsForNewerVersionOfFw { + get { + return ResourceManager.GetString("kstidProjectIsForNewerVersionOfFw", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} has {1} entries referenced by {2} senses.. + /// + internal static string kstidReversalIndexDeletionText { + get { + return ResourceManager.GetString("kstidReversalIndexDeletionText", resourceCulture); + } + } + } } diff --git a/Src/FDO/Properties/Resources.resx b/Src/FDO/Properties/Resources.resx index 39451c7c1f..b85563cc10 100644 --- a/Src/FDO/Properties/Resources.resx +++ b/Src/FDO/Properties/Resources.resx @@ -147,9 +147,6 @@ Caption for error dialog - - ../Resources/question.ico;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - This project is for a newer version of FieldWorks. diff --git a/Src/FDO/SilentFdoUserAction.cs b/Src/FDO/SilentFdoUserAction.cs new file mode 100644 index 0000000000..9e51f1c041 --- /dev/null +++ b/Src/FDO/SilentFdoUserAction.cs @@ -0,0 +1,84 @@ +// --------------------------------------------------------------------------------------------- +#region // Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Distributable under the terms of either the Common Public License or the +// GNU Lesser General Public License, as specified in the LICENSING.txt file. +// +#endregion +// --------------------------------------------------------------------------------------------- +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using SIL.FieldWorks.Common.FwUtils; + +namespace SIL.FieldWorks.FDO +{ + /// + /// Silent implementation of FdoUserAction with reasonable defaults for + /// actions which should not require user intervention + /// + public class SilentFdoUserAction : IFdoUserAction + { + /// + /// Check with user regarding conflicting changes + /// + /// True if user wishes to revert to saved state. False otherwise. + public bool ConflictingSave() + { + // Assume saved data is correct data + return true; + } + + /// + /// Inform the user of a lost connection + /// + /// True if user wishes to attempt reconnect. False otherwise. + public bool ConnectionLost() + { + // Assume we don't to continue to attempt to reconnect endlessly + return false; + } + + /// + /// Check with user regarding which files to use + /// + /// + public FileSelection ChooseFilesToUse() + { + // Assume newer files are correct files + return FileSelection.OkKeepNewer; + } + + /// + /// Check with user regarding restoring linked files in the project folder or original path + /// + /// True if user wishes to restore linked files in project folder. False to leave them in the original location. + public bool RestoreLinkedFilesInProjectFolder() + { + // Assume linked files go in project folder + return true; + } + + /// + /// Cannot restore linked files to original path. + /// Check with user regarding restoring linked files in the project folder or not at all + /// + /// OkYes to restore to project folder, OkNo to skip restoring linked files, Cancel otherwise + public YesNoCancel CannotRestoreLinkedFilesToOriginalLocation() + { + // Assume linked files go in project folder + return YesNoCancel.OkYes; + } + + /// + /// Displays information to the user + /// + public void MessageBox() + { + throw new NotImplementedException(); + } + } +} diff --git a/Src/FDO/fdoCache.cs b/Src/FDO/fdoCache.cs index b86d25b8a5..fa7ec401c4 100644 --- a/Src/FDO/fdoCache.cs +++ b/Src/FDO/fdoCache.cs @@ -377,7 +377,6 @@ private static bool IsUpdatedWsInUse(StringBuilder updatedWssInUseBuilder) /// Create a new language project for the new language name /// /// The progress dialog. - /// /// One or more parameters, supplied in this order: /// 0. A string containing the name of the project (required); /// 1. A ThreadHelper used for invoking actions on the main UI thread (required); @@ -390,7 +389,7 @@ private static bool IsUpdatedWsInUse(StringBuilder updatedWssInUseBuilder) /// Path of the newly created project file. /// Override DisplayUi to prevent progress dialog from showing. /// ------------------------------------------------------------------------------------ - public static string CreateNewLangProj(IThreadedProgress progressDlg, IFdoUserAction userAction, params object[] parameters) + public static string CreateNewLangProj(IThreadedProgress progressDlg, params object[] parameters) { if (parameters == null || parameters.Length < 2) throw new ArgumentException("Parameters must include at least a project name and the ThreadHelper"); @@ -421,7 +420,7 @@ public static string CreateNewLangProj(IThreadedProgress progressDlg, IFdoUserAc var projectId = new SimpleProjectId(FDOBackendProviderType.kXML, dbFileName); using (var cache = CreateCacheInternal(projectId, - userIcuLocale, threadHelper, dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg), userAction)) + userIcuLocale, threadHelper, dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg), new SilentFdoUserAction())) { if (progressDlg != null) { @@ -534,7 +533,7 @@ public static string CreateNewLangProj(IThreadedProgress progressDlg, IFdoUserAc cache.SaveAndForceNewestXmlForCmObjectWithoutUnitOfWork(null, cache.m_serviceLocator.ObjectRepository.AllInstances().ToList()); } } - return ClientServerServices.Current.Local.ConvertToDb4oBackendIfNeeded(progressDlg, dbFileName, userAction); + return ClientServerServices.Current.Local.ConvertToDb4oBackendIfNeeded(progressDlg, dbFileName); } /// diff --git a/Src/FDOBrowser/FDOBrowser.csproj b/Src/FDOBrowser/FDOBrowser.csproj index 2f39ae7546..c2d50e58c3 100644 --- a/Src/FDOBrowser/FDOBrowser.csproj +++ b/Src/FDOBrowser/FDOBrowser.csproj @@ -154,7 +154,7 @@ - + Form diff --git a/Src/FDOBrowser/FDOBrowserForm.cs b/Src/FDOBrowser/FDOBrowserForm.cs index 5515cb9ab5..3ba1187900 100644 --- a/Src/FDOBrowser/FDOBrowserForm.cs +++ b/Src/FDOBrowser/FDOBrowserForm.cs @@ -382,12 +382,12 @@ protected override void OpenFile(string fileName) m_ThreadHelper = new ThreadHelper(); if (isMemoryBEP) - m_cache = FdoCache.CreateCacheWithNewBlankLangProj(new BrowserProjectId(bepType, null), "en", "en", "en", m_ThreadHelper, new FdoUserAction()); + m_cache = FdoCache.CreateCacheWithNewBlankLangProj(new BrowserProjectId(bepType, null), "en", "en", "en", m_ThreadHelper, new FdoBrowserUserAction()); else { using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(this, m_ThreadHelper)) { - m_cache = FdoCache.CreateCacheFromExistingData(new BrowserProjectId(bepType, fileName), "en", progressDlg, new FdoUserAction()); + m_cache = FdoCache.CreateCacheFromExistingData(new BrowserProjectId(bepType, fileName), "en", progressDlg, new FdoBrowserUserAction()); } } // var v = m_cache. diff --git a/Src/FDOBrowser/FDOClassList.cs b/Src/FDOBrowser/FDOClassList.cs index 888c2bf83c..b2aebcf8c7 100644 --- a/Src/FDOBrowser/FDOClassList.cs +++ b/Src/FDOBrowser/FDOClassList.cs @@ -139,7 +139,7 @@ private static void LoadFDOClassNames() if (s_allFDOClassNames != null) return; - using (FdoCache cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", null, new FdoUserAction())) + using (FdoCache cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", null, new FdoBrowserUserAction())) { IFwMetaDataCacheManaged mdc = (IFwMetaDataCacheManaged)cache.MainCacheAccessor.MetaDataCache; s_allFDOClassNames = new List(); diff --git a/Src/FDOBrowser/FdoBrowserUserAction.cs b/Src/FDOBrowser/FdoBrowserUserAction.cs new file mode 100644 index 0000000000..913277df85 --- /dev/null +++ b/Src/FDOBrowser/FdoBrowserUserAction.cs @@ -0,0 +1,92 @@ +// --------------------------------------------------------------------------------------------- +#region // Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Distributable under the terms of either the Common Public License or the +// GNU Lesser General Public License, as specified in the LICENSING.txt file. +// +#endregion +// --------------------------------------------------------------------------------------------- +using System; +using System.Windows.Forms; +using SIL.FieldWorks.Common.FwUtils; + +namespace FDOBrowser +{ + class FdoBrowserUserAction : IFdoUserAction + { + /// + /// Check with user regarding conflicting changes + /// + /// True if user wishes to revert to saved state. False otherwise. + public bool ConflictingSave() + { + DialogResult dialogResult = System.Windows.Forms.MessageBox.Show("There are conflicting changes from another user. Do you want to load the latest saved version?", "Conflicting Changes", MessageBoxButtons.YesNo); + return dialogResult == DialogResult.Yes; + } + + /// + /// Inform the user of a lost connection + /// + /// True if user wishes to attempt reconnect. False otherwise. + public bool ConnectionLost() + { + DialogResult dialogResult = System.Windows.Forms.MessageBox.Show("The connection has been lost. Do you wish to attempt a reconnect?", "Connection Lost", MessageBoxButtons.YesNo); + return dialogResult == DialogResult.Yes; + } + + public FileSelection ChooseFilesToUse() + { + DialogResult dialogResult = System.Windows.Forms.MessageBox.Show("Some files are newer than the files to be restored. Use these newer files?", "Files To Restore Are Older", MessageBoxButtons.YesNoCancel); + switch (dialogResult) + { + case DialogResult.Yes: + return FileSelection.OkKeepNewer; + case DialogResult.No: + return FileSelection.OkUseOlder; + case DialogResult.Cancel: + default: + return FileSelection.Cancel; + } + } + + /// + /// Check with user regarding restoring linked files in the project folder or original path + /// + /// True if user wishes to restore linked files in project folder. False to leave them in the original location. + public bool RestoreLinkedFilesInProjectFolder() + { + DialogResult dialogResult = System.Windows.Forms.MessageBox.Show("During restore, do you want to move linked files from their current location to the project folder?", "Restore Linked Files", MessageBoxButtons.YesNo); + return dialogResult == DialogResult.Yes; + } + + /// + /// Cannot restore linked files to original path. + /// Check with user regarding restoring linked files in the project folder or not at all + /// + /// OkYes to restore to project folder, OkNo to skip restoring linked files, Cancel otherwise + public YesNoCancel CannotRestoreLinkedFilesToOriginalLocation() + { + DialogResult dialogResult = System.Windows.Forms.MessageBox.Show("Linked files cannot stay in original location and will be moved to project folder. Restore linked files?", "Cannot Restore in Original Location", MessageBoxButtons.YesNoCancel); + switch (dialogResult) + { + case DialogResult.Yes: + return YesNoCancel.OkYes; + case DialogResult.No: + return YesNoCancel.OkNo; + case DialogResult.Cancel: + default: + return YesNoCancel.Cancel; + } + } + + /// + /// Displays information to the user + /// + public void MessageBox() + { + throw new NotImplementedException(); + } + } +} diff --git a/Src/FDOBrowser/FdoUserAction.cs b/Src/FDOBrowser/FdoUserAction.cs deleted file mode 100644 index 6f4062b28f..0000000000 --- a/Src/FDOBrowser/FdoUserAction.cs +++ /dev/null @@ -1,47 +0,0 @@ -// --------------------------------------------------------------------------------------------- -#region // Copyright (c) 2013, SIL International. All Rights Reserved. -// -// Copyright (c) 2013, SIL International. All Rights Reserved. -// -// Distributable under the terms of either the Common Public License or the -// GNU Lesser General Public License, as specified in the LICENSING.txt file. -// -#endregion -// --------------------------------------------------------------------------------------------- -using System; -using System.Windows.Forms; -using SIL.FieldWorks.Common.FwUtils; - -namespace FDOBrowser -{ - class FdoUserAction : IFdoUserAction - { - /// - /// Check with user regarding conflicting changes - /// - /// True if user wishes to revert to saved state. False otherwise. - public bool ConflictingSave() - { - DialogResult dialogResult = System.Windows.Forms.MessageBox.Show("There are conflicting changes from another user. Do you want to load the latest saved version?", "Conflicting Changes", MessageBoxButtons.YesNo); - return dialogResult == DialogResult.Yes; - } - - /// - /// Inform the user of a lost connection - /// - /// True if user wishes to attempt reconnect. False otherwise. - public bool ConnectionLost() - { - DialogResult dialogResult = System.Windows.Forms.MessageBox.Show("The connection has been lost. Do you wish to attempt a reconnect?", "Connection Lost", MessageBoxButtons.YesNo); - return dialogResult == DialogResult.Yes; - } - - /// - /// Displays information to the user - /// - public void MessageBox() - { - throw new NotImplementedException(); - } - } -} diff --git a/Src/FDOBrowser/ModelWnd.cs b/Src/FDOBrowser/ModelWnd.cs index 485986ab02..10385dbcc0 100644 --- a/Src/FDOBrowser/ModelWnd.cs +++ b/Src/FDOBrowser/ModelWnd.cs @@ -40,7 +40,7 @@ public ModelWnd() m_lvModel.Font = SystemFonts.MenuFont; // Add model browsing cache (no data, just model browsing). - m_cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", new ThreadHelper(), new FdoUserAction()); + m_cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", new ThreadHelper(), new FdoBrowserUserAction()); m_mdc = (IFwMetaDataCacheManaged)m_cache.MainCacheAccessor.MetaDataCache; PopulateModelTree(); diff --git a/Src/FDO/DomainServices/BackupRestore/CantRestoreLinkedFilesToOriginalLocation.Designer.cs b/Src/FdoUi/CantRestoreLinkedFilesToOriginalLocation.Designer.cs similarity index 96% rename from Src/FDO/DomainServices/BackupRestore/CantRestoreLinkedFilesToOriginalLocation.Designer.cs rename to Src/FdoUi/CantRestoreLinkedFilesToOriginalLocation.Designer.cs index a00bc34fcf..1836d3d297 100644 --- a/Src/FDO/DomainServices/BackupRestore/CantRestoreLinkedFilesToOriginalLocation.Designer.cs +++ b/Src/FdoUi/CantRestoreLinkedFilesToOriginalLocation.Designer.cs @@ -1,6 +1,6 @@ -using System.Windows.Forms; +using System.Windows.Forms; -namespace SIL.FieldWorks.FDO.DomainServices.BackupRestore +namespace SIL.FieldWorks.FdoUi { partial class CantRestoreLinkedFilesToOriginalLocation { @@ -71,7 +71,7 @@ private void InitializeComponent() // // pictureBox1 // - this.pictureBox1.Image = global::SIL.FieldWorks.FDO.Properties.Resources.question; + this.pictureBox1.Image = global::SIL.FieldWorks.FdoUi.Properties.Resources.question; resources.ApplyResources(this.pictureBox1, "pictureBox1"); this.pictureBox1.Name = "pictureBox1"; this.pictureBox1.TabStop = false; diff --git a/Src/FDO/DomainServices/BackupRestore/CantRestoreLinkedFilesToOriginalLocation.cs b/Src/FdoUi/CantRestoreLinkedFilesToOriginalLocation.cs similarity index 84% rename from Src/FDO/DomainServices/BackupRestore/CantRestoreLinkedFilesToOriginalLocation.cs rename to Src/FdoUi/CantRestoreLinkedFilesToOriginalLocation.cs index 40b237ec8a..963f7c3611 100644 --- a/Src/FDO/DomainServices/BackupRestore/CantRestoreLinkedFilesToOriginalLocation.cs +++ b/Src/FdoUi/CantRestoreLinkedFilesToOriginalLocation.cs @@ -1,14 +1,9 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.Linq; -using System.Text; +using System; using System.Windows.Forms; using SIL.FieldWorks.Common.FwUtils; using XCore; -namespace SIL.FieldWorks.FDO.DomainServices.BackupRestore +namespace SIL.FieldWorks.FdoUi { /// /// diff --git a/Src/FDO/DomainServices/BackupRestore/CantRestoreLinkedFilesToOriginalLocation.resx b/Src/FdoUi/CantRestoreLinkedFilesToOriginalLocation.resx similarity index 99% rename from Src/FDO/DomainServices/BackupRestore/CantRestoreLinkedFilesToOriginalLocation.resx rename to Src/FdoUi/CantRestoreLinkedFilesToOriginalLocation.resx index 5ddd81ebef..484e6aa2dd 100644 --- a/Src/FDO/DomainServices/BackupRestore/CantRestoreLinkedFilesToOriginalLocation.resx +++ b/Src/FdoUi/CantRestoreLinkedFilesToOriginalLocation.resx @@ -1,4 +1,4 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 60, 12 + + + 488, 52 + + + + 3 + + + Some files in the Linked Files folder are newer than the ones which will be restored, and these may not be files that this FieldWorks project links to yet. + + + label_message + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 7 + + + 60, 64 + + + 488, 41 + + + 4 + + + Would you like to keep the newer files in the folder or replace them with the older ones from the backup? + + + label_Question + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 6 + + + 12, 12 + + + 42, 38 + + + 5 + + + pictureBox1 + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 5 + + + True + + + + NoControl + + + 64, 132 + + + 192, 17 + + + 13 + + + Use the older files from the backup. + + + radio_Overwrite + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + NoControl + + + 64, 109 + + + 164, 17 + + + 12 + + + Keep newer files in the folder. + + + radio_Keep + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + NoControl + + + 474, 157 + + + 75, 23 + + + 11 + + + Help + + + button_Help + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + NoControl + + + 393, 157 + + + 75, 23 + + + 10 + + + Cancel + + + button_Cancel + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + NoControl + + + 312, 157 + + + 75, 23 + + + 9 + + + OK + + + button_OK + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + True + + + 6, 13 + + + 561, 192 + + + Linked files in backup are older + + + FilesToRestoreAreOlder + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Src/FdoUi/Properties/Resources.Designer.cs b/Src/FdoUi/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..6e6fd1571e --- /dev/null +++ b/Src/FdoUi/Properties/Resources.Designer.cs @@ -0,0 +1,70 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.1008 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SIL.FieldWorks.FdoUi.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SIL.FieldWorks.FdoUi.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + internal static System.Drawing.Bitmap question { + get { + object obj = ResourceManager.GetObject("question", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/Src/FdoUi/Properties/Resources.resx b/Src/FdoUi/Properties/Resources.resx new file mode 100644 index 0000000000..5a6e3854f2 --- /dev/null +++ b/Src/FdoUi/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ../Resources/question.ico;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/Src/FDO/Resources/question.ico b/Src/FdoUi/Resources/question.ico similarity index 100% rename from Src/FDO/Resources/question.ico rename to Src/FdoUi/Resources/question.ico diff --git a/Src/FDO/DomainServices/BackupRestore/RestoreLinkedFilesToProjectsFolder.Designer.cs b/Src/FdoUi/RestoreLinkedFilesToProjectsFolder.Designer.cs similarity index 96% rename from Src/FDO/DomainServices/BackupRestore/RestoreLinkedFilesToProjectsFolder.Designer.cs rename to Src/FdoUi/RestoreLinkedFilesToProjectsFolder.Designer.cs index 28c0d504cb..cfdf6a1758 100644 --- a/Src/FDO/DomainServices/BackupRestore/RestoreLinkedFilesToProjectsFolder.Designer.cs +++ b/Src/FdoUi/RestoreLinkedFilesToProjectsFolder.Designer.cs @@ -1,4 +1,4 @@ -namespace SIL.FieldWorks.FDO.DomainServices.BackupRestore +namespace SIL.FieldWorks.FdoUi { partial class RestoreLinkedFilesToProjectsFolder { @@ -65,7 +65,7 @@ private void InitializeComponent() // // pictureBox1 // - this.pictureBox1.Image = global::SIL.FieldWorks.FDO.Properties.Resources.question; + this.pictureBox1.Image = global::SIL.FieldWorks.FdoUi.Properties.Resources.question; resources.ApplyResources(this.pictureBox1, "pictureBox1"); this.pictureBox1.Name = "pictureBox1"; this.pictureBox1.TabStop = false; diff --git a/Src/FDO/DomainServices/BackupRestore/RestoreLinkedFilesToProjectsFolder.cs b/Src/FdoUi/RestoreLinkedFilesToProjectsFolder.cs similarity index 83% rename from Src/FDO/DomainServices/BackupRestore/RestoreLinkedFilesToProjectsFolder.cs rename to Src/FdoUi/RestoreLinkedFilesToProjectsFolder.cs index 41e4980f5f..276e671c59 100644 --- a/Src/FDO/DomainServices/BackupRestore/RestoreLinkedFilesToProjectsFolder.cs +++ b/Src/FdoUi/RestoreLinkedFilesToProjectsFolder.cs @@ -1,14 +1,9 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.Linq; -using System.Text; +using System; using System.Windows.Forms; using SIL.FieldWorks.Common.FwUtils; using XCore; -namespace SIL.FieldWorks.FDO.DomainServices.BackupRestore +namespace SIL.FieldWorks.FdoUi { /// /// diff --git a/Src/FDO/DomainServices/BackupRestore/RestoreLinkedFilesToProjectsFolder.resx b/Src/FdoUi/RestoreLinkedFilesToProjectsFolder.resx similarity index 99% rename from Src/FDO/DomainServices/BackupRestore/RestoreLinkedFilesToProjectsFolder.resx rename to Src/FdoUi/RestoreLinkedFilesToProjectsFolder.resx index beae349b88..003ef62648 100644 --- a/Src/FDO/DomainServices/BackupRestore/RestoreLinkedFilesToProjectsFolder.resx +++ b/Src/FdoUi/RestoreLinkedFilesToProjectsFolder.resx @@ -1,4 +1,4 @@ - + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - text/microsoft-resx + text/microsoft-resx - 2.0 + 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + - 64, 16 + 64, 16 - 256, 23 + 256, 23 - + - 0 + 0 - You are deleting the following item: + You are deleting the following item: - label1 + label1 - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - $this + $this - 7 + 7 + + + + Bottom, Right - 32, 248 + 32, 248 - 278, 23 - - - Bottom, Right + 278, 23 - 2 + 2 - Do you want to continue with the deletion? + Do you want to continue with the deletion? - label2 + label2 - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - $this + $this - 6 + 6 - Delete + Delete + + + Bottom, Right - 73, 269 + 73, 269 - 75, 23 - - - Bottom, Right + 75, 23 - 4 + 4 - &Delete + &Delete - m_deleteButton + m_deleteButton - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - $this + $this - 5 + 5 - Cancel + Cancel + + + Bottom, Right - 154, 269 + 154, 269 - 75, 23 - - - Bottom, Right + 75, 23 - 3 + 3 - &Cancel + &Cancel - m_cancelButton + m_cancelButton - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - $this + $this - 4 + 4 - - iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAANdJREFUWEftl9EO - gCAIRev/P9pmy8ZI4XJ14yHbXA+pHC6YcB7xpzhLzviW/opq9B6l2KPNe97+zs4MyOgISsBQIF1vlYev - MpZCjBpDqRmAqlAEwowzC4BCRJMMCoHMEUsJ17jw4mMYPSWWEqkAkPFVCvRU+DcA7P3KEMgwbICtwFYg - XYFarcAQM9exdSvCAF5NiH7X1zIFELmCNVivLoAhRmFgvW8VazoAlIyzSYgUp6lFKRQOJgcQz3X3Eu4N - nA6J646sn5R3DGdbM0mc1pz2ZBv2BEycL1UsThcV7omAAAAAAElFTkSuQmCC + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAASRJREFUWEe1zVsO + wzAQQtHuf9NpaJnIdS+Tl4J0vgbs14UsOx7J9sGy9Mbu6nYOfZrUXg9dyd6jqNmcCj4kunVoI74fCj5Q + dO/QprjTBocjdTq0GbmHwcFMvQ5tZu7+Bcsz9Tq0mbn7EywSdTu0Ie5vwRJRt0Mb4v4WLBF1O7Qh7n+C + hUT9Dm0Sb/iY1EcJbRJv+JjURwltEm/4mNRHCW0Sb/iY1EcJbRJv+JjURwltEm/4mNRHCW0Sb/iY1EcJ + bRJvPsECUbdDG+L+Fiw9SX9+v/4GS3u0u7n9CRaJuoS6xP2/YJmoS6hL3MfgYKROhzYj99rgsOjeoU1x + 51DwgaI7oW5x51TwIdGNUFd8v5QjD+NN6r66nd3PythdPZL5k9mJvF5v0K5VDpC1lD0AAAAASUVORK5C + YII= - 16, 8 + 16, 8 - 32, 32 + 32, 32 - 5 + 5 - pictureBox1 + pictureBox1 - System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - $this + $this - 3 + 3 + + + Top, Left, Right - 32, 48 + 32, 48 - 264, 129 - - - Top, Bottom, Left, Right + 264, 129 - 1 + 1 - panel1 + panel1 - System.Windows.Forms.Panel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - $this + $this - 1 + 1 + + + Top, Left, Right - 32, 183 + 32, 183 - 264, 55 - - - Bottom, Left, Right + 264, 55 - 7 + 7 - panel2 + panel2 - System.Windows.Forms.Panel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - $this + $this - 0 + 0 + + + Bottom, Right - False + False - 235, 269 + 235, 269 - 75, 23 - - - Bottom, Right + 75, 23 - 6 + 6 - Help + Help - False + False - buttonHelp + buttonHelp - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - $this + $this - 2 + 2 - - True + + True - 5, 13 + 5, 13 - 334, 300 + 334, 300 - - CenterParent + CenterParent - Delete: + Delete: - ConfirmDeleteObjectDlg + ConfirmDeleteObjectDlg - System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 \ No newline at end of file diff --git a/Src/FdoUi/FdoUiCore.cs b/Src/FdoUi/FdoUiCore.cs index 4e2751272b..00733ee6e3 100644 --- a/Src/FdoUi/FdoUiCore.cs +++ b/Src/FdoUi/FdoUiCore.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Drawing; using System.IO; +using System.Linq; using System.Windows.Forms; using System.Xml; using SIL.CoreImpl; @@ -36,7 +37,7 @@ public interface IFwGuiControl : IFWDisposable /// subclasses. Many classes may implement them only using the approach here, which /// for some of them is very minimal. Override and enhance where possible. /// - public enum VcFrags : int + public enum VcFrags { // numbers below this are reserved for internal use by VCs. kfragShortName = 10567, // an arbitrary number, unlikely to be confused with others. @@ -53,7 +54,7 @@ public class CmObjectUi : IxCoreColleague, IFWDisposable { #region Data members - protected XCore.Mediator m_mediator; + protected Mediator m_mediator; private Command m_command; protected ICmObject m_obj; protected int m_hvo; @@ -63,7 +64,7 @@ public class CmObjectUi : IxCoreColleague, IFWDisposable // The value is the corresponding clsid that actually occurs in the switch. // Review JohnH (JohnT): would it be more efficient to store a Class object in the map, // and use reflection to make an instance? - static Dictionary m_subclasses = new Dictionary(); + static readonly Dictionary m_subclasses = new Dictionary(); protected Control m_hostControl; // An additional target that should be included when the CmObjectUi acts as an xcore colleague. private IxCoreColleague m_additonalTarget; @@ -98,7 +99,7 @@ public string ClassName } } - public virtual XCore.Mediator Mediator + public virtual Mediator Mediator { set { @@ -274,8 +275,7 @@ private static CmObjectUi MakeUi(FdoCache cache, int hvo, int clsid) // the switch below, the dictioanry will give us the appropriate clsid that IS in the // map, so the loop below will have only one iteration. Otherwise, we start the // search with the clsid of the object itself. - int realClsid; - realClsid = m_subclasses.ContainsKey(clsid) ? m_subclasses[clsid] : clsid; + int realClsid = m_subclasses.ContainsKey(clsid) ? m_subclasses[clsid] : clsid; // Each iteration investigates whether we have a CmObjectUi subclass that // corresponds to realClsid. If not, we move on to the base class of realClsid. // In this way, the CmObjectUi subclass we return is the one designed for the @@ -283,7 +283,7 @@ private static CmObjectUi MakeUi(FdoCache cache, int hvo, int clsid) CmObjectUi result = null; while (result == null) { - switch ((int)realClsid) + switch (realClsid) { // Todo: lots more useful cases. case WfiAnalysisTags.kClassId: @@ -365,7 +365,7 @@ private static CmObjectUi MakeUi(FdoCache cache, int hvo, int clsid) /// public static CmObjectUi CreateNewUiObject(Mediator mediator, int classId, int hvoOwner, int flid, int insertionPosition) { - FdoCache cache = (FdoCache)mediator.PropertyTable.GetValue("cache"); + var cache = (FdoCache)mediator.PropertyTable.GetValue("cache"); CmObjectUi newUiObj; switch (classId) { @@ -408,7 +408,7 @@ internal static CmObjectUi DefaultCreateNewUiObject(int classId, int hvoOwner, i CmObjectUi newUiObj = null; UndoableUnitOfWorkHelper.Do(FdoUiStrings.ksUndoInsert, FdoUiStrings.ksRedoInsert, cache.ServiceLocator.GetInstance(), () => { - int newHvo = cache.DomainDataByFlid.MakeNewObject((int)classId, hvoOwner, flid, insertionPosition); + int newHvo = cache.DomainDataByFlid.MakeNewObject(classId, hvoOwner, flid, insertionPosition); newUiObj = MakeUi(cache, newHvo, classId); }); return newUiObj; @@ -433,7 +433,7 @@ public void CheckDisposed() /// /// True, if the object has been disposed. /// - private bool m_isDisposed = false; + private bool m_isDisposed; /// /// See if the object has been disposed. @@ -494,7 +494,7 @@ public void Dispose() /// protected virtual void Dispose(bool disposing) { - System.Diagnostics.Debug.WriteLineIf(!disposing, "****** Missing Dispose() call for " + GetType().Name + ". ****** "); + Debug.WriteLineIf(!disposing, "****** Missing Dispose() call for " + GetType().Name + ". ****** "); // Must not be run more than once. if (m_isDisposed) return; @@ -504,8 +504,9 @@ protected virtual void Dispose(bool disposing) // Dispose managed resources here. if (m_mediator != null) m_mediator.RemoveColleague(this); - if (m_vc != null && (m_vc is IDisposable)) - (m_vc as IDisposable).Dispose(); + var disposableVC = m_vc as IDisposable; + if (disposableVC != null) + disposableVC.Dispose(); // Leave this static alone. //if (m_subclasses != null) // m_subclasses.Clear(); @@ -530,7 +531,7 @@ protected virtual void Dispose(bool disposing) #region IxCoreColleague implementation/ - public void Init(XCore.Mediator mediator, System.Xml.XmlNode configurationParameters) + public void Init(Mediator mediator, XmlNode configurationParameters) { CheckDisposed(); @@ -542,14 +543,14 @@ public void Init(XCore.Mediator mediator, System.Xml.XmlNode configurationParame /// 2) be potential recipients of a broadcast /// /// - public XCore.IxCoreColleague[] GetMessageTargets() + public IxCoreColleague[] GetMessageTargets() { CheckDisposed(); if (m_additonalTarget != null) - return new XCore.IxCoreColleague[] { m_additonalTarget, this }; - else - return new XCore.IxCoreColleague[] { this }; + return new[] { m_additonalTarget, this }; + + return new IxCoreColleague[] { this }; } /// @@ -595,7 +596,7 @@ public virtual void LaunchGuiControl(Command command) XmlNode xnControl = command.ConfigurationNode.SelectSingleNode(xpathToControl); if (xnControl != null) { - using (IFwGuiControl dlg = DynamicLoader.CreateObject(xnControl.SelectSingleNode("dynamicloaderinfo")) as IFwGuiControl) + using (var dlg = (IFwGuiControl) DynamicLoader.CreateObject(xnControl.SelectSingleNode("dynamicloaderinfo"))) { dlg.Init(m_mediator, xnControl.SelectSingleNode("parameters"), Object); dlg.Launch(); @@ -620,8 +621,8 @@ public virtual bool OnJumpToTool(object commandObject) { CheckDisposed(); - XCore.Command command = (XCore.Command)commandObject; - string tool = SIL.Utils.XmlUtils.GetManditoryAttributeValue(command.Parameters[0], "tool"); + var command = (Command) commandObject; + string tool = XmlUtils.GetManditoryAttributeValue(command.Parameters[0], "tool"); var guid = GuidForJumping(commandObject); m_mediator.PostMessage("FollowLink", new FwLinkArgs(tool, guid)); return true; @@ -633,12 +634,12 @@ public virtual bool OnJumpToTool(object commandObject) /// /// /// - public virtual bool OnDisplayJumpToTool(object commandObject, ref XCore.UIItemDisplayProperties display) + public virtual bool OnDisplayJumpToTool(object commandObject, ref UIItemDisplayProperties display) { CheckDisposed(); - XCore.Command command = (XCore.Command)commandObject; - string tool = SIL.Utils.XmlUtils.GetManditoryAttributeValue(command.Parameters[0], "tool"); + var command = (Command) commandObject; + string tool = XmlUtils.GetManditoryAttributeValue(command.Parameters[0], "tool"); //string areaChoice = m_mediator.PropertyTable.GetStringProperty("areaChoice", null); //string toolChoice = m_mediator.PropertyTable.GetStringProperty("ToolForAreaNamed_" + areaChoice, null); string toolChoice = m_mediator.PropertyTable.GetStringProperty("currentContentControl", null); @@ -647,7 +648,7 @@ public virtual bool OnDisplayJumpToTool(object commandObject, ref XCore.UIItemDi display.Visible = display.Enabled = false; return true; } - string className = SIL.Utils.XmlUtils.GetManditoryAttributeValue(command.Parameters[0], "className"); + string className = XmlUtils.GetManditoryAttributeValue(command.Parameters[0], "className"); int specifiedClsid = 0; @@ -702,22 +703,16 @@ private ICmObject GetCurrentCmObject() return obj; } - protected virtual bool ShouldDisplayMenuForClass(int specifiedClsid, XCore.UIItemDisplayProperties display) + protected virtual bool ShouldDisplayMenuForClass(int specifiedClsid, UIItemDisplayProperties display) { if (specifiedClsid == 0) return false; // a special magic class id, only enabled explicitly. - if (this.Object.ClassID == specifiedClsid) + if (Object.ClassID == specifiedClsid) return true; - else - { - int baseClsid = m_cache.DomainDataByFlid.MetaDataCache.GetBaseClsId(Object.ClassID); - if (baseClsid == specifiedClsid) //handle one level of subclassing - return true; - else - { - return false; - } - } + int baseClsid = m_cache.DomainDataByFlid.MetaDataCache.GetBaseClsId(Object.ClassID); + if (baseClsid == specifiedClsid) //handle one level of subclassing + return true; + return false; } /// @@ -766,7 +761,6 @@ public bool HandleRightClick(Mediator mediator, Control hostControl, bool should /// This method is typically used as the menuAdjuster argument in calling HandleRightClick. /// It's important that it marks the same menu item as selected by HandlCtrlClick. /// - /// public static void MarkCtrlClickItem(ContextMenuStrip menu) { foreach (var item in menu.Items) @@ -793,7 +787,7 @@ public static void MarkCtrlClickItem(ContextMenuStrip menu) public bool HandleCtrlClick(Mediator mediator, Control hostControl) { Mediator = mediator; - XWindow window = (XWindow)mediator.PropertyTable.GetValue("window"); + var window = (XWindow)mediator.PropertyTable.GetValue("window"); m_hostControl = hostControl; var group = window.GetChoiceGroupForMenu(ContextMenuId); // temporarily the CmObjectUi must function as a colleague that can implement commands. @@ -811,7 +805,7 @@ public bool HandleCtrlClick(Mediator mediator, Control hostControl) } finally { - this.Dispose(); + Dispose(); } return false; } @@ -845,17 +839,18 @@ public bool HandleRightClick(Mediator mediator, Control hostControl, bool should /// /// True, if the menu handler is to dispose of the CmObjectUi after menu closing /// + /// /// public bool HandleRightClick(Mediator mediator, Control hostControl, bool shouldDisposeThisWhenClosed, string sMenuId, Action adjustMenu) { CheckDisposed(); Mediator = mediator; - XWindow window = (XWindow)mediator.PropertyTable.GetValue("window"); + var window = (XWindow) mediator.PropertyTable.GetValue("window"); m_hostControl = hostControl; string sHostType = m_hostControl.GetType().Name; - string sType = this.Object.GetType().Name; + string sType = Object.GetType().Name; if (sHostType == "XmlBrowseView" && sType == "CmBaseAnnotation") { @@ -893,7 +888,7 @@ public bool HandleRightClick(Mediator mediator, Control hostControl, bool should /// /// /// - public virtual bool OnDisplayDeleteSelectedItem(object commandObject, ref XCore.UIItemDisplayProperties display) + public virtual bool OnDisplayDeleteSelectedItem(object commandObject, ref UIItemDisplayProperties display) { CheckDisposed(); @@ -915,18 +910,16 @@ public virtual string DisplayNameOfClass { CheckDisposed(); - if (Object is ICmPossibility) - { - var possibility = Object as ICmPossibility; - return possibility.ItemTypeName(m_mediator.StringTbl); - } + var poss = Object as ICmPossibility; + if (poss != null) + return poss.ItemTypeName(m_mediator.StringTbl); string typeName = Object.GetType().Name; string className = m_mediator.StringTbl.GetString(typeName, "ClassNames"); if (className == "*" + typeName + "*") className = typeName; - string altName = null; - IFsFeatureSystem featsys = Object.OwnerOfClass(FsFeatureSystemTags.kClassId) as IFsFeatureSystem; + string altName; + var featsys = Object.OwnerOfClass(FsFeatureSystemTags.kClassId) as IFsFeatureSystem; if (featsys != null) { if (featsys.OwningFlid == LangProjectTags.kflidPhFeatureSystem) @@ -960,7 +953,7 @@ public void OnDeleteSelectedItem(object commandObject) if (m_obj is IWfiMorphBundle) { // we want to delete the owner, not just this object itself. - using (CmObjectUi owner = CmObjectUi.MakeUi(m_cache, m_obj.Owner.Hvo)) + using (CmObjectUi owner = MakeUi(m_cache, m_obj.Owner.Hvo)) { owner.Mediator = m_mediator; owner.DeleteUnderlyingObject(); @@ -977,6 +970,18 @@ public void OnDeleteSelectedItem(object commandObject) } } + public virtual bool CanDelete(out string cannotDeleteMsg) + { + if (Object.CanDelete) + { + cannotDeleteMsg = null; + return true; + } + + cannotDeleteMsg = FdoUiStrings.ksCannotDeleteItem; + return false; + } + /// /// Delete the object, after showing a confirmation dialog. /// Return true if deleted, false, if cancelled. @@ -995,12 +1000,16 @@ public bool DeleteUnderlyingObject() } else { - Form mainWindow = (Form)m_mediator.PropertyTable.GetValue("window"); + var mainWindow = (Form) m_mediator.PropertyTable.GetValue("window"); using (new WaitCursor(mainWindow)) { - using (ConfirmDeleteObjectDlg dlg = new ConfirmDeleteObjectDlg(m_mediator.HelpTopicProvider)) + using (var dlg = new ConfirmDeleteObjectDlg(m_mediator.HelpTopicProvider)) { - dlg.SetDlgInfo(this, m_cache, Mediator); + string cannotDeleteMsg; + if (CanDelete(out cannotDeleteMsg)) + dlg.SetDlgInfo(this, m_cache, Mediator); + else + dlg.SetDlgInfo(this, m_cache, Mediator, m_cache.TsStrFactory.MakeString(cannotDeleteMsg, m_cache.DefaultUserWs)); if (DialogResult.Yes == dlg.ShowDialog(mainWindow)) { ReallyDeleteUnderlyingObject(); @@ -1021,13 +1030,16 @@ protected virtual void DoRelatedCleanupForDeleteObject() // For media and pictures: should we delete the file also? // arguably this should be on a subclass, but it's easier to share behavior for both here. ICmFile file = null; - if (m_obj is ICmPicture) + var pict = m_obj as ICmPicture; + if (pict != null) { - file = ((ICmPicture) m_obj).PictureFileRA; + file = pict.PictureFileRA; } - else if (m_obj is ICmMedia) + else { - file = ((ICmMedia) m_obj).MediaFileRA; + var media = m_obj as ICmMedia; + if (media != null) + file = media.MediaFileRA; } ConsiderDeletingRelatedFile(file, m_mediator); } @@ -1054,30 +1066,30 @@ public static void ConsiderDeletingRelatedFile(ICmFile file, Mediator mediator) var app = mediator.PropertyTable.GetValue("App") as FwApp; if (app != null) app.PictureHolder.ReleasePicture(file.AbsoluteInternalPath); - } - string fileToDelete = file.AbsoluteInternalPath; - // I'm not sure why, but if we try to delete it right away, we typically get a failure, - // with an exception indicating that something is using the file, despite the code above that - // tries to make our picture cache let go of it. - // However, waiting until idle seems to solve the problem. - mediator.IdleQueue.Add(IdleQueuePriority.Low, obj => - { - try + string fileToDelete = file.AbsoluteInternalPath; + // I'm not sure why, but if we try to delete it right away, we typically get a failure, + // with an exception indicating that something is using the file, despite the code above that + // tries to make our picture cache let go of it. + // However, waiting until idle seems to solve the problem. + mediator.IdleQueue.Add(IdleQueuePriority.Low, obj => { - File.Delete(fileToDelete); - } - catch (IOException) - { - // If we can't actually delete the file for some reason, don't bother the user complaining. - } - return true; // task is complete, don't try again. - }); - file.Delete(); + try + { + File.Delete(fileToDelete); + } + catch (IOException) + { + // If we can't actually delete the file for some reason, don't bother the user complaining. + } + return true; // task is complete, don't try again. + }); + file.Delete(); + } } protected virtual void ReallyDeleteUnderlyingObject() { - Logger.WriteEvent("Deleting '" + this.Object.ShortName + "'..."); + Logger.WriteEvent("Deleting '" + Object.ShortName + "'..."); UndoableUnitOfWorkHelper.DoUsingNewOrCurrentUOW(FdoUiStrings.ksUndoDelete, FdoUiStrings.ksRedoDelete, m_cache.ActionHandlerAccessor, () => { @@ -1099,13 +1111,13 @@ public void MergeUnderlyingObject(bool fLoseNoTextData) { CheckDisposed(); - Form mainWindow = (Form)m_mediator.PropertyTable.GetValue("window"); + var mainWindow = (Form) m_mediator.PropertyTable.GetValue("window"); using (new WaitCursor(mainWindow)) { - using (MergeObjectDlg dlg = new MergeObjectDlg(m_mediator.HelpTopicProvider)) + using (var dlg = new MergeObjectDlg(m_mediator.HelpTopicProvider)) { - WindowParams wp = new WindowParams(); - List mergeCandidates = new List(); + var wp = new WindowParams(); + var mergeCandidates = new List(); string guiControl, helpTopic; DummyCmObject dObj = GetMergeinfo(wp, mergeCandidates, out guiControl, out helpTopic); mergeCandidates.Sort(); @@ -1122,16 +1134,12 @@ public void MergeUnderlyingObject(bool fLoseNoTextData) /// strings and owned atomic objects; otherwise, we don't change any that aren't null /// to begin with. /// - /// protected virtual void ReallyMergeUnderlyingObject(int survivorHvo, bool fLoseNoTextData) { ICmObject survivor = m_cache.ServiceLocator.GetInstance().GetObject(survivorHvo); - Logger.WriteEvent("Merging '" + this.Object.ShortName + "' into '" + survivor.ShortName + "'."); - IActionHandler ah = m_cache.ServiceLocator.GetInstance(); - UndoableUnitOfWorkHelper.Do(FdoUiStrings.ksUndoMerge, FdoUiStrings.ksRedoMerge, ah, () => - { - survivor.MergeObject(this.Object, fLoseNoTextData); - }); + Logger.WriteEvent("Merging '" + Object.ShortName + "' into '" + survivor.ShortName + "'."); + var ah = m_cache.ServiceLocator.GetInstance(); + UndoableUnitOfWorkHelper.Do(FdoUiStrings.ksUndoMerge, FdoUiStrings.ksRedoMerge, ah, () => survivor.MergeObject(Object, fLoseNoTextData)); Logger.WriteEvent("Done Merging."); m_obj = null; } @@ -1151,7 +1159,7 @@ public virtual void MoveUnderlyingObjectToCopyOfOwner() { CheckDisposed(); - Form mainWindow = (Form)m_mediator.PropertyTable.GetValue("window"); + var mainWindow = (Form) m_mediator.PropertyTable.GetValue("window"); MessageBox.Show(mainWindow, FdoUiStrings.ksCannotMoveObjectToCopy, FdoUiStrings.ksBUG); } @@ -1202,7 +1210,7 @@ static public uint RGB(Color c) /// static public uint RGB(int r, int g, int b) { - return ((uint)(((byte)(r) | ((short)((byte)(g)) << 8)) | (((short)(byte)(b)) << 16))); + return ((uint)(((byte)(r) | ((byte)(g) << 8)) | ((byte)(b) << 16))); } @@ -1218,7 +1226,7 @@ static public uint RGB(int r, int g, int b) static public List ParseSinglePropertySequenceValueIntoHvos(string singlePropertySequenceValue, FdoCache cacheForCheckingValidity, int expectedClassId) { - List hvos = new List(); + var hvos = new List(); if (String.IsNullOrEmpty(singlePropertySequenceValue)) return hvos; FdoCache cache = cacheForCheckingValidity; @@ -1265,15 +1273,11 @@ public override void Display(IVwEnv vwenv, int hvo, int frag) { case (int)VcFrags.kfragHeadWord: var le = co as ILexEntry; - if (le != null) - vwenv.AddString(le.HeadWord); - else - vwenv.AddString(tsf.MakeString(co.ShortName, wsUi)); + vwenv.AddString(le != null ? le.HeadWord : tsf.MakeString(co.ShortName, wsUi)); break; case (int)VcFrags.kfragShortName: vwenv.AddString(tsf.MakeString(co.ShortName, wsUi)); break; - case (int)VcFrags.kfragName: default: vwenv.AddString(tsf.MakeString(co.ToString(), wsUi)); break; @@ -1304,10 +1308,7 @@ public override void Display(IVwEnv vwenv, int hvo, int frag) case (int)VcFrags.kfragHeadWord: co = m_cache.ServiceLocator.GetInstance().GetObject(hvo); var le = co as ILexEntry; - if (le != null) - vwenv.AddString(le.HeadWord); - else - vwenv.AddString(tsf.MakeString(co.ShortName, wsAnal)); + vwenv.AddString(le != null ? le.HeadWord : tsf.MakeString(co.ShortName, wsAnal)); break; case (int)VcFrags.kfragShortName: co = m_cache.ServiceLocator.GetInstance().GetObject(hvo); @@ -1316,7 +1317,6 @@ public override void Display(IVwEnv vwenv, int hvo, int frag) case (int)VcFrags.kfragPosAbbrAnalysis: vwenv.AddStringAltMember(CmPossibilityTags.kflidAbbreviation, wsAnal, this); break; - case (int)VcFrags.kfragName: default: co = m_cache.ServiceLocator.GetInstance().GetObject(hvo); vwenv.AddString(tsf.MakeString(co.ToString(), wsAnal)); @@ -1341,15 +1341,8 @@ public CmNamedObjVc(FdoCache cache, int flidName) public override void Display(IVwEnv vwenv, int hvo, int frag) { - switch (frag) - { - case (int)VcFrags.kfragName: // Use the name for both name and short name. - case (int)VcFrags.kfragShortName: - default: - int wsUi = vwenv.DataAccess.WritingSystemFactory.UserWs; - vwenv.AddStringAltMember(m_flidName, wsUi, this); - break; - } + int wsUi = vwenv.DataAccess.WritingSystemFactory.UserWs; + vwenv.AddStringAltMember(m_flidName, wsUi, this); } } /// @@ -1383,7 +1376,7 @@ public override void Display(IVwEnv vwenv, int hvo, int frag) /// Special VC for classes that have a reference to a CmPossibility whose name/abbr should be /// used as the name/abbr for this. /// - public class CmPossRefVc : CmObjectUi.CmObjectVc + public class CmPossRefVc : CmObjectVc { protected int m_flidRef; // flid that refers to the CmPossibility @@ -1402,7 +1395,7 @@ private bool HandleObjMissing(IVwEnv vwenv, int hvo) int wsUi = vwenv.DataAccess.WritingSystemFactory.UserWs; ITsStrFactory tsf = m_cache.TsStrFactory; vwenv.AddString(tsf.MakeString(FdoUiStrings.ksQuestions, wsUi)); // was "??", not "???" - vwenv.NoteDependency(new int[] { hvo }, new int[] { m_flidRef }, 1); + vwenv.NoteDependency(new[] { hvo }, new[] { m_flidRef }, 1); return false; } return true; @@ -1430,7 +1423,6 @@ public override void Display(IVwEnv vwenv, int hvo, int frag) vwenv.AddObjProp(m_flidRef, this, kfragName); break; default: - case kfragName: vwenv.AddStringAltMember(CmPossibilityTags.kflidName, m_cache.ServiceLocator.WritingSystems.DefaultAnalysisWritingSystem.Handle, this); @@ -1461,15 +1453,11 @@ public override void Display(IVwEnv vwenv, int hvo, int frag) { case (int)VcFrags.kfragHeadWord: var le = co as ILexEntry; - if (le != null) - vwenv.AddString(le.HeadWord); - else - vwenv.AddString(tsf.MakeString(co.ShortName, wsVern)); + vwenv.AddString(le != null ? le.HeadWord : tsf.MakeString(co.ShortName, wsVern)); break; case (int)VcFrags.kfragShortName: vwenv.AddString(tsf.MakeString(co.ShortName, wsVern)); break; - case (int)VcFrags.kfragName: default: vwenv.AddString(tsf.MakeString(co.ToString(), wsVern)); break; @@ -1515,7 +1503,7 @@ public override IVwViewConstructor Vc } } - public override bool OnDisplayJumpToTool(object commandObject, ref XCore.UIItemDisplayProperties display) + public override bool OnDisplayJumpToTool(object commandObject, ref UIItemDisplayProperties display) { CheckDisposed(); @@ -1528,10 +1516,10 @@ public override bool OnDisplayJumpToTool(object commandObject, ref XCore.UIItemD // commands if we just leave specifiedClsid zero (code takes the second branch of the if below, // since CmObject does not inherit from CmPossibility, and depending on the override // usually it isn't displayed, but there may be some override that does. - if ((m_cache.DomainDataByFlid.MetaDataCache as IFwMetaDataCacheManaged).ClassExists(className)) + if (((IFwMetaDataCacheManaged) m_cache.DomainDataByFlid.MetaDataCache).ClassExists(className)) specifiedClsid = m_cache.DomainDataByFlid.MetaDataCache.GetClassId(className); - var cp = Object as ICmPossibility; + var cp = (ICmPossibility) Object; var owningList = cp.OwningList; if (m_cache.ClassIsOrInheritsFrom(specifiedClsid, CmPossibilityTags.kClassId) || specifiedClsid == LexEntryTypeTags.kClassId) // these appear in 2 separate lists. @@ -1558,14 +1546,10 @@ public override bool OnDisplayJumpToTool(object commandObject, ref XCore.UIItemD return true; } - public static string FormatDisplayTextWithListName(FdoCache cache, XCore.Mediator mediator, + public static string FormatDisplayTextWithListName(FdoCache cache, Mediator mediator, ICmPossibilityList pssl, ref UIItemDisplayProperties display) { - string listName; - if (pssl.Owner != null) - listName = cache.DomainDataByFlid.MetaDataCache.GetFieldName((int)pssl.OwningFlid); - else - listName = pssl.Name.BestAnalysisVernacularAlternative.Text; + string listName = pssl.Owner != null ? cache.DomainDataByFlid.MetaDataCache.GetFieldName(pssl.OwningFlid) : pssl.Name.BestAnalysisVernacularAlternative.Text; string itemTypeName = pssl.ItemsTypeName(mediator.StringTbl); if (itemTypeName != "*" + listName + "*") { @@ -1627,16 +1611,19 @@ private static bool CheckAndReportBadDiscourseTemplateAdd(FdoCache cache, int hv if (cache.ServiceLocator.GetInstance().GetObject(hvoList).OwningFlid != DsDiscourseDataTags.kflidConstChartTempl) return false; // some other list we don't care about. // We can't turn a column into a group if it's in use. - var col = cache.ServiceLocator.GetInstance().GetObject(hvoItem); - // If the item doesn't already have children, we can only add them if it isn't already in use - // as a column: we don't want to change a column into a group. Thus, if there are no - // children, we generally call the same routine as when deleting. - // However, that routine has a special case to prevent deletion of the default template even - // if NOT in use...and we must not prevent adding to that when it is empty! Indeed any - // empty CHART can always be added to, so only if col's owner is a CmPossibility (it's not a root - // item in the templates list) do we need to check for it being in use. - if (col.SubPossibilitiesOS.Count == 0 && col.Owner is ICmPossibility && col.CheckAndReportProtectedChartColumn()) - return true; + ICmPossibility poss = cache.ServiceLocator.GetInstance().GetObject(hvoItem); + using (var col = new CmPossibilityUi(poss)) + { + // If the item doesn't already have children, we can only add them if it isn't already in use + // as a column: we don't want to change a column into a group. Thus, if there are no + // children, we generally call the same routine as when deleting. + // However, that routine has a special case to prevent deletion of the default template even + // if NOT in use...and we must not prevent adding to that when it is empty! Indeed any + // empty CHART can always be added to, so only if col's owner is a CmPossibility (it's not a root + // item in the templates list) do we need to check for it being in use. + if (poss.SubPossibilitiesOS.Count == 0 && poss.Owner is ICmPossibility && col.CheckAndReportProtectedChartColumn()) + return true; + } // Finally, we have to confirm the three-level rule. var owner = cache.ServiceLocator.GetInstance().GetObject(hvoItem).Owner; if (hvoItem != hvoRootItem && owner != null && owner.Hvo != hvoRootItem) @@ -1651,11 +1638,88 @@ private static bool CheckAndReportBadDiscourseTemplateAdd(FdoCache cache, int hv public new static CmObjectUi CreateNewUiObject(Mediator mediator, int classId, int hvoOwner, int flid, int insertionPosition) { - FdoCache cache = (FdoCache)mediator.PropertyTable.GetValue("cache"); + var cache = (FdoCache) mediator.PropertyTable.GetValue("cache"); if (CheckAndReportProblemAddingSubitem(cache, hvoOwner)) return null; return DefaultCreateNewUiObject(classId, hvoOwner, flid, insertionPosition, cache); } + + public override bool CanDelete(out string cannotDeleteMsg) + { + if (!CanModifyChartColumn(out cannotDeleteMsg)) + return false; + + if (!CanDeleteTextMarkupTag(out cannotDeleteMsg)) + return false; + + return base.CanDelete(out cannotDeleteMsg); + } + + public bool CheckAndReportProtectedChartColumn() + { + string msg; + if (!CanModifyChartColumn(out msg)) + { + MessageBoxUtils.Show(msg, FdoUiStrings.ksWarningCaption, MessageBoxButtons.OK, MessageBoxIcon.Warning); + return true; + } + return false; + } + + private bool CanModifyChartColumn(out string msg) + { + var poss = (ICmPossibility) Object; + if (poss.IsDefaultDiscourseTemplate) + { + msg = FdoUiStrings.ksCantDeleteDefaultDiscourseTemplate; + return false; + } + + if (poss.IsInUseAsChartColumn) + { + var rootPossibility = (ICmPossibility) Object; + while (rootPossibility.Owner is ICmPossibility) + rootPossibility = (ICmPossibility) rootPossibility.Owner; + IDsChart chart = rootPossibility.Services.GetInstance().InstancesWithTemplate(rootPossibility).First(); + string textName = ((IDsConstChart) chart).BasedOnRA.Title.BestAnalysisVernacularAlternative.Text; + // This is an actual column; it's a problem if it has instances + msg = string.Format(FdoUiStrings.ksCantModifyTemplateInUse, textName); + return false; + } + + msg = null; + return true; + } + + private bool CanDeleteTextMarkupTag(out string msg) + { + var poss = (ICmPossibility) Object; + if (poss.IsLastTextMarkupTag) + { + msg = FdoUiStrings.ksCantDeleteLastTagList; + return false; + } + + ITextTag usedTag = poss.Services.GetInstance().GetByTextMarkupTag(poss).FirstOrDefault(); + if (usedTag != null) + { + string textName = null; + if (usedTag.BeginSegmentRA != null) + { + var ws = usedTag.Cache.LangProject.DefaultWsForMagicWs(WritingSystemServices.kwsFirstAnalOrVern); + var text = (IStText) usedTag.BeginSegmentRA.Owner.Owner; + textName = text.Title.get_String(ws).Text; + if (String.IsNullOrEmpty(textName)) + textName = text.ShortName; + } + msg = string.Format(poss.SubPossibilitiesOS.Count == 0 ? FdoUiStrings.ksCantDeleteMarkupTagInUse + : FdoUiStrings.ksCantDeleteMarkupTypeInUse, textName); + return false; + } + + msg = null; + return true; + } } @@ -1678,8 +1742,7 @@ internal MoMorphSynAnalysisUi() { } - protected override bool ShouldDisplayMenuForClass(int specifiedClsid, - XCore.UIItemDisplayProperties display) + protected override bool ShouldDisplayMenuForClass(int specifiedClsid, UIItemDisplayProperties display) { return (PartOfSpeechTags.kClassId == specifiedClsid) && (GuidForJumping(null) != Guid.Empty); @@ -1803,11 +1866,10 @@ internal MoStemMsaUi() /// public override Guid GuidForJumping(object commandObject) { - IMoStemMsa msa = Object as IMoStemMsa; + var msa = (IMoStemMsa) Object; if (msa.PartOfSpeechRA == null) return Guid.Empty; - else - return msa.PartOfSpeechRA.Guid; + return msa.PartOfSpeechRA.Guid; } } /// @@ -1836,11 +1898,10 @@ internal MoInflAffMsaUi() /// public override Guid GuidForJumping(object commandObject) { - IMoInflAffMsa msa = Object as IMoInflAffMsa; + var msa = (IMoInflAffMsa) Object; if (msa.PartOfSpeechRA == null) return Guid.Empty; - else - return msa.PartOfSpeechRA.Guid; + return msa.PartOfSpeechRA.Guid; } } @@ -1874,11 +1935,10 @@ public override Guid GuidForJumping(object commandObject) // we could get at the "to" part of speech using a separate menu command // or else, if this ends up being drawn by a view constructor rather than a string which combines both are from and the to, // then we will know which item of the user clicked on and can open the appropriate one. - IMoDerivAffMsa msa = Object as IMoDerivAffMsa; + var msa = (IMoDerivAffMsa) Object; if (msa.FromPartOfSpeechRA == null) return Guid.Empty; - else - return msa.FromPartOfSpeechRA.Guid; + return msa.FromPartOfSpeechRA.Guid; } } @@ -1906,8 +1966,8 @@ internal LexSenseUi() { } /// public override Guid GuidForJumping(object commandObject) { - XCore.Command command = (XCore.Command)commandObject; - string className = SIL.Utils.XmlUtils.GetManditoryAttributeValue(command.Parameters[0], "className"); + var command = (Command) commandObject; + string className = XmlUtils.GetManditoryAttributeValue(command.Parameters[0], "className"); if (className == "LexSense") return Object.Guid; ICmObject cmo = GetSelfOrParentOfClass(Object, LexEntryTags.kClassId); @@ -1929,7 +1989,7 @@ public override bool OnDisplayDeleteSelectedItem(object commandObject, ref UIIte return true; } - protected override bool ShouldDisplayMenuForClass(int specifiedClsid, XCore.UIItemDisplayProperties display) + protected override bool ShouldDisplayMenuForClass(int specifiedClsid, UIItemDisplayProperties display) { // Debug.WriteLine("LexSenseUi:"+display.Text+": "+ (LexEntry.kclsidLexEntry == specifiedClsid)); return LexEntryTags.kClassId == specifiedClsid || LexSenseTags.kClassId == specifiedClsid; @@ -1941,10 +2001,10 @@ protected override DummyCmObject GetMergeinfo(WindowParams wp, List rghvoExclude = new List(); + var rghvoExclude = new List(); foreach (var ls in sense.AllSenses) rghvoExclude.Add(ls.Hvo); foreach (var senseInner in le.AllSenses) @@ -1978,8 +2038,8 @@ public override void MoveUnderlyingObjectToCopyOfOwner() obj = obj.Owner; clid = obj.ClassID; } - var le = obj as ILexEntry; - le.MoveSenseToCopy(Object as ILexSense); + var le = (ILexEntry) obj; + le.MoveSenseToCopy((ILexSense) Object); } /// /// When inserting a LexSense, copy the MSA from the one we are inserting after, or the @@ -1995,11 +2055,11 @@ public override void MoveUnderlyingObjectToCopyOfOwner() public new static LexSenseUi CreateNewUiObject(Mediator mediator, int classId, int hvoOwner, int flid, int insertionPosition) { LexSenseUi result = null; - FdoCache cache = (FdoCache)mediator.PropertyTable.GetValue("cache"); + var cache = (FdoCache) mediator.PropertyTable.GetValue("cache"); UndoableUnitOfWorkHelper.Do(FdoUiStrings.ksUndoInsertSense, FdoUiStrings.ksRedoInsertSense, cache.ServiceLocator.GetInstance(), () => { - ICmObject owner = null; + ICmObject owner; int hvoMsa = 0; int chvo = cache.DomainDataByFlid.get_VecSize(hvoOwner, flid); if (chvo == 0) @@ -2052,7 +2112,6 @@ public override void MoveUnderlyingObjectToCopyOfOwner() /// /// /// LexSense whose MSA we will use/change - /// /// private static int GetSafeHvoMsa(FdoCache cache, ILexSense ls) { @@ -2116,8 +2175,8 @@ public override string ContextMenuId { CheckDisposed(); - int clidDst = m_cache.DomainDataByFlid.MetaDataCache.GetDstClsId((int)m_flid); - switch ((int)clidDst) + int clidDst = m_cache.DomainDataByFlid.MetaDataCache.GetDstClsId(m_flid); + switch (clidDst) { case PhEnvironmentTags.kClassId: return "mnuEnvReferenceChoices"; @@ -2134,9 +2193,9 @@ public override string ContextMenuId /// internal class FdoRefSeq { - FdoCache m_cache; - int m_hvo; - int m_flid; + readonly FdoCache m_cache; + readonly int m_hvo; + readonly int m_flid; internal FdoRefSeq(FdoCache cache, int hvo, int flid) { @@ -2170,7 +2229,7 @@ internal void RemoveAt(int ihvo) internal void Insert(int ihvo, int hvo) { - m_cache.DomainDataByFlid.Replace(m_hvo, m_flid, ihvo, ihvo, new int[] { hvo }, 1); + m_cache.DomainDataByFlid.Replace(m_hvo, m_flid, ihvo, ihvo, new[] { hvo }, 1); } } @@ -2183,7 +2242,7 @@ internal void Insert(int ihvo, int hvo) /// public class ReferenceSequenceUi : VectorReferenceUi { - FdoRefSeq m_fdoRS = null; + readonly FdoRefSeq m_fdoRS; public ReferenceSequenceUi(FdoCache cache, ICmObject rootObj, int referenceFlid, int targetHvo) : base(cache, rootObj, referenceFlid, targetHvo) @@ -2208,7 +2267,7 @@ protected int ComputeTargetVectorIndex() return -1; } - public override bool OnDisplayMoveTargetUpInSequence(object commandObject, ref XCore.UIItemDisplayProperties display) + public override bool OnDisplayMoveTargetUpInSequence(object commandObject, ref UIItemDisplayProperties display) { CheckDisposed(); @@ -2230,7 +2289,7 @@ public override bool OnDisplayMoveTargetUpInSequence(object commandObject, ref X return true; } - public override bool OnDisplayMoveTargetDownInSequence(object commandObject, ref XCore.UIItemDisplayProperties display) + public override bool OnDisplayMoveTargetDownInSequence(object commandObject, ref UIItemDisplayProperties display) { CheckDisposed(); @@ -2319,15 +2378,15 @@ public class ReferenceBaseUi : CmObjectUi public ReferenceBaseUi(FdoCache cache, ICmObject rootObj, int referenceFlid, int targetHvo) { // determine whether this is an atomic or vector relationship. - Debug.Assert(cache.IsReferenceProperty((int)referenceFlid)); + Debug.Assert(cache.IsReferenceProperty(referenceFlid)); Debug.Assert(rootObj != null); - base.m_cache = cache; - base.m_hvo = rootObj.Hvo; - base.m_obj = rootObj; + m_cache = cache; + m_hvo = rootObj.Hvo; + m_obj = rootObj; m_flid = referenceFlid; m_hvoTarget = targetHvo; - m_targetUi = CmObjectUi.MakeUi(m_cache, m_hvoTarget); + m_targetUi = MakeUi(m_cache, m_hvoTarget); } /// @@ -2342,7 +2401,7 @@ public ReferenceBaseUi(FdoCache cache, ICmObject rootObj, int referenceFlid, int static public ReferenceBaseUi MakeUi(FdoCache cache, ICmObject rootObj, int referenceFlid, int targetHvo) { - CellarPropertyType iType = (CellarPropertyType)cache.DomainDataByFlid.MetaDataCache.GetFieldType(referenceFlid); + var iType = (CellarPropertyType)cache.DomainDataByFlid.MetaDataCache.GetFieldType(referenceFlid); if (iType == CellarPropertyType.ReferenceSequence || iType == CellarPropertyType.ReferenceCollection) return new VectorReferenceUi(cache, rootObj, referenceFlid, targetHvo); if (iType == CellarPropertyType.ReferenceAtomic) @@ -2365,13 +2424,10 @@ public ReferenceBaseUi() { } public override bool OnDisplayJumpToTool(object commandObject, ref UIItemDisplayProperties display) { CheckDisposed(); - bool result; if (m_targetUi != null) - result = m_targetUi.OnDisplayJumpToTool(commandObject, ref display); - else - result = base.OnDisplayJumpToTool(commandObject, ref display); - return result; + return m_targetUi.OnDisplayJumpToTool(commandObject, ref display); + return base.OnDisplayJumpToTool(commandObject, ref display); } /// @@ -2386,8 +2442,7 @@ public override bool OnJumpToTool(object commandObject) if (m_targetUi != null) return m_targetUi.OnJumpToTool(commandObject); - else - return base.OnJumpToTool(commandObject); + return base.OnJumpToTool(commandObject); } /// @@ -2398,7 +2453,7 @@ public override bool OnJumpToTool(object commandObject) /// /// /// - public virtual bool OnDisplayMoveTargetUpInSequence(object commandObject, ref XCore.UIItemDisplayProperties display) + public virtual bool OnDisplayMoveTargetUpInSequence(object commandObject, ref UIItemDisplayProperties display) { CheckDisposed(); @@ -2412,7 +2467,7 @@ public virtual bool OnDisplayMoveTargetUpInSequence(object commandObject, ref XC /// /// /// - public virtual bool OnDisplayMoveTargetDownInSequence(object commandObject, ref XCore.UIItemDisplayProperties display) + public virtual bool OnDisplayMoveTargetDownInSequence(object commandObject, ref UIItemDisplayProperties display) { CheckDisposed(); @@ -2420,7 +2475,7 @@ public virtual bool OnDisplayMoveTargetDownInSequence(object commandObject, ref return true; } - public override XCore.Mediator Mediator + public override Mediator Mediator { get { @@ -2464,25 +2519,21 @@ internal MoFormUi() { } /// public override Guid GuidForJumping(object commandObject) { - XCore.Command cmd = (XCore.Command)commandObject; - string className = SIL.Utils.XmlUtils.GetManditoryAttributeValue(cmd.Parameters[0], "className"); + var cmd = (Command) commandObject; + string className = XmlUtils.GetManditoryAttributeValue(cmd.Parameters[0], "className"); if (className == "LexEntry") { ICmObject cmo = GetSelfOrParentOfClass(Object, LexEntryTags.kClassId); return (cmo == null) ? Guid.Empty : cmo.Guid; } - else - { - return Object.Guid; - } + return Object.Guid; } - protected override bool ShouldDisplayMenuForClass(int specifiedClsid, XCore.UIItemDisplayProperties display) + protected override bool ShouldDisplayMenuForClass(int specifiedClsid, UIItemDisplayProperties display) { if (LexEntryTags.kClassId == specifiedClsid) return true; - else - return DomainObjectServices.IsSameOrSubclassOf(m_cache.DomainDataByFlid.MetaDataCache, this.Object.ClassID, specifiedClsid); + return DomainObjectServices.IsSameOrSubclassOf(m_cache.DomainDataByFlid.MetaDataCache, Object.ClassID, specifiedClsid); } protected override DummyCmObject GetMergeinfo(WindowParams wp, List mergeCandidates, out string guiControl, out string helpTopic) @@ -2491,7 +2542,7 @@ protected override DummyCmObject GetMergeinfo(WindowParams wp, List // This code was generated by a tool. -// Runtime Version:4.0.30319.296 +// Runtime Version:4.0.30319.18052 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -87,6 +87,24 @@ internal static string ksBUG { } } + /// + /// Looks up a localized string similar to Sorry, FieldWorks cannot delete this item.. + /// + internal static string ksCannotDeleteItem { + get { + return ResourceManager.GetString("ksCannotDeleteItem", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sorry, FieldWorks cannot delete this wordform because it occurs in your texts.. + /// + internal static string ksCannotDeleteWordform { + get { + return ResourceManager.GetString("ksCannotDeleteWordform", resourceCulture); + } + } + /// /// Looks up a localized string similar to Could not find the correct object to jump to.. /// @@ -105,6 +123,51 @@ internal static string ksCannotMoveObjectToCopy { } } + /// + /// Looks up a localized string similar to The default discourse chart template cannot be deleted, moved or promoted.. + /// + internal static string ksCantDeleteDefaultDiscourseTemplate { + get { + return ResourceManager.GetString("ksCantDeleteDefaultDiscourseTemplate", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The last remaining Text Markup tag list cannot be deleted.. + /// + internal static string ksCantDeleteLastTagList { + get { + return ResourceManager.GetString("ksCantDeleteLastTagList", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You cannot delete a Text Markup tag when there are texts using the tag. One such text using this tag is {0}.. + /// + internal static string ksCantDeleteMarkupTagInUse { + get { + return ResourceManager.GetString("ksCantDeleteMarkupTagInUse", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You cannot delete a Text Markup type when there are texts using its tags. One such text using this type of tag is {0}.. + /// + internal static string ksCantDeleteMarkupTypeInUse { + get { + return ResourceManager.GetString("ksCantDeleteMarkupTypeInUse", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This part of a chart template cannot be moved or deleted, because it or one of its children is in use in one or more charts (e.g., {0}).. + /// + internal static string ksCantModifyTemplateInUse { + get { + return ResourceManager.GetString("ksCantModifyTemplateInUse", resourceCulture); + } + } + /// /// Looks up a localized string similar to (Ctrl-Click). /// @@ -547,6 +610,15 @@ internal static string ksUndoMerge { } } + /// + /// Looks up a localized string similar to Warning. + /// + internal static string ksWarningCaption { + get { + return ResourceManager.GetString("ksWarningCaption", resourceCulture); + } + } + /// /// Looks up a localized string similar to Words related by semantic domain to {0}:. /// diff --git a/Src/FdoUi/Resources/FdoUiStrings.resx b/Src/FdoUi/Resources/FdoUiStrings.resx index 1a11fdcd2c..9c2c05a38d 100644 --- a/Src/FdoUi/Resources/FdoUiStrings.resx +++ b/Src/FdoUi/Resources/FdoUiStrings.resx @@ -301,4 +301,33 @@ Without these, we cannot find related entries. Undo Assign Features to Phonemes + + Sorry, FieldWorks cannot delete this item. + + + Sorry, FieldWorks cannot delete this wordform because it occurs in your texts. + + + The default discourse chart template cannot be deleted, moved or promoted. + Error message attempting to delete the one and only discourse chart template. Same message is used for moving or promoting. + + + The last remaining Text Markup tag list cannot be deleted. + Error message attempting to delete the one and only text markup tag type. + + + You cannot delete a Text Markup tag when there are texts using the tag. One such text using this tag is {0}. + {0} is (one) text that prevents the delete. + + + You cannot delete a Text Markup type when there are texts using its tags. One such text using this type of tag is {0}. + {0} is (one) text that prevents the delete. + + + This part of a chart template cannot be moved or deleted, because it or one of its children is in use in one or more charts (e.g., {0}). + {0} is the title of a text, or possibly a scripture reference. + + + Warning + \ No newline at end of file diff --git a/Src/FdoUi/WfiWordformUi.cs b/Src/FdoUi/WfiWordformUi.cs index 8bd5dec59c..3ec4326550 100644 --- a/Src/FdoUi/WfiWordformUi.cs +++ b/Src/FdoUi/WfiWordformUi.cs @@ -70,5 +70,13 @@ protected override bool IsAcceptableContextToJump(string toolCurrent, string too return base.IsAcceptableContextToJump(toolCurrent, toolTarget); } + public override bool CanDelete(out string cannotDeleteMsg) + { + if (base.CanDelete(out cannotDeleteMsg)) + return true; + cannotDeleteMsg = FdoUiStrings.ksCannotDeleteWordform; + return false; + } + } } diff --git a/Src/xWorks/RecordBarTreeHandler.cs b/Src/xWorks/RecordBarTreeHandler.cs index 2fdbb62a05..a1fe2101db 100644 --- a/Src/xWorks/RecordBarTreeHandler.cs +++ b/Src/xWorks/RecordBarTreeHandler.cs @@ -19,7 +19,7 @@ // -------------------------------------------------------------------------------------------- using System; -using System.Linq; +using SIL.FieldWorks.FdoUi; using XCore; using System.Collections; using System.Collections.Generic; @@ -54,7 +54,7 @@ public abstract class RecordBarHandler : IFWDisposable static public RecordBarHandler Create(Mediator mediator, XmlNode toolConfiguration) { - RecordBarHandler handler = null; + RecordBarHandler handler; XmlNode node = toolConfiguration.SelectSingleNode("treeBarHandler"); if (node == null) handler = new RecordBarListHandler(); @@ -210,11 +210,6 @@ protected virtual bool ShouldAddNode(ICmObject obj) /// public class PossibilityTreeBarHandler : TreeBarHandler { - //must have a constructor with no parameters, to use with the dynamic loader. - public PossibilityTreeBarHandler() - { - } - protected override string GetDisplayPropertyName { get @@ -223,8 +218,7 @@ protected override string GetDisplayPropertyName // seems to load quicker for Semantic Domains and AnthroCodes. if (m_includeAbbr) return "LongName"; - else - return base.GetDisplayPropertyName; + return base.GetDisplayPropertyName; } } @@ -258,7 +252,7 @@ protected virtual void UpdateHeaderVisibility() /// protected override void AddSubNodes(ICmObject obj, TreeNodeCollection parentsCollection) { - var pss = obj as ICmPossibility; + var pss = (ICmPossibility) obj; foreach (var subPss in pss.SubPossibilitiesOS) { AddTreeNode(subPss, parentsCollection); @@ -313,19 +307,22 @@ void MoveItem(int distance) return; } - var column = m_possRepo.GetObject(hvoMove); - if (column.CheckAndReportProtectedChartColumn()) - return; + ICmPossibility column = m_possRepo.GetObject(hvoMove); + using (var columnUI = new CmPossibilityUi(column)) + { + if (columnUI.CheckAndReportProtectedChartColumn()) + return; + } var owner = column.Owner; if (owner == null) // probably not possible return; int hvoOwner = owner.Hvo; int ownFlid = column.OwningFlid; - int oldIndex = m_cache.DomainDataByFlid.GetObjIndex(hvoOwner, (int)ownFlid, column.Hvo); + int oldIndex = m_cache.DomainDataByFlid.GetObjIndex(hvoOwner, ownFlid, column.Hvo); int newIndex = oldIndex + distance; if (newIndex < 0) return; - int cobj = m_cache.DomainDataByFlid.get_VecSize(hvoOwner, (int)ownFlid); + int cobj = m_cache.DomainDataByFlid.get_VecSize(hvoOwner, ownFlid); if (newIndex >= cobj) return; // Without this, we insert it before the next object, which is the one it's already before, @@ -352,7 +349,7 @@ public class TreeBarHandler : RecordBarHandler TreeView m_tree; int m_typeSize; // font size for the tree's fonts. // map from writing system to font. - Dictionary m_dictFonts = new Dictionary(); + readonly Dictionary m_dictFonts = new Dictionary(); //must have a constructor with no parameters, to use with the dynamic loader. protected TreeBarHandler() @@ -441,7 +438,7 @@ public override void ReloadItem(ICmObject currentObject) if (currentObject == null || m_hvoToTreeNodeTable.Count == 0) return; - if (this.IsShowing) + if (IsShowing) { m_fOutOfDate = false; } @@ -476,7 +473,7 @@ public override void PopulateRecordBar(RecordList list) { CheckDisposed(); - if (this.IsShowing) + if (IsShowing) { m_fOutOfDate = false; } @@ -488,12 +485,12 @@ public override void PopulateRecordBar(RecordList list) m_list = list; - XWindow window = (XWindow)m_mediator.PropertyTable.GetValue("window"); + var window = (XWindow)m_mediator.PropertyTable.GetValue("window"); using (new WaitCursor(window)) { window.TreeBarControl.IsFlatList = false; - TreeView tree = (TreeView)window.TreeStyleRecordList; - Set expandedItems = new Set(); + var tree = (TreeView)window.TreeStyleRecordList; + var expandedItems = new Set(); if (m_tree != null && !m_expand) GetExpandedItems(m_tree.Nodes, expandedItems); m_tree = tree; @@ -503,14 +500,14 @@ public override void PopulateRecordBar(RecordList list) // If we fail to do this, switching to a different list causes drag and drop to stop working. ReleaseRecordBar(); - tree.NodeMouseClick += new TreeNodeMouseClickEventHandler(tree_NodeMouseClick); - tree.MouseDown += new MouseEventHandler(tree_MouseDown); - tree.MouseMove += new MouseEventHandler(tree_MouseMove); - tree.DragDrop += new DragEventHandler(tree_DragDrop); - tree.DragOver += new DragEventHandler(tree_DragOver); - tree.GiveFeedback += new GiveFeedbackEventHandler(tree_GiveFeedback); + tree.NodeMouseClick += tree_NodeMouseClick; + tree.MouseDown += tree_MouseDown; + tree.MouseMove += tree_MouseMove; + tree.DragDrop += tree_DragDrop; + tree.DragOver += tree_DragOver; + tree.GiveFeedback += tree_GiveFeedback; tree.ContextMenuStrip = CreateTreebarContextMenuStrip(); - tree.ContextMenuStrip.MouseClick += new MouseEventHandler(tree_MouseClicked); + tree.ContextMenuStrip.MouseClick += tree_MouseClicked; tree.AllowDrop = true; tree.BeginUpdate(); window.ClearRecordBarList(); //don't want to directly clear the nodes, because that causes an event to be fired as every single note is removed! @@ -520,7 +517,7 @@ public override void PopulateRecordBar(RecordList list) m_typeSize = list.TypeSize; AddTreeNodes(list.SortedObjects, tree); - tree.Font = new System.Drawing.Font(list.FontName, m_typeSize); + tree.Font = new Font(list.FontName, m_typeSize); tree.ShowRootLines = m_hierarchical; if (m_expand) @@ -578,8 +575,8 @@ private void ExpandItems(TreeNodeCollection treeNodeCollection, Set expande protected virtual ContextMenuStrip CreateTreebarContextMenuStrip() { - ToolStripMenuItem promoteMenuItem = new ToolStripMenuItem(xWorksStrings.Promote); - ContextMenuStrip contStrip = new ContextMenuStrip(); + var promoteMenuItem = new ToolStripMenuItem(xWorksStrings.Promote); + var contStrip = new ContextMenuStrip(); contStrip.Items.Add(promoteMenuItem); return contStrip; } @@ -590,12 +587,12 @@ public override void ReleaseRecordBar() if (m_tree != null) { - m_tree.NodeMouseClick -= new TreeNodeMouseClickEventHandler(tree_NodeMouseClick); - m_tree.MouseDown -= new MouseEventHandler(tree_MouseDown); - m_tree.MouseMove -= new MouseEventHandler(tree_MouseMove); - m_tree.DragDrop -= new DragEventHandler(tree_DragDrop); - m_tree.DragOver -= new DragEventHandler(tree_DragOver); - m_tree.GiveFeedback -= new GiveFeedbackEventHandler(tree_GiveFeedback); + m_tree.NodeMouseClick -= tree_NodeMouseClick; + m_tree.MouseDown -= tree_MouseDown; + m_tree.MouseMove -= tree_MouseMove; + m_tree.DragDrop -= tree_DragDrop; + m_tree.DragOver -= tree_DragOver; + m_tree.GiveFeedback -= tree_GiveFeedback; } } @@ -637,12 +634,12 @@ void tree_MouseClicked(object sender, MouseEventArgs e) if (item == null) return; - string ItemSelected = item.Text; - if (ItemSelected.Equals(xWorksStrings.Promote)) + string itemSelected = item.Text; + if (itemSelected.Equals(xWorksStrings.Promote)) tree_Promote(); - else if (ItemSelected.Equals(xWorksStrings.MoveDown)) + else if (itemSelected.Equals(xWorksStrings.MoveDown)) tree_moveDown(); - else if (ItemSelected.Equals(xWorksStrings.MoveUp)) + else if (itemSelected.Equals(xWorksStrings.MoveUp)) tree_moveUp(); } } @@ -670,15 +667,12 @@ void tree_DragOver(object sender, DragEventArgs e) } // An inactive handler is unfortunately also being notified. Don't express any // opinion at all about drag effects. - LocalDragItem item = (LocalDragItem)e.Data.GetData(typeof(LocalDragItem)); + var item = (LocalDragItem)e.Data.GetData(typeof(LocalDragItem)); if (item.Handler != this) return; TreeNode destNode; - if (OkToDrop(sender, e, out destNode)) - e.Effect = DragDropEffects.Move; - else - e.Effect = DragDropEffects.None; + e.Effect = OkToDrop(sender, e, out destNode) ? DragDropEffects.Move : DragDropEffects.None; if (destNode != m_dragHiliteNode) { ClearDragHilite(); @@ -692,7 +686,7 @@ void tree_MouseMove(object sender, MouseEventArgs e) { if ((e.Button & MouseButtons.Left) != MouseButtons.Left) return; - TreeView tree = sender as TreeView; + var tree = sender as TreeView; if (tree == null) return; // The location here is always different than the one in tree_MouseDown. @@ -703,7 +697,7 @@ void tree_MouseMove(object sender, MouseEventArgs e) TreeNode selItem = tree.GetNodeAt(m_mouseDownLocation); if (selItem == null) return; - LocalDragItem item = new LocalDragItem(this, selItem); + var item = new LocalDragItem(this, selItem); tree.DoDragDrop(item, DragDropEffects.Move); ClearDragHilite(); } @@ -719,7 +713,7 @@ void tree_DragDrop(object sender, DragEventArgs e) if (!OkToDrop(sender, e, out destNode)) return; // Notification also gets sent to inactive handlers, which should ignore it. - LocalDragItem item = (LocalDragItem)e.Data.GetData(typeof(LocalDragItem)); + var item = (LocalDragItem)e.Data.GetData(typeof(LocalDragItem)); if (item.Handler != this) return; if (e.Effect != DragDropEffects.Move) @@ -730,16 +724,16 @@ void tree_DragDrop(object sender, DragEventArgs e) private void MoveItem(object sender, TreeNode destNode, TreeNode sourceItem) { var hvoMove = (int)sourceItem.Tag; - ICmObject dest; var hvoDest = 0; int flidDest; var cache = (FdoCache)m_mediator.PropertyTable.GetValue("cache"); var move = cache.ServiceLocator.GetObject(hvoMove); var moveLabel = sourceItem.Text; TreeNodeCollection newSiblings; - var tree = sender as TreeView; + var tree = (TreeView) sender; if (destNode == null) { + ICmObject dest; for (dest = move.Owner; dest != null; dest = dest.Owner) { if (!(dest is ICmPossibilityList)) @@ -802,7 +796,7 @@ private void MoveItem(object sender, TreeNode destNode, TreeNode sourceItem) /// true if a problem was reported and the move should be cancelled. private bool CheckAndReportForbiddenMove(int hvoMove, int hvoDest) { - var cache = (FdoCache)m_mediator.PropertyTable.GetValue("cache"); + var cache = (FdoCache) m_mediator.PropertyTable.GetValue("cache"); var movingPossItem = m_possRepo.GetObject(hvoMove); if (movingPossItem != null) { @@ -816,12 +810,12 @@ private bool CheckAndReportForbiddenMove(int hvoMove, int hvoDest) // 1. Check to see if hvoRootItem is a chart template containing our target. // If so, hvoPossList is owned in the chart templates property. if (m_objRepo.GetObject(hvoPossList).OwningFlid == DsDiscourseDataTags.kflidConstChartTempl) - return CheckAndReportBadDiscourseTemplateMove(cache, movingPossItem, hvoRootItem, hvoPossList, hvoDest); + return CheckAndReportBadDiscourseTemplateMove(movingPossItem, hvoRootItem, hvoPossList, hvoDest); // 2. Check to see if hvoRootItem is a TextMarkup TagList containing our target (i.e. a Tag type). // If so, hvoPossList is owned in the text markup tags property. if (m_objRepo.GetObject(hvoPossList).OwningFlid == LangProjectTags.kflidTextMarkupTags) - return CheckAndReportBadTagListMove(cache, movingPossItem, hvoRootItem, hvoPossList, hvoDest); + return CheckAndReportBadTagListMove(movingPossItem, hvoRootItem, hvoPossList, hvoDest); } return false; // not detecting problems with moving other kinds of things. } @@ -829,13 +823,12 @@ private bool CheckAndReportForbiddenMove(int hvoMove, int hvoDest) /// /// Checks for and reports any disallowed tag list moves. /// - /// /// The proposed tag item to move. /// The hvo of the top-level Tag Type Possibility containing the moving item. /// The hvo of the main PossiblityList grouping all TextMarkup Tags. /// The hvo of the destination tag item. /// true if we found and reported a bad move. - private bool CheckAndReportBadTagListMove(FdoCache cache, ICmPossibility movingTagItem, int hvoSubListRoot, + private bool CheckAndReportBadTagListMove(ICmPossibility movingTagItem, int hvoSubListRoot, int hvoMainTagList, int hvoDest) { // Check if movingTagItem is a top-level Tag Type. @@ -857,7 +850,7 @@ private bool CheckAndReportBadTagListMove(FdoCache cache, ICmPossibility movingT return false; } if (hvoDest == hvoMainTagList) - { + { // Can't promote tag to Tag Type root MessageBox.Show(m_tree, xWorksStrings.ksCantPromoteTag, xWorksStrings.ksProhibitedMovement, MessageBoxButtons.OK, MessageBoxIcon.Warning); @@ -867,55 +860,60 @@ private bool CheckAndReportBadTagListMove(FdoCache cache, ICmPossibility movingT MessageBox.Show(m_tree, xWorksStrings.ksTagListTooDeep, xWorksStrings.ksProhibitedMovement, MessageBoxButtons.OK, MessageBoxIcon.Warning); return true; - } + } /// /// Checks for and reports any disallowed discourse template moves. /// - /// /// The proposed possibility item (template column) to move. /// The hvo of the affected Chart Template (only 'default' exists so far). /// The hvo of the Template List. /// The hvo of the destination item. /// true means we found and reported a bad move. - private bool CheckAndReportBadDiscourseTemplateMove(FdoCache cache, ICmPossibility movingColumn, int hvoTemplate, + private bool CheckAndReportBadDiscourseTemplateMove(ICmPossibility movingColumn, int hvoTemplate, int hvoTemplateList, int hvoDest) { - // First, check whether we're allowed to manipulate this column at all. This is the same check as + using (var movingColumnUI = new CmPossibilityUi(movingColumn)) + { + // First, check whether we're allowed to manipulate this column at all. This is the same check as // whether we're allowed to delete it. - if (movingColumn.CheckAndReportProtectedChartColumn()) + if (movingColumnUI.CheckAndReportProtectedChartColumn()) return true; - // Other things being equal, we now need to make sure we aren't messing up the chart levels - // Unless something is badly wrong, the destination is either the root template, - // a column group one level down from the root template, a column two levels down, - // or the base list. + } + // Other things being equal, we now need to make sure we aren't messing up the chart levels + // Unless something is badly wrong, the destination is either the root template, + // a column group one level down from the root template, a column two levels down, + // or the base list. if (hvoDest == hvoTemplateList) - { - MessageBox.Show(m_tree, xWorksStrings.ksCantPromoteGroupToTemplate, - xWorksStrings.ksProhibitedMovement, MessageBoxButtons.OK, MessageBoxIcon.Warning); - return true; - } + { + MessageBox.Show(m_tree, xWorksStrings.ksCantPromoteGroupToTemplate, + xWorksStrings.ksProhibitedMovement, MessageBoxButtons.OK, MessageBoxIcon.Warning); + return true; + } // if the destination IS the root, that's fine...anything can move there. if (hvoDest == hvoTemplate) - return false; + return false; // It's OK to move a leaf to a group (one level down from the root, as long as // the destination 'group' isn't a column that's in use. bool moveColumnIsLeaf = movingColumn.SubPossibilitiesOS.Count == 0; if (m_objRepo.GetObject(hvoDest).Owner.Hvo == hvoTemplate && moveColumnIsLeaf) + { + ICmPossibility dest = m_possRepo.GetObject(hvoDest); + using (var destUI = new CmPossibilityUi(dest)) { - var dest = m_possRepo.GetObject(hvoDest); // If it isn't already a group, we can only turn it into one if it's empty if (dest.SubPossibilitiesOS.Count == 0) - return dest.CheckAndReportProtectedChartColumn(); - // If it's already a group it should be fine as a destination. - return false; + return destUI.CheckAndReportProtectedChartColumn(); } - // Anything else represents an attempt to make the tree too deep, e.g., moving a - // column into child column, or a group into another group. - MessageBox.Show(m_tree, xWorksStrings.ksTemplateTooDeep, - xWorksStrings.ksProhibitedMovement, MessageBoxButtons.OK, MessageBoxIcon.Warning); - return true; + // If it's already a group it should be fine as a destination. + return false; } + // Anything else represents an attempt to make the tree too deep, e.g., moving a + // column into child column, or a group into another group. + MessageBox.Show(m_tree, xWorksStrings.ksTemplateTooDeep, + xWorksStrings.ksProhibitedMovement, MessageBoxButtons.OK, MessageBoxIcon.Warning); + return true; + } private bool OkToDrop(object sender, DragEventArgs e, out TreeNode destNode) { @@ -923,19 +921,19 @@ private bool OkToDrop(object sender, DragEventArgs e, out TreeNode destNode) // Don't allow drop in non-hierarchical lists. if (m_list.OwningObject is ICmPossibilityList && (m_list.OwningObject as ICmPossibilityList).Depth < 2) return false; - TreeView tree = sender as TreeView; + var tree = sender as TreeView; if (tree == null) return false; if (!e.Data.GetDataPresent(typeof(LocalDragItem))) return false; destNode = tree.GetNodeAt(tree.PointToClient(new Point(e.X, e.Y))); - LocalDragItem item = (LocalDragItem)e.Data.GetData(typeof(LocalDragItem)); + var item = (LocalDragItem)e.Data.GetData(typeof(LocalDragItem)); if (item.SourceNode == destNode) return false; - int hvoMove = (int)item.SourceNode.Tag; + var hvoMove = (int) item.SourceNode.Tag; int hvoDest = 0; if (destNode != null) - hvoDest = (int)destNode.Tag; + hvoDest = (int) destNode.Tag; if (hvoDest <= 0) return false; // It must not be that hvoMove owns hvoDest @@ -952,7 +950,7 @@ private bool OkToDrop(object sender, DragEventArgs e, out TreeNode destNode) void tree_MouseDown(object sender, MouseEventArgs e) { - TreeView tree = sender as TreeView; + var tree = (TreeView) sender; if (e.Button != MouseButtons.Left) { TreeNode node = tree.GetNodeAt(e.X, e.Y); @@ -1045,9 +1043,7 @@ protected virtual string GetTreeNodeLabel(ICmObject obj, out Font font) protected virtual TreeNode AddTreeNode(ICmObject obj, TreeNodeCollection parentsCollection) { Font font; - TreeNode node = new TreeNode( GetTreeNodeLabel(obj, out font) ); - node.Tag = obj.Hvo; //note that we could store the whole object instead. - node.NodeFont = font; + var node = new TreeNode( GetTreeNodeLabel(obj, out font) ) {Tag = obj.Hvo, NodeFont = font}; parentsCollection.Add(node); AddToTreeNodeTable(obj.Hvo, node); AddSubNodes(obj, node.Nodes); @@ -1068,8 +1064,8 @@ public override void UpdateSelection(ICmObject currentObject) { CheckDisposed(); - XWindow window = (XWindow)m_mediator.PropertyTable.GetValue("window"); - TreeView tree = (TreeView)window.TreeStyleRecordList; + var window = (XWindow)m_mediator.PropertyTable.GetValue("window"); + var tree = (TreeView)window.TreeStyleRecordList; if (currentObject == null) { tree.SelectedNode = null; @@ -1097,8 +1093,8 @@ public override void UpdateSelection(ICmObject currentObject) /// class LocalDragItem { - TreeBarHandler m_handler; // handler dragging from - TreeNode m_sourceTreeNode; // tree node being dragged + readonly TreeBarHandler m_handler; // handler dragging from + readonly TreeNode m_sourceTreeNode; // tree node being dragged public LocalDragItem(TreeBarHandler handler, TreeNode sourceTreeNode) { diff --git a/Src/xWorks/RecordClerk.cs b/Src/xWorks/RecordClerk.cs index a60579fad9..e407c92e04 100644 --- a/Src/xWorks/RecordClerk.cs +++ b/Src/xWorks/RecordClerk.cs @@ -1477,13 +1477,6 @@ public bool OnDeleteRecord(object commandObject) if (CurrentObjectHvo == 0) return true; - // Don't allow an object to be deleted if it shouldn't be deleted. - if (!CanDelete()) - { - ReportCannotDelete(); - return true; - } - //when we are doing an automated test, we don't know how to click the "yes" button, so //look into the property table to see if there is a property controlling what we should do. var doingAutomatedTest = m_mediator.PropertyTable.GetBoolProperty("DoingAutomatedTest", false); @@ -1494,26 +1487,11 @@ public bool OnDeleteRecord(object commandObject) { using (CmObjectUi uiObj = CmObjectUi.MakeUi(thingToDelete)) { - if (thingToDelete.CanDelete) - { + string cannotDeleteMsg; + if (uiObj.CanDelete(out cannotDeleteMsg)) dlg.SetDlgInfo(uiObj, Cache, m_mediator); - } else - { - ITsString tssNote; - switch (thingToDelete.ClassID) - { - case WfiWordformTags.kClassId: - tssNote = Cache.TsStrFactory.MakeString(xWorksStrings.ksCannotWordform, - Cache.DefaultUserWs); - break; - default: - tssNote = Cache.TsStrFactory.MakeString(xWorksStrings.ksCannotDeleteItem, - Cache.DefaultUserWs); - break; - } - dlg.SetDlgInfo(uiObj, Cache, m_mediator, tssNote); - } + dlg.SetDlgInfo(uiObj, Cache, m_mediator, Cache.TsStrFactory.MakeString(cannotDeleteMsg, Cache.DefaultUserWs)); } var window = (Form) m_mediator.PropertyTable.GetValue("window"); if (doingAutomatedTest || diff --git a/Src/xWorks/xWorksStrings.Designer.cs b/Src/xWorks/xWorksStrings.Designer.cs index 5346c98a88..17d31fdd86 100644 --- a/Src/xWorks/xWorksStrings.Designer.cs +++ b/Src/xWorks/xWorksStrings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.296 +// Runtime Version:4.0.30319.18052 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -482,24 +482,6 @@ internal static string ksCanBeConfiguredInMoreDetail { } } - /// - /// Looks up a localized string similar to Sorry, FieldWorks cannot delete this item.. - /// - internal static string ksCannotDeleteItem { - get { - return ResourceManager.GetString("ksCannotDeleteItem", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Sorry, FieldWorks cannot delete this wordform because it occurs in your texts.. - /// - internal static string ksCannotWordform { - get { - return ResourceManager.GetString("ksCannotWordform", resourceCulture); - } - } - /// /// Looks up a localized string similar to You cannot demote a list of Text Markup Tags into another list.. /// diff --git a/Src/xWorks/xWorksStrings.resx b/Src/xWorks/xWorksStrings.resx index 2aab0e9594..2929297dcd 100644 --- a/Src/xWorks/xWorksStrings.resx +++ b/Src/xWorks/xWorksStrings.resx @@ -561,12 +561,6 @@ Are you SURE you want to delete the field {2}? Duplicate List Name used by AddListDlg - - Sorry, FieldWorks cannot delete this wordform because it occurs in your texts. - - - Sorry, FieldWorks cannot delete this item. - Undo Insert Media From 874b2cf436b9c2d071558f59855e3bbffb906d86 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Mon, 2 Dec 2013 14:48:44 +0700 Subject: [PATCH 008/143] Move more UI elements out of FDO and its references Delete unused FindFileStatusDialog. Move ProgressBarWrapper, FWVersionTooOld, ImageCollection. Change-Id: I2adf2185661d918f12d2c8af43dedf65f244a7ab --- Src/Common/FwUtils/FwUtils.csproj | 1 - .../FwUtilsTests/DummyFdoUserAction.cs | 8 - Src/Common/FwUtils/IFdoUserAction.cs | 5 - .../BackupRestore/ProjectRestoreService.cs | 2 +- .../DataMigration/ImportFrom6_0.cs | 8 +- .../FDOTests/DuplicateAnalysisFixerTests.cs | 8 +- .../FDOTests/DuplicateWordformFixerTests.cs | 2 +- Src/FDO/FDOTests/FDOTests.csproj | 6 + Src/FDO/FDOTests/LingTests.cs | 1 + Src/FDO/SilentFdoUserAction.cs | 8 - Src/FDOBrowser/FdoBrowserUserAction.cs | 8 - Src/FdoUi/FdoUi.csproj | 11 +- Src/FdoUi/FdoUserActionWindowsForms.cs | 11 - .../FwUtils => FdoUi}/ProgressBarWrapper.cs | 6 +- .../Interlinear/DuplicateAnalysisFixer.cs | 10 +- .../Interlinear/DuplicateWordformFixer.cs | 8 +- Src/LexText/Lexicon/HomographResetter.cs | 2 +- .../Lexicon/LexEntryInflTypeConverter.cs | 9 +- .../FWVersionTooOld.Designer.cs | 2 +- .../FWVersionTooOld.cs | 2 +- .../FWVersionTooOld.resx | 0 Src/MigrateSqlDbs/MigrateSqlDbs.csproj | 12 +- Src/MigrateSqlDbs/Program.cs | 12 +- Src/Utilities/BasicUtils/BasicUtils.csproj | 9 +- .../BasicUtils/FindFileStatusDialog.cs | 149 ----------- .../BasicUtils/FindFileStatusDialog.resx | 234 ------------------ Src/Utilities/XMLUtils/XMLUtils.csproj | 3 - .../XMLUtils => XCore}/ImageCollection.cs | 12 +- Src/XCore/PaneBarContainer.cs | 2 +- .../XCoreAdapterSilSidePane/AdapterBase.cs | 6 +- Src/XCore/XCoreAdapterSilSidePane/PaneBar.cs | 4 +- .../XCoreAdapterSilSidePane/PanelButton.cs | 4 +- .../XCoreAdapterSilSidePane/PanelMenu.cs | 4 +- Src/XCore/xCore.csproj | 9 +- Src/XCore/xCoreInterfaces/IImageCollection.cs | 32 +++ Src/XCore/xCoreInterfaces/IPaneBar.cs | 2 +- Src/XCore/xCoreInterfaces/IUIAdapter.cs | 5 +- .../xCoreInterfaces/xCoreInterfaces.csproj | 3 +- .../CommandBarAdaptor.cs | 4 +- Src/XCore/xCoreOpenSourceAdapter/PaneBar.cs | 2 +- .../xCoreOpenSourceAdapter/ReBarAdapter.cs | 2 +- .../RebarMenuAdapter.cs | 2 +- .../xCoreOpenSourceAdapter/SidebarAdapter.cs | 6 +- 43 files changed, 115 insertions(+), 521 deletions(-) rename Src/{Common/FwUtils => FdoUi}/ProgressBarWrapper.cs (94%) rename Src/{FdoUi/Dialogs => MigrateSqlDbs}/FWVersionTooOld.Designer.cs (98%) rename Src/{FdoUi/Dialogs => MigrateSqlDbs}/FWVersionTooOld.cs (97%) rename Src/{FdoUi/Dialogs => MigrateSqlDbs}/FWVersionTooOld.resx (100%) delete mode 100644 Src/Utilities/BasicUtils/FindFileStatusDialog.cs delete mode 100644 Src/Utilities/BasicUtils/FindFileStatusDialog.resx rename Src/{Utilities/XMLUtils => XCore}/ImageCollection.cs (97%) create mode 100644 Src/XCore/xCoreInterfaces/IImageCollection.cs diff --git a/Src/Common/FwUtils/FwUtils.csproj b/Src/Common/FwUtils/FwUtils.csproj index a9abb03425..b4fb494a71 100644 --- a/Src/Common/FwUtils/FwUtils.csproj +++ b/Src/Common/FwUtils/FwUtils.csproj @@ -204,7 +204,6 @@ - Code diff --git a/Src/Common/FwUtils/FwUtilsTests/DummyFdoUserAction.cs b/Src/Common/FwUtils/FwUtilsTests/DummyFdoUserAction.cs index 89e98f45ec..66f00c5abb 100644 --- a/Src/Common/FwUtils/FwUtilsTests/DummyFdoUserAction.cs +++ b/Src/Common/FwUtils/FwUtilsTests/DummyFdoUserAction.cs @@ -66,14 +66,6 @@ public YesNoCancel CannotRestoreLinkedFilesToOriginalLocation() throw new NotImplementedException(); } - /// - /// Displays Fieldworks data version too old information - /// - public void VersionTooOld(string version) - { - throw new NotImplementedException(); - } - /// /// Displays information to the user /// diff --git a/Src/Common/FwUtils/IFdoUserAction.cs b/Src/Common/FwUtils/IFdoUserAction.cs index 017dc6e32c..a01bfe9bb0 100644 --- a/Src/Common/FwUtils/IFdoUserAction.cs +++ b/Src/Common/FwUtils/IFdoUserAction.cs @@ -51,11 +51,6 @@ public interface IFdoUserAction /// OkYes to restore to project folder, OkNo to skip restoring linked files, Cancel otherwise YesNoCancel CannotRestoreLinkedFilesToOriginalLocation(); - /// - /// Displays Fieldworks data version too old information - /// - void VersionTooOld(string version); - /// /// Displays information to the user /// diff --git a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs index 340bffc1c4..e49db51bb4 100644 --- a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs +++ b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs @@ -136,7 +136,7 @@ public void RestoreProject(IThreadedProgress progressDlg) private void ImportFrom6_0Backup(BackupFileSettings fileSettings, IThreadedProgress progressDlg) { - ImportFrom6_0 importer = new ImportFrom6_0(progressDlg, m_userAction); + ImportFrom6_0 importer = new ImportFrom6_0(progressDlg); string projFile; if (!importer.Import(fileSettings.File, m_restoreSettings.ProjectName, out projFile)) { diff --git a/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs b/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs index 4307101932..c3791ed6a9 100644 --- a/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs +++ b/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs @@ -51,7 +51,6 @@ public class ImportFrom6_0 readonly bool m_fVerboseDebug; private readonly IThreadedProgress m_progressDlg; - private readonly IFdoUserAction m_userAction; #endregion /// @@ -63,17 +62,16 @@ public class ImportFrom6_0 /// /// Constructor for run-time debugging. /// - public ImportFrom6_0(IThreadedProgress progressDlg, IFdoUserAction userAction, bool fDebug) + public ImportFrom6_0(IThreadedProgress progressDlg, bool fDebug) { m_progressDlg = progressDlg; - m_userAction = userAction; m_fVerboseDebug = fDebug; } /// /// Constructor. /// - public ImportFrom6_0(IThreadedProgress progressDlg, IFdoUserAction userAction) : this(progressDlg, userAction, false) + public ImportFrom6_0(IThreadedProgress progressDlg) : this(progressDlg, false) { } #endregion @@ -424,8 +422,6 @@ private string FindComDllIfRegistered(RegistryKey clsidKey, string sClsid, ref s { if (!String.IsNullOrEmpty(version) && version.CompareTo("5.4") < 0) { - m_userAction.VersionTooOld(version); - string launchesFlex = "0"; string launchesTE = "0"; if (RegistryHelper.KeyExists(FwRegistryHelper.FieldWorksRegistryKey, "Language Explorer")) diff --git a/Src/FDO/FDOTests/DuplicateAnalysisFixerTests.cs b/Src/FDO/FDOTests/DuplicateAnalysisFixerTests.cs index 87cec96d10..f315cd3bc8 100644 --- a/Src/FDO/FDOTests/DuplicateAnalysisFixerTests.cs +++ b/Src/FDO/FDOTests/DuplicateAnalysisFixerTests.cs @@ -1,14 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Text; +using System.Diagnostics.CodeAnalysis; using System.Windows.Forms; using NUnit.Framework; using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices; +using SIL.FieldWorks.FdoUi; namespace SIL.FieldWorks.FDO.FDOTests { diff --git a/Src/FDO/FDOTests/DuplicateWordformFixerTests.cs b/Src/FDO/FDOTests/DuplicateWordformFixerTests.cs index 55b1ca6eb3..af90d68462 100644 --- a/Src/FDO/FDOTests/DuplicateWordformFixerTests.cs +++ b/Src/FDO/FDOTests/DuplicateWordformFixerTests.cs @@ -2,8 +2,8 @@ using System.Windows.Forms; using NUnit.Framework; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices; +using SIL.FieldWorks.FdoUi; namespace SIL.FieldWorks.FDO.FDOTests { diff --git a/Src/FDO/FDOTests/FDOTests.csproj b/Src/FDO/FDOTests/FDOTests.csproj index dd3e901bfa..dee8e55439 100644 --- a/Src/FDO/FDOTests/FDOTests.csproj +++ b/Src/FDO/FDOTests/FDOTests.csproj @@ -562,6 +562,12 @@ true + + + {7B119B65-DD6F-4AFB-BBA3-682DC084FB33} + FdoUi + + ../../../DistFiles diff --git a/Src/FDO/FDOTests/LingTests.cs b/Src/FDO/FDOTests/LingTests.cs index 16057fe5fe..58705d787e 100644 --- a/Src/FDO/FDOTests/LingTests.cs +++ b/Src/FDO/FDOTests/LingTests.cs @@ -28,6 +28,7 @@ using SIL.FieldWorks.FDO.Validation; using SIL.FieldWorks.FDO.DomainServices; using SIL.CoreImpl; +using SIL.FieldWorks.FdoUi; using SIL.Utils; namespace SIL.FieldWorks.FDO.FDOTests.LingTests diff --git a/Src/FDO/SilentFdoUserAction.cs b/Src/FDO/SilentFdoUserAction.cs index 1fffbbcc49..c7162e32fc 100644 --- a/Src/FDO/SilentFdoUserAction.cs +++ b/Src/FDO/SilentFdoUserAction.cs @@ -73,14 +73,6 @@ public YesNoCancel CannotRestoreLinkedFilesToOriginalLocation() return YesNoCancel.OkYes; } - /// - /// Displays Fieldworks data version too old information - /// - public void VersionTooOld(string version) - { - // Informational only - } - /// /// Displays information to the user /// diff --git a/Src/FDOBrowser/FdoBrowserUserAction.cs b/Src/FDOBrowser/FdoBrowserUserAction.cs index 3c7ef7af07..913277df85 100644 --- a/Src/FDOBrowser/FdoBrowserUserAction.cs +++ b/Src/FDOBrowser/FdoBrowserUserAction.cs @@ -81,14 +81,6 @@ public YesNoCancel CannotRestoreLinkedFilesToOriginalLocation() } } - /// - /// Displays Fieldworks data version too old information - /// - public void VersionTooOld(string version) - { - System.Windows.Forms.MessageBox.Show("Cannot migrate your data to this version of FieldWorks.", "Cannot Migrate Data"); - } - /// /// Displays information to the user /// diff --git a/Src/FdoUi/FdoUi.csproj b/Src/FdoUi/FdoUi.csproj index 5acd48892c..f30f02edab 100644 --- a/Src/FdoUi/FdoUi.csproj +++ b/Src/FdoUi/FdoUi.csproj @@ -219,12 +219,6 @@ FilesToRestoreAreOlder.cs - - Form - - - FWVersionTooOld.cs - Form @@ -266,6 +260,7 @@ UserControl + True True @@ -305,10 +300,6 @@ FilesToRestoreAreOlder.cs Designer - - FWVersionTooOld.cs - Designer - MergeObjectDlg.cs Designer diff --git a/Src/FdoUi/FdoUserActionWindowsForms.cs b/Src/FdoUi/FdoUserActionWindowsForms.cs index fd1156b4ee..172d88f698 100644 --- a/Src/FdoUi/FdoUserActionWindowsForms.cs +++ b/Src/FdoUi/FdoUserActionWindowsForms.cs @@ -112,17 +112,6 @@ public YesNoCancel CannotRestoreLinkedFilesToOriginalLocation() } } - /// - /// Displays Fieldworks data version too old information - /// - public void VersionTooOld(string version) - { - using (var dlg = new FWVersionTooOld(version)) - { - dlg.ShowDialog(); - } - } - /// /// Displays information to the user /// diff --git a/Src/Common/FwUtils/ProgressBarWrapper.cs b/Src/FdoUi/ProgressBarWrapper.cs similarity index 94% rename from Src/Common/FwUtils/ProgressBarWrapper.cs rename to Src/FdoUi/ProgressBarWrapper.cs index 282763d1f6..d300241cb2 100644 --- a/Src/Common/FwUtils/ProgressBarWrapper.cs +++ b/Src/FdoUi/ProgressBarWrapper.cs @@ -1,4 +1,4 @@ -// --------------------------------------------------------------------------------------------- +// --------------------------------------------------------------------------------------------- #region // Copyright (c) 2013, SIL International. All Rights Reserved. // // Copyright (c) 2013, SIL International. All Rights Reserved. @@ -13,8 +13,10 @@ using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Windows.Forms; +using SIL.FieldWorks.Common.FwUtils; +using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; -namespace SIL.FieldWorks.Common.FwUtils +namespace SIL.FieldWorks.FdoUi { /// /// Wrapper class to allow a ProgressBar to function as an IProgress diff --git a/Src/LexText/Interlinear/DuplicateAnalysisFixer.cs b/Src/LexText/Interlinear/DuplicateAnalysisFixer.cs index f6585be725..f78157fc65 100644 --- a/Src/LexText/Interlinear/DuplicateAnalysisFixer.cs +++ b/Src/LexText/Interlinear/DuplicateAnalysisFixer.cs @@ -1,16 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Text; -using System.Windows.Forms; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.Infrastructure; +using SIL.FieldWorks.FdoUi; using SIL.FieldWorks.FwCoreDlgs; -using SIL.FieldWorks.IText; namespace SIL.FieldWorks.IText { diff --git a/Src/LexText/Interlinear/DuplicateWordformFixer.cs b/Src/LexText/Interlinear/DuplicateWordformFixer.cs index 699361e858..e995bbff00 100644 --- a/Src/LexText/Interlinear/DuplicateWordformFixer.cs +++ b/Src/LexText/Interlinear/DuplicateWordformFixer.cs @@ -1,14 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Text; using System.Windows.Forms; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.Infrastructure; +using SIL.FieldWorks.FdoUi; using SIL.FieldWorks.FwCoreDlgs; namespace SIL.FieldWorks.IText diff --git a/Src/LexText/Lexicon/HomographResetter.cs b/Src/LexText/Lexicon/HomographResetter.cs index b31ac37690..f1cb8ae327 100644 --- a/Src/LexText/Lexicon/HomographResetter.cs +++ b/Src/LexText/Lexicon/HomographResetter.cs @@ -1,8 +1,8 @@ using System.Diagnostics; using System.Linq; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.Infrastructure; +using SIL.FieldWorks.FdoUi; using SIL.FieldWorks.FwCoreDlgs; using System.Windows.Forms; diff --git a/Src/LexText/Lexicon/LexEntryInflTypeConverter.cs b/Src/LexText/Lexicon/LexEntryInflTypeConverter.cs index bf0267f6e3..6c16bc4c36 100644 --- a/Src/LexText/Lexicon/LexEntryInflTypeConverter.cs +++ b/Src/LexText/Lexicon/LexEntryInflTypeConverter.cs @@ -1,18 +1,15 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; -using System.Drawing; using System.Linq; using System.Windows.Forms; -using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.Common.Controls; using SIL.FieldWorks.Common.Framework.DetailControls; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; -using SIL.FieldWorks.FDO.Application; using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.FwCoreDlgs; using SIL.Utils; +using ProgressBarWrapper = SIL.FieldWorks.FdoUi.ProgressBarWrapper; namespace SIL.FieldWorks.XWorks.LexEd { @@ -206,7 +203,7 @@ public override void Process() protected override void Convert(IEnumerable itemsToChange) { - m_cache.LanguageProject.LexDbOA.ConvertLexEntryInflTypes(new SIL.FieldWorks.Common.FwUtils.ProgressBarWrapper(m_dlg.ProgressBar), itemsToChange); + m_cache.LanguageProject.LexDbOA.ConvertLexEntryInflTypes(new ProgressBarWrapper(m_dlg.ProgressBar), itemsToChange); } } @@ -258,7 +255,7 @@ public override void Process() protected override void Convert(IEnumerable itemsToChange) { - m_cache.LanguageProject.LexDbOA.ConvertLexEntryTypes(new SIL.FieldWorks.Common.FwUtils.ProgressBarWrapper(m_dlg.ProgressBar), itemsToChange); + m_cache.LanguageProject.LexDbOA.ConvertLexEntryTypes(new ProgressBarWrapper(m_dlg.ProgressBar), itemsToChange); } #endregion IUtility implementation diff --git a/Src/FdoUi/Dialogs/FWVersionTooOld.Designer.cs b/Src/MigrateSqlDbs/FWVersionTooOld.Designer.cs similarity index 98% rename from Src/FdoUi/Dialogs/FWVersionTooOld.Designer.cs rename to Src/MigrateSqlDbs/FWVersionTooOld.Designer.cs index 8ce85d1545..b00a292583 100644 --- a/Src/FdoUi/Dialogs/FWVersionTooOld.Designer.cs +++ b/Src/MigrateSqlDbs/FWVersionTooOld.Designer.cs @@ -13,7 +13,7 @@ // --------------------------------------------------------------------------------------------- using System.Diagnostics.CodeAnalysis; -namespace SIL.FieldWorks.FdoUi.Dialogs +namespace SIL.FieldWorks.MigrateSqlDbs.MigrateProjects { partial class FWVersionTooOld { diff --git a/Src/FdoUi/Dialogs/FWVersionTooOld.cs b/Src/MigrateSqlDbs/FWVersionTooOld.cs similarity index 97% rename from Src/FdoUi/Dialogs/FWVersionTooOld.cs rename to Src/MigrateSqlDbs/FWVersionTooOld.cs index 6f2044dd5f..a9cb118780 100644 --- a/Src/FdoUi/Dialogs/FWVersionTooOld.cs +++ b/Src/MigrateSqlDbs/FWVersionTooOld.cs @@ -15,7 +15,7 @@ using System.Diagnostics; using System.Windows.Forms; -namespace SIL.FieldWorks.FdoUi.Dialogs +namespace SIL.FieldWorks.MigrateSqlDbs.MigrateProjects { /// ---------------------------------------------------------------------------------------- /// diff --git a/Src/FdoUi/Dialogs/FWVersionTooOld.resx b/Src/MigrateSqlDbs/FWVersionTooOld.resx similarity index 100% rename from Src/FdoUi/Dialogs/FWVersionTooOld.resx rename to Src/MigrateSqlDbs/FWVersionTooOld.resx diff --git a/Src/MigrateSqlDbs/MigrateSqlDbs.csproj b/Src/MigrateSqlDbs/MigrateSqlDbs.csproj index 9600ce9159..c745516189 100644 --- a/Src/MigrateSqlDbs/MigrateSqlDbs.csproj +++ b/Src/MigrateSqlDbs/MigrateSqlDbs.csproj @@ -105,6 +105,12 @@ CommonAssemblyInfo.cs + + Form + + + FWVersionTooOld.cs + Form @@ -119,6 +125,10 @@ + + FWVersionTooOld.cs + Designer + MigrateProjects.cs Designer @@ -185,4 +195,4 @@ ../../DistFiles - + \ No newline at end of file diff --git a/Src/MigrateSqlDbs/Program.cs b/Src/MigrateSqlDbs/Program.cs index 53e844039a..600f8cb5c8 100644 --- a/Src/MigrateSqlDbs/Program.cs +++ b/Src/MigrateSqlDbs/Program.cs @@ -26,7 +26,6 @@ using Palaso.WritingSystems.Migration.WritingSystemsLdmlV0To1Migration; using SIL.FieldWorks.Common.Controls; using SIL.FieldWorks.Common.FwUtils; -using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices.DataMigration; using SIL.Utils; @@ -107,12 +106,21 @@ static int Main(string[] rgArgs) using (var progressDlg = new ProgressDialogWithTask(null, new ThreadHelper())) { - ImportFrom6_0 importer = new ImportFrom6_0(progressDlg, new SilentFdoUserAction(), s_fDebug); + ImportFrom6_0 importer = new ImportFrom6_0(progressDlg, s_fDebug); if (!importer.IsFwSqlServerInstalled()) return -1; string version; if (!importer.IsValidOldFwInstalled(out version)) + { + if (!String.IsNullOrEmpty(version) && version.CompareTo("5.4") < 0) + { + using (var dlg = new FWVersionTooOld(version)) + { + dlg.ShowDialog(); + } + } return -1; + } List projects = GetProjectList(); if (projects.Count > 0) { diff --git a/Src/Utilities/BasicUtils/BasicUtils.csproj b/Src/Utilities/BasicUtils/BasicUtils.csproj index 0c72340599..caa30a53c1 100644 --- a/Src/Utilities/BasicUtils/BasicUtils.csproj +++ b/Src/Utilities/BasicUtils/BasicUtils.csproj @@ -116,9 +116,6 @@ - - Form - @@ -150,10 +147,6 @@ ColorStrings.Designer.cs Designer - - FindFileStatusDialog.cs - Designer - Designer @@ -186,4 +179,4 @@ - + \ No newline at end of file diff --git a/Src/Utilities/BasicUtils/FindFileStatusDialog.cs b/Src/Utilities/BasicUtils/FindFileStatusDialog.cs deleted file mode 100644 index fea2810ae0..0000000000 --- a/Src/Utilities/BasicUtils/FindFileStatusDialog.cs +++ /dev/null @@ -1,149 +0,0 @@ -// -------------------------------------------------------------------------------------------- -#region // Copyright (c) 2009, SIL International. All Rights Reserved. -// -// Copyright (c) 2009, SIL International. All Rights Reserved. -// -// Distributable under the terms of either the Common Public License or the -// GNU Lesser General Public License, as specified in the LICENSING.txt file. -// -#endregion -// -// File: FindFileStatusDialog.cs -// Responsibility: DavidO -// -------------------------------------------------------------------------------------------- -using System.Windows.Forms; - -namespace SIL.Utils -{ - /// --------------------------------------------------------------------------------------- - /// - /// FindFileStatusDialog provides a dialog box for the FindFile method in DriveUtil. - /// It provides the caller of FindFile the means to display the current path being - /// searched during a file (or file pattern) search operation. It also provides a - /// means via the 'Cancel' button, for the end user to abort the search operation. - /// - /// --------------------------------------------------------------------------------------- - public class FindFileStatusDialog : System.Windows.Forms.Form - { - private System.Windows.Forms.Label lblSearching; - private System.Windows.Forms.Label lblCurrentFolder; - private System.Windows.Forms.Button btnCancel; - /// - /// Required designer variable. - /// - private System.ComponentModel.Container components = null; - - /// ----------------------------------------------------------------------------------- - /// - /// Constructor. - /// - /// ----------------------------------------------------------------------------------- - public FindFileStatusDialog() - { - // - // Required for Windows Form Designer support - // - InitializeComponent(); - - } - - /// ----------------------------------------------------------------------------------- - /// - /// Clean up any resources being used. - /// - /// ----------------------------------------------------------------------------------- - protected override void Dispose( bool disposing ) - { - System.Diagnostics.Debug.WriteLineIf(!disposing, "****** Missing Dispose() call for " + GetType().Name + ". ****** "); - // Must not be run more than once. - if (IsDisposed) - return; - - if( disposing ) - { - if(components != null) - { - components.Dispose(); - } - } - base.Dispose( disposing ); - } - - #region Windows Form Designer generated code - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FindFileStatusDialog)); - this.lblSearching = new System.Windows.Forms.Label(); - this.lblCurrentFolder = new System.Windows.Forms.Label(); - this.btnCancel = new System.Windows.Forms.Button(); - this.SuspendLayout(); - // - // lblSearching - // - resources.ApplyResources(this.lblSearching, "lblSearching"); - this.lblSearching.FlatStyle = System.Windows.Forms.FlatStyle.System; - this.lblSearching.Name = "lblSearching"; - // - // lblCurrentFolder - // - this.lblCurrentFolder.FlatStyle = System.Windows.Forms.FlatStyle.System; - resources.ApplyResources(this.lblCurrentFolder, "lblCurrentFolder"); - this.lblCurrentFolder.Name = "lblCurrentFolder"; - // - // btnCancel - // - this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; - resources.ApplyResources(this.btnCancel, "btnCancel"); - this.btnCancel.Name = "btnCancel"; - this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); - // - // FindFileStatusDialog - // - resources.ApplyResources(this, "$this"); - this.CancelButton = this.btnCancel; - this.Controls.Add(this.btnCancel); - this.Controls.Add(this.lblSearching); - this.Controls.Add(this.lblCurrentFolder); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "FindFileStatusDialog"; - this.ShowInTaskbar = false; - this.ResumeLayout(false); - this.PerformLayout(); - - } - #endregion - - /// ----------------------------------------------------------------------------------- - /// - /// Handles the Cancel button's click event. - /// - /// ----------------------------------------------------------------------------------- - private void btnCancel_Click(object sender, System.EventArgs e) - { - this.DialogResult = DialogResult.Cancel; - this.Close(); - } - - /// ----------------------------------------------------------------------------------- - /// - /// Gets or sets the file name and it's path that's displayed in the dialog. - /// - /// - /// ----------------------------------------------------------------------------------- - public string FullFileName - { - get {return lblCurrentFolder.Text;} - set - { - if (lblCurrentFolder.Text != value) - lblCurrentFolder.Text = value; - } - } - } -} diff --git a/Src/Utilities/BasicUtils/FindFileStatusDialog.resx b/Src/Utilities/BasicUtils/FindFileStatusDialog.resx deleted file mode 100644 index d917d56661..0000000000 --- a/Src/Utilities/BasicUtils/FindFileStatusDialog.resx +++ /dev/null @@ -1,234 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - True - - - - NoControl - - - - 16, 16 - - - 90, 13 - - - 0 - - - Searching Folder: - - - lblSearching - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 1 - - - NoControl - - - 16, 40 - - - 353, 47 - - - 1 - - - # - - - lblCurrentFolder - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 2 - - - System - - - NoControl - - - 310, 93 - - - 65, 25 - - - 29 - - - Cancel - - - btnCancel - - - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 0 - - - True - - - 5, 13 - - - 381, 124 - - - NoControl - - - CenterParent - - - Searching... - - - FindFileStatusDialog - - - System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/Src/Utilities/XMLUtils/XMLUtils.csproj b/Src/Utilities/XMLUtils/XMLUtils.csproj index 88aef93d0b..2e80695765 100644 --- a/Src/Utilities/XMLUtils/XMLUtils.csproj +++ b/Src/Utilities/XMLUtils/XMLUtils.csproj @@ -132,9 +132,6 @@ Code - - Code - Code diff --git a/Src/Utilities/XMLUtils/ImageCollection.cs b/Src/XCore/ImageCollection.cs similarity index 97% rename from Src/Utilities/XMLUtils/ImageCollection.cs rename to Src/XCore/ImageCollection.cs index e6be7b4305..5876f86a2e 100644 --- a/Src/Utilities/XMLUtils/ImageCollection.cs +++ b/Src/XCore/ImageCollection.cs @@ -17,18 +17,16 @@ // -------------------------------------------------------------------------------------------- using System; using System.Drawing; -using System.Collections; -using System.ComponentModel; +using System.IO; +using System.Reflection; using System.Windows.Forms; -using System.Diagnostics; using System.Xml; -using System.Reflection; -using System.IO; +using SIL.Utils; -namespace SIL.Utils +namespace XCore { /// - public class ImageCollection: IDisposable + public class ImageCollection: IImageCollection { protected ImageList m_images; protected System.Collections.Specialized.StringCollection m_labels; diff --git a/Src/XCore/PaneBarContainer.cs b/Src/XCore/PaneBarContainer.cs index db15e154e2..39be195b5d 100644 --- a/Src/XCore/PaneBarContainer.cs +++ b/Src/XCore/PaneBarContainer.cs @@ -133,7 +133,7 @@ public void Init(Mediator mediator, XmlNode configurationParameters) if (groupId != null) { XWindow window = (XWindow)m_mediator.PropertyTable.GetValue("window"); - SIL.Utils.ImageCollection small = (SIL.Utils.ImageCollection)m_mediator.PropertyTable.GetValue("smallImages"); + ImageCollection small = (ImageCollection)m_mediator.PropertyTable.GetValue("smallImages"); paneBar.Init(small, (IUIMenuAdapter)window.MenuAdapter, m_mediator); } ReloadPaneBar(paneBar); diff --git a/Src/XCore/XCoreAdapterSilSidePane/AdapterBase.cs b/Src/XCore/XCoreAdapterSilSidePane/AdapterBase.cs index 73ae6370d3..147033bc51 100644 --- a/Src/XCore/XCoreAdapterSilSidePane/AdapterBase.cs +++ b/Src/XCore/XCoreAdapterSilSidePane/AdapterBase.cs @@ -47,11 +47,11 @@ public abstract class AdapterBase : IUIAdapter /// /// Collection of small images. /// - protected ImageCollection m_smallImages; + protected IImageCollection m_smallImages; /// /// Collection of large images. /// - protected ImageCollection m_largeImages; + protected IImageCollection m_largeImages; /// /// The subclass specific main control that is given back to the adapter library client. /// @@ -130,7 +130,7 @@ public AdapterBase() /// XCore Mediator. /// A Control for use by client. public virtual System.Windows.Forms.Control Init(System.Windows.Forms.Form window, - ImageCollection smallImages, ImageCollection largeImages, Mediator mediator) + IImageCollection smallImages, IImageCollection largeImages, Mediator mediator) { m_window = window; m_smallImages = smallImages; diff --git a/Src/XCore/XCoreAdapterSilSidePane/PaneBar.cs b/Src/XCore/XCoreAdapterSilSidePane/PaneBar.cs index 9978fc889b..bad757f664 100644 --- a/Src/XCore/XCoreAdapterSilSidePane/PaneBar.cs +++ b/Src/XCore/XCoreAdapterSilSidePane/PaneBar.cs @@ -98,7 +98,7 @@ protected override void OnPaint (PaintEventArgs e) /// public class PaneBar : System.Windows.Forms.UserControl, IPaneBar, IxCoreColleague { - private ImageCollection m_smallImages; + private IImageCollection m_smallImages; private IUIMenuAdapter m_menuBarAdapter; @@ -261,7 +261,7 @@ public void Init (Mediator mediator, System.Xml.XmlNode config) /// /// /// - public void Init (ImageCollection smallImages, IUIMenuAdapter menuBarAdapter, Mediator mediator) + public void Init (IImageCollection smallImages, IUIMenuAdapter menuBarAdapter, Mediator mediator) { m_mediator = mediator; mediator.AddColleague(this); diff --git a/Src/XCore/XCoreAdapterSilSidePane/PanelButton.cs b/Src/XCore/XCoreAdapterSilSidePane/PanelButton.cs index 34347e9b57..68dbacf190 100644 --- a/Src/XCore/XCoreAdapterSilSidePane/PanelButton.cs +++ b/Src/XCore/XCoreAdapterSilSidePane/PanelButton.cs @@ -9,10 +9,10 @@ namespace XCore class PanelButton : PanelEx { - private ImageCollection m_images; + private IImageCollection m_images; private bool mouseOverControl = false; - public PanelButton(XCore.ChoiceBase choice, ImageCollection images):base() + public PanelButton(XCore.ChoiceBase choice, IImageCollection images):base() { m_images = images; diff --git a/Src/XCore/XCoreAdapterSilSidePane/PanelMenu.cs b/Src/XCore/XCoreAdapterSilSidePane/PanelMenu.cs index 3b3f27a744..f2d2530132 100644 --- a/Src/XCore/XCoreAdapterSilSidePane/PanelMenu.cs +++ b/Src/XCore/XCoreAdapterSilSidePane/PanelMenu.cs @@ -10,12 +10,12 @@ namespace XCore class PanelMenu : PanelEx { - private ImageCollection m_images; + private IImageCollection m_images; private IUIMenuAdapter m_menuBarAdapter; private XCore.ChoiceGroup m_group; - public PanelMenu(XCore.ChoiceGroup group, ImageCollection images, XCore.IUIMenuAdapter menuBarAdapter):base() + public PanelMenu(XCore.ChoiceGroup group, IImageCollection images, XCore.IUIMenuAdapter menuBarAdapter):base() { m_group = group; m_images = images; diff --git a/Src/XCore/xCore.csproj b/Src/XCore/xCore.csproj index 48a502c599..8d92c59680 100644 --- a/Src/XCore/xCore.csproj +++ b/Src/XCore/xCore.csproj @@ -1,4 +1,4 @@ - + Local @@ -145,14 +145,14 @@ \usr\lib\cli\geckofx-14.0.1\geckofx-core-14.dll - + \usr\lib\cli\geckofx-14.0.1\Geckofx-Winforms-14.dll - + PreserveNewest - + CommonAssemblyInfo.cs @@ -176,6 +176,7 @@ UserControl + UserControl diff --git a/Src/XCore/xCoreInterfaces/IImageCollection.cs b/Src/XCore/xCoreInterfaces/IImageCollection.cs new file mode 100644 index 0000000000..fb4177615f --- /dev/null +++ b/Src/XCore/xCoreInterfaces/IImageCollection.cs @@ -0,0 +1,32 @@ +using System; +using System.Drawing; +using System.Windows.Forms; +using System.Xml; + +namespace XCore +{ + public interface IImageCollection : IDisposable + { + /// + bool IsDisposed { get; } + + /// + ImageList ImageList { get; } + + /// + /// append the images in this list to our ImageList + /// + /// the ImageList to append + /// the labels, in order, for each imaging the list + void AddList (ImageList list, string[] labels); + + /// + Image GetImage(string label); + + /// + int GetImageIndex(string label); + + /// + void AddList(XmlNodeList nodes); + } +} \ No newline at end of file diff --git a/Src/XCore/xCoreInterfaces/IPaneBar.cs b/Src/XCore/xCoreInterfaces/IPaneBar.cs index 379ccfd9e4..2e190bea04 100644 --- a/Src/XCore/xCoreInterfaces/IPaneBar.cs +++ b/Src/XCore/xCoreInterfaces/IPaneBar.cs @@ -7,7 +7,7 @@ string Text set; } - void Init (SIL.Utils.ImageCollection smallImages, IUIMenuAdapter menuBarAdapter, Mediator mediator); + void Init (IImageCollection smallImages, IUIMenuAdapter menuBarAdapter, Mediator mediator); void RefreshPane(); diff --git a/Src/XCore/xCoreInterfaces/IUIAdapter.cs b/Src/XCore/xCoreInterfaces/IUIAdapter.cs index 8304e5ef76..581ffa0139 100644 --- a/Src/XCore/xCoreInterfaces/IUIAdapter.cs +++ b/Src/XCore/xCoreInterfaces/IUIAdapter.cs @@ -14,7 +14,6 @@ // -------------------------------------------------------------------------------------------- using System.Diagnostics.CodeAnalysis; -using System.Xml; using System.Drawing; using System.Windows.Forms; //for ImageList using System.Reflection; @@ -26,8 +25,8 @@ namespace XCore { public interface IUIAdapter { - Control Init(System.Windows.Forms.Form window, ImageCollection smallImages, - ImageCollection largeImages, Mediator mediator); + Control Init(System.Windows.Forms.Form window, IImageCollection smallImages, + IImageCollection largeImages, Mediator mediator); void CreateUIForChoiceGroupCollection(ChoiceGroupCollection groupCollection); void CreateUIForChoiceGroup(ChoiceGroup group); void OnIdle(); diff --git a/Src/XCore/xCoreInterfaces/xCoreInterfaces.csproj b/Src/XCore/xCoreInterfaces/xCoreInterfaces.csproj index b356099c14..3b3e96e5c7 100644 --- a/Src/XCore/xCoreInterfaces/xCoreInterfaces.csproj +++ b/Src/XCore/xCoreInterfaces/xCoreInterfaces.csproj @@ -1,4 +1,4 @@ - + Local @@ -138,6 +138,7 @@ + Code diff --git a/Src/XCore/xCoreOpenSourceAdapter/CommandBarAdaptor.cs b/Src/XCore/xCoreOpenSourceAdapter/CommandBarAdaptor.cs index e497c7647d..beb877e12a 100644 --- a/Src/XCore/xCoreOpenSourceAdapter/CommandBarAdaptor.cs +++ b/Src/XCore/xCoreOpenSourceAdapter/CommandBarAdaptor.cs @@ -9,8 +9,8 @@ namespace XCore public abstract class CommandBarAdaptor: IDisposable { protected Form m_window; - protected ImageCollection m_smallImages; - protected ImageCollection m_largeImages; + protected IImageCollection m_smallImages; + protected IImageCollection m_largeImages; protected CommandBarManager m_commandBarManager = new CommandBarManager(); public CommandBarAdaptor() diff --git a/Src/XCore/xCoreOpenSourceAdapter/PaneBar.cs b/Src/XCore/xCoreOpenSourceAdapter/PaneBar.cs index 48ad6407d6..b055b81330 100644 --- a/Src/XCore/xCoreOpenSourceAdapter/PaneBar.cs +++ b/Src/XCore/xCoreOpenSourceAdapter/PaneBar.cs @@ -46,7 +46,7 @@ public void RefreshPane() /// /// /// - public void Init (SIL.Utils.ImageCollection smallImages, IUIMenuAdapter menuBarAdapter, Mediator mediator) + public void Init (IImageCollection smallImages, IUIMenuAdapter menuBarAdapter, Mediator mediator) { } diff --git a/Src/XCore/xCoreOpenSourceAdapter/ReBarAdapter.cs b/Src/XCore/xCoreOpenSourceAdapter/ReBarAdapter.cs index bb904cf289..c84b070578 100644 --- a/Src/XCore/xCoreOpenSourceAdapter/ReBarAdapter.cs +++ b/Src/XCore/xCoreOpenSourceAdapter/ReBarAdapter.cs @@ -38,7 +38,7 @@ public ReBarAdapter() { } - public System.Windows.Forms.Control Init (System.Windows.Forms.Form window, ImageCollection smallImages, ImageCollection largeImages, Mediator mediator) + public System.Windows.Forms.Control Init (System.Windows.Forms.Form window, IImageCollection smallImages, IImageCollection largeImages, Mediator mediator) { m_window = window; m_smallImages = smallImages; m_largeImages = largeImages; diff --git a/Src/XCore/xCoreOpenSourceAdapter/RebarMenuAdapter.cs b/Src/XCore/xCoreOpenSourceAdapter/RebarMenuAdapter.cs index ce1701c001..384a9032d5 100644 --- a/Src/XCore/xCoreOpenSourceAdapter/RebarMenuAdapter.cs +++ b/Src/XCore/xCoreOpenSourceAdapter/RebarMenuAdapter.cs @@ -55,7 +55,7 @@ protected override void Dispose(bool fDisposing) base.Dispose(fDisposing); } - public System.Windows.Forms.Control Init (System.Windows.Forms.Form window, ImageCollection smallImages, ImageCollection largeImages, Mediator mediator) + public System.Windows.Forms.Control Init (System.Windows.Forms.Form window, IImageCollection smallImages, IImageCollection largeImages, Mediator mediator) { m_window = window; m_smallImages = smallImages; diff --git a/Src/XCore/xCoreOpenSourceAdapter/SidebarAdapter.cs b/Src/XCore/xCoreOpenSourceAdapter/SidebarAdapter.cs index 65732a7a0f..d2d76c95ac 100644 --- a/Src/XCore/xCoreOpenSourceAdapter/SidebarAdapter.cs +++ b/Src/XCore/xCoreOpenSourceAdapter/SidebarAdapter.cs @@ -36,8 +36,8 @@ namespace XCore /// public class SidebarAdapter: IUIAdapter, IDisposable { - protected ImageCollection m_smallImages; - protected ImageCollection m_largeImages; + protected IImageCollection m_smallImages; + protected IImageCollection m_largeImages; protected OutlookBar m_bar; protected Mediator m_mediator; @@ -139,7 +139,7 @@ public void PropertyChanged(OutlookBarBand band, OutlookBarProperty property) } } - public System.Windows.Forms.Control Init(System.Windows.Forms.Form window, ImageCollection smallImages, ImageCollection largeImages, Mediator mediator) + public System.Windows.Forms.Control Init(System.Windows.Forms.Form window, IImageCollection smallImages, IImageCollection largeImages, Mediator mediator) { m_mediator = mediator; m_smallImages= smallImages; From e8e0a4b2c74af7f1874c459c576fa2f4f7168729 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Tue, 3 Dec 2013 10:08:23 +0700 Subject: [PATCH 009/143] Move more UI elements out of FDO and its references Move ErrorReport calls behind the IFdoUserAction interface. Change-Id: I05504a56c1394f0d70201476a04b90f3d925e249 --- .../FwUtilsTests/DummyFdoUserAction.cs | 35 +++++++++++++++++++ Src/Common/FwUtils/IFdoUserAction.cs | 19 ++++++++++ .../DataMigration/ImportFrom6_0.cs | 28 +++++++-------- .../DataStoreInitializationServices.cs | 3 +- .../DomainServices/DomainObjectServices.cs | 34 +++--------------- Src/FDO/FDOTests/FdoScriptureTests.cs | 20 +++-------- .../Infrastructure/Impl/CmObjectSurrogate.cs | 3 +- .../Infrastructure/Impl/XMLBackendProvider.cs | 2 +- Src/FDO/SilentFdoUserAction.cs | 25 +++++++++++++ Src/FDOBrowser/FdoBrowserUserAction.cs | 26 ++++++++++++++ Src/FdoUi/FdoUi.csproj | 7 +++- Src/FdoUi/FdoUserActionWindowsForms.cs | 27 ++++++++++++++ 12 files changed, 166 insertions(+), 63 deletions(-) diff --git a/Src/Common/FwUtils/FwUtilsTests/DummyFdoUserAction.cs b/Src/Common/FwUtils/FwUtilsTests/DummyFdoUserAction.cs index 66f00c5abb..ebd0f55a13 100644 --- a/Src/Common/FwUtils/FwUtilsTests/DummyFdoUserAction.cs +++ b/Src/Common/FwUtils/FwUtilsTests/DummyFdoUserAction.cs @@ -12,6 +12,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using Microsoft.Win32; namespace SIL.FieldWorks.Common.FwUtils { @@ -20,6 +21,14 @@ namespace SIL.FieldWorks.Common.FwUtils /// public class DummyFdoUserAction : IFdoUserAction { + /// + /// Gets the error message. + /// + /// + /// The error message. + /// + public string ErrorMessage { get; private set; } + /// /// Check with user regarding conflicting changes /// @@ -73,5 +82,31 @@ public void MessageBox() { throw new NotImplementedException(); } + + /// + /// Show a dialog or output to the error log, as appropriate. + /// + /// the exception you want to report + /// set to true if the error is lethal, otherwise + /// false. + /// True if the error was lethal and the user chose to exit the application, + /// false otherwise. + public bool ReportException(Exception error, bool isLethal) + { + // Store the message so we can check it later + ErrorMessage = error.Message; + return isLethal; + } + + /// + /// Reports duplicate guids to the user + /// + /// The application key. + /// The email address. + /// The error text. + public void ReportDuplicateGuids(RegistryKey applicationKey, string emailAddress, string errorText) + { + throw new NotImplementedException(); + } } } diff --git a/Src/Common/FwUtils/IFdoUserAction.cs b/Src/Common/FwUtils/IFdoUserAction.cs index a01bfe9bb0..7201430320 100644 --- a/Src/Common/FwUtils/IFdoUserAction.cs +++ b/Src/Common/FwUtils/IFdoUserAction.cs @@ -12,6 +12,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using Microsoft.Win32; namespace SIL.FieldWorks.Common.FwUtils { @@ -55,6 +56,24 @@ public interface IFdoUserAction /// Displays information to the user /// void MessageBox(); + + /// + /// Show a dialog or output to the error log, as appropriate. + /// + /// the exception you want to report + /// set to true if the error is lethal, otherwise + /// false. + /// True if the error was lethal and the user chose to exit the application, + /// false otherwise. + bool ReportException(Exception error, bool isLethal); + + /// + /// Reports duplicate guids to the user + /// + /// The application key. + /// The email address. + /// The error text. + void ReportDuplicateGuids(RegistryKey applicationKey, string emailAddress, string errorText); } /// diff --git a/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs b/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs index c3791ed6a9..5f401651d8 100644 --- a/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs +++ b/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs @@ -257,7 +257,7 @@ public bool IsFwSqlServerInstalled() catch (Exception) { if (m_fVerboseDebug) - MessageBoxUtils.Show("The FieldWorks installation of SQL Server (MSSQL$SILFW) does not exist.", + Debug.WriteLine("The FieldWorks installation of SQL Server (MSSQL$SILFW) does not exist.", "DEBUG!"); return false; // The FieldWorks installation of SQL Server isn't available } @@ -282,7 +282,7 @@ public bool IsValidOldFwInstalled(out string version) if (clsidKey == null) { if (m_fVerboseDebug) - MessageBoxUtils.Show("Unable to open the CLSID registry subkey????", "DEBUG!"); + Debug.WriteLine("Unable to open the CLSID registry subkey????"); return false; } // check for registered class id for FwXmlData. @@ -290,7 +290,7 @@ public bool IsValidOldFwInstalled(out string version) if (cellarPath == null) { if (m_fVerboseDebug) - MessageBoxUtils.Show("FwCellar.dll is not registered.", "DEBUG!"); + Debug.WriteLine("FwCellar.dll is not registered.", "DEBUG!"); return false; } // check for registered class id for MigrateData. @@ -298,7 +298,7 @@ public bool IsValidOldFwInstalled(out string version) if (migratePath == null) { if (m_fVerboseDebug) - MessageBoxUtils.Show("MigrateData.dll is not registered.", "DEBUG!"); + Debug.WriteLine("MigrateData.dll is not registered.", "DEBUG!"); return false; } // check for registered class id for LgWritingSystemFactory. @@ -306,7 +306,7 @@ public bool IsValidOldFwInstalled(out string version) if (languagePath == null) { if (m_fVerboseDebug) - MessageBoxUtils.Show("Language.dll is not registered.", "DEBUG!"); + Debug.WriteLine("Language.dll is not registered.", "DEBUG!"); return false; } // check for registered class id for TsStrFactory. @@ -314,7 +314,7 @@ public bool IsValidOldFwInstalled(out string version) if (kernelPath == null) { if (m_fVerboseDebug) - MessageBoxUtils.Show("FwKernel.dll is not registered.", "DEBUG!"); + Debug.WriteLine("FwKernel.dll is not registered.", "DEBUG!"); return false; } // check for registered class id for OleDbEncap. @@ -322,7 +322,7 @@ public bool IsValidOldFwInstalled(out string version) if (dbaccessPath == null) { if (m_fVerboseDebug) - MessageBoxUtils.Show("DbAccess.dll is not registered.", "DEBUG!"); + Debug.WriteLine("DbAccess.dll is not registered.", "DEBUG!"); return false; } // Get (and save) the path to dumpxml.exe. @@ -340,7 +340,7 @@ public bool IsValidOldFwInstalled(out string version) if (!File.Exists(m_dumpxmlPath)) { if (m_fVerboseDebug) - MessageBoxUtils.Show("Cannot find dumpxml.exe in the old FieldWorks installation.", "DEBUG!"); + Debug.WriteLine("Cannot find dumpxml.exe in the old FieldWorks installation.", "DEBUG!"); return false; } } @@ -355,7 +355,7 @@ public bool IsValidOldFwInstalled(out string version) if (!File.Exists(scriptPath)) { if (m_fVerboseDebug) - MessageBoxUtils.Show("Cannot find DataMigration\\200259To200260.sql in the old FieldWorks installation.", "DEBUG!"); + Debug.WriteLine("Cannot find DataMigration\\200259To200260.sql in the old FieldWorks installation.", "DEBUG!"); return false; } } @@ -363,7 +363,7 @@ public bool IsValidOldFwInstalled(out string version) if (!File.Exists(m_dbPath)) { if (m_fVerboseDebug) - MessageBoxUtils.Show("Cannot find MSSQLMigration\\db.exe in the FieldWorks 7.0 or later installation.", "DEBUG!"); + Debug.WriteLine("Cannot find MSSQLMigration\\db.exe in the FieldWorks 7.0 or later installation.", "DEBUG!"); return false; } return true; @@ -376,7 +376,7 @@ public bool IsValidOldFwInstalled(out string version) string msg = String.Format( "An exception was thrown while checking for an old version of FieldWorks:{1}{0}", e.Message, Environment.NewLine); - MessageBoxUtils.Show(msg, "DEBUG!"); + Debug.WriteLine(msg, "DEBUG!"); } } return false; @@ -398,7 +398,7 @@ private string FindComDllIfRegistered(RegistryKey clsidKey, string sClsid, ref s if (m_fVerboseDebug) { string msg = String.Format("Nonexistent file for a registered COM DLL: {0}", dllPath); - MessageBox.Show(msg, "DEBUG!"); + Debug.WriteLine(msg, "DEBUG!"); } return null; } @@ -414,7 +414,7 @@ private string FindComDllIfRegistered(RegistryKey clsidKey, string sClsid, ref s { string msg = String.Format("Multiple versions found in the registered COM DLLs: {0} and {1} [{2}]", version, fileVersion, dllPath); - MessageBoxUtils.Show(msg, "DEBUG!"); + Debug.WriteLine(msg, "DEBUG!"); } return null; // don't want a mix of versions!! } @@ -443,7 +443,7 @@ private string FindComDllIfRegistered(RegistryKey clsidKey, string sClsid, ref s { string msg = String.Format("Invalid version found in a registered COM DLL: {0} [{1}]", version, dllPath); - MessageBox.Show(msg, "DEBUG!"); + Debug.WriteLine(msg, "DEBUG!"); } return null; } diff --git a/Src/FDO/DomainServices/DataStoreInitializationServices.cs b/Src/FDO/DomainServices/DataStoreInitializationServices.cs index c96eb52c41..ddd4df8fc7 100644 --- a/Src/FDO/DomainServices/DataStoreInitializationServices.cs +++ b/Src/FDO/DomainServices/DataStoreInitializationServices.cs @@ -17,6 +17,7 @@ using System.Linq; using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainImpl; using SIL.Utils; using SILUBS.SharedScrUtils; @@ -385,7 +386,7 @@ private static void FixSegmentsForScriptureParas(FdoCache cache) if (hadError) { // Tell the user that something bad happened - ErrorReporter.ReportException(new Exception("Error during resegmentation"), null, null, null, false); + cache.ServiceLocator.GetInstance().ReportException(new Exception("Error during resegmentation"), false); } } diff --git a/Src/FDO/DomainServices/DomainObjectServices.cs b/Src/FDO/DomainServices/DomainObjectServices.cs index a1a1194456..1ed7984857 100644 --- a/Src/FDO/DomainServices/DomainObjectServices.cs +++ b/Src/FDO/DomainServices/DomainObjectServices.cs @@ -36,36 +36,9 @@ public static class ScriptureServices { /// Book marker public static readonly string kMarkerBook = @"\id"; - /// Delegate to report a non-fatal "warning" message - private static Action ReportWarning; internal const char kKeyTokenSeparator = '\uffff'; - /// ------------------------------------------------------------------------------------ - /// - /// Initializes the class. - /// - /// ------------------------------------------------------------------------------------ - static ScriptureServices() - { - InitializeWarningHandler(); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Initializes the delegate for reporting warnings. - /// - /// This needs to be a separate method because it is called by reflection in - /// test(s). - /// ------------------------------------------------------------------------------------ - private static void InitializeWarningHandler() - { - ReportWarning = sMsg => - { - ErrorReporter.ReportException(new Exception(sMsg), null, null, null, false); - }; - } - /// ------------------------------------------------------------------------------------ /// /// Creates the import source key for a hashtable. @@ -459,7 +432,8 @@ internal static void AdjustObjectsInArchivedBook(IScrBook book, IScrBook archive ITsTextProps ttp; ITsPropsBldr propsBldr; int iFootnote = 0; - var pictureRepo = book.Cache.ServiceLocator.GetInstance(); + IFdoServiceLocator serviceLocator = book.Cache.ServiceLocator; + var pictureRepo = serviceLocator.GetInstance(); foreach (IScrTxtPara revPara in archivedBook.Paragraphs) { //TODO: TE-5082 Duplicate code! The following should call or use common code with @@ -504,7 +478,7 @@ internal static void AdjustObjectsInArchivedBook(IScrBook book, IScrBook archive BCVRef.MakeReferenceString(startRef, endRef, ":", "-") + " with guid " + guid + " does not have a corresponding footnote object owned by " + book.BookId + " or refers to a footnote that is owned by another ORC that occurs earlier."; - ReportWarning(sMsg); + serviceLocator.GetInstance().ReportException(new Exception(sMsg), false); break; } Logger.WriteEvent("Footnotes out of order in " + book.BookId + ". Expected footnote with guid " + guid + @@ -558,7 +532,7 @@ internal static void AdjustObjectsInArchivedBook(IScrBook book, IScrBook archive { string sMsg = (archivedBook.FootnotesOS.Count - iFootnote) + " footnote(s) in " + book.BookId + " did not correspond to any owned footnotes in the vernacular text of that book. They have been moved to the end of the footnote sequence."; - ReportWarning(sMsg); + serviceLocator.GetInstance().ReportException(new Exception(sMsg), false); } } diff --git a/Src/FDO/FDOTests/FdoScriptureTests.cs b/Src/FDO/FDOTests/FdoScriptureTests.cs index d470fba207..f5fb39648e 100644 --- a/Src/FDO/FDOTests/FdoScriptureTests.cs +++ b/Src/FDO/FDOTests/FdoScriptureTests.cs @@ -18,6 +18,7 @@ using NUnit.Framework; using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Common.ScriptureUtils; using SIL.Utils; using SIL.FieldWorks.Test.TestUtils; @@ -315,19 +316,6 @@ public override void TestSetup() m_servloc = Cache.ServiceLocator; } - /// ------------------------------------------------------------------------------------ - /// - /// Override to end the undoable UOW, Undo everything, and 'commit', - /// which will essentially clear out the Redo stack. - /// - /// ------------------------------------------------------------------------------------ - public override void TestTearDown() - { - base.TestTearDown(); - - ReflectionHelper.CallMethod(typeof(ScriptureServices), "InitializeWarningHandler"); - } - /// ------------------------------------------------------------------------------------ /// /// Does setup for all the tests @@ -2553,8 +2541,6 @@ public void SavedVersion_BogusUnownedFootnoteORC() IScrFootnote footnoteOrig2 = AddFootnote(hebrews, para2, 0); // archive draft - string sWarningMessage = null; - ReflectionHelper.SetAction(typeof(ScriptureServices), "ReportWarning", sMsg => { sWarningMessage = sMsg; }); IScrDraft draft = m_servloc.GetInstance().Create("", new [] { hebrews }); Assert.AreEqual(1, m_scr.ArchivedDraftsOC.Count); @@ -2600,6 +2586,10 @@ public void SavedVersion_BogusUnownedFootnoteORC() string sOrc = tss.get_RunText(0); Assert.AreEqual(StringUtils.kChObject, sOrc[0]); + // Expecting error to have been thrown in ScriptureServices.AdjustObjectsInArchivedBook, so now we make sure the error is the one expected. + var userAction = Cache.ServiceLocator.GetInstance(); + Assert.IsTrue(userAction is DummyFdoUserAction); + string sWarningMessage = ((DummyFdoUserAction)userAction).ErrorMessage; Assert.AreEqual("1 footnote(s) in HEB did not correspond to any owned footnotes in the vernacular text of that book. They have been moved to the end of the footnote sequence.", sWarningMessage); } diff --git a/Src/FDO/Infrastructure/Impl/CmObjectSurrogate.cs b/Src/FDO/Infrastructure/Impl/CmObjectSurrogate.cs index c056303c89..22809020f9 100644 --- a/Src/FDO/Infrastructure/Impl/CmObjectSurrogate.cs +++ b/Src/FDO/Infrastructure/Impl/CmObjectSurrogate.cs @@ -9,6 +9,7 @@ using System.Text; using System.Windows.Forms; using System.Xml.Linq; +using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; using System.Threading; @@ -551,7 +552,7 @@ ICmObject ICmObjectOrSurrogate.Object m_cache.ThreadHelper.Invoke(() => { MessageBox.Show(null, msg, Strings.ksErrorCaption, MessageBoxButtons.OK, MessageBoxIcon.Error); - ErrorReporter.ReportException(new Exception(fullMsg, e), null, null, null, true); + m_cache.ServiceLocator.GetInstance().ReportException(new Exception(fullMsg, e), true); }); } return m_object; diff --git a/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs b/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs index e625c3a366..5269c8ab11 100644 --- a/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs @@ -305,7 +305,7 @@ internal virtual void ReportDuplicateGuidsIfTheyExist() sb.AppendLine(String.Format(Strings.ksDuplicateGuidsMsg2, guid)); sb.AppendLine(); } - ErrorReporter.ReportDuplicateGuids(FwRegistryHelper.FieldWorksRegistryKey, "FLExErrors@sil.org", null, sb.ToString()); + m_cache.ServiceLocator.GetInstance().ReportDuplicateGuids(FwRegistryHelper.FieldWorksRegistryKey, "FLExErrors@sil.org", sb.ToString()); } } diff --git a/Src/FDO/SilentFdoUserAction.cs b/Src/FDO/SilentFdoUserAction.cs index c7162e32fc..3eee9519e6 100644 --- a/Src/FDO/SilentFdoUserAction.cs +++ b/Src/FDO/SilentFdoUserAction.cs @@ -12,6 +12,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using Microsoft.Win32; using SIL.FieldWorks.Common.FwUtils; namespace SIL.FieldWorks.FDO @@ -80,5 +81,29 @@ public void MessageBox() { // Informational only } + + /// + /// Show a dialog or output to the error log, as appropriate. + /// + /// the exception you want to report + /// set to true if the error is lethal, otherwise + /// false. + /// True if the error was lethal and the user chose to exit the application, + /// false otherwise. + public bool ReportException(Exception error, bool isLethal) + { + return isLethal; + } + + /// + /// Reports duplicate guids to the user + /// + /// The application key. + /// The email address. + /// The error text. + public void ReportDuplicateGuids(RegistryKey applicationKey, string emailAddress, string errorText) + { + // Informational only + } } } diff --git a/Src/FDOBrowser/FdoBrowserUserAction.cs b/Src/FDOBrowser/FdoBrowserUserAction.cs index 913277df85..0c05e83eb2 100644 --- a/Src/FDOBrowser/FdoBrowserUserAction.cs +++ b/Src/FDOBrowser/FdoBrowserUserAction.cs @@ -10,6 +10,7 @@ // --------------------------------------------------------------------------------------------- using System; using System.Windows.Forms; +using Microsoft.Win32; using SIL.FieldWorks.Common.FwUtils; namespace FDOBrowser @@ -88,5 +89,30 @@ public void MessageBox() { throw new NotImplementedException(); } + + /// + /// Show a dialog or output to the error log, as appropriate. + /// + /// the exception you want to report + /// set to true if the error is lethal, otherwise + /// false. + /// True if the error was lethal and the user chose to exit the application, + /// false otherwise. + public bool ReportException(Exception error, bool isLethal) + { + DialogResult dialogResult = System.Windows.Forms.MessageBox.Show("Close application? Error: " + error.Message, "Application Error", MessageBoxButtons.YesNo); + return dialogResult == DialogResult.Yes; + } + + /// + /// Reports duplicate guids to the user + /// + /// The application key. + /// The email address. + /// The error text. + public void ReportDuplicateGuids(RegistryKey applicationKey, string emailAddress, string errorText) + { + System.Windows.Forms.MessageBox.Show(errorText, "Duplicate Guids"); + } } } diff --git a/Src/FdoUi/FdoUi.csproj b/Src/FdoUi/FdoUi.csproj index f30f02edab..b5e4b0b1f9 100644 --- a/Src/FdoUi/FdoUi.csproj +++ b/Src/FdoUi/FdoUi.csproj @@ -372,5 +372,10 @@ - + + + {9CCBECEC-513C-4DA4-A4CE-F5361B633760} + Reporting + + \ No newline at end of file diff --git a/Src/FdoUi/FdoUserActionWindowsForms.cs b/Src/FdoUi/FdoUserActionWindowsForms.cs index 172d88f698..f1a3b0115c 100644 --- a/Src/FdoUi/FdoUserActionWindowsForms.cs +++ b/Src/FdoUi/FdoUserActionWindowsForms.cs @@ -8,10 +8,13 @@ // #endregion // --------------------------------------------------------------------------------------------- +using System; using System.Windows.Forms; +using Microsoft.Win32; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.BackupRestore; using SIL.FieldWorks.FdoUi.Dialogs; +using SIL.Utils; using XCore; namespace SIL.FieldWorks.FdoUi @@ -119,5 +122,29 @@ public void MessageBox() { //System.Windows.Forms.MessageBox.Show(); } + + /// + /// show a dialog or output to the error log, as appropriate. + /// + /// the exception you want to report + /// set to true if the error is lethal, otherwise + /// false. + /// True if the error was lethal and the user chose to exit the application, + /// false otherwise. + public bool ReportException(Exception error, bool isLethal) + { + return ErrorReporter.ReportException(error, null, null, null, isLethal); + } + + /// + /// Reports duplicate guids to the user + /// + /// The application key. + /// The email address. + /// The error text. + public void ReportDuplicateGuids(RegistryKey applicationKey, string emailAddress, string errorText) + { + ErrorReporter.ReportDuplicateGuids(applicationKey, emailAddress, null, errorText); + } } } From 4d994c809260a0bd7d9fd418871edc58259fba1a Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Tue, 3 Dec 2013 15:50:04 +0700 Subject: [PATCH 010/143] Remove all dialogs from FDO Move FdoUiStrings.resx back to original location Change-Id: Id3769a2f3c719af619daf0129f6b8c7f47fcbca4 --- Src/FdoUi/FdoUi.csproj | 18 +++++++++--------- .../{Resources => }/FdoUiStrings.Designer.cs | 0 Src/FdoUi/{Resources => }/FdoUiStrings.resx | 0 3 files changed, 9 insertions(+), 9 deletions(-) rename Src/FdoUi/{Resources => }/FdoUiStrings.Designer.cs (100%) rename Src/FdoUi/{Resources => }/FdoUiStrings.resx (100%) diff --git a/Src/FdoUi/FdoUi.csproj b/Src/FdoUi/FdoUi.csproj index b5e4b0b1f9..029c968d54 100644 --- a/Src/FdoUi/FdoUi.csproj +++ b/Src/FdoUi/FdoUi.csproj @@ -240,6 +240,11 @@ Code + + FdoUiStrings.resx + True + True + Code @@ -266,11 +271,6 @@ True Resources.resx - - FdoUiStrings.resx - True - True - Code @@ -316,14 +316,14 @@ SummaryDialogForm.cs Designer - + ResXFileCodeGenerator - Resources.Designer.cs + FdoUiStrings.Designer.cs Designer - + ResXFileCodeGenerator - FdoUiStrings.Designer.cs + Resources.Designer.cs Designer diff --git a/Src/FdoUi/Resources/FdoUiStrings.Designer.cs b/Src/FdoUi/FdoUiStrings.Designer.cs similarity index 100% rename from Src/FdoUi/Resources/FdoUiStrings.Designer.cs rename to Src/FdoUi/FdoUiStrings.Designer.cs diff --git a/Src/FdoUi/Resources/FdoUiStrings.resx b/Src/FdoUi/FdoUiStrings.resx similarity index 100% rename from Src/FdoUi/Resources/FdoUiStrings.resx rename to Src/FdoUi/FdoUiStrings.resx From 2af83890cd666c0a365530e51a776f79065d2a23 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Tue, 3 Dec 2013 15:56:42 +0700 Subject: [PATCH 011/143] removed WinForms references from UnitOfWorkService refactored ThreadHelper into an interface Change-Id: Ibee4a7a9bdcfe6a4a06809b5488f12d16cc659f2 --- .../FwControls/FilterAllTextsDialog.cs | 7 +- .../FwControlsTests/ProgressDlgTests.cs | 5 +- .../FwControls/ObtainProjectMethod.cs | 66 +-- .../FwControls/ProgressDialogImpl.Designer.cs | 17 +- .../Controls/FwControls/ProgressDialogImpl.cs | 20 +- .../FwControls/ProgressDialogImpl.resx | 292 +++++----- .../FwControls/ProgressDialogWithTask.cs | 204 ++++--- .../ScrControls/FilterTextsDialogTE.cs | 2 +- .../TestColumnConfigureDialog.cs | 4 +- Src/Common/FieldWorks/FieldWorks.cs | 41 +- Src/Common/FieldWorks/FieldWorksManager.cs | 2 +- .../Framework/StatusBarProgressHandler.cs | 20 +- Src/Common/Framework/StylesXmlAccessor.cs | 7 +- Src/Common/FwUtils/ConsoleProgress.cs | 30 +- Src/Common/FwUtils/FwUtils.csproj | 1 - .../FwUtils/FwUtilsTests/FwUtilsTests.csproj | 1 - Src/Common/FwUtils/IProgress.cs | 71 +-- Src/Common/FwUtils/IThreadedProgress.cs | 11 +- Src/Common/PrintLayout/PublicationControl.cs | 4 +- Src/Common/RootSite/RootSiteEditingHelper.cs | 2 +- .../BackupRestore/ProjectBackupService.cs | 3 +- .../DomainServices/ClientServerServices.cs | 30 +- .../DataMigration/FdoDataMigrationManager.cs | 1 - .../DataMigration/ImportFrom6_0.cs | 8 +- Src/FDO/DomainServices/FwStyleSheet.cs | 4 +- Src/FDO/FDO.csproj | 2 +- .../FDOTests}/DummyFdoUserAction.cs | 30 +- Src/FDO/FDOTests/DummyProgressDlg.cs | 42 +- Src/FDO/FDOTests/FDOTests.csproj | 1 + Src/FDO/FDOTests/FdoCacheTests.cs | 72 +-- Src/FDO/FDOTests/FdoTestBase.cs | 13 +- .../PersistingLayerTests.BEPPortTests.cs | 11 +- Src/FDO/FDOTests/XmlImportDataTests.cs | 3 +- Src/FDO/FDOTests/XmlListTests.cs | 4 +- Src/FDO/FDOTests/XmlTranslatedListsTests.cs | 3 +- Src/FDO/FdoCacheIFwDisposableInterfaceImpl.cs | 2 - Src/{Common/FwUtils => FDO}/IFdoUserAction.cs | 18 +- .../Infrastructure/Impl/CmObjectSurrogate.cs | 2 +- Src/FDO/Infrastructure/Impl/UndoStack.cs | 8 +- .../Infrastructure/Impl/UnitOfWorkService.cs | 18 +- .../Impl/UserActivityMonitor.cs | 41 -- Src/FDO/SilentFdoUserAction.cs | 32 +- Src/FDO/fdoCache.cs | 88 +-- Src/FDOBrowser/FDOBrowserForm.Designer.cs | 3 - Src/FDOBrowser/FDOBrowserForm.cs | 12 +- Src/FDOBrowser/FDOClassList.cs | 12 +- Src/FDOBrowser/FdoBrowserUserAction.cs | 26 +- Src/FDOBrowser/ModelWnd.cs | 2 +- Src/FdoUi/FdoUserActionWindowsForms.cs | 58 +- Src/FdoUi/ProgressBarWrapper.cs | 19 +- .../BackupRestore/BackupProjectDlg.cs | 2 +- Src/FwCoreDlgs/ChooseLangProjectDialog.cs | 11 +- Src/FwCoreDlgs/FwNewLangProject.cs | 2 +- Src/FwCoreDlgs/FwSplashScreen.cs | 26 +- Src/FwCoreDlgs/RealSplashScreen.cs | 23 +- .../Interlinear/BIRDInterlinearImporter.cs | 8 +- .../Interlinear/InterlinearImportDlg.cs | 2 +- .../Interlinear/InterlinearSfmImportWizard.cs | 2 +- Src/LexText/Interlinear/LinguaLinksImport.cs | 4 +- .../Interlinear/LinguaLinksImportDlg.cs | 16 +- .../DataNotebook/NotebookImportWiz.cs | 4 +- .../LexTextControls/LexImportWizard.cs | 2 +- .../LexTextControlsTests/LiftExportTests.cs | 7 +- Src/LexText/LexTextControls/LiftImportDlg.cs | 6 +- .../LexTextDll/FlexStylesXmlAccessor.cs | 2 +- Src/LexText/Lexicon/FLExBridgeListener.cs | 12 +- Src/LexText/Morphology/ConcordanceDlg.cs | 16 +- .../ParserEngine/ParserCore/HCWorker.cs | 9 +- ...nvalidReduplicationEnvironmentException.cs | 20 + .../ParserEngine/ParserCore/ParserCore.csproj | 1 + .../ParserCore/ParserCoreStrings.Designer.cs | 536 +++++++++--------- .../ParserCore/ParserCoreStrings.resx | 267 +++++---- Src/LexText/ParserEngine/ParserCore/Worker.cs | 2 +- Src/LexText/ParserUI/ParserListener.cs | 17 +- .../ParserUI/ParserUIStrings.Designer.cs | 20 +- Src/LexText/ParserUI/ParserUIStrings.resx | 7 + Src/LexText/ParserUI/TryAWordDlg.cs | 16 +- Src/MigrateSqlDbs/Program.cs | 3 +- Src/TE/DiffView/BookMerger.cs | 2 +- Src/TE/TeDialogs/ArchiveMaintenanceDialog.cs | 4 +- Src/TE/TeDialogs/ImportedBooks.cs | 4 +- Src/TE/TeDialogs/ScriptureProperties.cs | 4 +- Src/TE/TeImportExport/ExportRtf.cs | 4 +- Src/TE/TeImportExport/ExportUsfm.cs | 2 +- Src/TE/TeImportExport/ExportXhtml.cs | 2 +- Src/TE/TeImportExport/ExportXml.cs | 2 +- Src/TE/TeImportExport/TeImportManager.cs | 5 +- Src/TE/TeKeyTerms/KeyTermsViewWrapper.cs | 2 +- Src/TE/TeScrInitializer/TeKeyTermsInit.cs | 2 +- Src/Utilities/BasicUtils/BasicUtils.csproj | 2 + .../SingleThreadedSynchronizeInvoke.cs | 94 +++ .../BasicUtils/SynchronizeInvokeExtensions.cs | 95 ++++ Src/Utilities/BasicUtils/ThreadHelper.cs | 109 +--- Src/Utilities/FixFwData/Program.cs | 7 +- Src/Utilities/FixFwDataDll/ErrorFixer.cs | 3 +- Src/xWorks/ExportDialog.cs | 8 +- Src/xWorks/FwXWindow.cs | 2 +- Src/xWorks/NotebookExportDialog.cs | 2 +- Src/xWorks/xWorksTests/ExportDialogTests.cs | 4 +- 99 files changed, 1426 insertions(+), 1351 deletions(-) rename Src/{Common/FwUtils/FwUtilsTests => FDO/FDOTests}/DummyFdoUserAction.cs (79%) rename Src/{Common/FwUtils => FDO}/IFdoUserAction.cs (88%) delete mode 100644 Src/FDO/Infrastructure/Impl/UserActivityMonitor.cs create mode 100644 Src/LexText/ParserEngine/ParserCore/InvalidReduplicationEnvironmentException.cs create mode 100644 Src/Utilities/BasicUtils/SingleThreadedSynchronizeInvoke.cs create mode 100644 Src/Utilities/BasicUtils/SynchronizeInvokeExtensions.cs diff --git a/Src/Common/Controls/FwControls/FilterAllTextsDialog.cs b/Src/Common/Controls/FwControls/FilterAllTextsDialog.cs index 837a1cc35c..bdbaa143a5 100644 --- a/Src/Common/Controls/FwControls/FilterAllTextsDialog.cs +++ b/Src/Common/Controls/FwControls/FilterAllTextsDialog.cs @@ -18,7 +18,6 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Resources; using XCore; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.Common.Controls { @@ -260,9 +259,9 @@ protected override void OnHandleCreated(EventArgs e) { // Selecting node(s) changed something, so save it so that the UI doesn't become // unresponsive - using (var progressDlg = new ProgressDialogWithTask(this, m_cache.ThreadHelper)) + using (var progressDlg = new ProgressDialogWithTask(this)) { - progressDlg.ProgressBarStyle = ProgressBarStyle.Marquee; + progressDlg.IsIndeterminate = true; progressDlg.Title = Text; progressDlg.Message = ResourceHelper.GetResourceString("kstidSavingChanges"); progressDlg.RunTask((progDlg, parms) => @@ -283,7 +282,7 @@ protected override void OnHandleCreated(EventArgs e) /// /// /// ------------------------------------------------------------------------------------ - protected override void m_btnHelp_Click(object sender, System.EventArgs e) + protected override void m_btnHelp_Click(object sender, EventArgs e) { ShowHelp.ShowHelpTopic(m_helpTopicProvider, m_helpTopicId); } diff --git a/Src/Common/Controls/FwControls/FwControlsTests/ProgressDlgTests.cs b/Src/Common/Controls/FwControls/FwControlsTests/ProgressDlgTests.cs index a0f0e79b91..630a5c09ab 100644 --- a/Src/Common/Controls/FwControls/FwControlsTests/ProgressDlgTests.cs +++ b/Src/Common/Controls/FwControls/FwControlsTests/ProgressDlgTests.cs @@ -33,7 +33,7 @@ public class DummyProgressDlg : ProgressDialogWithTask /// Initializes a new instance of the class. /// /// ------------------------------------------------------------------------------------ - public DummyProgressDlg() : base(null, new ThreadHelper()) + public DummyProgressDlg() : base(new ThreadHelper()) { } @@ -42,8 +42,7 @@ protected override void Dispose(bool disposing) { if (disposing && !IsDisposed) { - if (ThreadHelper != null) - ThreadHelper.Dispose(); + ((ThreadHelper) SynchronizeInvoke).Dispose(); } base.Dispose(disposing); } diff --git a/Src/Common/Controls/FwControls/ObtainProjectMethod.cs b/Src/Common/Controls/FwControls/ObtainProjectMethod.cs index c1728b9444..2364b688e8 100644 --- a/Src/Common/Controls/FwControls/ObtainProjectMethod.cs +++ b/Src/Common/Controls/FwControls/ObtainProjectMethod.cs @@ -1,4 +1,5 @@ -using System.IO; +using System.ComponentModel; +using System.IO; using System.Text; using System.Windows.Forms; using System.Xml; @@ -9,7 +10,6 @@ using SIL.FieldWorks.FDO.Infrastructure.Impl; using SIL.Utils; using XCore; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.Common.Controls { @@ -25,7 +25,7 @@ public static class ObtainProjectMethod /// /// Null if the operation was cancelled or otherwise did not work. The full pathname of an fwdata file, if it did work. public static string ObtainProjectFromAnySource(Form parent, IHelpTopicProvider helpTopicProvider, - out ObtainedProjectType obtainedProjectType, IFdoUserAction userAction) + out ObtainedProjectType obtainedProjectType) { bool dummy; string fwdataFileFullPathname; @@ -46,7 +46,7 @@ public static string ObtainProjectFromAnySource(Form parent, IHelpTopicProvider if (fwdataFileFullPathname.EndsWith("lift")) { - fwdataFileFullPathname = CreateProjectFromLift(parent, helpTopicProvider, fwdataFileFullPathname, userAction); + fwdataFileFullPathname = CreateProjectFromLift(parent, helpTopicProvider, fwdataFileFullPathname); obtainedProjectType = ObtainedProjectType.Lift; } @@ -56,7 +56,7 @@ public static string ObtainProjectFromAnySource(Form parent, IHelpTopicProvider /// /// Create a new Fieldworks project and import a lift file into it. Return the .fwdata path. /// - private static string CreateProjectFromLift(Form parent, IHelpTopicProvider helpTopicProvider, string liftPath, IFdoUserAction userAction) + private static string CreateProjectFromLift(Form parent, IHelpTopicProvider helpTopicProvider, string liftPath) { string projectPath; FdoCache cache; @@ -68,34 +68,25 @@ private static string CreateProjectFromLift(Form parent, IHelpTopicProvider help var anthroListFile = ReflectionHelper.CallStaticMethod(@"FwCoreDlgs.dll", @"SIL.FieldWorks.FwCoreDlgs.FwCheckAnthroListDlg", @"PickAnthroList", parent, null, helpTopicProvider); - // Do NOT dispose of the thread helper until we dispose of the cache... - // CreateProjectTask makes it the thread helper of the FdoCache that it creates and returns, - // and we must NOT dispose of the cache's thread helper until after we import the lexicon. - // We will actually dispose it twice, most likely, since disposing the cache will dispose it; - // but this is harmless. - using (var helper = new ThreadHelper()) + using (var progressDlg = new ProgressDialogWithTask(parent)) { - using (var progressDlg = new ProgressDialogWithTask(parent, helper)) - { - progressDlg.ProgressBarStyle = ProgressBarStyle.Continuous; - progressDlg.Title = FwControls.ksCreatingLiftProject; - var cacheReceiver = new FdoCache[1]; // a clumsy way of handling an out parameter, consistent with RunTask - projectPath = (string)progressDlg.RunTask(true, (progress, parameters) => CreateProjectTask(progress, userAction, parameters), - new object[] { liftPath, helper, anthroListFile, cacheReceiver }); - cache = cacheReceiver[0]; - } + progressDlg.Title = FwControls.ksCreatingLiftProject; + var cacheReceiver = new FdoCache[1]; // a clumsy way of handling an out parameter, consistent with RunTask + projectPath = (string)progressDlg.RunTask(true, CreateProjectTask, + new[] { liftPath, parent, anthroListFile, cacheReceiver }); + cache = cacheReceiver[0]; + } - // this is a horrible way to invoke this, but the current project organization does not allow us to reference - // the LexEdDll project, nor is there any straightforward way to move the code we need into some project we can - // reference, or any obviously suitable project to move it to without creating other References loops. - // One nasty reflection call seems less technical debt than creating an otherwise unnecessary project. - // (It puts up its own progress dialog.) - ReflectionHelper.CallStaticMethod(@"LexEdDll.dll", @"SIL.FieldWorks.XWorks.LexEd.FLExBridgeListener", - @"ImportObtainedLexicon", cache, liftPath, parent); + // this is a horrible way to invoke this, but the current project organization does not allow us to reference + // the LexEdDll project, nor is there any straightforward way to move the code we need into some project we can + // reference, or any obviously suitable project to move it to without creating other References loops. + // One nasty reflection call seems less technical debt than creating an otherwise unnecessary project. + // (It puts up its own progress dialog.) + ReflectionHelper.CallStaticMethod(@"LexEdDll.dll", @"SIL.FieldWorks.XWorks.LexEd.FLExBridgeListener", + @"ImportObtainedLexicon", cache, liftPath, parent); - ProjectLockingService.UnlockCurrentProject(cache); // finish all saves and completely write the file so we can proceed to open it - cache.Dispose(); - } + ProjectLockingService.UnlockCurrentProject(cache); // finish all saves and completely write the file so we can proceed to open it + cache.Dispose(); return projectPath; } @@ -105,27 +96,26 @@ private static string CreateProjectFromLift(Form parent, IHelpTopicProvider help /// as a background task while showing the dialog. /// /// - /// /// A specific list is required...see the first few lines of the method. /// - private static object CreateProjectTask(IThreadedProgress progress, IFdoUserAction userAction, object[] parameters) + private static object CreateProjectTask(IThreadedProgress progress, object[] parameters) { // Get required parameters. Ideally these would just be the signature of the method, but RunTask requires object[]. - var liftPathname = (string)parameters[0]; - var helper = (ThreadHelper)parameters[1]; - var anthroFile = (string)parameters[2]; - var cacheReceiver = (FdoCache[])parameters[3]; + var liftPathname = (string) parameters[0]; + var synchronizeInvoke = (ISynchronizeInvoke) parameters[1]; + var anthroFile = (string) parameters[2]; + var cacheReceiver = (FdoCache[]) parameters[3]; IWritingSystem wsVern, wsAnalysis; RetrieveDefaultWritingSystemsFromLift(liftPathname, out wsVern, out wsAnalysis); string projectPath = FdoCache.CreateNewLangProj(progress, Directory.GetParent(Path.GetDirectoryName(liftPathname)).Parent.Name, // Get the new Flex project name from the Lift pathname. - helper, wsAnalysis, wsVern, null, null, null, anthroFile); + synchronizeInvoke, wsAnalysis, wsVern, null, null, null, anthroFile); // This is a temporary cache, just to do the import, and AFAIK we have no access to the current // user WS. So create it as "English". Put it in the array to return to the caller. - cacheReceiver[0] = FdoCache.CreateCacheFromLocalProjectFile(projectPath, "en", progress, userAction); + cacheReceiver[0] = FdoCache.CreateCacheFromLocalProjectFile(projectPath, "en", progress, new SilentFdoUserAction(synchronizeInvoke)); return projectPath; } diff --git a/Src/Common/Controls/FwControls/ProgressDialogImpl.Designer.cs b/Src/Common/Controls/FwControls/ProgressDialogImpl.Designer.cs index 06901adb1e..410bb0c5fb 100644 --- a/Src/Common/Controls/FwControls/ProgressDialogImpl.Designer.cs +++ b/Src/Common/Controls/FwControls/ProgressDialogImpl.Designer.cs @@ -55,29 +55,30 @@ private void InitializeComponent() this.progressBar = new System.Windows.Forms.ProgressBar(); this.btnCancel = new System.Windows.Forms.Button(); this.SuspendLayout(); - // + // // lblStatusMessage - // + // this.lblStatusMessage.AutoEllipsis = true; resources.ApplyResources(this.lblStatusMessage, "lblStatusMessage"); this.lblStatusMessage.Name = "lblStatusMessage"; - // + // // progressBar - // + // resources.ApplyResources(this.progressBar, "progressBar"); this.progressBar.Name = "progressBar"; this.progressBar.Step = 1; - // + this.progressBar.Style = System.Windows.Forms.ProgressBarStyle.Continuous; + // // btnCancel - // + // this.btnCancel.Cursor = System.Windows.Forms.Cursors.Arrow; this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; resources.ApplyResources(this.btnCancel, "btnCancel"); this.btnCancel.Name = "btnCancel"; this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); - // + // // ProgressDialogImpl - // + // resources.ApplyResources(this, "$this"); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.CancelButton = this.btnCancel; diff --git a/Src/Common/Controls/FwControls/ProgressDialogImpl.cs b/Src/Common/Controls/FwControls/ProgressDialogImpl.cs index 96823e642d..50d5aa62f6 100644 --- a/Src/Common/Controls/FwControls/ProgressDialogImpl.cs +++ b/Src/Common/Controls/FwControls/ProgressDialogImpl.cs @@ -19,7 +19,6 @@ using System.Windows.Forms; using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.Common.Controls { @@ -281,6 +280,15 @@ public string CancelButtonText } } + /// + /// Gets an object to be used for ensuring that required tasks are invoked on the main + /// UI thread. + /// + public ISynchronizeInvoke SynchronizeInvoke + { + get { return this; } + } + /// ------------------------------------------------------------------------------------ /// /// Gets the form displaying the progress (used for message box owners, etc). @@ -291,15 +299,13 @@ public Form Form get { return this; } } - /// ------------------------------------------------------------------------------------ /// - /// Gets or sets the style of the ProgressBar. + /// Gets or sets a value indicating whether this progress is indeterminate. /// - /// ------------------------------------------------------------------------------------ - public ProgressBarStyle ProgressBarStyle + public bool IsIndeterminate { - get { return ProgressBarStyleExtensions.Convert(progressBar.Style); } - set { progressBar.Style = ProgressBarStyleExtensions.Convert(value); } + get { return progressBar.Style == ProgressBarStyle.Marquee; } + set { progressBar.Style = value ? ProgressBarStyle.Marquee : ProgressBarStyle.Continuous; } } #endregion diff --git a/Src/Common/Controls/FwControls/ProgressDialogImpl.resx b/Src/Common/Controls/FwControls/ProgressDialogImpl.resx index 136760a418..3e83cd4d6c 100644 --- a/Src/Common/Controls/FwControls/ProgressDialogImpl.resx +++ b/Src/Common/Controls/FwControls/ProgressDialogImpl.resx @@ -1,231 +1,231 @@ - + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - text/microsoft-resx + text/microsoft-resx - 2.0 + 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + - NoControl + NoControl - + - 15, 12 + 15, 12 - 388, 13 + 388, 13 - + - 5 + 5 - # + # - lblStatusMessage + lblStatusMessage - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - $this + $this - 0 + 0 - Top, Left, Right + Top, Left, Right - NoControl + NoControl - 15, 32 + 15, 32 - 388, 20 + 388, 20 - 4 + 4 - progressBar + progressBar - System.Windows.Forms.ProgressBar, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Windows.Forms.ProgressBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - $this + $this - 1 + 1 - System + System - NoControl + NoControl - 145, 68 + 145, 68 - 133, 23 + 133, 23 - 3 + 3 - Cancel + Cancel - btnCancel + btnCancel - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - $this + $this - 2 + 2 - - True + + True - ProgressDialogImp + ProgressDialogImp - 6, 13 + 6, 13 - 422, 102 + 422, 102 - Manual + Manual - Progress Dialog + Progress Dialog - ProgressDialogImpl + ProgressDialogImpl - System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 \ No newline at end of file diff --git a/Src/Common/Controls/FwControls/ProgressDialogWithTask.cs b/Src/Common/Controls/FwControls/ProgressDialogWithTask.cs index 2e05dc22ce..bdfd6a40bf 100644 --- a/Src/Common/Controls/FwControls/ProgressDialogWithTask.cs +++ b/Src/Common/Controls/FwControls/ProgressDialogWithTask.cs @@ -22,7 +22,6 @@ using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.Application.ApplicationServices; using System.IO; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.Common.Controls { @@ -44,17 +43,18 @@ public class ProgressDialogWithTask : IThreadedProgress, IFWDisposable protected IProgress m_progressDialog; private readonly bool m_fCreatedProgressDlg; private volatile bool m_fDisposed; + private readonly Form m_owner; private Func m_backgroundTask; private object[] m_parameters; private object m_RetValue; private Exception m_Exception; - private ThreadHelper m_threadHelper; private bool m_fOwnerWasTopMost; private BackgroundWorker m_worker; - private readonly ISynchronizeInvoke m_synchInvoke; + private readonly ISynchronizeInvoke m_synchronizeInvoke; #endregion #region Constructors + /// ------------------------------------------------------------------------------------ /// /// Initializes a new instance of the class that @@ -62,44 +62,49 @@ public class ProgressDialogWithTask : IThreadedProgress, IFWDisposable /// /// The object that will be used to track the progress. /// ------------------------------------------------------------------------------------ - public ProgressDialogWithTask(IProgress progress) : - this(progress, null, progress.Form) + public ProgressDialogWithTask(IProgress progress) + : this(progress, null, progress.SynchronizeInvoke) { } - /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class that + /// Initializes a new instance of the class that /// will create an actual progress dialog box to track the progress. /// /// The form to use as the owner when creating the actual progress /// dialog. - /// The thread helper (must been created on the UI thread). - /// ------------------------------------------------------------------------------------ - public ProgressDialogWithTask(Form owner, ThreadHelper threadHelper) : - this(null, owner, (ISynchronizeInvoke)owner ?? threadHelper) + public ProgressDialogWithTask(Form owner) + : this(null, owner, owner) { - m_threadHelper = threadHelper; - m_fCreatedProgressDlg = true; } - /// ------------------------------------------------------------------------------------ /// /// Initializes a new instance of the class. /// + /// + public ProgressDialogWithTask(ISynchronizeInvoke synchronizeInvoke) + : this(null, null, synchronizeInvoke) + { + } + + /// + /// Initializes a new instance of the class. + /// /// An external implementation of IProgress that should be /// used to report progress. If this is null, then this class will create a generic /// progress dialog for the purpose of running tasks. /// The "owning" form (can be null if progressDlg is specified or if /// there is no suitable form available to own the progress dialog) - /// Object that can ensure that certain operations are - /// invoked on the UI thread. - /// ------------------------------------------------------------------------------------ - private ProgressDialogWithTask(IProgress progress, Form owner, ISynchronizeInvoke synchInvoke) + /// The synchronize invoke. + private ProgressDialogWithTask(IProgress progress, Form owner, ISynchronizeInvoke synchronizeInvoke) { - m_synchInvoke = synchInvoke; m_progressDialog = progress; - InitOnOwnerThread(owner); + m_owner = owner; + m_synchronizeInvoke = synchronizeInvoke; + m_fCreatedProgressDlg = progress == null; + InitOnOwnerThread(); + if (m_synchronizeInvoke == null) + m_synchronizeInvoke = m_progressDialog.SynchronizeInvoke; m_progressDialog.Canceling += m_progressDialog_Canceling; m_progressDialog.Form.FormClosing += m_progressDialog_FormClosing; m_worker.DoWork += RunBackgroundTask; @@ -108,18 +113,18 @@ private ProgressDialogWithTask(IProgress progress, Form owner, ISynchronizeInvok [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", Justification="m_worker gets disposed in Dispose()")] - private void InitOnOwnerThread(Form owner) + private void InitOnOwnerThread() { - if (m_synchInvoke != null && m_synchInvoke.InvokeRequired) + if (m_synchronizeInvoke != null && m_synchronizeInvoke.InvokeRequired) { - m_synchInvoke.Invoke((Action
)InitOnOwnerThread, new object[] { owner }); + m_synchronizeInvoke.Invoke(InitOnOwnerThread); return; } m_worker = new BackgroundWorker { WorkerSupportsCancellation = true }; if (m_progressDialog == null) { - m_progressDialog = new ProgressDialogWithTaskDlgImpl(owner); + m_progressDialog = new ProgressDialogWithTaskDlgImpl(m_owner); } // This is the only way to force handle creation for a form that is not yet visible. @@ -227,9 +232,9 @@ public virtual void Step(int cSteps) { CheckDisposed(); - if (m_fCreatedProgressDlg && m_synchInvoke.InvokeRequired) + if (m_fCreatedProgressDlg && m_synchronizeInvoke.InvokeRequired) { - m_synchInvoke.Invoke((Action)Step, new object[] {cSteps}); + m_synchronizeInvoke.Invoke((Action)Step, new object[] {cSteps}); return; } m_progressDialog.Position += (cSteps > 0) ? cSteps : m_progressDialog.StepSize; @@ -245,16 +250,16 @@ public virtual string Title { CheckDisposed(); - if (m_fCreatedProgressDlg && m_synchInvoke.InvokeRequired) - return (string)m_synchInvoke.Invoke((Func)(() => m_progressDialog.Title), null); + if (m_fCreatedProgressDlg && m_synchronizeInvoke.InvokeRequired) + return (string)m_synchronizeInvoke.Invoke((Func)(() => m_progressDialog.Title), null); return m_progressDialog.Title; } set { CheckDisposed(); - if (m_fCreatedProgressDlg && m_synchInvoke.InvokeRequired) - m_synchInvoke.Invoke((Action)(s => m_progressDialog.Title = s), new [] {value}); + if (m_fCreatedProgressDlg && m_synchronizeInvoke.InvokeRequired) + m_synchronizeInvoke.Invoke((Action)(s => m_progressDialog.Title = s), new [] {value}); else m_progressDialog.Title = value; } @@ -270,16 +275,16 @@ public virtual string Message { CheckDisposed(); - if (m_fCreatedProgressDlg && m_synchInvoke.InvokeRequired) - return (string)m_synchInvoke.Invoke((Func)(() => m_progressDialog.Message), null); + if (m_fCreatedProgressDlg && m_synchronizeInvoke.InvokeRequired) + return (string)m_synchronizeInvoke.Invoke((Func)(() => m_progressDialog.Message), null); return m_progressDialog.Message; } set { CheckDisposed(); - if (m_fCreatedProgressDlg && m_synchInvoke.InvokeRequired) - m_synchInvoke.Invoke((Action)(s => m_progressDialog.Message = s), new [] {value}); + if (m_fCreatedProgressDlg && m_synchronizeInvoke.InvokeRequired) + m_synchronizeInvoke.Invoke((Action)(s => m_progressDialog.Message = s), new [] {value}); else m_progressDialog.Message = value; } @@ -295,16 +300,16 @@ public virtual int Position { CheckDisposed(); - if (m_fCreatedProgressDlg && m_synchInvoke.InvokeRequired) - return (int)m_synchInvoke.Invoke((Func)(() => m_progressDialog.Position), null); + if (m_fCreatedProgressDlg && m_synchronizeInvoke.InvokeRequired) + return (int)m_synchronizeInvoke.Invoke((Func)(() => m_progressDialog.Position), null); return m_progressDialog.Position; } set { CheckDisposed(); - if (m_fCreatedProgressDlg && m_synchInvoke.InvokeRequired) - m_synchInvoke.Invoke((Action)(i => m_progressDialog.Position = i), new object[] {value}); + if (m_fCreatedProgressDlg && m_synchronizeInvoke.InvokeRequired) + m_synchronizeInvoke.Invoke((Action)(i => m_progressDialog.Position = i), new object[] {value}); else m_progressDialog.Position = value; } @@ -320,16 +325,16 @@ public virtual int StepSize { CheckDisposed(); - if (m_fCreatedProgressDlg && m_synchInvoke.InvokeRequired) - return (int)m_synchInvoke.Invoke((Func)(() => m_progressDialog.StepSize), null); + if (m_fCreatedProgressDlg && m_synchronizeInvoke.InvokeRequired) + return (int)m_synchronizeInvoke.Invoke((Func)(() => m_progressDialog.StepSize), null); return m_progressDialog.StepSize; } set { CheckDisposed(); - if (m_fCreatedProgressDlg && m_synchInvoke.InvokeRequired) - m_synchInvoke.Invoke((Action)(i => m_progressDialog.StepSize = i), new object[] {value}); + if (m_fCreatedProgressDlg && m_synchronizeInvoke.InvokeRequired) + m_synchronizeInvoke.Invoke((Action)(i => m_progressDialog.StepSize = i), new object[] {value}); else m_progressDialog.StepSize = value; } @@ -346,7 +351,28 @@ public virtual Form Form get { CheckDisposed(); - return m_progressDialog.Form.Visible ? m_progressDialog.Form : m_synchInvoke as Form; + return m_progressDialog.Form.Visible ? m_progressDialog.Form : m_owner; + } + } + + /// + /// Gets or sets a value indicating whether this progress is indeterminate. + /// + public bool IsIndeterminate + { + get + { + if (m_fCreatedProgressDlg && m_synchronizeInvoke.InvokeRequired) + return m_synchronizeInvoke.Invoke(() => m_progressDialog.IsIndeterminate); + return m_progressDialog.IsIndeterminate; + } + + set + { + if (m_fCreatedProgressDlg && m_synchronizeInvoke.InvokeRequired) + m_synchronizeInvoke.Invoke(() => m_progressDialog.IsIndeterminate = value); + else + m_progressDialog.IsIndeterminate = value; } } @@ -360,16 +386,16 @@ public int Minimum { CheckDisposed(); - if (m_fCreatedProgressDlg && m_synchInvoke.InvokeRequired) - return (int)m_synchInvoke.Invoke((Func)(() => m_progressDialog.Minimum), null); + if (m_fCreatedProgressDlg && m_synchronizeInvoke.InvokeRequired) + return (int)m_synchronizeInvoke.Invoke((Func)(() => m_progressDialog.Minimum), null); return m_progressDialog.Maximum; } set { CheckDisposed(); - if (m_fCreatedProgressDlg && m_synchInvoke.InvokeRequired) - m_synchInvoke.Invoke((Action)(i => m_progressDialog.Minimum = i), new object[] {value}); + if (m_fCreatedProgressDlg && m_synchronizeInvoke.InvokeRequired) + m_synchronizeInvoke.Invoke((Action)(i => m_progressDialog.Minimum = i), new object[] {value}); else m_progressDialog.Maximum = value; } @@ -387,16 +413,16 @@ public int Maximum { CheckDisposed(); - if (m_fCreatedProgressDlg && m_synchInvoke.InvokeRequired) - return (int)m_synchInvoke.Invoke((Func) (() => m_progressDialog.Maximum), null); + if (m_fCreatedProgressDlg && m_synchronizeInvoke.InvokeRequired) + return (int)m_synchronizeInvoke.Invoke((Func) (() => m_progressDialog.Maximum), null); return m_progressDialog.Maximum; } set { CheckDisposed(); - if (m_fCreatedProgressDlg && m_synchInvoke.InvokeRequired) - m_synchInvoke.Invoke((Action) (i => m_progressDialog.Maximum = i), new object[] {value}); + if (m_fCreatedProgressDlg && m_synchronizeInvoke.InvokeRequired) + m_synchronizeInvoke.Invoke((Action) (i => m_progressDialog.Maximum = i), new object[] {value}); else m_progressDialog.Maximum = value; } @@ -418,8 +444,8 @@ public string CancelButtonText if (!(m_progressDialog is ProgressDialogImpl)) throw new InvalidOperationException("The underlying progress dialog implementation probably does not implement CancelButtonText."); - if (m_synchInvoke.InvokeRequired) - return (string)m_synchInvoke.Invoke((Func)(() => ((ProgressDialogImpl)m_progressDialog).CancelButtonText), null); + if (m_synchronizeInvoke.InvokeRequired) + return (string)m_synchronizeInvoke.Invoke((Func)(() => ((ProgressDialogImpl)m_progressDialog).CancelButtonText), null); return ((ProgressDialogImpl)m_progressDialog).CancelButtonText; } set @@ -429,35 +455,13 @@ public string CancelButtonText if (!(m_progressDialog is ProgressDialogImpl)) throw new InvalidOperationException("The underlying progress dialog implementation probably does not implement CancelButtonText."); - if (m_synchInvoke.InvokeRequired) - m_synchInvoke.Invoke((Action)(s => ((ProgressDialogImpl)m_progressDialog).CancelButtonText = s), new object[] {value}); + if (m_synchronizeInvoke.InvokeRequired) + m_synchronizeInvoke.Invoke((Action)(s => ((ProgressDialogImpl)m_progressDialog).CancelButtonText = s), new object[] {value}); else ((ProgressDialogImpl)m_progressDialog).CancelButtonText = value; } } - /// ------------------------------------------------------------------------------------ - /// - /// Gets or sets the style of the ProgressBar. - /// - /// ------------------------------------------------------------------------------------ - public ProgressBarStyle ProgressBarStyle - { - get - { - if (m_fCreatedProgressDlg && m_synchInvoke.InvokeRequired) - return (ProgressBarStyle) m_synchInvoke.Invoke((Func) (() => m_progressDialog.ProgressBarStyle), null); - return m_progressDialog.ProgressBarStyle; - } - set - { - if (m_fCreatedProgressDlg && m_synchInvoke.InvokeRequired) - m_synchInvoke.Invoke((Action) (style => m_progressDialog.ProgressBarStyle = style), new object[] {value}); - else - m_progressDialog.ProgressBarStyle = value; - } - } - /// ------------------------------------------------------------------------------------ /// /// Gets or sets a value indicating whether or not the progress indicator can restart @@ -509,16 +513,16 @@ public bool AllowCancel { CheckDisposed(); - if (m_fCreatedProgressDlg && m_synchInvoke.InvokeRequired) - return (bool)m_synchInvoke.Invoke((Func)(() => m_progressDialog.AllowCancel), null); + if (m_fCreatedProgressDlg && m_synchronizeInvoke.InvokeRequired) + return (bool)m_synchronizeInvoke.Invoke((Func)(() => m_progressDialog.AllowCancel), null); return m_progressDialog.AllowCancel; } set { CheckDisposed(); - if (m_fCreatedProgressDlg && m_synchInvoke.InvokeRequired) - m_synchInvoke.Invoke((Action)(f => m_progressDialog.AllowCancel = f), new object[] {value}); + if (m_fCreatedProgressDlg && m_synchronizeInvoke.InvokeRequired) + m_synchronizeInvoke.Invoke((Action)(f => m_progressDialog.AllowCancel = f), new object[] {value}); else m_progressDialog.AllowCancel = value; } @@ -530,19 +534,9 @@ public bool AllowCancel /// UI thread. /// /// ------------------------------------------------------------------------------------ - public ThreadHelper ThreadHelper + public ISynchronizeInvoke SynchronizeInvoke { - get - { - if (m_threadHelper == null && m_synchInvoke != null) - { - if (m_fCreatedProgressDlg && m_synchInvoke.InvokeRequired) - { - m_synchInvoke.Invoke((Action)(() => { m_threadHelper = new ThreadHelper(); }), null); - } - } - return m_threadHelper; - } + get { return m_synchronizeInvoke; } } /// ------------------------------------------------------------------------------------ @@ -597,8 +591,8 @@ public object RunTask(bool fDisplayUi, Func if (!fDisplayUi) { - if (m_synchInvoke.InvokeRequired) - m_synchInvoke.Invoke((Action) (() => m_progressDialog.Form.WindowState = FormWindowState.Minimized), null); + if (m_synchronizeInvoke.InvokeRequired) + m_synchronizeInvoke.Invoke((Action) (() => m_progressDialog.Form.WindowState = FormWindowState.Minimized), null); else m_progressDialog.Form.WindowState = FormWindowState.Minimized; } @@ -609,8 +603,8 @@ public object RunTask(bool fDisplayUi, Func // course throws an exception. This is really a bug in Mono's Form.ShowDialog implementation. if (Application.OpenForms.Count == 0 && fDisplayUi && !MiscUtils.IsUnix) { - if (m_synchInvoke.InvokeRequired) - m_synchInvoke.Invoke((Action)(() => m_progressDialog.Form.ShowInTaskbar = true), null); + if (m_synchronizeInvoke.InvokeRequired) + m_synchronizeInvoke.Invoke((Action)(() => m_progressDialog.Form.ShowInTaskbar = true), null); else m_progressDialog.Form.ShowInTaskbar = true; } @@ -640,9 +634,9 @@ private void LaunchDialogAndTask(IWin32Window owner) var progressDlg = m_progressDialog as ProgressDialogWithTaskDlgImpl; if (progressDlg != null) { - if (m_synchInvoke.InvokeRequired) + if (m_synchronizeInvoke.InvokeRequired) { - m_synchInvoke.Invoke((Func)progressDlg.LaunchDialogAndStartTask, + m_synchronizeInvoke.Invoke((Func)progressDlg.LaunchDialogAndStartTask, new object[] { owner }); } else @@ -652,9 +646,9 @@ private void LaunchDialogAndTask(IWin32Window owner) } else { - if (m_synchInvoke.InvokeRequired) + if (m_synchronizeInvoke.InvokeRequired) { - m_synchInvoke.Invoke((Func)m_progressDialog.Form.ShowDialog, + m_synchronizeInvoke.Invoke((Func)m_progressDialog.Form.ShowDialog, new object[] { owner }); } else @@ -720,7 +714,7 @@ public static void ImportTranslatedListsForWs(Form parentWindow, FdoCache cache, string path = XmlTranslatedLists.TranslatedListsPathForWs(ws); if (!File.Exists(path)) return; - using (var dlg = new ProgressDialogWithTask(parentWindow, cache.ThreadHelper)) + using (var dlg = new ProgressDialogWithTask(parentWindow)) { dlg.AllowCancel = true; dlg.Maximum = 200; @@ -771,7 +765,7 @@ private void RunBackgroundTask(object sender, DoWorkEventArgs e) } catch (Exception ex) { - System.Diagnostics.Debug.WriteLine("Got exception in background thread: " + ex.Message); + Debug.WriteLine("Got exception in background thread: " + ex.Message); m_Exception = ex; } finally @@ -813,8 +807,8 @@ private void m_progressDialog_FormClosing(object sender, FormClosingEventArgs e) private void m_worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { - if (m_fCreatedProgressDlg && m_synchInvoke.InvokeRequired) - m_synchInvoke.Invoke((Action)m_progressDialog.Form.Close, null); + if (m_fCreatedProgressDlg && m_synchronizeInvoke.InvokeRequired) + m_synchronizeInvoke.Invoke((Action)m_progressDialog.Form.Close, null); else m_progressDialog.Form.Close(); } diff --git a/Src/Common/Controls/ScrControls/FilterTextsDialogTE.cs b/Src/Common/Controls/ScrControls/FilterTextsDialogTE.cs index 66769e3942..b5ee9c9e12 100644 --- a/Src/Common/Controls/ScrControls/FilterTextsDialogTE.cs +++ b/Src/Common/Controls/ScrControls/FilterTextsDialogTE.cs @@ -47,7 +47,7 @@ public FilterTextsDialogTE(FdoCache cache, IStText[] objList, : base(cache, objList, helpTopicProvider) { m_bookImporter = importer; - using (var progressDlg = new ProgressDialogWithTask(null, cache.ThreadHelper)) + using (var progressDlg = new ProgressDialogWithTask(this)) { // This somewhat duplicates some logic in FieldWorks.GetHelpTopicProvider, but it feels // wrong to reference the main exe even though I can't find an actual circular dependency. diff --git a/Src/Common/Controls/XMLViews/XMLViewsTests/TestColumnConfigureDialog.cs b/Src/Common/Controls/XMLViews/XMLViewsTests/TestColumnConfigureDialog.cs index 9ec9ee7d8c..05e8e44faf 100644 --- a/Src/Common/Controls/XMLViews/XMLViewsTests/TestColumnConfigureDialog.cs +++ b/Src/Common/Controls/XMLViews/XMLViewsTests/TestColumnConfigureDialog.cs @@ -16,6 +16,7 @@ using SIL.FieldWorks.Common.Controls; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; +using SIL.FieldWorks.FDO.FDOTests; using SIL.FieldWorks.Test.TestUtils; using SIL.Utils; using XCore; @@ -35,7 +36,7 @@ public void SetUp() m_mediator = new Mediator(); m_mediator.StringTbl = new StringTable("../../DistFiles/Language Explorer/Configuration"); m_cache = FdoCache.CreateCacheWithNewBlankLangProj( - new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "en", "en", new ThreadHelper(), new DummyFdoUserAction()); + new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "en", "en", new DummyFdoUserAction()); m_mediator.PropertyTable.SetProperty("cache", m_cache); } @@ -43,7 +44,6 @@ public void SetUp() public void TearDown() { m_mediator.Dispose(); - m_cache.ThreadHelper.Dispose(); m_cache.Dispose(); } diff --git a/Src/Common/FieldWorks/FieldWorks.cs b/Src/Common/FieldWorks/FieldWorks.cs index d8a5d09e74..0cdd5d8089 100644 --- a/Src/Common/FieldWorks/FieldWorks.cs +++ b/Src/Common/FieldWorks/FieldWorks.cs @@ -60,7 +60,6 @@ using Gecko; #else using NetSparkle; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; #endif @@ -242,7 +241,7 @@ static int Main(string[] rgArgs) s_noUserInterface = appArgs.NoUserInterface; s_appServerMode = appArgs.AppServerMode; - s_userAction = new FdoUserActionWindowsForms(GetHelpTopicProvider(appArgs.AppAbbrev)); + s_userAction = new FdoUserActionWindowsForms(GetHelpTopicProvider(appArgs.AppAbbrev), s_threadHelper); if (Settings.Default.CallUpgrade) { @@ -771,15 +770,15 @@ private static FdoCache CreateCache(ProjectId projectId) WriteSplashScreen(string.Format(Properties.Resources.kstidLoadingProject, projectId.UiName)); Form owner = s_splashScreen != null ? s_splashScreen.Form : Form.ActiveForm; - using (var progressDlg = new ProgressDialogWithTask(owner, s_threadHelper)) + using (var progressDlg = new ProgressDialogWithTask(owner)) { FdoCache cache = FdoCache.CreateCacheFromExistingData(projectId, s_sWsUser, progressDlg, s_userAction); - cache.ProjectNameChanged += ProjectNameChanged; - cache.ServiceLocator.GetInstance().OnSave += FieldWorks_OnSave; + cache.ProjectNameChanged += ProjectNameChanged; + cache.ServiceLocator.GetInstance().OnSave += FieldWorks_OnSave; - SetupErrorPropertiesNeedingCache(cache); - return cache; - } + SetupErrorPropertiesNeedingCache(cache); + return cache; + } } /// ------------------------------------------------------------------------------------ @@ -1620,7 +1619,7 @@ private static ProjectId ShowWelcomeDialog(FwAppArgs args, FwApp startingApp, Pr projectToTry = null; // If the user cancels the send/receive, this null will result in a return to the welcome dialog. // Hard to say what Form.ActiveForm is here. The splash and welcome dlgs are both gone. var projectDataPathname = ObtainProjectMethod.ObtainProjectFromAnySource(Form.ActiveForm, - helpTopicProvider, out obtainedProjectType, s_userAction); + helpTopicProvider, out obtainedProjectType); if (!string.IsNullOrEmpty(projectDataPathname)) { projectToTry = new ProjectId(FDOBackendProviderType.kXML, projectDataPathname, null); @@ -1692,7 +1691,7 @@ internal static ProjectId ChooseLangProject(Form dialogOwner, IHelpTopicProvider { return null; } - using (var dlg = new ChooseLangProjectDialog(helpTopicProvider, false, s_userAction)) + using (var dlg = new ChooseLangProjectDialog(helpTopicProvider, false)) { dlg.ShowDialog(dialogOwner); var app = helpTopicProvider as IApp; @@ -1952,7 +1951,7 @@ private static bool UpdateProjectsSharing(bool fShareProjects, Form dialogOwner { // We aren't going to convert this one, so no complication to just switching it. // Both these setters check and do nothing if not changed. - using (var progressDlg = new ProgressDialogWithTask(null, s_threadHelper)) + using (var progressDlg = new ProgressDialogWithTask(s_threadHelper)) { return ClientServerServices.Current.Local.SetProjectSharing(fShareProjects, progressDlg, s_userAction); } @@ -1961,7 +1960,7 @@ private static bool UpdateProjectsSharing(bool fShareProjects, Form dialogOwner bool fSuccess = false; ExecuteWithAllFwProcessesShutDown(GetCommandLineAbbrevForAppName(fwApp.ApplicationName), () => { - using (var progressDlg = new ProgressDialogWithTask(null, s_threadHelper)) + using (var progressDlg = new ProgressDialogWithTask(s_threadHelper)) { fSuccess = ClientServerServices.Current.Local.SetProjectSharing(fShareProjects, progressDlg, s_userAction); } @@ -2109,7 +2108,7 @@ private static ProjectId MoveProjectFolders(string oldFolderForProjects, string { List rgErrors = new List(); bool fCopy = MustCopyFoldersAndFiles(oldFolderForProjects, newFolderForProjects); - using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(null, s_threadHelper)) + using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(s_threadHelper)) { string[] subDirs = Directory.GetDirectories(oldFolderForProjects); progressDlg.Maximum = subDirs.Length; @@ -2463,7 +2462,7 @@ private static void RestoreCurrentProject(FwRestoreProjectSettings restoreSettin /// ------------------------------------------------------------------------------------ private static void DoRestore(ProjectRestoreService restoreService) { - using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(null, s_threadHelper)) + using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(s_threadHelper)) restoreService.RestoreProject(progressDlg); } @@ -2484,7 +2483,7 @@ private static void DoRestore(ProjectRestoreService restoreService) private static bool BackupProjectForRestore(FwRestoreProjectSettings restoreSettings, FdoCache existingCache, Form dialogOwner) { - using (var progressDlg = new ProgressDialogWithTask(dialogOwner, s_threadHelper)) + using (var progressDlg = new ProgressDialogWithTask(dialogOwner)) { FdoCache cache = existingCache ?? FdoCache.CreateCacheFromExistingData( new ProjectId(restoreSettings.Settings.FullProjectPath, null), @@ -2856,7 +2855,7 @@ internal static void KickOffAppFromOtherProcess(FwAppArgs args) if (s_appServerMode) { // Make sure the cache is initialized for the application. - using (ProgressDialogWithTask dlg = new ProgressDialogWithTask(null, s_threadHelper)) + using (ProgressDialogWithTask dlg = new ProgressDialogWithTask(s_threadHelper)) InitializeApp(app, dlg); return; } @@ -2884,7 +2883,7 @@ internal static void KickOffAppFromOtherProcess(FwAppArgs args) else { // Make sure the cache is initialized for the application - using (ProgressDialogWithTask dlg = new ProgressDialogWithTask(otherApp.ActiveMainWindow, s_threadHelper)) + using (var dlg = new ProgressDialogWithTask(otherApp.ActiveMainWindow)) InitializeApp(app, dlg); } }); @@ -3069,11 +3068,11 @@ private static bool InitializeApp(FwApp app, IProgress progressDlg) if (progressDlg != null) { progressDlg.Message = String.Format(Properties.Resources.kstidSaving, s_cache.ProjectId.UiName); - progressDlg.ProgressBarStyle = ProgressBarStyle.Marquee; + progressDlg.IsIndeterminate = true; } s_cache.ServiceLocator.GetInstance().Save(); if (progressDlg != null) - progressDlg.ProgressBarStyle = ProgressBarStyle.Continuous; + progressDlg.IsIndeterminate = false; } return CreateAndInitNewMainWindow(app, true, null, false); @@ -3823,12 +3822,12 @@ private static void ExitCleanly() { DataUpdateMonitor.ClearSemaphore(); - using (var progressDlg = new ProgressDialogWithTask(null, s_threadHelper)) + using (var progressDlg = new ProgressDialogWithTask(s_threadHelper)) { progressDlg.Title = string.Format(ResourceHelper.GetResourceString("kstidShutdownCaption"), s_cache.ProjectId.UiName); progressDlg.AllowCancel = false; - progressDlg.ProgressBarStyle = ProgressBarStyle.Marquee; + progressDlg.IsIndeterminate = true; var stackMgr = s_cache.ServiceLocator.GetInstance(); if (stackMgr.HasUnsavedChanges) progressDlg.RunTask(true, CommitAndDisposeCache); diff --git a/Src/Common/FieldWorks/FieldWorksManager.cs b/Src/Common/FieldWorks/FieldWorksManager.cs index 09e1543833..ee70deec7c 100644 --- a/Src/Common/FieldWorks/FieldWorksManager.cs +++ b/Src/Common/FieldWorks/FieldWorksManager.cs @@ -18,7 +18,7 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; using System.Windows.Forms; -using XCore; +using SIL.Utils; namespace SIL.FieldWorks { diff --git a/Src/Common/Framework/StatusBarProgressHandler.cs b/Src/Common/Framework/StatusBarProgressHandler.cs index c03b2529dc..1f55873ab5 100644 --- a/Src/Common/Framework/StatusBarProgressHandler.cs +++ b/Src/Common/Framework/StatusBarProgressHandler.cs @@ -21,7 +21,6 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.Common.Framework { @@ -195,6 +194,15 @@ public bool Canceled get { return false; } } + /// + /// Gets an object to be used for ensuring that required tasks are invoked on the main + /// UI thread. + /// + public ISynchronizeInvoke SynchronizeInvoke + { + get { return m_progressBar.Control; } + } + /// ------------------------------------------------------------------------------------ /// /// Gets the progress as a form (used for message box owners, etc). @@ -207,15 +215,13 @@ public Form Form get { return m_progressBar.Control.FindForm(); } } - /// ------------------------------------------------------------------------------------ /// - /// Gets or sets the progress bar style. + /// Gets or sets a value indicating whether this progress is indeterminate. /// - /// ------------------------------------------------------------------------------------ - public ProgressBarStyle ProgressBarStyle + public bool IsIndeterminate { - get { return ProgressBarStyleExtensions.Convert(m_progressBar.Style); } - set { m_progressBar.Style = ProgressBarStyleExtensions.Convert(value); } + get { return m_progressBar.Style == ProgressBarStyle.Marquee; } + set { m_progressBar.Style = value ? ProgressBarStyle.Marquee : ProgressBarStyle.Blocks; } } /// ------------------------------------------------------------------------------------ diff --git a/Src/Common/Framework/StylesXmlAccessor.cs b/Src/Common/Framework/StylesXmlAccessor.cs index 473f3aecc8..7aa083dd26 100644 --- a/Src/Common/Framework/StylesXmlAccessor.cs +++ b/Src/Common/Framework/StylesXmlAccessor.cs @@ -18,7 +18,6 @@ using System.Diagnostics.CodeAnalysis; using System.Drawing; using System.Globalization; -using System.Linq; using System.Xml; using SIL.FieldWorks.Common.FwUtils; @@ -463,14 +462,14 @@ private void CreateAndUpdateStyles(XmlNodeList tagList) } SetFontProperties(styleName, styleTag, - ((tpt, nVar, nVal) => m_cache.ThreadHelper.Invoke(() => propsBldr.SetIntPropValues(tpt, nVar, nVal))), - ((tpt, sVal) => m_cache.ThreadHelper.Invoke(() => propsBldr.SetStrPropValue(tpt, sVal))), + ((tpt, nVar, nVal) => m_progressDlg.SynchronizeInvoke.Invoke(() => propsBldr.SetIntPropValues(tpt, nVar, nVal))), + ((tpt, sVal) => m_progressDlg.SynchronizeInvoke.Invoke(() => propsBldr.SetStrPropValue(tpt, sVal))), option); // Get paragraph properties if (style.Type == StyleType.kstParagraph) SetParagraphProperties(styleName, styleTag, - ((tpt, nVar, nVal) => m_cache.ThreadHelper.Invoke(() => propsBldr.SetIntPropValues(tpt, nVar, nVal))), + ((tpt, nVar, nVal) => m_progressDlg.SynchronizeInvoke.Invoke(() => propsBldr.SetIntPropValues(tpt, nVar, nVal))), option); style.Rules = propsBldr.GetTextProps(); diff --git a/Src/Common/FwUtils/ConsoleProgress.cs b/Src/Common/FwUtils/ConsoleProgress.cs index b9239c3659..995fc78bc4 100644 --- a/Src/Common/FwUtils/ConsoleProgress.cs +++ b/Src/Common/FwUtils/ConsoleProgress.cs @@ -12,6 +12,8 @@ // Responsibility: mcconnel // --------------------------------------------------------------------------------------------- using System; +using System.ComponentModel; +using SIL.Utils; namespace SIL.FieldWorks.Common.FwUtils { @@ -24,6 +26,7 @@ namespace SIL.FieldWorks.Common.FwUtils /// ---------------------------------------------------------------------------------------- public class ConsoleProgress : IProgress { + private readonly SingleThreadedSynchronizeInvoke m_sychronizeInvoke = new SingleThreadedSynchronizeInvoke(); int m_min; int m_max = 100; string m_message; @@ -41,6 +44,15 @@ public bool DotsWritten #region IProgress Members + /// + /// Gets an object to be used for ensuring that required tasks are invoked on the main + /// UI thread. + /// + public ISynchronizeInvoke SynchronizeInvoke + { + get { return m_sychronizeInvoke; } + } + /// /// Gets the form displaying the progress (used for message box owners, etc). If the progress /// is not associated with a visible Form, then this returns its owning form, if any. @@ -50,6 +62,15 @@ public System.Windows.Forms.Form Form get { return null; } } + /// + /// Gets or sets a value indicating whether this progress is indeterminate. + /// + public bool IsIndeterminate + { + get { return false; } + set { } + } + /// /// Gets or sets the maximum value of the progress bar. /// @@ -170,15 +191,6 @@ public bool AllowCancel /// public event System.ComponentModel.CancelEventHandler Canceling; - /// - /// Gets or sets the progress bar style. - /// - public ProgressBarStyle ProgressBarStyle - { - get { return ProgressBarStyle.Continuous; } - set { } - } - #endregion } } diff --git a/Src/Common/FwUtils/FwUtils.csproj b/Src/Common/FwUtils/FwUtils.csproj index b4fb494a71..9b731f79d1 100644 --- a/Src/Common/FwUtils/FwUtils.csproj +++ b/Src/Common/FwUtils/FwUtils.csproj @@ -176,7 +176,6 @@ - diff --git a/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj b/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj index 91de873255..0b8a84df8c 100644 --- a/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj +++ b/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj @@ -148,7 +148,6 @@ - diff --git a/Src/Common/FwUtils/IProgress.cs b/Src/Common/FwUtils/IProgress.cs index fce56ee342..8d7b7ad81a 100644 --- a/Src/Common/FwUtils/IProgress.cs +++ b/Src/Common/FwUtils/IProgress.cs @@ -93,6 +93,12 @@ int Maximum set; } + /// + /// Gets an object to be used for ensuring that required tasks are invoked on the main + /// UI thread. + /// + ISynchronizeInvoke SynchronizeInvoke { get; } + /// /// Gets the form displaying the progress (used for message box owners, etc). If the progress /// is not associated with a visible Form, then this returns its owning form, if any. @@ -103,9 +109,9 @@ System.Windows.Forms.Form Form } /// - /// Gets or sets the progress bar style. + /// Gets or sets a value indicating whether this progress is indeterminate. /// - ProgressBarStyle ProgressBarStyle { get; set; } + bool IsIndeterminate { get; set; } /// /// Gets or sets a value indicating whether the opertation executing on the separate thread @@ -113,65 +119,4 @@ System.Windows.Forms.Form Form /// bool AllowCancel { get; set; } } - - /// - /// Specifies the style that a uses to indicate the progress of an operation. - /// - /// 2 - public enum ProgressBarStyle - { - /// - /// Blocks - /// - Blocks, - /// - /// Continuous - /// - Continuous, - /// - /// Marquee - /// - Marquee - } - - /// - /// Methods for the ProgressBarStyle enum - /// - public static class ProgressBarStyleExtensions - { - /// - /// Converts from Windows Forms ProgressBarStyle - /// - /// From. - /// - public static ProgressBarStyle Convert(System.Windows.Forms.ProgressBarStyle from) - { - switch (from) - { - case System.Windows.Forms.ProgressBarStyle.Blocks: - return ProgressBarStyle.Blocks; - case System.Windows.Forms.ProgressBarStyle.Continuous: - return ProgressBarStyle.Continuous; - default: - return ProgressBarStyle.Marquee; - } - } - /// - /// Converts to Windows Forms ProgressBarStyle - /// - /// From. - /// - public static System.Windows.Forms.ProgressBarStyle Convert(ProgressBarStyle from) - { - switch (from) - { - case ProgressBarStyle.Blocks: - return System.Windows.Forms.ProgressBarStyle.Blocks; - case ProgressBarStyle.Continuous: - return System.Windows.Forms.ProgressBarStyle.Continuous; - default: - return System.Windows.Forms.ProgressBarStyle.Marquee; - } - } - } } diff --git a/Src/Common/FwUtils/IThreadedProgress.cs b/Src/Common/FwUtils/IThreadedProgress.cs index 9288f1603c..e70589cc9f 100644 --- a/Src/Common/FwUtils/IThreadedProgress.cs +++ b/Src/Common/FwUtils/IThreadedProgress.cs @@ -11,7 +11,6 @@ // File: IThreadedProgress.cs // --------------------------------------------------------------------------------------------- using System; -using SIL.Utils; namespace SIL.FieldWorks.Common.FwUtils { @@ -23,14 +22,6 @@ namespace SIL.FieldWorks.Common.FwUtils /// -------------------------------------------------------------------------------------------- public interface IThreadedProgress : IProgress { - /// ------------------------------------------------------------------------------------ - /// - /// Gets an object to be used for ensuring that required tasks are invoked on the main - /// UI thread. - /// - /// ------------------------------------------------------------------------------------ - ThreadHelper ThreadHelper { get; } - /// ------------------------------------------------------------------------------------ /// /// Gets a value indicating whether the task has been canceled. @@ -80,7 +71,7 @@ public class WorkerThreadException : Exception { /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The message. /// The inner exception. diff --git a/Src/Common/PrintLayout/PublicationControl.cs b/Src/Common/PrintLayout/PublicationControl.cs index febdbe85ff..8fbc7251f3 100644 --- a/Src/Common/PrintLayout/PublicationControl.cs +++ b/Src/Common/PrintLayout/PublicationControl.cs @@ -1,4 +1,4 @@ -// -------------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------- #region /// Copyright (c) 2004, SIL International. All Rights Reserved. // // Copyright (c) 2004, SIL International. All Rights Reserved. @@ -3218,7 +3218,7 @@ public virtual bool OnViewUpdatePageBreak(object args) CheckDisposed(); IVwRootBox focusedRootBox = FocusedRootBox; - using (var dialog = new ProgressDialogWithTask(FindForm(), Cache.ThreadHelper)) + using (var dialog = new ProgressDialogWithTask(FindForm())) { dialog.CancelButtonText = ResourceHelper.GetResourceString("kstidUpdatePageBreakButtonText"); dialog.Title = ResourceHelper.GetResourceString("kstidUpdatePageBreakWindowCaption"); diff --git a/Src/Common/RootSite/RootSiteEditingHelper.cs b/Src/Common/RootSite/RootSiteEditingHelper.cs index 6ad95b256a..1adbba3e96 100644 --- a/Src/Common/RootSite/RootSiteEditingHelper.cs +++ b/Src/Common/RootSite/RootSiteEditingHelper.cs @@ -554,7 +554,7 @@ private void HandleSelectionChange() // in response to that. There's also a chance we'll never get a selection, but that // might be okay, too, in some views. // Also, need to use Invoke, since this may be running on a progress thread. - Cache.ThreadHelper.Invoke(() => + Control.Invoke(() => { IVwRootBox rootb = EditedRootBox; RootSite site = null; diff --git a/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs b/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs index 7bdd98d6f6..0193985c3b 100644 --- a/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs +++ b/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs @@ -21,7 +21,6 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Infrastructure; using SIL.Utils; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.FDO.DomainServices.BackupRestore { @@ -62,7 +61,7 @@ public string BackupProject(IThreadedProgress progressDlg) var filesToZip = CreateListOfFilesToZip(); progressDlg.Title = Strings.ksBackupProgressCaption; - progressDlg.ProgressBarStyle = ProgressBarStyle.Marquee; + progressDlg.IsIndeterminate = true; progressDlg.AllowCancel = false; m_failedFiles.Clear(); // I think it's always a new instance, but play safe. backupFile = (string)progressDlg.RunTask(true, BackupTask, filesToZip); diff --git a/Src/FDO/DomainServices/ClientServerServices.cs b/Src/FDO/DomainServices/ClientServerServices.cs index dd79f637d7..597f66a61d 100644 --- a/Src/FDO/DomainServices/ClientServerServices.cs +++ b/Src/FDO/DomainServices/ClientServerServices.cs @@ -28,7 +28,6 @@ using SIL.FieldWorks.FDO.Infrastructure.Impl; using SIL.FieldWorks.Resources; using SIL.Utils; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.FDO.DomainServices { @@ -778,7 +777,6 @@ private bool ConvertAllProjectsToXml(IThreadedProgress progressDlg, IFdoUserActi progressDlg.Title = Strings.ksConvertingToNonShared; progressDlg.AllowCancel = false; - progressDlg.ProgressBarStyle = ProgressBarStyle.Continuous; progressDlg.Maximum = Directory.GetDirectories(DirectoryFinder.ProjectsDirectory).Count(); progressDlg.RunTask(true, (progress, args) => ConvertAllProjectsToXmlTask(progress, userAction, args)); return true; @@ -826,7 +824,6 @@ private bool ConvertAllProjectsToDb4o(IThreadedProgress progressDlg) { progressDlg.Title = Strings.ksConvertingToShared; progressDlg.AllowCancel = false; - progressDlg.ProgressBarStyle = ProgressBarStyle.Continuous; progressDlg.Maximum = Directory.GetDirectories(DirectoryFinder.ProjectsDirectory).Count(); return (bool)progressDlg.RunTask(true, ConvertAllProjectsToDb4o); } @@ -915,22 +912,21 @@ public string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string try { - using (var tempCache = FdoCache.CreateCacheFromExistingData( - new SimpleProjectId(FDOBackendProviderType.kXML, xmlFilename), "en", progressDlg, new SilentFdoUserAction())) - { - - // The zero in the object array is for db4o and causes it not to open a port. - // This is fine since we aren't yet trying to start up on this restored database. - // The null says we are creating the file on the local host. - using (var copyCache = FdoCache.CreateCacheCopy( - new SimpleProjectId(FDOBackendProviderType.kDb4oClientServer, desiredPath), "en", tempCache, progressDlg.ThreadHelper, new SilentFdoUserAction())) + using (var tempCache = FdoCache.CreateCacheFromExistingData(new SimpleProjectId(FDOBackendProviderType.kXML, xmlFilename), + "en", progressDlg, new SilentFdoUserAction(progressDlg.SynchronizeInvoke))) { - copyCache.ServiceLocator.GetInstance().Commit(new HashSet(), - new HashSet(), new HashSet()); - // Enhance JohnT: how can we tell this succeeded? + + // The zero in the object array is for db4o and causes it not to open a port. + // This is fine since we aren't yet trying to start up on this restored database. + // The null says we are creating the file on the local host. + using (var copyCache = FdoCache.CreateCacheCopy(new SimpleProjectId(FDOBackendProviderType.kDb4oClientServer, desiredPath), + "en", tempCache, new SilentFdoUserAction(progressDlg.SynchronizeInvoke))) + { + copyCache.ServiceLocator.GetInstance().Commit(new HashSet(), new HashSet(), new HashSet()); + // Enhance JohnT: how can we tell this succeeded? + } } } - } catch (Exception) { // If we couldn't convert it, try not to leave a corrupted file around. @@ -965,7 +961,7 @@ public string CopyToXmlFile(FdoCache source, string destDir) try { using (var copyCache = FdoCache.CreateCacheCopy( - new SimpleProjectId(FDOBackendProviderType.kXML, newFilePath), "en", source, source.ThreadHelper, source.ServiceLocator.GetInstance())) + new SimpleProjectId(FDOBackendProviderType.kXML, newFilePath), "en", source, source.ServiceLocator.GetInstance())) { copyCache.ServiceLocator.GetInstance().Commit( new HashSet(), diff --git a/Src/FDO/DomainServices/DataMigration/FdoDataMigrationManager.cs b/Src/FDO/DomainServices/DataMigration/FdoDataMigrationManager.cs index 03a0348d15..98bb13986c 100644 --- a/Src/FDO/DomainServices/DataMigration/FdoDataMigrationManager.cs +++ b/Src/FDO/DomainServices/DataMigration/FdoDataMigrationManager.cs @@ -174,7 +174,6 @@ public void PerformMigration(IDomainObjectDTORepository domainObjectDtoRepositor currentDataStoreModelVersion, updateToVersion)); progressDlg.Title = Strings.ksDataMigrationCaption; - progressDlg.ProgressBarStyle = ProgressBarStyle.Continuous; progressDlg.AllowCancel = false; progressDlg.Minimum = 0; progressDlg.Maximum = (updateToVersion - currentDataStoreModelVersion) + 1; diff --git a/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs b/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs index 5f401651d8..a34b44137c 100644 --- a/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs +++ b/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs @@ -20,7 +20,6 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Resources; using SIL.Utils; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration { @@ -204,7 +203,6 @@ private bool UnzipFile(ZipFile zipFile, ZipEntry entry, string message, out stri using (var stream = zipFile.GetInputStream(entry)) { m_progressDlg.Title = Strings.ksConverting; - m_progressDlg.ProgressBarStyle = ProgressBarStyle.Continuous; m_progressDlg.Maximum = (int)entry.Size; if (File.Exists(tempPath)) File.Delete(tempPath); // if we tried and failed earlier, try again. @@ -524,7 +522,7 @@ private bool CallDbProgram(string args, string progressMsg, string errorMsgFmt) { using (var process = CreateAndInitProcess(m_dbPath, args)) { - m_progressDlg.ProgressBarStyle = ProgressBarStyle.Marquee; // Can't get actual progress from external program + m_progressDlg.IsIndeterminate = true; // Can't get actual progress from external program m_progressDlg.Title = Strings.ksConverting; if (!(bool)m_progressDlg.RunTask(true, ProcessFile, process, progressMsg)) { @@ -550,7 +548,7 @@ public bool DumpDatabaseAsXml(string dbName, string tempXmlPath, string progress { using (var process = CreateAndInitProcess(m_dumpxmlPath, "-d \"" + dbName + "\" -o \"" + tempXmlPath + '"')) { - m_progressDlg.ProgressBarStyle = ProgressBarStyle.Marquee; // Can't get actual progress from external program + m_progressDlg.IsIndeterminate = true; // Can't get actual progress from external program m_progressDlg.Title = Strings.ksConverting; if (!(bool)m_progressDlg.RunTask(true, ProcessFile, process, progressMsg)) { @@ -666,7 +664,7 @@ public bool ImportFrom6_0Xml(string pathname, string folderName, string projectF Path.Combine(DirectoryFinder.FWCodeDirectory, "ConverterConsole.exe"), '"' + pathname + "\" \"" + projectFile + '"')) { - m_progressDlg.ProgressBarStyle = ProgressBarStyle.Marquee; // Can't get actual progress from external program + m_progressDlg.IsIndeterminate = true; // Can't get actual progress from external program m_progressDlg.Title = Strings.ksConverting; string message = String.Format(Strings.ksConvertingFile, Path.GetFileNameWithoutExtension(projectFile)); if (!(bool)m_progressDlg.RunTask(true, ProcessFile, process, message)) diff --git a/Src/FDO/DomainServices/FwStyleSheet.cs b/Src/FDO/DomainServices/FwStyleSheet.cs index 1a97321d5c..b64c286070 100644 --- a/Src/FDO/DomainServices/FwStyleSheet.cs +++ b/Src/FDO/DomainServices/FwStyleSheet.cs @@ -116,7 +116,7 @@ public class StyleInfoCollection : KeyedCollection { /// -------------------------------------------------------------------------------- /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// -------------------------------------------------------------------------------- public StyleInfoCollection() @@ -927,7 +927,7 @@ private LgCharRenderProps GetStyleChrps(string stylename, int ws, ILgWritingSyst // that the property store does not implement IVwPropertyStore. See FWR-1918. // Some more sophisticated trick may be needed if it is ever the case that the stylesheet // is NOT created on the main UI thread. - return m_fdoCache.ThreadHelper.Invoke(() => GetChrps(ws, ttp, wsf)); + return m_fdoCache.ServiceLocator.GetInstance().SynchronizeInvoke.Invoke(() => GetChrps(ws, ttp, wsf)); } /// ------------------------------------------------------------------------------------ diff --git a/Src/FDO/FDO.csproj b/Src/FDO/FDO.csproj index 1ff2d2abec..98eb94c80f 100644 --- a/Src/FDO/FDO.csproj +++ b/Src/FDO/FDO.csproj @@ -375,6 +375,7 @@ + @@ -397,7 +398,6 @@ - diff --git a/Src/Common/FwUtils/FwUtilsTests/DummyFdoUserAction.cs b/Src/FDO/FDOTests/DummyFdoUserAction.cs similarity index 79% rename from Src/Common/FwUtils/FwUtilsTests/DummyFdoUserAction.cs rename to Src/FDO/FDOTests/DummyFdoUserAction.cs index ebd0f55a13..5248bb80c4 100644 --- a/Src/Common/FwUtils/FwUtilsTests/DummyFdoUserAction.cs +++ b/Src/FDO/FDOTests/DummyFdoUserAction.cs @@ -1,4 +1,4 @@ -// --------------------------------------------------------------------------------------------- +// --------------------------------------------------------------------------------------------- #region // Copyright (c) 2013, SIL International. All Rights Reserved. // // Copyright (c) 2013, SIL International. All Rights Reserved. @@ -9,18 +9,30 @@ #endregion // --------------------------------------------------------------------------------------------- using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using SIL.Utils; using Microsoft.Win32; -namespace SIL.FieldWorks.Common.FwUtils +namespace SIL.FieldWorks.FDO.FDOTests { /// /// Dummy implementation of FdoUserAction for unit tests /// + [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", + Justification="m_threadHelper is a singleton and disposed by the SingletonsContainer")] public class DummyFdoUserAction : IFdoUserAction { + private readonly ThreadHelper m_threadHelper = SingletonsContainer.Get(); + + /// + /// Gets the object that is used to invoke methods on the main UI thread. + /// + public ISynchronizeInvoke SynchronizeInvoke + { + get { return m_threadHelper; } + } + /// /// Gets the error message. /// @@ -47,6 +59,14 @@ public bool ConnectionLost() throw new NotImplementedException(); } + /// + /// Gets the last time that there was user activity. + /// + public DateTime LastActivityTime + { + get { return DateTime.Now; } + } + /// /// Check with user regarding which files to use /// diff --git a/Src/FDO/FDOTests/DummyProgressDlg.cs b/Src/FDO/FDOTests/DummyProgressDlg.cs index 8706fbe6d8..b3887276c2 100644 --- a/Src/FDO/FDOTests/DummyProgressDlg.cs +++ b/Src/FDO/FDOTests/DummyProgressDlg.cs @@ -16,7 +16,6 @@ using System.Windows.Forms; using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.FDO.FDOTests { @@ -97,6 +96,15 @@ public void Step(int amount) /// public int Maximum { get; set; } + /// + /// Gets an object to be used for ensuring that required tasks are invoked on the main + /// UI thread. + /// + public ISynchronizeInvoke SynchronizeInvoke + { + get { return m_threadHelper; } + } + /// /// Gets or sets a value indicating whether the task has been canceled. /// @@ -116,6 +124,15 @@ public Form Form get { return null; } } + /// + /// Gets or sets a value indicating whether this progress is indeterminate. + /// + public bool IsIndeterminate + { + get { return false; } + set { } + } + /// ------------------------------------------------------------------------------------ /// /// Gets or sets a value indicating whether the opertation executing on the separate thread @@ -163,29 +180,6 @@ public object RunTask(Func backgroundTask, return backgroundTask(this, parameters); } - /// ------------------------------------------------------------------------------------ - /// - /// Gets a thread helper used for ensuring that required tasks are invoked on the main - /// UI thread. - /// - /// null - /// ------------------------------------------------------------------------------------ - public ThreadHelper ThreadHelper - { - get { return m_threadHelper; } - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets or sets the progress bar style. - /// - /// ------------------------------------------------------------------------------------ - public ProgressBarStyle ProgressBarStyle - { - get { return ProgressBarStyle.Continuous; } - set { } - } - #endregion } } diff --git a/Src/FDO/FDOTests/FDOTests.csproj b/Src/FDO/FDOTests/FDOTests.csproj index dee8e55439..1ee3c244e4 100644 --- a/Src/FDO/FDOTests/FDOTests.csproj +++ b/Src/FDO/FDOTests/FDOTests.csproj @@ -299,6 +299,7 @@ + diff --git a/Src/FDO/FDOTests/FdoCacheTests.cs b/Src/FDO/FDOTests/FdoCacheTests.cs index 29c9656e19..ad3fae314d 100644 --- a/Src/FDO/FDOTests/FdoCacheTests.cs +++ b/Src/FDO/FDOTests/FdoCacheTests.cs @@ -218,10 +218,9 @@ private static void RemoveTestDirs(List preExistingDirs, IEnumerable(); - dataSetup.LoadDomain(BackendBulkLoadDomain.All); - cache.Dispose(); - cache.CheckDisposed(); - } + var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), + "en", "fr", "en", m_userAction); + // Init backend data provider + var dataSetup = cache.ServiceLocator.GetInstance(); + dataSetup.LoadDomain(BackendBulkLoadDomain.All); + cache.Dispose(); + cache.CheckDisposed(); } /// @@ -453,18 +447,15 @@ public void CacheCheckDisposedTest() [Test] public void CacheIsDisposedTest() { - using (var threadHelper = new ThreadHelper()) - { - // This can't be in the minimalist class, because it disposes the cache. - var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", threadHelper, m_userAction); - // Init backend data provider - var dataSetup = cache.ServiceLocator.GetInstance(); - dataSetup.LoadDomain(BackendBulkLoadDomain.All); - Assert.IsFalse(cache.IsDisposed, "Should not have been disposed."); - cache.Dispose(); - Assert.IsTrue(cache.IsDisposed, "Should have been disposed."); - } + // This can't be in the minimalist class, because it disposes the cache. + var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), + "en", "fr", "en", m_userAction); + // Init backend data provider + var dataSetup = cache.ServiceLocator.GetInstance(); + dataSetup.LoadDomain(BackendBulkLoadDomain.All); + Assert.IsFalse(cache.IsDisposed, "Should not have been disposed."); + cache.Dispose(); + Assert.IsTrue(cache.IsDisposed, "Should have been disposed."); } /// @@ -473,17 +464,14 @@ public void CacheIsDisposedTest() [Test] public void CacheDisposedForFDOObject() { - using (var threadHelper = new ThreadHelper()) - { - var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", threadHelper, m_userAction); - // Init backend data provider - var dataSetup = cache.ServiceLocator.GetInstance(); - dataSetup.LoadDomain(BackendBulkLoadDomain.All); - var lp = cache.LanguageProject; - cache.Dispose(); - Assert.IsFalse(lp.IsValidObject); - } + var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), + "en", "fr", "en", m_userAction); + // Init backend data provider + var dataSetup = cache.ServiceLocator.GetInstance(); + dataSetup.LoadDomain(BackendBulkLoadDomain.All); + var lp = cache.LanguageProject; + cache.Dispose(); + Assert.IsFalse(lp.IsValidObject); } /// @@ -492,9 +480,8 @@ public void CacheDisposedForFDOObject() [Test] public void FDOObjectDeleted() { - using (var threadHelper = new ThreadHelper()) using (var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", threadHelper, m_userAction)) + "en", "fr", "en", m_userAction)) { // Init backend data provider var dataSetup = cache.ServiceLocator.GetInstance(); @@ -515,10 +502,9 @@ public void FDOObjectDeleted() [Test] public void NumberOfRemoteClients_NotClientServer_ReturnsZero() { - using (var threadHelper = new ThreadHelper()) using ( var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", threadHelper, m_userAction)) + "en", "fr", "en", m_userAction)) { Assert.AreEqual(0, cache.NumberOfRemoteClients); } diff --git a/Src/FDO/FDOTests/FdoTestBase.cs b/Src/FDO/FDOTests/FdoTestBase.cs index 19aa8ddcf4..9e79d19bdb 100644 --- a/Src/FDO/FDOTests/FdoTestBase.cs +++ b/Src/FDO/FDOTests/FdoTestBase.cs @@ -16,10 +16,7 @@ // Implements FdoTestBase, the base class for the FDO tests // // -------------------------------------------------------------------------------------------- -using System; -using System.Collections.Generic; using System.IO; -using System.Linq; using NUnit.Framework; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.Common.FwUtils; @@ -27,7 +24,6 @@ using SIL.FieldWorks.Test.TestUtils; using SIL.Utils; using SIL.CoreImpl; -using SIL.FieldWorks.FDO.Infrastructure.Impl; namespace SIL.FieldWorks.FDO.FDOTests { @@ -107,7 +103,7 @@ protected void SetupEverythingButBase() DisposeEverythingButBase(); // We need FieldWorks here to get the correct registry key HKLM\Software\SIL\FieldWorks. // The default without this would be HKLM\Software\SIL\SIL FieldWorks, which breaks some tests. - SIL.Utils.RegistryHelper.ProductName = "FieldWorks"; + RegistryHelper.ProductName = "FieldWorks"; m_cache = CreateCache(); m_actionHandler = m_cache.ServiceLocator.GetInstance(); } @@ -131,11 +127,7 @@ public override void FixtureTeardown() protected void DisposeEverythingButBase() { if (m_cache != null) - { - if (m_cache.ThreadHelper != null) - m_cache.ThreadHelper.Dispose(); m_cache.Dispose(); - } m_cache = null; m_actionHandler = null; } @@ -182,9 +174,8 @@ public virtual void TestTearDown() /// a working FdoCache protected FdoCache BootstrapSystem(IProjectIdentifier projectId, BackendBulkLoadDomain loadType) { - // This thread helper will be disposed in FixtureTeardown along with the cache. var retval = m_internalRestart ? FdoCache.CreateCacheFromExistingData(projectId, "en", new DummyProgressDlg(), new DummyFdoUserAction()) : - FdoCache.CreateCacheWithNewBlankLangProj(projectId, "en", "fr", "en", new ThreadHelper(), new DummyFdoUserAction()); + FdoCache.CreateCacheWithNewBlankLangProj(projectId, "en", "fr", "en", new DummyFdoUserAction()); var dataSetup = retval.ServiceLocator.GetInstance(); dataSetup.LoadDomain(loadType); return retval; diff --git a/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs b/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs index 1ac5939336..a5bba5f6a9 100644 --- a/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs +++ b/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs @@ -10,7 +10,6 @@ using SIL.FieldWorks.FDO.FDOTests; using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.Test.TestUtils; -using SIL.Utils; namespace SIL.FieldWorks.FDO.CoreTests.PersistingLayerTests { @@ -208,10 +207,9 @@ public void PortAllBEPsTestsUsingAnAlreadyOpenedSource( // Set up data source, but only do it once. var sourceGuids = new List(); - using (var threadHelper = new ThreadHelper()) using (var sourceCache = FdoCache.CreateCacheWithNewBlankLangProj( new TestProjectId(sourceBackendStartupParameters.ProjectId.Type, - sourceBackendStartupParameters.ProjectId.Path), "en", "fr", "en", threadHelper, new DummyFdoUserAction())) + sourceBackendStartupParameters.ProjectId.Path), "en", "fr", "en", new DummyFdoUserAction())) { // BEP is a singleton, so we shouldn't call Dispose on it. This will be done // by service locator. @@ -224,10 +222,9 @@ public void PortAllBEPsTestsUsingAnAlreadyOpenedSource( DeleteDatabase(targetBackendStartupParameters); // Migrate source data to new BEP. - using (var otherThreadHelper = new ThreadHelper()) using (var targetCache = FdoCache.CreateCacheCopy( new TestProjectId(targetBackendStartupParameters.ProjectId.Type, - targetBackendStartupParameters.ProjectId.Path), "en", sourceCache, otherThreadHelper, new DummyFdoUserAction())) + targetBackendStartupParameters.ProjectId.Path), "en", sourceCache, new DummyFdoUserAction())) { // BEP is a singleton, so we shouldn't call Dispose on it. This will be done // by service locator. @@ -276,7 +273,7 @@ public void PortAllBEPsTestsUsingAnUnopenedSource( sourceBackendStartupParameters.ProjectId.Path); IThreadedProgress progressDlg = new DummyProgressDlg(); using (FdoCache sourceCache = FdoCache.CreateCacheWithNewBlankLangProj( - projId, "en", "fr", "en", progressDlg.ThreadHelper, new DummyFdoUserAction())) + projId, "en", "fr", "en", new DummyFdoUserAction())) { // BEP is a singleton, so we shouldn't call Dispose on it. This will be done // by service locator. @@ -290,7 +287,7 @@ public void PortAllBEPsTestsUsingAnUnopenedSource( // Migrate source data to new BEP. progressDlg = new DummyProgressDlg(); using (var targetCache = FdoCache.CreateCacheWithNoLangProj( - new TestProjectId(targetBackendStartupParameters.ProjectId.Type, null), "en", progressDlg.ThreadHelper, new DummyFdoUserAction())) + new TestProjectId(targetBackendStartupParameters.ProjectId.Type, null), "en", new DummyFdoUserAction())) { // BEP is a singleton, so we shouldn't call Dispose on it. This will be done // by service locator. diff --git a/Src/FDO/FDOTests/XmlImportDataTests.cs b/Src/FDO/FDOTests/XmlImportDataTests.cs index 67af2a691a..cee95ea23e 100644 --- a/Src/FDO/FDOTests/XmlImportDataTests.cs +++ b/Src/FDO/FDOTests/XmlImportDataTests.cs @@ -54,7 +54,7 @@ public void CreateTestCache() { m_now = DateTime.Now; m_cache = FdoCache.CreateCacheWithNewBlankLangProj( - new TestProjectId(FDOBackendProviderType.kMemoryOnly, "MemoryOnly.mem"), "en", "fr", "en", new ThreadHelper(), new DummyFdoUserAction()); + new TestProjectId(FDOBackendProviderType.kMemoryOnly, "MemoryOnly.mem"), "en", "fr", "en", new DummyFdoUserAction()); IDataSetup dataSetup = m_cache.ServiceLocator.GetInstance(); dataSetup.LoadDomain(BackendBulkLoadDomain.All); if (m_cache.LangProject != null) @@ -82,7 +82,6 @@ public void DestroyTestCache() { if (m_cache != null) { - m_cache.ThreadHelper.Dispose(); m_cache.Dispose(); m_cache = null; } diff --git a/Src/FDO/FDOTests/XmlListTests.cs b/Src/FDO/FDOTests/XmlListTests.cs index 08199c39d2..3a38a5b942 100644 --- a/Src/FDO/FDOTests/XmlListTests.cs +++ b/Src/FDO/FDOTests/XmlListTests.cs @@ -16,7 +16,6 @@ using System.IO; using NUnit.Framework; using SIL.FieldWorks.FDO.Application.ApplicationServices; -using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.Test.TestUtils; using SIL.Utils; using SIL.FieldWorks.Common.FwUtils; @@ -600,7 +599,7 @@ public class XmlListTests : BaseTest public void CreateMockCache() { m_cache = FdoCache.CreateCacheWithNewBlankLangProj( - new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "es", "en", new ThreadHelper(), new DummyFdoUserAction()); + new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "es", "en", new DummyFdoUserAction()); } /// @@ -609,7 +608,6 @@ public void CreateMockCache() [TearDown] public void DestroyMockCache() { - m_cache.ThreadHelper.Dispose(); m_cache.Dispose(); m_cache = null; } diff --git a/Src/FDO/FDOTests/XmlTranslatedListsTests.cs b/Src/FDO/FDOTests/XmlTranslatedListsTests.cs index 0fe2e4a93b..6de8400bdf 100644 --- a/Src/FDO/FDOTests/XmlTranslatedListsTests.cs +++ b/Src/FDO/FDOTests/XmlTranslatedListsTests.cs @@ -644,7 +644,7 @@ public class XmlTranslatedListsTests : BaseTest public void CreateMockCache() { m_cache = FdoCache.CreateCacheWithNewBlankLangProj( - new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "es", "en", new ThreadHelper(), new DummyFdoUserAction()); + new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "es", "en", new DummyFdoUserAction()); var xl = new XmlList(); using (var reader = new StringReader(XmlListTests.s_ksPartsOfSpeechXml)) @@ -673,7 +673,6 @@ public void CreateMockCache() [TearDown] public void DestroyMockCache() { - m_cache.ThreadHelper.Dispose(); m_cache.Dispose(); m_cache = null; } diff --git a/Src/FDO/FdoCacheIFwDisposableInterfaceImpl.cs b/Src/FDO/FdoCacheIFwDisposableInterfaceImpl.cs index d1f76c9376..6db2d8869e 100644 --- a/Src/FDO/FdoCacheIFwDisposableInterfaceImpl.cs +++ b/Src/FDO/FdoCacheIFwDisposableInterfaceImpl.cs @@ -12,7 +12,6 @@ using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.FDO.IOC; using SIL.Utils; -using SIL.FieldWorks.FDO.Infrastructure; namespace SIL.FieldWorks.FDO { @@ -161,7 +160,6 @@ private void Dispose(bool disposing) // Main data members. m_lgwsFactory = null; m_serviceLocator = null; - m_threadHelper = null; m_isDisposed = true; } diff --git a/Src/Common/FwUtils/IFdoUserAction.cs b/Src/FDO/IFdoUserAction.cs similarity index 88% rename from Src/Common/FwUtils/IFdoUserAction.cs rename to Src/FDO/IFdoUserAction.cs index 7201430320..96b585d832 100644 --- a/Src/Common/FwUtils/IFdoUserAction.cs +++ b/Src/FDO/IFdoUserAction.cs @@ -1,4 +1,4 @@ -// --------------------------------------------------------------------------------------------- +// --------------------------------------------------------------------------------------------- #region // Copyright (c) 2013, SIL International. All Rights Reserved. // // Copyright (c) 2013, SIL International. All Rights Reserved. @@ -9,18 +9,21 @@ #endregion // --------------------------------------------------------------------------------------------- using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.ComponentModel; using Microsoft.Win32; -namespace SIL.FieldWorks.Common.FwUtils +namespace SIL.FieldWorks.FDO { /// /// Used for getting user feedback while processing FDO requests /// public interface IFdoUserAction { + /// + /// Gets the object that is used to invoke methods on the main UI thread. + /// + ISynchronizeInvoke SynchronizeInvoke { get; } + /// /// Check with user regarding conflicting changes /// @@ -33,6 +36,11 @@ public interface IFdoUserAction /// True if user wishes to attempt reconnect. False otherwise. bool ConnectionLost(); + /// + /// Gets the last time that there was user activity. + /// + DateTime LastActivityTime { get; } + /// /// Check with user regarding which files to use /// diff --git a/Src/FDO/Infrastructure/Impl/CmObjectSurrogate.cs b/Src/FDO/Infrastructure/Impl/CmObjectSurrogate.cs index 22809020f9..f278985bf3 100644 --- a/Src/FDO/Infrastructure/Impl/CmObjectSurrogate.cs +++ b/Src/FDO/Infrastructure/Impl/CmObjectSurrogate.cs @@ -549,7 +549,7 @@ ICmObject ICmObjectOrSurrogate.Object const int nLines = 40; if (lines.Length > nLines) msg = String.Join("\n", lines.Take(nLines).ToArray()) + "\n..."; - m_cache.ThreadHelper.Invoke(() => + m_cache.ServiceLocator.GetInstance().SynchronizeInvoke.Invoke(() => { MessageBox.Show(null, msg, Strings.ksErrorCaption, MessageBoxButtons.OK, MessageBoxIcon.Error); m_cache.ServiceLocator.GetInstance().ReportException(new Exception(fullMsg, e), true); diff --git a/Src/FDO/Infrastructure/Impl/UndoStack.cs b/Src/FDO/Infrastructure/Impl/UndoStack.cs index 3b12ded3c2..f7e87f8171 100644 --- a/Src/FDO/Infrastructure/Impl/UndoStack.cs +++ b/Src/FDO/Infrastructure/Impl/UndoStack.cs @@ -8,12 +8,10 @@ // Responsibility: Randy Regnier // -------------------------------------------------------------------------------------------- using System; -using System.Collections; using System.ComponentModel; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Linq; -using System.Threading; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.FDO.Application; using SIL.Utils; @@ -98,6 +96,7 @@ internal sealed class UndoStack : IActionHandler, IActionHandlerExtensions private bool m_createMarkIfNeeded; internal FdoUnitOfWork m_currentBundle; private readonly UnitOfWorkService m_uowService; + private readonly IFdoUserAction m_userAction; // Positive values count unsaved bundles in m_undoBundles. // Negative values count unsaved bundles in m_redoBundles, that is, things Undone since the last Save. private int m_countUnsavedBundles; @@ -106,9 +105,10 @@ internal sealed class UndoStack : IActionHandler, IActionHandlerExtensions #endregion #region Constructor - public UndoStack(UnitOfWorkService uowService) + public UndoStack(UnitOfWorkService uowService, IFdoUserAction userAction) { m_uowService = uowService; + m_userAction = userAction; m_undoBundles = new Stack(); m_redoBundles = new Stack(); m_currentBundle = null; @@ -371,7 +371,7 @@ private void EndUndoTaskCommon(bool updateDateModified) /// ------------------------------------------------------------------------------------ private void DoTasksForEndOfPropChanged(FdoUnitOfWork uow, bool fromUndoRedo) { - ((CmObjectRepository)m_uowService.ObjectRepository).Cache.ThreadHelper.Invoke(() => + m_userAction.SynchronizeInvoke.Invoke(() => { if (!fromUndoRedo) { diff --git a/Src/FDO/Infrastructure/Impl/UnitOfWorkService.cs b/Src/FDO/Infrastructure/Impl/UnitOfWorkService.cs index a0251e38a0..3057147ed0 100644 --- a/Src/FDO/Infrastructure/Impl/UnitOfWorkService.cs +++ b/Src/FDO/Infrastructure/Impl/UnitOfWorkService.cs @@ -12,9 +12,11 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading; +using System.Timers; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.FDO.Application; using SIL.FieldWorks.Common.FwUtils; +using SIL.Utils; using Timer = System.Timers.Timer; namespace SIL.FieldWorks.FDO.Infrastructure.Impl @@ -93,11 +95,10 @@ internal enum FdoBusinessTransactionState } public event EventHandler OnSave; - private readonly UserActivityMonitor m_monitor; private DateTime m_lastSave = DateTime.Now; private readonly Timer m_saveTimer = new Timer(); - private bool m_fInSaveInternal = false; + private bool m_fInSaveInternal; /// /// Non-null if a Save has failed due to conflicting changes (client-server only). @@ -172,9 +173,8 @@ internal UnitOfWorkService(IDataStorer dataStorer, IdentityMap identityMap, ICmO // Make a separate stack as the initial default. This should be mainly used in tests. // It serves to keep undoable UOWs separate from non-undoable ones, the only things ever put on the NonUndoableStack. m_currentUndoStack = m_activeUndoStack = (UndoStack)CreateUndoStack(); - m_monitor = new UserActivityMonitor(); - System.Windows.Forms.Application.AddMessageFilter(m_monitor); + m_saveTimer.SynchronizingObject = userAction.SynchronizeInvoke; m_saveTimer.Interval = 1000; m_saveTimer.Elapsed += SaveOnIdle; m_saveTimer.Start(); @@ -225,7 +225,7 @@ private void Dispose(bool fDisposing) } #endregion - void SaveOnIdle(object sender, EventArgs e) + void SaveOnIdle(object sender, ElapsedEventArgs e) { lock (this) { @@ -250,7 +250,7 @@ void SaveOnIdle(object sender, EventArgs e) if (DateTime.Now - m_lastSave < TimeSpan.FromSeconds(10.0)) return; // Nor if it's been less than 2s since the user did something. We don't want to interrupt continuous activity. - if (DateTime.Now - m_monitor.LastActivityTime < TimeSpan.FromSeconds(2.0)) + if (DateTime.Now - m_userAction.LastActivityTime < TimeSpan.FromSeconds(2.0)) return; SaveInternal(); @@ -383,7 +383,7 @@ private void GetUserInputOnConflictingSave() private void RaiseSave(bool undoable) { if (OnSave != null) - OnSave(this, new SaveEventArgs() {UndoableChanges = undoable, Cache = ((CmObjectRepository)ObjectRepository).Cache}); + OnSave(this, new SaveEventArgs {UndoableChanges = undoable, Cache = ((CmObjectRepository)ObjectRepository).Cache}); } /// @@ -532,7 +532,7 @@ internal void SendPropChangedNotifications(IEnumerable change // This is very likely to modify the UI, so if the UOW is not being done on the UI thread, we need // to do at least this part on that thread. One known case is a task being done in the background // thread of ProgressDialogWithTask. - ((CmObjectRepository)ObjectRepository).Cache.ThreadHelper.Invoke(() => + m_userAction.SynchronizeInvoke.Invoke(() => { var subscribers = m_changeWatchers.ToArray(); var changes = changesEnum.ToList(); @@ -945,7 +945,7 @@ public void EndReadTask() /// public IActionHandler CreateUndoStack() { - var result = new UndoStack(this); + var result = new UndoStack(this, m_userAction); m_undoStacks.Add(result); return result; } diff --git a/Src/FDO/Infrastructure/Impl/UserActivityMonitor.cs b/Src/FDO/Infrastructure/Impl/UserActivityMonitor.cs deleted file mode 100644 index ca9967a5c3..0000000000 --- a/Src/FDO/Infrastructure/Impl/UserActivityMonitor.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows.Forms; -using SIL.Utils; - -namespace SIL.FieldWorks.FDO.Infrastructure.Impl -{ - /// - /// This class is a message filter which can be installed in order to track when the user last - /// pressed a key or did any mouse action, including moving the mouse. - /// - class UserActivityMonitor : IMessageFilter - { - internal DateTime LastActivityTime; - - private IntPtr m_lastMousePosition; - - public bool PreFilterMessage(ref Message m) - { - if(m.Msg == (int)Win32.WinMsgs.WM_MOUSEMOVE) - { - // For mouse move, we get spurious ones when it didn't really move. So check the actual position. - if (m.LParam != m_lastMousePosition) - { - LastActivityTime = DateTime.Now; - m_lastMousePosition = m.LParam; - // Enhance JohnT: suppress ones where it doesn't move?? - } - return false; - } - if ((m.Msg >= (int)Win32.WinMsgs.WM_MOUSE_Min && m.Msg <= (int)Win32.WinMsgs.WM_MOUSE_Max) - || (m.Msg >= (int)Win32.WinMsgs.WM_KEY_Min && m.Msg <= (int)Win32.WinMsgs.WM_KEY_Max)) - { - LastActivityTime = DateTime.Now; - } - return false; // don't want to block any messages. - } - } -} diff --git a/Src/FDO/SilentFdoUserAction.cs b/Src/FDO/SilentFdoUserAction.cs index 3eee9519e6..df5a4d91ca 100644 --- a/Src/FDO/SilentFdoUserAction.cs +++ b/Src/FDO/SilentFdoUserAction.cs @@ -9,11 +9,8 @@ #endregion // --------------------------------------------------------------------------------------------- using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.ComponentModel; using Microsoft.Win32; -using SIL.FieldWorks.Common.FwUtils; namespace SIL.FieldWorks.FDO { @@ -23,6 +20,25 @@ namespace SIL.FieldWorks.FDO /// public class SilentFdoUserAction : IFdoUserAction { + private readonly ISynchronizeInvoke m_synchronizeInvoke; + + /// + /// Initializes a new instance of the class. + /// + /// The synchronize invoke. + public SilentFdoUserAction(ISynchronizeInvoke synchronizeInvoke) + { + m_synchronizeInvoke = synchronizeInvoke; + } + + /// + /// Gets the object that is used to invoke methods on the main UI thread. + /// + public ISynchronizeInvoke SynchronizeInvoke + { + get { return m_synchronizeInvoke; } + } + /// /// Check with user regarding conflicting changes /// @@ -43,6 +59,14 @@ public bool ConnectionLost() return false; } + /// + /// Gets the last time that there was user activity. + /// + public DateTime LastActivityTime + { + get { return DateTime.Now; } + } + /// /// Check with user regarding which files to use /// diff --git a/Src/FDO/fdoCache.cs b/Src/FDO/fdoCache.cs index fa7ec401c4..e2ce827186 100644 --- a/Src/FDO/fdoCache.cs +++ b/Src/FDO/fdoCache.cs @@ -36,7 +36,6 @@ using SIL.CoreImpl; using SIL.FieldWorks.FDO.Infrastructure.Impl; using SIL.Utils.FileDialog; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.FDO { @@ -51,9 +50,8 @@ namespace SIL.FieldWorks.FDO public sealed partial class FdoCache { #region Data Members - private ThreadHelper m_threadHelper; // FdoCache is NOT responsible to dispose this (typically FieldWorks.s_threadHelper) private IFdoServiceLocator m_serviceLocator; - private static object m_syncRoot = new object(); + private static readonly object m_syncRoot = new object(); /// /// This is the 'hvo' for null values. (This is not very identifiable, but unfortunately, a lot of code (e.g., in Views) knows that @@ -99,14 +97,12 @@ public sealed partial class FdoCache /// /// Identifies the new project to create. /// The ICU locale of the default user WS. - /// The thread helper used for invoking actions on the main - /// UI thread. /// /// ------------------------------------------------------------------------------------ public static FdoCache CreateCacheWithNoLangProj(IProjectIdentifier projectId, - string userWsIcuLocale, ThreadHelper threadHelper, IFdoUserAction userAction) + string userWsIcuLocale, IFdoUserAction userAction) { - FdoCache createdCache = CreateCacheInternal(projectId, threadHelper, userAction); + FdoCache createdCache = CreateCacheInternal(projectId, userAction); createdCache.FullyInitializedAndReadyToRock = true; return createdCache; } @@ -126,15 +122,13 @@ public static FdoCache CreateCacheWithNoLangProj(IProjectIdentifier projectId, /// system. /// The ICU locale of the default user writing /// system. - /// The thread helper used for invoking actions on the main - /// UI thread. /// /// ------------------------------------------------------------------------------------ public static FdoCache CreateCacheWithNewBlankLangProj(IProjectIdentifier projectId, string analWsIcuLocale, string vernWsIcuLocale, string userWsIcuLocale, - ThreadHelper threadHelper, IFdoUserAction userAction) + IFdoUserAction userAction) { - FdoCache createdCache = CreateCacheInternal(projectId, userWsIcuLocale, threadHelper, + FdoCache createdCache = CreateCacheInternal(projectId, userWsIcuLocale, dataSetup => dataSetup.CreateNewLanguageProject(projectId), userAction); NonUndoableUnitOfWorkHelper.Do(createdCache.ActionHandlerAccessor, () => { @@ -159,9 +153,9 @@ public static FdoCache CreateCacheWithNewBlankLangProj(IProjectIdentifier projec public static FdoCache CreateCacheFromExistingData(IProjectIdentifier projectId, string userWsIcuLocale, IThreadedProgress progressDlg, IFdoUserAction userAction) { - return CreateCacheInternal(projectId, userWsIcuLocale, progressDlg.ThreadHelper, + return CreateCacheInternal(projectId, userWsIcuLocale, dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg), - cache => cache.Initialize(userWsIcuLocale, progressDlg), userAction); + cache => cache.Initialize(userWsIcuLocale), userAction); } /// ------------------------------------------------------------------------------------ @@ -178,9 +172,9 @@ public static FdoCache CreateCacheFromLocalProjectFile(string projectPath, string userWsIcuLocale, IThreadedProgress progressDlg, IFdoUserAction userAction) { var projectId = new SimpleProjectId(FDOBackendProviderType.kXML, projectPath); - return CreateCacheInternal(projectId, userWsIcuLocale, progressDlg.ThreadHelper, + return CreateCacheInternal(projectId, userWsIcuLocale, dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg), - cache => cache.Initialize(userWsIcuLocale, progressDlg), userAction); + cache => cache.Initialize(userWsIcuLocale), userAction); } /// ------------------------------------------------------------------------------------ @@ -191,14 +185,12 @@ public static FdoCache CreateCacheFromLocalProjectFile(string projectPath, /// Identifies the project to create (i.e., the copy). /// The ICU locale of the default user WS. /// The FdoCache to copy - /// The thread helper used for invoking actions on the main - /// UI thread. /// /// ------------------------------------------------------------------------------------ public static FdoCache CreateCacheCopy(IProjectIdentifier projectId, - string userWsIcuLocale, FdoCache sourceCache, ThreadHelper threadHelper, IFdoUserAction userAction) + string userWsIcuLocale, FdoCache sourceCache, IFdoUserAction userAction) { - return CreateCacheInternal(projectId, userWsIcuLocale, threadHelper, + return CreateCacheInternal(projectId, userWsIcuLocale, dataSetup => dataSetup.InitializeFromSource(projectId, sourceCache), userAction); } @@ -207,12 +199,9 @@ public static FdoCache CreateCacheCopy(IProjectIdentifier projectId, /// Creates a new FdoCache that uses a specified data provider. /// /// Identifies the project to create or load. - /// The thread helper used for invoking actions on the main - /// UI thread. /// /// ------------------------------------------------------------------------------------ - private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, - ThreadHelper threadHelper, IFdoUserAction userAction) + private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, IFdoUserAction userAction) { FDOBackendProviderType providerType = projectId.Type; if (providerType == FDOBackendProviderType.kXMLWithMemoryOnlyWsMgr) @@ -223,7 +212,6 @@ private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, var createdCache = servLoc.GetInstance(); createdCache.m_serviceLocator = servLoc; createdCache.m_lgwsFactory = servLoc.GetInstance(); - createdCache.m_threadHelper = threadHelper; return createdCache; } @@ -233,15 +221,13 @@ private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, /// /// Identifies the project to create or load. /// The ICU locale of the default user WS. - /// The thread helper used for invoking actions on the main - /// UI thread. /// The data setup action to perform. /// /// ------------------------------------------------------------------------------------ private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, - string userWsIcuLocale, ThreadHelper threadHelper, Action doThe, IFdoUserAction userAction) + string userWsIcuLocale, Action doThe, IFdoUserAction userAction) { - return CreateCacheInternal(projectId, userWsIcuLocale, threadHelper, doThe, null, userAction); + return CreateCacheInternal(projectId, userWsIcuLocale, doThe, null, userAction); } /// ------------------------------------------------------------------------------------ @@ -250,24 +236,22 @@ private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, /// /// Identifies the project to create or load. /// The ICU locale of the default user WS. - /// The thread helper used for invoking actions on the main - /// UI thread. /// The data setup action to perform. /// The initialization step to perfrom (can be null). /// /// The newly created cache /// ------------------------------------------------------------------------------------ private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, - string userWsIcuLocale, ThreadHelper threadHelper, Action doThe, + string userWsIcuLocale, Action doThe, Action initialize, IFdoUserAction userAction) { FDOBackendProviderType providerType = projectId.Type; bool useMemoryWsManager = (providerType == FDOBackendProviderType.kMemoryOnly || providerType == FDOBackendProviderType.kXMLWithMemoryOnlyWsMgr); - FdoCache createdCache = CreateCacheInternal(projectId, threadHelper, userAction); + FdoCache createdCache = CreateCacheInternal(projectId, userAction); // Init backend data provider - IDataSetup dataSetup = createdCache.ServiceLocator.GetInstance(); + var dataSetup = createdCache.ServiceLocator.GetInstance(); dataSetup.UseMemoryWritingSystemManager = useMemoryWsManager; doThe(dataSetup); if (initialize != null) @@ -295,7 +279,7 @@ private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, /// Initializes this cache (called whenever the cache is created). /// /// ------------------------------------------------------------------------------------ - private void Initialize(string userWsIcuLocale, IThreadedProgress progressDlg) + private void Initialize(string userWsIcuLocale) { // check for updated global writing systems and ask the user if they want to use it var writingSystemsWithNewerGlobalVersions = new List(); @@ -379,7 +363,7 @@ private static bool IsUpdatedWsInUse(StringBuilder updatedWssInUseBuilder) /// The progress dialog. /// One or more parameters, supplied in this order: /// 0. A string containing the name of the project (required); - /// 1. A ThreadHelper used for invoking actions on the main UI thread (required); + /// 1. An ISynchronizeInvoke used for invoking actions on the main UI thread (required); /// 2. An IWritingSystem to be used as the default analylis writing system (default: English); /// 3. An IWritingSystem to be used as the default vernacular writing system (default: French); /// 4. A string with the ICU locale of the UI writing system (default: "en"). @@ -392,11 +376,11 @@ private static bool IsUpdatedWsInUse(StringBuilder updatedWssInUseBuilder) public static string CreateNewLangProj(IThreadedProgress progressDlg, params object[] parameters) { if (parameters == null || parameters.Length < 2) - throw new ArgumentException("Parameters must include at least a project name and the ThreadHelper"); + throw new ArgumentException("Parameters must include at least a project name and a SynchronizeInvoke object"); var projectName = (string)parameters[0]; if (string.IsNullOrEmpty(projectName)) - throw new ArgumentNullException("projectName", "Cannot be null or empty"); - var threadHelper = (ThreadHelper)parameters[1]; + throw new ArgumentNullException("parameters", "Cannot be null or empty"); + var synchronizeInvoke = (ISynchronizeInvoke) parameters[1]; IWritingSystem analWrtSys = (parameters.Length > 2) ? (IWritingSystem)parameters[2] : null; IWritingSystem vernWrtSys = (parameters.Length > 3) ? (IWritingSystem)parameters[3] : null; var userIcuLocale = (parameters.Length > 4 && parameters[4] != null) ? (string)parameters[4] : "en"; @@ -419,8 +403,8 @@ public static string CreateNewLangProj(IThreadedProgress progressDlg, params obj } var projectId = new SimpleProjectId(FDOBackendProviderType.kXML, dbFileName); - using (var cache = CreateCacheInternal(projectId, - userIcuLocale, threadHelper, dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg), new SilentFdoUserAction())) + using (var cache = CreateCacheInternal(projectId, userIcuLocale, + dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg), new SilentFdoUserAction(synchronizeInvoke))) { if (progressDlg != null) { @@ -522,7 +506,7 @@ public static string CreateNewLangProj(IThreadedProgress progressDlg, params obj // Rewrite all objects to make sure they all have all of the basic properties. if (progressDlg != null) { - progressDlg.ProgressBarStyle = ProgressBarStyle.Marquee; + progressDlg.IsIndeterminate = true; progressDlg.Message = AppStrings.InitializeSavingMigratedDataProgressMessage; progressDlg.RunTask(cache.SaveAndForceNewestXmlForCmObjectWithoutUnitOfWork, cache.m_serviceLocator.ObjectRepository.AllInstances().ToList()); @@ -865,16 +849,6 @@ internal static object SyncRoot get { return m_syncRoot; } } - /// ------------------------------------------------------------------------------------ - /// - /// Gets the thread helper used for invoking actions on the main UI thread. - /// - /// ------------------------------------------------------------------------------------ - public ThreadHelper ThreadHelper - { - get { return m_threadHelper; } - } - /// ------------------------------------------------------------------------------------ /// /// Gets the information about the loaded project. @@ -1463,14 +1437,14 @@ private void EnsureValidLinkedFilesFolder() if (MiscUtils.RunningTests) return; - var linkedFilesFolder = this.LangProject.LinkedFilesRootDir; - var defaultFolder = DirectoryFinder.GetDefaultLinkedFilesDir(this.ProjectId.ProjectFolder); + var linkedFilesFolder = LangProject.LinkedFilesRootDir; + var defaultFolder = DirectoryFinder.GetDefaultLinkedFilesDir(ProjectId.ProjectFolder); EnsureValidLinkedFilesFolderCore(linkedFilesFolder, defaultFolder); if (!Directory.Exists(linkedFilesFolder)) { if (!Directory.Exists(defaultFolder)) - defaultFolder = this.ProjectId.ProjectFolder; + defaultFolder = ProjectId.ProjectFolder; MessageBox.Show(String.Format(Strings.ksInvalidLinkedFilesFolder, linkedFilesFolder), Strings.ksErrorCaption); while (!Directory.Exists(linkedFilesFolder)) { @@ -1483,8 +1457,8 @@ private void EnsureValidLinkedFilesFolder() linkedFilesFolder = folderBrowserDlg.SelectedPath; } } - NonUndoableUnitOfWorkHelper.DoUsingNewOrCurrentUOW(this.ActionHandlerAccessor, () => - { this.LangProject.LinkedFilesRootDir = linkedFilesFolder; }); + NonUndoableUnitOfWorkHelper.DoUsingNewOrCurrentUOW(ActionHandlerAccessor, () => + { LangProject.LinkedFilesRootDir = linkedFilesFolder; }); } } @@ -2022,7 +1996,7 @@ public static List ConvertCmObjectsToHvoList(IEnumerable ConvertCmObjectsToHvos(IEnumerable cmObjects) where TDerived : ICmObject { - foreach (ICmObject cmObject in cmObjects) + foreach (TDerived cmObject in cmObjects) yield return cmObject.Hvo; } } diff --git a/Src/FDOBrowser/FDOBrowserForm.Designer.cs b/Src/FDOBrowser/FDOBrowserForm.Designer.cs index 2d1113faea..83d56ec786 100644 --- a/Src/FDOBrowser/FDOBrowserForm.Designer.cs +++ b/Src/FDOBrowser/FDOBrowserForm.Designer.cs @@ -26,11 +26,8 @@ protected override void Dispose(bool disposing) m_cache.ServiceLocator.GetInstance().Commit(); m_cache.Dispose(); } - if (m_ThreadHelper != null) - m_ThreadHelper.Dispose(); } m_cache = null; // Don't try to use it again - m_ThreadHelper = null; base.Dispose(disposing); } diff --git a/Src/FDOBrowser/FDOBrowserForm.cs b/Src/FDOBrowser/FDOBrowserForm.cs index 3ba1187900..4d1151807b 100644 --- a/Src/FDOBrowser/FDOBrowserForm.cs +++ b/Src/FDOBrowser/FDOBrowserForm.cs @@ -8,7 +8,6 @@ using System.Reflection; using System.Resources; using System.Windows.Forms; -using FwRemoteDatabaseConnector; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.Common.Controls; using SIL.FieldWorks.Common.Framework.DetailControls; @@ -16,10 +15,8 @@ using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.Application; using SIL.FieldWorks.FDO.Infrastructure; -using SIL.FieldWorks.FDO.Infrastructure.Impl; using SIL.FieldWorks.Resources; using SIL.ObjectBrowser; -using SIL.Utils; using WeifenLuo.WinFormsUI.Docking; using XCore; @@ -52,7 +49,6 @@ public partial class FDOBrowserForm : ObjectBrowser, IHelpTopicProvider private InspectorWnd m_repositoryWnd; private int saveClid; private string FileName = string.Empty; - private ThreadHelper m_ThreadHelper; //private FwTextBox m_textBox; //private System.Windows.Forms.Panel panel1; @@ -378,16 +374,14 @@ protected override void OpenFile(string fileName) // Init backend data provider // TODO: Get the correct ICU local for the user writing system - if (m_ThreadHelper == null) - m_ThreadHelper = new ThreadHelper(); if (isMemoryBEP) - m_cache = FdoCache.CreateCacheWithNewBlankLangProj(new BrowserProjectId(bepType, null), "en", "en", "en", m_ThreadHelper, new FdoBrowserUserAction()); + m_cache = FdoCache.CreateCacheWithNewBlankLangProj(new BrowserProjectId(bepType, null), "en", "en", "en", new FdoBrowserUserAction(this)); else { - using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(this, m_ThreadHelper)) + using (var progressDlg = new ProgressDialogWithTask(this)) { - m_cache = FdoCache.CreateCacheFromExistingData(new BrowserProjectId(bepType, fileName), "en", progressDlg, new FdoBrowserUserAction()); + m_cache = FdoCache.CreateCacheFromExistingData(new BrowserProjectId(bepType, fileName), "en", progressDlg, new FdoBrowserUserAction(this)); } } // var v = m_cache. diff --git a/Src/FDOBrowser/FDOClassList.cs b/Src/FDOBrowser/FDOClassList.cs index b2aebcf8c7..d77e58e907 100644 --- a/Src/FDOBrowser/FDOClassList.cs +++ b/Src/FDOBrowser/FDOClassList.cs @@ -139,15 +139,15 @@ private static void LoadFDOClassNames() if (s_allFDOClassNames != null) return; - using (FdoCache cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", null, new FdoBrowserUserAction())) + using (FdoCache cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", new FdoBrowserUserAction(null))) { - IFwMetaDataCacheManaged mdc = (IFwMetaDataCacheManaged)cache.MainCacheAccessor.MetaDataCache; - s_allFDOClassNames = new List(); + IFwMetaDataCacheManaged mdc = (IFwMetaDataCacheManaged)cache.MainCacheAccessor.MetaDataCache; + s_allFDOClassNames = new List(); - foreach (int clsid in mdc.GetClassIds()) - s_allFDOClassNames.Add(mdc.GetClassName(clsid)); + foreach (int clsid in mdc.GetClassIds()) + s_allFDOClassNames.Add(mdc.GetClassName(clsid)); - s_allFDOClassNames.Sort((x, y) => x.CompareTo(y)); + s_allFDOClassNames.Sort((x, y) => x.CompareTo(y)); } } diff --git a/Src/FDOBrowser/FdoBrowserUserAction.cs b/Src/FDOBrowser/FdoBrowserUserAction.cs index 0c05e83eb2..c4cbbc9244 100644 --- a/Src/FDOBrowser/FdoBrowserUserAction.cs +++ b/Src/FDOBrowser/FdoBrowserUserAction.cs @@ -9,14 +9,30 @@ #endregion // --------------------------------------------------------------------------------------------- using System; +using System.ComponentModel; using System.Windows.Forms; using Microsoft.Win32; -using SIL.FieldWorks.Common.FwUtils; +using SIL.FieldWorks.FDO; namespace FDOBrowser { class FdoBrowserUserAction : IFdoUserAction { + private readonly ISynchronizeInvoke m_synchronizeInvoke; + + public FdoBrowserUserAction(ISynchronizeInvoke synchronizeInvoke) + { + m_synchronizeInvoke = synchronizeInvoke; + } + + /// + /// Gets the object that is used to invoke methods on the main UI thread. + /// + public ISynchronizeInvoke SynchronizeInvoke + { + get { return m_synchronizeInvoke; } + } + /// /// Check with user regarding conflicting changes /// @@ -90,6 +106,14 @@ public void MessageBox() throw new NotImplementedException(); } + /// + /// Gets the last time that there was user activity. + /// + public DateTime LastActivityTime + { + get { return DateTime.Now; } + } + /// /// Show a dialog or output to the error log, as appropriate. /// diff --git a/Src/FDOBrowser/ModelWnd.cs b/Src/FDOBrowser/ModelWnd.cs index 10385dbcc0..a45fa36e9d 100644 --- a/Src/FDOBrowser/ModelWnd.cs +++ b/Src/FDOBrowser/ModelWnd.cs @@ -40,7 +40,7 @@ public ModelWnd() m_lvModel.Font = SystemFonts.MenuFont; // Add model browsing cache (no data, just model browsing). - m_cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", new ThreadHelper(), new FdoBrowserUserAction()); + m_cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", new FdoBrowserUserAction(this)); m_mdc = (IFwMetaDataCacheManaged)m_cache.MainCacheAccessor.MetaDataCache; PopulateModelTree(); diff --git a/Src/FdoUi/FdoUserActionWindowsForms.cs b/Src/FdoUi/FdoUserActionWindowsForms.cs index f1a3b0115c..6dd7643439 100644 --- a/Src/FdoUi/FdoUserActionWindowsForms.cs +++ b/Src/FdoUi/FdoUserActionWindowsForms.cs @@ -9,10 +9,11 @@ #endregion // --------------------------------------------------------------------------------------------- using System; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Windows.Forms; using Microsoft.Win32; -using SIL.FieldWorks.Common.FwUtils; -using SIL.FieldWorks.FDO.DomainServices.BackupRestore; +using SIL.FieldWorks.FDO; using SIL.FieldWorks.FdoUi.Dialogs; using SIL.Utils; using XCore; @@ -25,10 +26,21 @@ namespace SIL.FieldWorks.FdoUi public class FdoUserActionWindowsForms : IFdoUserAction { private readonly IHelpTopicProvider m_helpTopicProvider; + private readonly ISynchronizeInvoke m_synchronizeInvoke; - public FdoUserActionWindowsForms(IHelpTopicProvider helpTopicProvider) + public FdoUserActionWindowsForms(IHelpTopicProvider helpTopicProvider, ISynchronizeInvoke synchronizeInvoke) { m_helpTopicProvider = helpTopicProvider; + m_synchronizeInvoke = synchronizeInvoke; + Application.AddMessageFilter(new UserActivityMonitor(this)); + } + + /// + /// Gets the object that is used to invoke methods on the main UI thread. + /// + public ISynchronizeInvoke SynchronizeInvoke + { + get { return m_synchronizeInvoke; } } /// @@ -136,6 +148,8 @@ public bool ReportException(Exception error, bool isLethal) return ErrorReporter.ReportException(error, null, null, null, isLethal); } + public DateTime LastActivityTime { get; private set; } + /// /// Reports duplicate guids to the user /// @@ -146,5 +160,43 @@ public void ReportDuplicateGuids(RegistryKey applicationKey, string emailAddress { ErrorReporter.ReportDuplicateGuids(applicationKey, emailAddress, null, errorText); } + + /// + /// This class is a message filter which can be installed in order to track when the user last + /// pressed a key or did any mouse action, including moving the mouse. + /// + [SuppressMessage("Gendarme.Rules.Design", "TypesWithNativeFieldsShouldBeDisposableRule", Justification="No unmanaged resources to release")] + class UserActivityMonitor : IMessageFilter + { + private readonly FdoUserActionWindowsForms m_userAction; + + public UserActivityMonitor(FdoUserActionWindowsForms userAction) + { + m_userAction = userAction; + } + + private IntPtr m_lastMousePosition; + + public bool PreFilterMessage(ref Message m) + { + if(m.Msg == (int)Win32.WinMsgs.WM_MOUSEMOVE) + { + // For mouse move, we get spurious ones when it didn't really move. So check the actual position. + if (m.LParam != m_lastMousePosition) + { + m_userAction.LastActivityTime = DateTime.Now; + m_lastMousePosition = m.LParam; + // Enhance JohnT: suppress ones where it doesn't move?? + } + return false; + } + if ((m.Msg >= (int)Win32.WinMsgs.WM_MOUSE_Min && m.Msg <= (int)Win32.WinMsgs.WM_MOUSE_Max) + || (m.Msg >= (int)Win32.WinMsgs.WM_KEY_Min && m.Msg <= (int)Win32.WinMsgs.WM_KEY_Max)) + { + m_userAction.LastActivityTime = DateTime.Now; + } + return false; // don't want to block any messages. + } + } } } diff --git a/Src/FdoUi/ProgressBarWrapper.cs b/Src/FdoUi/ProgressBarWrapper.cs index d300241cb2..8385bd1665 100644 --- a/Src/FdoUi/ProgressBarWrapper.cs +++ b/Src/FdoUi/ProgressBarWrapper.cs @@ -14,7 +14,6 @@ using System.Diagnostics.CodeAnalysis; using System.Windows.Forms; using SIL.FieldWorks.Common.FwUtils; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.FdoUi { @@ -24,7 +23,6 @@ namespace SIL.FieldWorks.FdoUi [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", Justification="Disposable member is exposed for Dispose call if necessary")] public class ProgressBarWrapper : IProgress { - private readonly ProgressBar m_progressBar; /// /// Gets the wrapped ProgressBar @@ -119,6 +117,15 @@ public int Maximum set { m_progressBar.Maximum = value; } } + /// + /// Gets an object to be used for ensuring that required tasks are invoked on the main + /// UI thread. + /// + public ISynchronizeInvoke SynchronizeInvoke + { + get { return m_progressBar; } + } + /// /// Gets the form displaying the progress (used for message box owners, etc). If the progress /// is not associated with a visible Form, then this returns its owning form, if any. @@ -126,12 +133,12 @@ public int Maximum public Form Form { get; set; } /// - /// Gets or sets the progress bar style. + /// Gets or sets a value indicating whether this progress is indeterminate. /// - public ProgressBarStyle ProgressBarStyle + public bool IsIndeterminate { - get { return ProgressBarStyleExtensions.Convert(m_progressBar.Style); } - set { m_progressBar.Style = ProgressBarStyleExtensions.Convert(value); } + get { return m_progressBar.Style == ProgressBarStyle.Marquee; } + set { m_progressBar.Style = value ? ProgressBarStyle.Marquee : ProgressBarStyle.Continuous; } } /// diff --git a/Src/FwCoreDlgs/BackupRestore/BackupProjectDlg.cs b/Src/FwCoreDlgs/BackupRestore/BackupProjectDlg.cs index 1ab1252e3b..c600bfd3e5 100644 --- a/Src/FwCoreDlgs/BackupRestore/BackupProjectDlg.cs +++ b/Src/FwCoreDlgs/BackupRestore/BackupProjectDlg.cs @@ -169,7 +169,7 @@ private void m_backUp_Click(object sender, EventArgs e) try { using (new WaitCursor(this)) - using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(this, m_cache.ThreadHelper)) + using (var progressDlg = new ProgressDialogWithTask(this)) { BackupFilePath = m_presenter.BackupProject(progressDlg); } diff --git a/Src/FwCoreDlgs/ChooseLangProjectDialog.cs b/Src/FwCoreDlgs/ChooseLangProjectDialog.cs index 398e095234..d395f0ef0c 100644 --- a/Src/FwCoreDlgs/ChooseLangProjectDialog.cs +++ b/Src/FwCoreDlgs/ChooseLangProjectDialog.cs @@ -23,6 +23,7 @@ using System.Windows.Forms; using SIL.FieldWorks.Common.Controls; using SIL.FieldWorks.Common.FwUtils; +using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.Resources; using SIL.Utils; @@ -45,7 +46,6 @@ public partial class ChooseLangProjectDialog : Form private readonly Rectangle m_initialBounds = Rectangle.Empty; private readonly int m_initialSplitterPosition = -1; private ObtainedProjectType m_obtainedProjectType = ObtainedProjectType.None; - private IFdoUserAction m_userAction; #endregion #region LanguageProjectInfo class @@ -103,7 +103,7 @@ private ChooseLangProjectDialog() /// The initial client bounds of the dialog. /// The initial splitter position. /// ------------------------------------------------------------------------------------ - public ChooseLangProjectDialog(Rectangle bounds, int splitterPosition) : this(null, false, null) + public ChooseLangProjectDialog(Rectangle bounds, int splitterPosition) : this(null, false) { m_initialBounds = bounds; m_initialSplitterPosition = splitterPosition; @@ -120,10 +120,9 @@ public ChooseLangProjectDialog(Rectangle bounds, int splitterPosition) : this(nu /// If set to true the dialog will be /// used to assosiate a FieldWorks project with another application (e.g. Paratext). /// - /// /// ------------------------------------------------------------------------------------ public ChooseLangProjectDialog(IHelpTopicProvider helpTopicProvider, - bool openToAssosiateFwProject, IFdoUserAction userAction) + bool openToAssosiateFwProject) : this() { m_helpTopicProvider = helpTopicProvider; @@ -134,8 +133,6 @@ public ChooseLangProjectDialog(IHelpTopicProvider helpTopicProvider, if (openToAssosiateFwProject) Text = FwCoreDlgs.kstidOpenToAssociateFwProj; - m_userAction = userAction; - m_lblAddNetworkComp.Font = SystemFonts.IconTitleFont; m_lblChoosePrj.Font = SystemFonts.IconTitleFont; m_lblLookIn.Font = SystemFonts.IconTitleFont; @@ -564,7 +561,7 @@ private void OpenFwDataProjectLinkClicked(object sender, LinkLabelLinkClickedEve private void OpenBridgeProjectLinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { // ObtainProjectFromAnySource may return null, empty string, or the full pathname to an fwdata file. - Project = ObtainProjectMethod.ObtainProjectFromAnySource(this, m_helpTopicProvider, out m_obtainedProjectType, m_userAction); + Project = ObtainProjectMethod.ObtainProjectFromAnySource(this, m_helpTopicProvider, out m_obtainedProjectType); Server = null; if (String.IsNullOrEmpty(Project)) return; // Don't close the Open project dialog yet (LT-13187) diff --git a/Src/FwCoreDlgs/FwNewLangProject.cs b/Src/FwCoreDlgs/FwNewLangProject.cs index f6f40e84aa..c7fa25da0a 100644 --- a/Src/FwCoreDlgs/FwNewLangProject.cs +++ b/Src/FwCoreDlgs/FwNewLangProject.cs @@ -677,7 +677,7 @@ protected void CreateNewLangProjWithProgress() { try { - using (var progressDlg = new ProgressDialogWithTask(this, null)) + using (var progressDlg = new ProgressDialogWithTask(this)) { progressDlg.Title = string.Format(FwCoreDlgs.kstidCreateLangProjCaption, ProjectName); string anthroFile = null; diff --git a/Src/FwCoreDlgs/FwSplashScreen.cs b/Src/FwCoreDlgs/FwSplashScreen.cs index a5bb9052e3..93619a27e0 100644 --- a/Src/FwCoreDlgs/FwSplashScreen.cs +++ b/Src/FwCoreDlgs/FwSplashScreen.cs @@ -12,7 +12,6 @@ // Responsibility: TE Team // -------------------------------------------------------------------------------------------- using System; -using System.Drawing; using System.ComponentModel; using System.Diagnostics; using System.Reflection; @@ -20,7 +19,6 @@ using System.Windows.Forms; using SIL.FieldWorks.Common.FwUtils; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.FwCoreDlgs { @@ -380,6 +378,15 @@ public string Title set { } } + /// + /// Gets an object to be used for ensuring that required tasks are invoked on the main + /// UI thread. + /// + public ISynchronizeInvoke SynchronizeInvoke + { + get { return m_splashScreen; } + } + /// ------------------------------------------------------------------------------------ /// /// Gets the progress as a form (used for message box owners, etc). @@ -390,25 +397,24 @@ public Form Form get { return m_splashScreen; } } - /// ------------------------------------------------------------------------------------ /// - /// Gets or sets the style of the ProgressBar. + /// Gets or sets a value indicating whether this progress is indeterminate. /// - /// ------------------------------------------------------------------------------------ - public ProgressBarStyle ProgressBarStyle + public bool IsIndeterminate { get { if (m_splashScreen.InvokeRequired) - return (ProgressBarStyle)m_splashScreen.Invoke((Func)(() => m_splashScreen.ProgressBarStyle)); - return m_splashScreen.ProgressBarStyle; + return (bool) m_splashScreen.Invoke((Func)(() => m_splashScreen.IsIndeterminate)); + return m_splashScreen.IsIndeterminate; } + set { if (m_splashScreen.InvokeRequired) - m_splashScreen.Invoke((Action)(style => m_splashScreen.ProgressBarStyle = style), value); + m_splashScreen.Invoke((Action)(b => m_splashScreen.IsIndeterminate = b), value); else - m_splashScreen.ProgressBarStyle = value; + m_splashScreen.IsIndeterminate = value; } } diff --git a/Src/FwCoreDlgs/RealSplashScreen.cs b/Src/FwCoreDlgs/RealSplashScreen.cs index 86ef398445..061cf435bd 100644 --- a/Src/FwCoreDlgs/RealSplashScreen.cs +++ b/Src/FwCoreDlgs/RealSplashScreen.cs @@ -20,7 +20,6 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; using SIL.FieldWorks.Common.Controls; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.FwCoreDlgs { @@ -489,6 +488,15 @@ public string Message } } + /// + /// Gets an object to be used for ensuring that required tasks are invoked on the main + /// UI thread. + /// + public ISynchronizeInvoke SynchronizeInvoke + { + get { return this; } + } + /// ------------------------------------------------------------------------------------ /// /// Gets the form displaying the progress (used for message box owners, etc). If the progress @@ -500,18 +508,13 @@ public Form Form get { return this; } } - /// ------------------------------------------------------------------------------------ /// - /// Gets or sets the style of the ProgressBar. + /// Gets or sets a value indicating whether this progress is indeterminate. /// - /// ------------------------------------------------------------------------------------ - public ProgressBarStyle ProgressBarStyle + public bool IsIndeterminate { - get { return marqueeGif.Visible ? ProgressBarStyle.Marquee : ProgressBarStyle.Continuous; } - set - { - marqueeGif.Visible = (value == ProgressBarStyle.Marquee); - } + get { return marqueeGif.Visible; } + set { marqueeGif.Visible = value; } } /// ------------------------------------------------------------------------------------ diff --git a/Src/LexText/Interlinear/BIRDInterlinearImporter.cs b/Src/LexText/Interlinear/BIRDInterlinearImporter.cs index d0d8b8716a..e7c43921e6 100644 --- a/Src/LexText/Interlinear/BIRDInterlinearImporter.cs +++ b/Src/LexText/Interlinear/BIRDInterlinearImporter.cs @@ -494,7 +494,7 @@ private static bool CheckAndAddLanguagesInternal(FdoCache cache, Interlineartext //we need to invoke the dialog on the main thread so we can use the progress dialog as the parent. //otherwise the message box can be displayed behind everything var instructions = GetInstructions(interlinText, writingSystem.LanguageName, ITextStrings.ksImportVernacLangMissing); - IAsyncResult asyncResult = progress.ThreadHelper.BeginInvoke(new ShowDialogAboveProgressbarDelegate(ShowDialogAboveProgressbar), + IAsyncResult asyncResult = progress.SynchronizeInvoke.BeginInvoke(new ShowDialogAboveProgressbarDelegate(ShowDialogAboveProgressbar), new object[] { progress, @@ -502,7 +502,7 @@ private static bool CheckAndAddLanguagesInternal(FdoCache cache, Interlineartext ITextStrings.ksImportVernacLangMissingTitle, MessageBoxButtons.OKCancel }); - result = (DialogResult)progress.ThreadHelper.EndInvoke(asyncResult); + result = (DialogResult)progress.SynchronizeInvoke.EndInvoke(asyncResult); if (result == DialogResult.OK) { cache.LanguageProject.AddToCurrentVernacularWritingSystems((IWritingSystem)writingSystem); @@ -519,7 +519,7 @@ private static bool CheckAndAddLanguagesInternal(FdoCache cache, Interlineartext { var instructions = GetInstructions(interlinText, writingSystem.LanguageName, ITextStrings.ksImportAnalysisLangMissing); - IAsyncResult asyncResult = progress.ThreadHelper.BeginInvoke(new ShowDialogAboveProgressbarDelegate(ShowDialogAboveProgressbar), + IAsyncResult asyncResult = progress.SynchronizeInvoke.BeginInvoke(new ShowDialogAboveProgressbarDelegate(ShowDialogAboveProgressbar), new object[] { progress, @@ -527,7 +527,7 @@ private static bool CheckAndAddLanguagesInternal(FdoCache cache, Interlineartext ITextStrings.ksImportAnalysisLangMissingTitle, MessageBoxButtons.OKCancel }); - result = (DialogResult)progress.ThreadHelper.EndInvoke(asyncResult); + result = (DialogResult)progress.SynchronizeInvoke.EndInvoke(asyncResult); //alert the user if (result == DialogResult.OK) { diff --git a/Src/LexText/Interlinear/InterlinearImportDlg.cs b/Src/LexText/Interlinear/InterlinearImportDlg.cs index 2d03682d16..3a49931d4c 100644 --- a/Src/LexText/Interlinear/InterlinearImportDlg.cs +++ b/Src/LexText/Interlinear/InterlinearImportDlg.cs @@ -51,7 +51,7 @@ private void m_btnBrowse_Click(object sender, EventArgs e) private void m_btnOK_Click(object sender, EventArgs e) { - using (var dlg = new ProgressDialogWithTask(this, m_cache.ThreadHelper)) + using (var dlg = new ProgressDialogWithTask(this)) { dlg.AllowCancel = false; dlg.Minimum = 0; diff --git a/Src/LexText/Interlinear/InterlinearSfmImportWizard.cs b/Src/LexText/Interlinear/InterlinearSfmImportWizard.cs index 28290a8208..19a6598f70 100644 --- a/Src/LexText/Interlinear/InterlinearSfmImportWizard.cs +++ b/Src/LexText/Interlinear/InterlinearSfmImportWizard.cs @@ -517,7 +517,7 @@ protected override void OnFinishButton() SaveSettings(); if (string.IsNullOrEmpty(m_fileListBox.Text)) return; - using (var dlg = new ProgressDialogWithTask(this, m_cache.ThreadHelper)) + using (var dlg = new ProgressDialogWithTask(this)) { dlg.AllowCancel = false; dlg.Minimum = 0; diff --git a/Src/LexText/Interlinear/LinguaLinksImport.cs b/Src/LexText/Interlinear/LinguaLinksImport.cs index 399f03c146..754f0353e4 100644 --- a/Src/LexText/Interlinear/LinguaLinksImport.cs +++ b/Src/LexText/Interlinear/LinguaLinksImport.cs @@ -467,7 +467,7 @@ private static void NormalizeItems(item[] items) virtual protected DialogResult ShowPossibleMergeDialog(IThreadedProgress progress) { //we need to invoke the dialog on the main thread so we can use the progress dialog as the parent. //otherwise the message box can be displayed behind everything - IAsyncResult asyncResult = progress.ThreadHelper.BeginInvoke(new ShowDialogAboveProgressbarDelegate(ShowDialogAboveProgressbar), + IAsyncResult asyncResult = progress.SynchronizeInvoke.BeginInvoke(new ShowDialogAboveProgressbarDelegate(ShowDialogAboveProgressbar), new object[] { progress, @@ -475,7 +475,7 @@ virtual protected DialogResult ShowPossibleMergeDialog(IThreadedProgress progres ITextStrings.ksAskMergeInterlinearTextTitle, MessageBoxButtons.YesNo }); - return (DialogResult)progress.ThreadHelper.EndInvoke(asyncResult); + return (DialogResult)progress.SynchronizeInvoke.EndInvoke(asyncResult); } private static ITsString GetSpaceAdjustedPunctString(ILgWritingSystemFactory wsFactory, ITsStrFactory tsStrFactory, diff --git a/Src/LexText/Interlinear/LinguaLinksImportDlg.cs b/Src/LexText/Interlinear/LinguaLinksImportDlg.cs index 12a3624f11..3286f6017f 100644 --- a/Src/LexText/Interlinear/LinguaLinksImportDlg.cs +++ b/Src/LexText/Interlinear/LinguaLinksImportDlg.cs @@ -19,7 +19,6 @@ using SIL.FieldWorks.Common.RootSites; using SIL.FieldWorks.XWorks; using SilEncConverters40; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.IText { @@ -489,6 +488,16 @@ public bool Canceled get { throw new NotImplementedException(); } } + /// + /// Gets an object to be used for ensuring that required tasks are invoked on the main + /// UI thread. + /// + /// + public ISynchronizeInvoke SynchronizeInvoke + { + get { throw new NotImplementedException(); } + } + /// /// Gets the progress as a form (used for message box owners, etc). /// @@ -497,11 +506,12 @@ public Form Form get { throw new NotImplementedException(); } } - public ProgressBarStyle ProgressBarStyle + public bool IsIndeterminate { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } + public bool AllowCancel { get { throw new NotImplementedException(); } @@ -896,7 +906,7 @@ private void btnImport_Click(object sender, EventArgs e) { // if the shift key is down, then just build the phaseNoutput files bool runToCompletion = ((ModifierKeys & Keys.Shift) != Keys.Shift); - using (var dlg = new ProgressDialogWithTask(this, m_cache.ThreadHelper)) + using (var dlg = new ProgressDialogWithTask(this)) { dlg.AllowCancel = true; diff --git a/Src/LexText/LexTextControls/DataNotebook/NotebookImportWiz.cs b/Src/LexText/LexTextControls/DataNotebook/NotebookImportWiz.cs index 0211c6414c..a553b34504 100644 --- a/Src/LexText/LexTextControls/DataNotebook/NotebookImportWiz.cs +++ b/Src/LexText/LexTextControls/DataNotebook/NotebookImportWiz.cs @@ -40,7 +40,6 @@ using System.Globalization; using SIL.FieldWorks.Common.RootSites; using SilEncConverters40; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.LexText.Controls.DataNotebook { @@ -2473,12 +2472,11 @@ private void DoImport() { using (new WaitCursor(this)) { - using (var progressDlg = new ProgressDialogWithTask(this, m_cache.ThreadHelper)) + using (var progressDlg = new ProgressDialogWithTask(this)) { progressDlg.Minimum = 0; progressDlg.Maximum = 100; progressDlg.AllowCancel = true; - progressDlg.ProgressBarStyle = ProgressBarStyle.Continuous; progressDlg.Restartable = true; progressDlg.Title = String.Format(LexTextControls.ksImportingFrom0, m_sSfmDataFile); m_sLogFile = (string)progressDlg.RunTask(true, ImportStdFmtFile, diff --git a/Src/LexText/LexTextControls/LexImportWizard.cs b/Src/LexText/LexTextControls/LexImportWizard.cs index 41322b38d1..b22d71c469 100644 --- a/Src/LexText/LexTextControls/LexImportWizard.cs +++ b/Src/LexText/LexTextControls/LexImportWizard.cs @@ -1923,7 +1923,7 @@ protected override void OnFinishButton() SaveSettings(); - using (var dlg = new ProgressDialogWithTask(this, m_cache.ThreadHelper)) + using (var dlg = new ProgressDialogWithTask(this)) { dlg.AllowCancel = true; dlg.Maximum = 200; diff --git a/Src/LexText/LexTextControls/LexTextControlsTests/LiftExportTests.cs b/Src/LexText/LexTextControls/LexTextControlsTests/LiftExportTests.cs index d6b1311cd1..d780670a44 100644 --- a/Src/LexText/LexTextControls/LexTextControlsTests/LiftExportTests.cs +++ b/Src/LexText/LexTextControls/LexTextControlsTests/LiftExportTests.cs @@ -27,6 +27,7 @@ using SIL.FieldWorks.FDO.Application; using SIL.FieldWorks.FDO.Application.ApplicationServices; using SIL.FieldWorks.FDO.DomainServices; +using SIL.FieldWorks.FDO.FDOTests; using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.Test.TestUtils; using SIL.Utils; @@ -458,7 +459,6 @@ public class LiftExportTests : BaseTest "" + Environment.NewLine; private FdoCache m_cache; - private ThreadHelper m_ThreadHelper; private readonly Dictionary m_mapSemanticDomains = new Dictionary(); private readonly Dictionary m_mapPartsOfSpeech = @@ -489,9 +489,8 @@ public void CreateMockCache() var mockProjectName = "xxyyzProjectFolderForLIFTTest"; MockProjectFolder = Path.Combine(Path.GetTempPath(), mockProjectName); var mockProjectPath = Path.Combine(MockProjectFolder, mockProjectName + ".fwdata"); - m_ThreadHelper = new ThreadHelper(); m_cache = FdoCache.CreateCacheWithNewBlankLangProj( - new TestProjectId(FDOBackendProviderType.kMemoryOnly, mockProjectPath), "en", "fr", "en", m_ThreadHelper, new DummyFdoUserAction()); + new TestProjectId(FDOBackendProviderType.kMemoryOnly, mockProjectPath), "en", "fr", "en", new DummyFdoUserAction()); MockLinkedFilesFolder = Path.Combine(MockProjectFolder, DirectoryFinder.ksLinkedFilesDir); Directory.CreateDirectory(MockLinkedFilesFolder); //m_cache.LangProject.LinkedFilesRootDir = MockLinkedFilesFolder; this is already the default. @@ -1020,8 +1019,6 @@ public void DestroyMockCache() Directory.Delete(MockLinkedFilesFolder, true); m_cache.Dispose(); m_cache = null; - m_ThreadHelper.Dispose(); - m_ThreadHelper = null; } #endregion diff --git a/Src/LexText/LexTextControls/LiftImportDlg.cs b/Src/LexText/LexTextControls/LiftImportDlg.cs index 88444ba0d4..6911fb8480 100644 --- a/Src/LexText/LexTextControls/LiftImportDlg.cs +++ b/Src/LexText/LexTextControls/LiftImportDlg.cs @@ -35,7 +35,6 @@ using SIL.Utils; using SIL.Utils.FileDialog; using SIL.FieldWorks.Resources; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.LexText.Controls { @@ -165,12 +164,11 @@ private void DoImport() { using (new WaitCursor(this)) { - using (var progressDlg = new ProgressDialogWithTask(this, m_cache.ThreadHelper)) + using (var progressDlg = new ProgressDialogWithTask(this)) { progressDlg.Minimum = 0; progressDlg.Maximum = 100; progressDlg.AllowCancel = true; - progressDlg.ProgressBarStyle = ProgressBarStyle.Continuous; progressDlg.Restartable = true; progressDlg.Title = String.Format(LexTextControls.ksImportingFrom0, tbPath.Text); try @@ -290,7 +288,7 @@ private object ImportLIFT(IThreadedProgress progressDlg, params object[] paramet if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA) ClipboardUtils.SetDataObject(bldr.ToString(), true); else - progressDlg.ThreadHelper.Invoke(() => ClipboardUtils.SetDataObject(bldr.ToString(), true)); + progressDlg.SynchronizeInvoke.Invoke(() => ClipboardUtils.SetDataObject(bldr.ToString(), true)); SIL.Utils.Logger.WriteEvent(bldr.ToString()); } catch diff --git a/Src/LexText/LexTextDll/FlexStylesXmlAccessor.cs b/Src/LexText/LexTextDll/FlexStylesXmlAccessor.cs index feae970d84..8fc0637d2e 100644 --- a/Src/LexText/LexTextDll/FlexStylesXmlAccessor.cs +++ b/Src/LexText/LexTextDll/FlexStylesXmlAccessor.cs @@ -38,7 +38,7 @@ protected override string ResourceFilePathFromFwInstall /// ------------------------------------------------------------------------------------- /// /// Required implementation of abstract method gives name of the Flex styles sheet - /// resource + /// resource /// /// ------------------------------------------------------------------------------------- protected override string ResourceName diff --git a/Src/LexText/Lexicon/FLExBridgeListener.cs b/Src/LexText/Lexicon/FLExBridgeListener.cs index c0ae75a73e..a7c7e71964 100644 --- a/Src/LexText/Lexicon/FLExBridgeListener.cs +++ b/Src/LexText/Lexicon/FLExBridgeListener.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; @@ -24,7 +23,6 @@ using SIL.FieldWorks.XWorks.LexText; using SIL.Utils; using XCore; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.XWorks.LexEd { @@ -159,7 +157,7 @@ public bool OnObtainAnyFlexBridgeProject(object commandObject) { ObtainedProjectType obtainedProjectType; var newprojectPathname = ObtainProjectMethod.ObtainProjectFromAnySource(_parentForm, _mediator.HelpTopicProvider, - out obtainedProjectType, Cache.ServiceLocator.GetInstance()); + out obtainedProjectType); if (string.IsNullOrEmpty(newprojectPathname)) return true; // We dealt with it. _mediator.PropertyTable.SetProperty("LastBridgeUsed", obtainedProjectType == ObtainedProjectType.Lift ? "LiftBridge" : "FLExBridge", @@ -993,11 +991,9 @@ private bool ImportLiftCommon(FlexLiftMerger.MergeStyle mergeStyle) { using (new WaitCursor(_parentForm)) { - using (var helper = new ThreadHelper()) // not _cache.ThreadHelper, which might be for a different thread - using (var progressDlg = new ProgressDialogWithTask(_parentForm, helper)) + using (var progressDlg = new ProgressDialogWithTask(_parentForm)) { _progressDlg = progressDlg; - progressDlg.ProgressBarStyle = ProgressBarStyle.Continuous; try { progressDlg.Title = ResourceHelper.GetResourceString("kstidImportLiftlexicon"); @@ -1141,11 +1137,9 @@ public bool ExportLiftLexicon() { using (new WaitCursor(_parentForm)) { - using (var helper = new ThreadHelper()) // not _cache.ThreadHelper, which might be for a different thread - using (var progressDlg = new ProgressDialogWithTask(_parentForm, helper)) + using (var progressDlg = new ProgressDialogWithTask(_parentForm)) { _progressDlg = progressDlg; - progressDlg.ProgressBarStyle = ProgressBarStyle.Continuous; try { progressDlg.Title = ResourceHelper.GetResourceString("kstidExportLiftLexicon"); diff --git a/Src/LexText/Morphology/ConcordanceDlg.cs b/Src/LexText/Morphology/ConcordanceDlg.cs index 8dc860a4f8..5b4544b7fc 100644 --- a/Src/LexText/Morphology/ConcordanceDlg.cs +++ b/Src/LexText/Morphology/ConcordanceDlg.cs @@ -17,7 +17,6 @@ using XCore; using SIL.FieldWorks.Common.Controls; using SIL.CoreImpl; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.XWorks.MorphologyEditor { @@ -170,7 +169,7 @@ public ProgressReporting(ToolStripProgressBar bar) m_progressBar.Minimum = 0; m_progressBar.Maximum = 100; m_progressBar.Value = 0; - m_progressBar.ProgressBar.Style = ProgressBarStyleExtensions.Convert(ProgressBarStyle.Continuous); + m_progressBar.Style = ProgressBarStyle.Continuous; } #region IProgress Members @@ -192,17 +191,28 @@ public bool Canceled get { return false; } } + /// + /// Gets an object to be used for ensuring that required tasks are invoked on the main + /// UI thread. + /// + public ISynchronizeInvoke SynchronizeInvoke + { + get { return m_progressBar.Control; } + } + [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", Justification = "We're returning a reference")] public Form Form { get { return m_progressBar.Control.FindForm(); } } - public ProgressBarStyle ProgressBarStyle + + public bool IsIndeterminate { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } + public bool AllowCancel { get { throw new NotImplementedException(); } diff --git a/Src/LexText/ParserEngine/ParserCore/HCWorker.cs b/Src/LexText/ParserEngine/ParserCore/HCWorker.cs index 3f4da5a93c..17830d3318 100644 --- a/Src/LexText/ParserEngine/ParserCore/HCWorker.cs +++ b/Src/LexText/ParserEngine/ParserCore/HCWorker.cs @@ -639,15 +639,8 @@ protected override void LoadParser(ref XmlDocument model, XmlDocument template) m_cache.LangProject.PhonologicalDataOA.AllNaturalClassAbbrs().ToArray()); if (!validator.Recognize(environment)) { - string msg = String.Format(ParserCoreStrings.ksHermitCrabReduplicationProblem, form, - validator.ErrorMessage); - m_cache.ThreadHelper.Invoke(() => // We may be running in a background thread - { - MessageBox.Show(Form.ActiveForm, msg, ParserCoreStrings.ksBadAffixForm, - MessageBoxButtons.OK, MessageBoxIcon.Error); - }); m_loader.Reset(); // make sure nothing thinks it is in a useful state - return; // We can't load the parser, hopefully our caller will realize we failed. + throw new InvalidReduplicationEnvironmentException(validator.ErrorMessage, form); } } diff --git a/Src/LexText/ParserEngine/ParserCore/InvalidReduplicationEnvironmentException.cs b/Src/LexText/ParserEngine/ParserCore/InvalidReduplicationEnvironmentException.cs new file mode 100644 index 0000000000..fc787c3690 --- /dev/null +++ b/Src/LexText/ParserEngine/ParserCore/InvalidReduplicationEnvironmentException.cs @@ -0,0 +1,20 @@ +using System; + +namespace SIL.FieldWorks.WordWorks.Parser +{ + public class InvalidReduplicationEnvironmentException : Exception + { + private readonly string m_morpheme; + + public InvalidReduplicationEnvironmentException(string message, string morpheme) + : base(message) + { + m_morpheme = morpheme; + } + + public string Morpheme + { + get { return m_morpheme; } + } + } +} diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj b/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj index c2bec01a4a..53d62c2192 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj +++ b/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj @@ -199,6 +199,7 @@ Code + Code diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.Designer.cs b/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.Designer.cs index 269f43edae..ad75668330 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.Designer.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.269 +// Runtime Version:4.0.30319.18052 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -9,280 +9,262 @@ //------------------------------------------------------------------------------ namespace SIL.FieldWorks.WordWorks.Parser { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class ParserCoreStrings { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal ParserCoreStrings() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SIL.FieldWorks.WordWorks.Parser.ParserCoreStrings", typeof(ParserCoreStrings).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to Bad Affix Form. - /// - internal static string ksBadAffixForm { - get { - return ResourceManager.GetString("ksBadAffixForm", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Creating {0}. - /// - internal static string ksCreatingX { - get { - return ResourceManager.GetString("ksCreatingX", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Parse was not attempted because of errors in the lexical data. - /// - internal static string ksDidNotParse { - get { - return ResourceManager.GetString("ksDidNotParse", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to error encountered. - /// - internal static string ksErrorEncountered { - get { - return ResourceManager.GetString("ksErrorEncountered", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to finished. - /// - internal static string ksFinished { - get { - return ResourceManager.GetString("ksFinished", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The parser gave the following cryptic message (you may need to contact FieldWorks support to know what it means): {0}. - /// - internal static string ksHCDefaultErrorMsg { - get { - return ResourceManager.GetString("ksHCDefaultErrorMsg", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The phoneme {0} of lexical entry {1} is not defined. Please make sure all phonemes in all allomorphs of all entries have been defined.. - /// - internal static string ksHCInvalidEntryShape { - get { - return ResourceManager.GetString("ksHCInvalidEntryShape", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The phoneme {0} of affix {1} is not defined. Please make sure all phonemes in all allomorphs of all affixes have been defined.. - /// - internal static string ksHCInvalidRuleShape { - get { - return ResourceManager.GetString("ksHCInvalidRuleShape", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There is at least one undefined phoneme in the word '{0}'. The following phonemes were parsed: '{3}'. The problem begins with character/diacritic number {1} – that is, in the part of the word '{2}'. Please make sure all phonemes in the word have been defined.. - /// - internal static string ksHCInvalidWordform { - get { - return ResourceManager.GetString("ksHCInvalidWordform", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to A phonological rule is using a feature variable for feature {0}, but there is no corresponding feature variable in the environment.. - /// - internal static string ksHCUninstFeature { - get { - return ResourceManager.GetString("ksHCUninstFeature", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The Hermit Crab parser cannot currently run, because the morpheme "{0}" has an invalid reduplication environment. The problem is {1}.. - /// - internal static string ksHermitCrabReduplicationProblem { - get { - return ResourceManager.GetString("ksHermitCrabReduplicationProblem", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to . - /// - internal static string ksIdle_ { - get { - return ResourceManager.GetString("ksIdle_", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Making HC Files. - /// - internal static string ksMakingHCFiles { - get { - return ResourceManager.GetString("ksMakingHCFiles", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Making XAmple Files. - /// - internal static string ksMakingXAmpleFiles { - get { - return ResourceManager.GetString("ksMakingXAmpleFiles", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Preparing Templates for XAmple Files. - /// - internal static string ksPreparingTemplatesForXAmple { - get { - return ResourceManager.GetString("ksPreparingTemplatesForXAmple", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to ???. - /// - internal static string ksQuestions { - get { - return ResourceManager.GetString("ksQuestions", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Maximum permitted analyses ({0}) reached.. - /// - internal static string ksReachedMaxAnalysesAllowed { - get { - return ResourceManager.GetString("ksReachedMaxAnalysesAllowed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Maximum internal buffer size ({0}) reached.. - /// - internal static string ksReachedMaxInternalBufferSize { - get { - return ResourceManager.GetString("ksReachedMaxInternalBufferSize", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Retrieving Grammar and Lexicon. - /// - internal static string ksRetrievingGrammarAndLexicon { - get { - return ResourceManager.GetString("ksRetrievingGrammarAndLexicon", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Retrieving Template Information. - /// - internal static string ksRetrievingTemplateInformation { - get { - return ResourceManager.GetString("ksRetrievingTemplateInformation", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to started. - /// - internal static string ksStarted { - get { - return ResourceManager.GetString("ksStarted", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Trying Wordform {0}. - /// - internal static string ksTraceWordformX { - get { - return ResourceManager.GetString("ksTraceWordformX", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Updating: {0}. - /// - internal static string ksUpdateX { - get { - return ResourceManager.GetString("ksUpdateX", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Updating Grammar and Lexicon. - /// - internal static string ksUpdatingGrammarAndLexicon { - get { - return ResourceManager.GetString("ksUpdatingGrammarAndLexicon", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to {0}: error. - /// - internal static string ksX_error { - get { - return ResourceManager.GetString("ksX_error", resourceCulture); - } - } - } + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class ParserCoreStrings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal ParserCoreStrings() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SIL.FieldWorks.WordWorks.Parser.ParserCoreStrings", typeof(ParserCoreStrings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Creating {0}. + /// + internal static string ksCreatingX { + get { + return ResourceManager.GetString("ksCreatingX", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Parse was not attempted because of errors in the lexical data. + /// + internal static string ksDidNotParse { + get { + return ResourceManager.GetString("ksDidNotParse", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to error encountered. + /// + internal static string ksErrorEncountered { + get { + return ResourceManager.GetString("ksErrorEncountered", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to finished. + /// + internal static string ksFinished { + get { + return ResourceManager.GetString("ksFinished", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The parser gave the following cryptic message (you may need to contact FieldWorks support to know what it means): {0}. + /// + internal static string ksHCDefaultErrorMsg { + get { + return ResourceManager.GetString("ksHCDefaultErrorMsg", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The phoneme {0} of lexical entry {1} is not defined. Please make sure all phonemes in all allomorphs of all entries have been defined.. + /// + internal static string ksHCInvalidEntryShape { + get { + return ResourceManager.GetString("ksHCInvalidEntryShape", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The phoneme {0} of affix {1} is not defined. Please make sure all phonemes in all allomorphs of all affixes have been defined.. + /// + internal static string ksHCInvalidRuleShape { + get { + return ResourceManager.GetString("ksHCInvalidRuleShape", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There is at least one undefined phoneme in the word '{0}'. The following phonemes were parsed: '{3}'. The problem begins with character/diacritic number {1} – that is, in the part of the word '{2}'. Please make sure all phonemes in the word have been defined.. + /// + internal static string ksHCInvalidWordform { + get { + return ResourceManager.GetString("ksHCInvalidWordform", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A phonological rule is using a feature variable for feature {0}, but there is no corresponding feature variable in the environment.. + /// + internal static string ksHCUninstFeature { + get { + return ResourceManager.GetString("ksHCUninstFeature", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string ksIdle_ { + get { + return ResourceManager.GetString("ksIdle_", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Making HC Files. + /// + internal static string ksMakingHCFiles { + get { + return ResourceManager.GetString("ksMakingHCFiles", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Making XAmple Files. + /// + internal static string ksMakingXAmpleFiles { + get { + return ResourceManager.GetString("ksMakingXAmpleFiles", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Preparing Templates for XAmple Files. + /// + internal static string ksPreparingTemplatesForXAmple { + get { + return ResourceManager.GetString("ksPreparingTemplatesForXAmple", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ???. + /// + internal static string ksQuestions { + get { + return ResourceManager.GetString("ksQuestions", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Maximum permitted analyses ({0}) reached.. + /// + internal static string ksReachedMaxAnalysesAllowed { + get { + return ResourceManager.GetString("ksReachedMaxAnalysesAllowed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Maximum internal buffer size ({0}) reached.. + /// + internal static string ksReachedMaxInternalBufferSize { + get { + return ResourceManager.GetString("ksReachedMaxInternalBufferSize", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Retrieving Grammar and Lexicon. + /// + internal static string ksRetrievingGrammarAndLexicon { + get { + return ResourceManager.GetString("ksRetrievingGrammarAndLexicon", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Retrieving Template Information. + /// + internal static string ksRetrievingTemplateInformation { + get { + return ResourceManager.GetString("ksRetrievingTemplateInformation", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to started. + /// + internal static string ksStarted { + get { + return ResourceManager.GetString("ksStarted", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Trying Wordform {0}. + /// + internal static string ksTraceWordformX { + get { + return ResourceManager.GetString("ksTraceWordformX", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Updating: {0}. + /// + internal static string ksUpdateX { + get { + return ResourceManager.GetString("ksUpdateX", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Updating Grammar and Lexicon. + /// + internal static string ksUpdatingGrammarAndLexicon { + get { + return ResourceManager.GetString("ksUpdatingGrammarAndLexicon", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}: error. + /// + internal static string ksX_error { + get { + return ResourceManager.GetString("ksX_error", resourceCulture); + } + } + } } diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.resx b/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.resx index a12f333673..fbcb152889 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.resx +++ b/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.resx @@ -1,197 +1,190 @@  - + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - text/microsoft-resx + text/microsoft-resx - 2.0 + 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Bad Affix Form - Caption that goes with ksHermitCrabReduplicationProblem - - Creating {0} + Creating {0} - Parse was not attempted because of errors in the lexical data + Parse was not attempted because of errors in the lexical data - error encountered + error encountered - finished + finished - The parser gave the following cryptic message (you may need to contact FieldWorks support to know what it means): {0} + The parser gave the following cryptic message (you may need to contact FieldWorks support to know what it means): {0} - The phoneme {0} of lexical entry {1} is not defined. Please make sure all phonemes in all allomorphs of all entries have been defined. + The phoneme {0} of lexical entry {1} is not defined. Please make sure all phonemes in all allomorphs of all entries have been defined. - The phoneme {0} of affix {1} is not defined. Please make sure all phonemes in all allomorphs of all affixes have been defined. + The phoneme {0} of affix {1} is not defined. Please make sure all phonemes in all allomorphs of all affixes have been defined. - There is at least one undefined phoneme in the word '{0}'. The following phonemes were parsed: '{3}'. The problem begins with character/diacritic number {1} – that is, in the part of the word '{2}'. Please make sure all phonemes in the word have been defined. + There is at least one undefined phoneme in the word '{0}'. The following phonemes were parsed: '{3}'. The problem begins with character/diacritic number {1} – that is, in the part of the word '{2}'. Please make sure all phonemes in the word have been defined. - A phonological rule is using a feature variable for feature {0}, but there is no corresponding feature variable in the environment. - - - The Hermit Crab parser cannot currently run, because the morpheme "{0}" has an invalid reduplication environment. The problem is {1}. + A phonological rule is using a feature variable for feature {0}, but there is no corresponding feature variable in the environment. - + - Making HC Files + Making HC Files - Making XAmple Files + Making XAmple Files - Preparing Templates for XAmple Files + Preparing Templates for XAmple Files - ??? - missiing/undefined information + ??? + missiing/undefined information - Maximum permitted analyses ({0}) reached. + Maximum permitted analyses ({0}) reached. - Maximum internal buffer size ({0}) reached. + Maximum internal buffer size ({0}) reached. - Retrieving Grammar and Lexicon + Retrieving Grammar and Lexicon - Retrieving Template Information + Retrieving Template Information - started + started - Trying Wordform {0} + Trying Wordform {0} - Updating: {0} + Updating: {0} - Updating Grammar and Lexicon + Updating Grammar and Lexicon - {0}: error + {0}: error \ No newline at end of file diff --git a/Src/LexText/ParserEngine/ParserCore/Worker.cs b/Src/LexText/ParserEngine/ParserCore/Worker.cs index eac019bf03..ffc7827adb 100644 --- a/Src/LexText/ParserEngine/ParserCore/Worker.cs +++ b/Src/LexText/ParserEngine/ParserCore/Worker.cs @@ -213,7 +213,7 @@ public void ReloadGrammarAndLexicon() Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "ParserWorker.ReloadGrammarAndLexicon"); m_retriever.Reset(); CheckNeedsUpdate(); - } + } private void CheckNeedsUpdate() { diff --git a/Src/LexText/ParserUI/ParserListener.cs b/Src/LexText/ParserUI/ParserListener.cs index 3b112b9a6b..3376eb522b 100644 --- a/Src/LexText/ParserUI/ParserListener.cs +++ b/Src/LexText/ParserUI/ParserListener.cs @@ -237,9 +237,20 @@ private void UpdateStatusPanelProgress() if (ex != null) { DisconnectFromParser(); - var app = (IApp)m_mediator.PropertyTable.GetValue("App"); - ErrorReporter.ReportException(ex, app.SettingsKey, app.SupportEmailAddress, - app.ActiveMainWindow, false); + var iree = ex as InvalidReduplicationEnvironmentException; + if (iree != null) + { + string msg = String.Format(ParserUIStrings.ksHermitCrabReduplicationProblem, iree.Morpheme, + iree.Message); + MessageBox.Show(Form.ActiveForm, msg, ParserUIStrings.ksBadAffixForm, + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + else + { + var app = (IApp) m_mediator.PropertyTable.GetValue("App"); + ErrorReporter.ReportException(ex, app.SettingsKey, app.SupportEmailAddress, + app.ActiveMainWindow, false); + } } else { diff --git a/Src/LexText/ParserUI/ParserUIStrings.Designer.cs b/Src/LexText/ParserUI/ParserUIStrings.Designer.cs index adac826477..0283b72683 100644 --- a/Src/LexText/ParserUI/ParserUIStrings.Designer.cs +++ b/Src/LexText/ParserUI/ParserUIStrings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.18034 +// Runtime Version:4.0.30319.18052 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -69,6 +69,15 @@ internal static string ks_OK { } } + /// + /// Looks up a localized string similar to Bad Affix Form. + /// + internal static string ksBadAffixForm { + get { + return ResourceManager.GetString("ksBadAffixForm", resourceCulture); + } + } + /// /// Looks up a localized string similar to Changed value for {0} from {1} to {2}. The value must be between {3} and {4}, inclusive.. /// @@ -105,6 +114,15 @@ internal static string ksDoNotUseDefaultCompoundRules { } } + /// + /// Looks up a localized string similar to The Hermit Crab parser cannot currently run, because the morpheme "{0}" has an invalid reduplication environment. The problem is {1}.. + /// + internal static string ksHermitCrabReduplicationProblem { + get { + return ResourceManager.GetString("ksHermitCrabReduplicationProblem", resourceCulture); + } + } + /// /// Looks up a localized string similar to . /// diff --git a/Src/LexText/ParserUI/ParserUIStrings.resx b/Src/LexText/ParserUI/ParserUIStrings.resx index 69ddb2f25e..2b8cedd185 100644 --- a/Src/LexText/ParserUI/ParserUIStrings.resx +++ b/Src/LexText/ParserUI/ParserUIStrings.resx @@ -259,4 +259,11 @@ NoDefaultCompounding If true, no default compounding rules will be used. (Do Not Localize) + + Bad Affix Form + Caption that goes with ksHermitCrabReduplicationProblem + + + The Hermit Crab parser cannot currently run, because the morpheme "{0}" has an invalid reduplication environment. The problem is {1}. + \ No newline at end of file diff --git a/Src/LexText/ParserUI/TryAWordDlg.cs b/Src/LexText/ParserUI/TryAWordDlg.cs index 92ca2d3889..0cf5cd0903 100644 --- a/Src/LexText/ParserUI/TryAWordDlg.cs +++ b/Src/LexText/ParserUI/TryAWordDlg.cs @@ -29,6 +29,7 @@ using SIL.FieldWorks.Common.RootSites; using SIL.FieldWorks.Common.Widgets; using SIL.FieldWorks.FDO; +using SIL.FieldWorks.WordWorks.Parser; using SIL.Utils; using XCore; using SIL.FieldWorks.Common.FwUtils; @@ -535,8 +536,19 @@ private void m_timer_Tick(object sender, EventArgs e) m_parserListener.DisconnectFromParser(); m_statusLabel.Text = ParserStoppedMessage(); m_tryItButton.Enabled = true; - var app = (IApp) m_mediator.PropertyTable.GetValue("App"); - ErrorReporter.ReportException(ex, app.SettingsKey, app.SupportEmailAddress, this, false); + var iree = ex as InvalidReduplicationEnvironmentException; + if (iree != null) + { + string msg = String.Format(ParserUIStrings.ksHermitCrabReduplicationProblem, iree.Morpheme, + iree.Message); + MessageBox.Show(this, msg, ParserUIStrings.ksBadAffixForm, + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + else + { + var app = (IApp) m_mediator.PropertyTable.GetValue("App"); + ErrorReporter.ReportException(ex, app.SettingsKey, app.SupportEmailAddress, this, false); + } return; } diff --git a/Src/MigrateSqlDbs/Program.cs b/Src/MigrateSqlDbs/Program.cs index 600f8cb5c8..965d57cb43 100644 --- a/Src/MigrateSqlDbs/Program.cs +++ b/Src/MigrateSqlDbs/Program.cs @@ -104,7 +104,8 @@ static int Main(string[] rgArgs) var globalMigrator = new LdmlInFolderWritingSystemRepositoryMigrator(globalWsFolder, NoteMigration); globalMigrator.Migrate(); - using (var progressDlg = new ProgressDialogWithTask(null, new ThreadHelper())) + using (var threadHelper = new ThreadHelper()) + using (var progressDlg = new ProgressDialogWithTask(threadHelper)) { ImportFrom6_0 importer = new ImportFrom6_0(progressDlg, s_fDebug); if (!importer.IsFwSqlServerInstalled()) diff --git a/Src/TE/DiffView/BookMerger.cs b/Src/TE/DiffView/BookMerger.cs index 7af4afbfab..655278e10e 100644 --- a/Src/TE/DiffView/BookMerger.cs +++ b/Src/TE/DiffView/BookMerger.cs @@ -6698,7 +6698,7 @@ protected virtual bool DisplayUi /// ------------------------------------------------------------------------------------ public void RecalculateDifferences(Form owner) { - using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(owner, Cache.ThreadHelper)) + using (var progressDlg = new ProgressDialogWithTask(owner)) { progressDlg.Title = DlgResources.ResourceString("kstidCompareCaption"); progressDlg.Message = TeDiffViewResources.kstidRecalculateDiff; diff --git a/Src/TE/TeDialogs/ArchiveMaintenanceDialog.cs b/Src/TE/TeDialogs/ArchiveMaintenanceDialog.cs index 82a559550e..2f79c5b554 100644 --- a/Src/TE/TeDialogs/ArchiveMaintenanceDialog.cs +++ b/Src/TE/TeDialogs/ArchiveMaintenanceDialog.cs @@ -437,7 +437,7 @@ private void m_btnDiff_Click(object sender, System.EventArgs e) using (BookMerger merger = new BookMerger(m_cache, m_styleSheet, bookRev)) { - using (ProgressDialogWithTask progress = new ProgressDialogWithTask(this, m_cache.ThreadHelper)) + using (ProgressDialogWithTask progress = new ProgressDialogWithTask(this)) { progress.Title = DlgResources.ResourceString("kstidCompareCaption"); progress.Message = string.Format( @@ -597,7 +597,7 @@ private void m_btnCopyToCurr_Click(object sender, EventArgs e) // Perform an automerge of the original book and the saved version. using (BookMerger merger = new BookMerger(m_cache, m_styleSheet, savedBook)) { - using (ProgressDialogWithTask progress = new ProgressDialogWithTask(this, m_cache.ThreadHelper)) + using (ProgressDialogWithTask progress = new ProgressDialogWithTask(this)) { progress.Title = DlgResources.ResourceString("kstidOverwriteCaption"); progress.RunTask(merger.DoPartialOverwrite, sectionsToRemove); diff --git a/Src/TE/TeDialogs/ImportedBooks.cs b/Src/TE/TeDialogs/ImportedBooks.cs index f46eed9c00..1cdba4b6ac 100644 --- a/Src/TE/TeDialogs/ImportedBooks.cs +++ b/Src/TE/TeDialogs/ImportedBooks.cs @@ -428,7 +428,7 @@ public void ShowOrSave(IWin32Window wnd, bool fAutoAcceptChanges) continue; } - using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(m_owningForm, m_cache.ThreadHelper)) + using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(m_owningForm)) { bookMerger.AttemptAutoMerge = true; bookMerger.BookVersionAgent = this; @@ -1063,7 +1063,7 @@ protected virtual void PartialOverwrite(BookMerger bookMerger, List sectionsToRemove) { Logger.WriteEvent("Performing partial Overwrite of book: " + bookMerger.BookCurr.BookId); - using (ProgressDialogWithTask progress = new ProgressDialogWithTask(this, m_cache.ThreadHelper)) + using (ProgressDialogWithTask progress = new ProgressDialogWithTask(this)) { progress.Title = DlgResources.ResourceString("kstidOverwriteCaption"); progress.RunTask(bookMerger.DoPartialOverwrite, sectionsToRemove); diff --git a/Src/TE/TeDialogs/ScriptureProperties.cs b/Src/TE/TeDialogs/ScriptureProperties.cs index 5e1a404536..05485bee7c 100644 --- a/Src/TE/TeDialogs/ScriptureProperties.cs +++ b/Src/TE/TeDialogs/ScriptureProperties.cs @@ -810,7 +810,7 @@ private void UpdateFootnoteTabs() protected void ConvertChapterVerseNumbers() { // Show a progress dialog for this operation - using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(this, m_cache.ThreadHelper)) + using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(this)) { progressDlg.Minimum = 0; progressDlg.Maximum = m_scr.ScriptureBooksOS.Count; @@ -909,7 +909,7 @@ protected virtual bool ConvertChapterVerseNumbers(IScrTxtPara para, char zeroDig private void UpdateVerseBridges(string oldBridge) { // Show a progress dialog for this operation - using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(this, m_cache.ThreadHelper)) + using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(this)) { progressDlg.Minimum = 0; progressDlg.Maximum = m_scr.ScriptureBooksOS.Count; diff --git a/Src/TE/TeImportExport/ExportRtf.cs b/Src/TE/TeImportExport/ExportRtf.cs index 91123417d5..ba806bc804 100644 --- a/Src/TE/TeImportExport/ExportRtf.cs +++ b/Src/TE/TeImportExport/ExportRtf.cs @@ -882,7 +882,7 @@ public bool Run(Form dialogOwner) /// ------------------------------------------------------------------------------------ private void ExportKeyTerms(Form dialogOwner) { - using (var progressDlg = new ProgressDialogWithTask(dialogOwner, m_cache.ThreadHelper)) + using (var progressDlg = new ProgressDialogWithTask(dialogOwner)) { progressDlg.Title = DlgResources.ResourceString("kstidExportRtfKeyTerms"); progressDlg.Minimum = 1; @@ -927,7 +927,7 @@ private void ExportTE(Form dialogOwner) int sectionCount = 0; for (int i = 0; i < m_bookFilter.BookCount; i++) sectionCount += m_bookFilter.GetBook(i).SectionsOS.Count; - using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(dialogOwner, m_cache.ThreadHelper)) + using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(dialogOwner)) { progressDlg.Minimum = 0; progressDlg.Maximum = sectionCount; diff --git a/Src/TE/TeImportExport/ExportUsfm.cs b/Src/TE/TeImportExport/ExportUsfm.cs index 12b80474e1..7c22cfd8c5 100644 --- a/Src/TE/TeImportExport/ExportUsfm.cs +++ b/Src/TE/TeImportExport/ExportUsfm.cs @@ -634,7 +634,7 @@ public void Run(Form dialogOwner) } } - using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(dialogOwner, m_cache.ThreadHelper)) + using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(dialogOwner)) { try { diff --git a/Src/TE/TeImportExport/ExportXhtml.cs b/Src/TE/TeImportExport/ExportXhtml.cs index d7a74795f4..f8ca516ff2 100644 --- a/Src/TE/TeImportExport/ExportXhtml.cs +++ b/Src/TE/TeImportExport/ExportXhtml.cs @@ -208,7 +208,7 @@ private void ExportScripture(Form dialogOwner) int sectionCount = 0; for (int i = 0; i < m_bookFilter.BookCount; i++) sectionCount += m_bookFilter.GetBook(i).SectionsOS.Count; - using (var progressDlg = new ProgressDialogWithTask(dialogOwner, m_cache.ThreadHelper)) + using (var progressDlg = new ProgressDialogWithTask(dialogOwner)) { progressDlg.Minimum = 0; progressDlg.Maximum = sectionCount; diff --git a/Src/TE/TeImportExport/ExportXml.cs b/Src/TE/TeImportExport/ExportXml.cs index f73bd583a2..e7e007c132 100644 --- a/Src/TE/TeImportExport/ExportXml.cs +++ b/Src/TE/TeImportExport/ExportXml.cs @@ -437,7 +437,7 @@ private void ExportScripture(Form dialogOwner) int sectionCount = 0; for (int i = 0; i < m_bookFilter.BookCount; i++) sectionCount += m_bookFilter.GetBook(i).SectionsOS.Count; - using (var progressDlg = new ProgressDialogWithTask(dialogOwner, m_cache.ThreadHelper)) + using (var progressDlg = new ProgressDialogWithTask(dialogOwner)) { progressDlg.Minimum = 0; progressDlg.Maximum = sectionCount; diff --git a/Src/TE/TeImportExport/TeImportManager.cs b/Src/TE/TeImportExport/TeImportManager.cs index 9e75e8c4f0..2f7c36ab3b 100644 --- a/Src/TE/TeImportExport/TeImportManager.cs +++ b/Src/TE/TeImportExport/TeImportManager.cs @@ -32,7 +32,6 @@ using SIL.FieldWorks.FDO.Infrastructure; using SILUBS.SharedScrUtils; using XCore; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.TE { @@ -468,7 +467,7 @@ private ScrReference InternalImport(IScrImportSet importSettings, bool fDisplayU try { Logger.WriteEvent("Starting import"); - using (var progressDlg = new ProgressDialogWithTask(m_mainWnd, m_cache.ThreadHelper)) + using (var progressDlg = new ProgressDialogWithTask(m_mainWnd)) { progressDlg.CancelButtonText = TeResourceHelper.GetResourceString("kstidStopImporting"); @@ -476,8 +475,6 @@ private ScrReference InternalImport(IScrImportSet importSettings, bool fDisplayU TeResourceHelper.GetResourceString("kstidImportProgressCaption"); progressDlg.Message = TeResourceHelper.GetResourceString("kstidImportInitializing"); - if (importSettings == null) // XML (OXES) import - progressDlg.ProgressBarStyle = ProgressBarStyle.Continuous; using (TeImportUi importUi = CreateTeImportUi(progressDlg)) { diff --git a/Src/TE/TeKeyTerms/KeyTermsViewWrapper.cs b/Src/TE/TeKeyTerms/KeyTermsViewWrapper.cs index 9b224fb025..705c4608a5 100644 --- a/Src/TE/TeKeyTerms/KeyTermsViewWrapper.cs +++ b/Src/TE/TeKeyTerms/KeyTermsViewWrapper.cs @@ -349,7 +349,7 @@ public void UpdateKeyTermEquivalents(TextSelInfo tsiBeforeEdit) /// ------------------------------------------------------------------------------------ public void UpdateKeyTermEquivalents() { - using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(ParentForm, m_cache.ThreadHelper)) + using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(ParentForm)) { progressDlg.Title = TeResourceHelper.GetResourceString("kstidUpdateKeyTermEquivalentsProgressCaption"); progressDlg.AllowCancel = false; diff --git a/Src/TE/TeScrInitializer/TeKeyTermsInit.cs b/Src/TE/TeScrInitializer/TeKeyTermsInit.cs index 94cc177995..3b107bb7b3 100644 --- a/Src/TE/TeScrInitializer/TeKeyTermsInit.cs +++ b/Src/TE/TeScrInitializer/TeKeyTermsInit.cs @@ -352,7 +352,7 @@ private void EnsureCurrentLocalization(string locale, Form caller, } else { - using (ProgressDialogWithTask dlg = new ProgressDialogWithTask(caller, m_scr.Cache.ThreadHelper)) + using (ProgressDialogWithTask dlg = new ProgressDialogWithTask(caller)) { dlg.AllowCancel = false; dlg.RunTask(true, UpdateLocalization, loc, locale); diff --git a/Src/Utilities/BasicUtils/BasicUtils.csproj b/Src/Utilities/BasicUtils/BasicUtils.csproj index caa30a53c1..a7bbe2314e 100644 --- a/Src/Utilities/BasicUtils/BasicUtils.csproj +++ b/Src/Utilities/BasicUtils/BasicUtils.csproj @@ -101,7 +101,9 @@ + + diff --git a/Src/Utilities/BasicUtils/SingleThreadedSynchronizeInvoke.cs b/Src/Utilities/BasicUtils/SingleThreadedSynchronizeInvoke.cs new file mode 100644 index 0000000000..6d82b688ce --- /dev/null +++ b/Src/Utilities/BasicUtils/SingleThreadedSynchronizeInvoke.cs @@ -0,0 +1,94 @@ +using System; +using System.ComponentModel; +using System.Threading; + +namespace SIL.Utils +{ + /// + /// A simple, single-threaded implementation of ISynchronizeInvoke + /// + public class SingleThreadedSynchronizeInvoke : ISynchronizeInvoke + { + /// + /// Asynchronously executes the delegate on the thread that created this object. + /// + /// A to a method that takes parameters of the same number and type that are contained in . + /// An array of type to pass as arguments to the given method. This can be null if no arguments are needed. + /// + /// An interface that represents the asynchronous operation started by calling this method. + /// + public IAsyncResult BeginInvoke(Delegate method, object[] args) + { + return new AsyncResult(method.DynamicInvoke(args)); + } + + /// + /// Waits until the process started by calling completes, and then returns the value generated by the process. + /// + /// An interface that represents the asynchronous operation started by calling . + /// + /// An that represents the return value generated by the asynchronous operation. + /// + public object EndInvoke(IAsyncResult result) + { + return ((AsyncResult) result).Result; + } + + /// + /// Synchronously executes the delegate on the thread that created this object and marshals the call to the creating thread. + /// + /// A that contains a method to call, in the context of the thread for the control. + /// An array of type that represents the arguments to pass to the given method. This can be null if no arguments are needed. + /// + /// An that represents the return value from the delegate being invoked, or null if the delegate has no return value. + /// + public object Invoke(Delegate method, object[] args) + { + return method.DynamicInvoke(args); + } + + /// + /// Gets a value indicating whether the caller must call when calling an object that implements this interface. + /// + /// true if the caller must call ; otherwise, false. + public bool InvokeRequired + { + get { return false; } + } + + private class AsyncResult : IAsyncResult + { + private readonly object m_result; + + public AsyncResult(object result) + { + m_result = result; + } + + public object Result + { + get { return m_result; } + } + + public bool IsCompleted + { + get { return true; } + } + + public WaitHandle AsyncWaitHandle + { + get { throw new NotSupportedException(); } + } + + public object AsyncState + { + get { return null; } + } + + public bool CompletedSynchronously + { + get { return true; } + } + } + } +} diff --git a/Src/Utilities/BasicUtils/SynchronizeInvokeExtensions.cs b/Src/Utilities/BasicUtils/SynchronizeInvokeExtensions.cs new file mode 100644 index 0000000000..cefdc2180d --- /dev/null +++ b/Src/Utilities/BasicUtils/SynchronizeInvokeExtensions.cs @@ -0,0 +1,95 @@ +using System; +using System.ComponentModel; + +namespace SIL.Utils +{ + /// + /// ISynchronizeInvoke extension methods + /// + public static class SynchronizeInvokeExtensions + { + /// + /// Invokes the specified action synchronously on the thread on which this ThreadHelper + /// was created. If the calling thread is the thread on which this ThreadHelper was + /// created, no invoke is performed. + /// + /// The synchronize invoke object. + /// The action. + public static void Invoke(this ISynchronizeInvoke si, Action action) + { + if (si.InvokeRequired) + si.Invoke(action, null); + else + action(); + } + + /// + /// Invokes the specified function synchronously on the thread on which this + /// ThreadHelper was created. If the calling thread is the thread on which this + /// ThreadHelper was created, no invoke is performed. + /// + /// The synchronize invoke object. + /// The function. + public static TResult Invoke(this ISynchronizeInvoke si, Func func) + { + if (si.InvokeRequired) + return (TResult) si.Invoke(func, null); + return func(); + } + + /// + /// Invokes the specified action, asynchronously or not on the thread on which this + /// ThreadHelper was created + /// + /// The synchronize invoke object. + /// if set to true invoke asynchronously. + /// The action to perform. + public static void Invoke(this ISynchronizeInvoke si, bool invokeAsync, Action action) + { + if (invokeAsync) + si.InvokeAsync(action); + else + si.Invoke(action); + } + + /// + /// Executes the specified method asynchronously. The action will typically be called + /// when the the Application.Run() loop regains control or the next call to + /// Application.DoEvents() at some unspecified time in the future. + /// + public static void InvokeAsync(this ISynchronizeInvoke si, Action action) + { + si.BeginInvoke(action, null); + } + + /// + /// Executes the specified method asynchronously. The action will typically be called + /// when the the Application.Run() loop regains control or the next call to + /// Application.DoEvents() at some unspecified time in the future. + /// + public static void InvokeAsync(this ISynchronizeInvoke si, Action action, T param1) + { + si.BeginInvoke(action, new object[] {param1}); + } + + /// + /// Executes the specified method asynchronously. The action will typically be called + /// when the the Application.Run() loop regains control or the next call to + /// Application.DoEvents() at some unspecified time in the future. + /// + public static void InvokeAsync(this ISynchronizeInvoke si, Action action, T1 param1, T2 param2) + { + si.BeginInvoke(action, new object[] {param1, param2}); + } + + /// + /// Executes the specified method asynchronously. The action will typically be called + /// when the the Application.Run() loop regains control or the next call to + /// Application.DoEvents() at some unspecified time in the future. + /// + public static void InvokeAsync(this ISynchronizeInvoke si, Action action, T1 param1, T2 param2, T3 param3) + { + si.BeginInvoke(action, new object[] {param1, param2, param3}); + } + } +} diff --git a/Src/Utilities/BasicUtils/ThreadHelper.cs b/Src/Utilities/BasicUtils/ThreadHelper.cs index 6b79a8dae4..856621c6ab 100644 --- a/Src/Utilities/BasicUtils/ThreadHelper.cs +++ b/Src/Utilities/BasicUtils/ThreadHelper.cs @@ -70,7 +70,7 @@ private void Dispose(bool fDisposing) if (fDisposing && !IsDisposed) { // dispose managed and unmanaged objects - Invoke(() => m_invokeControl.Dispose()); + this.Invoke(() => m_invokeControl.Dispose()); } IsDisposed = true; } @@ -131,114 +131,7 @@ public bool InvokeRequired get { return m_invokeControl.InvokeRequired; } } - /// ------------------------------------------------------------------------------------ - /// - /// Invokes the specified action synchronously on the thread on which this ThreadHelper - /// was created. If the calling thread is the thread on which this ThreadHelper was - /// created, no invoke is performed. - /// - /// The action. - /// ------------------------------------------------------------------------------------ - public void Invoke(Action action) - { - if (m_invokeControl.InvokeRequired) - { - m_invokeControl.Invoke(action); - return; - } - action(); - } - /// ------------------------------------------------------------------------------------ - /// - /// Invokes the specified function synchronously on the thread on which this - /// ThreadHelper was created. If the calling thread is the thread on which this - /// ThreadHelper was created, no invoke is performed. - /// - /// The function. - /// ------------------------------------------------------------------------------------ - public TResult Invoke(Func func) - { - if (m_invokeControl.InvokeRequired) - return (TResult)m_invokeControl.Invoke(func); - return func(); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Invokes the specified action, asynchronously or not on the thread on which this - /// ThreadHelper was created - /// - /// if set to true invoke asynchronously. - /// The action to perform. - /// ------------------------------------------------------------------------------------ - public void Invoke(bool invokeAsync, Action action) - { - if (invokeAsync) - InvokeAsync(action); - else - Invoke(action); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Executes the specified method asynchronously. The action will typically be called - /// when the the Application.Run() loop regains control or the next call to - /// Application.DoEvents() at some unspecified time in the future. - /// - /// ------------------------------------------------------------------------------------ - public void InvokeAsync(Action action) - { - if (m_invokeControl.IsHandleCreated) - m_invokeControl.BeginInvoke(action); - else - { - // not ideal, but better than crashing - action(); - } - } - - /// ------------------------------------------------------------------------------------ - /// - /// Executes the specified method asynchronously. The action will typically be called - /// when the the Application.Run() loop regains control or the next call to - /// Application.DoEvents() at some unspecified time in the future. - /// - /// ------------------------------------------------------------------------------------ - public void InvokeAsync(Action action, T param1) - { - if (m_invokeControl.IsHandleCreated) - m_invokeControl.BeginInvoke(action, param1); - else - { - // not ideal, but better than crashing - action(param1); - } - } - - /// ------------------------------------------------------------------------------------ - /// - /// Executes the specified method asynchronously. The action will typically be called - /// when the the Application.Run() loop regains control or the next call to - /// Application.DoEvents() at some unspecified time in the future. - /// - /// ------------------------------------------------------------------------------------ - public void InvokeAsync(Action action, T1 param1, T2 param2) - { - m_invokeControl.BeginInvoke(action, param1, param2); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Executes the specified method asynchronously. The action will typically be called - /// when the the Application.Run() loop regains control or the next call to - /// Application.DoEvents() at some unspecified time in the future. - /// - /// ------------------------------------------------------------------------------------ - public void InvokeAsync(Action action, T1 param1, T2 param2, T3 param3) - { - m_invokeControl.BeginInvoke(action, param1, param2, param3); - } /// ------------------------------------------------------------------------------------ /// diff --git a/Src/Utilities/FixFwData/Program.cs b/Src/Utilities/FixFwData/Program.cs index a6d62ecfc1..2f42647042 100644 --- a/Src/Utilities/FixFwData/Program.cs +++ b/Src/Utilities/FixFwData/Program.cs @@ -19,7 +19,6 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FixData; using Palaso.UI.WindowsForms.HotSpot; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace FixFwData { @@ -84,11 +83,11 @@ public string Message public int StepSize { get; set; } public int Minimum { get; set; } public int Maximum { get; set; } + public ISynchronizeInvoke SynchronizeInvoke { get; private set; } public Form Form { get; private set; } - - public ProgressBarStyle ProgressBarStyle + public bool IsIndeterminate { - get { return ProgressBarStyle.Continuous; } + get { return false; } set { } } diff --git a/Src/Utilities/FixFwDataDll/ErrorFixer.cs b/Src/Utilities/FixFwDataDll/ErrorFixer.cs index f5fab5cf6b..e0c22ebf8c 100644 --- a/Src/Utilities/FixFwDataDll/ErrorFixer.cs +++ b/Src/Utilities/FixFwDataDll/ErrorFixer.cs @@ -11,7 +11,6 @@ // File: LinkFixer.cs // Responsibility: mcconnel // --------------------------------------------------------------------------------------------- -using System; using System.Collections.Generic; using System.Diagnostics; @@ -111,7 +110,7 @@ public void Process() { using (new WaitCursor(m_dlg)) { - using (var progressDlg = new ProgressDialogWithTask(m_dlg, null)) + using (var progressDlg = new ProgressDialogWithTask(m_dlg)) { string fixes = (string)progressDlg.RunTask(true, FixDataFile, pathname); if (fixes.Length > 0) diff --git a/Src/xWorks/ExportDialog.cs b/Src/xWorks/ExportDialog.cs index 61133f473d..83d15e4b17 100644 --- a/Src/xWorks/ExportDialog.cs +++ b/Src/xWorks/ExportDialog.cs @@ -45,7 +45,6 @@ using SIL.FieldWorks.Common.RootSites; using SIL.FieldWorks.LexText.Controls; using XCore; -using ProgressBarStyle = SIL.FieldWorks.Common.FwUtils.ProgressBarStyle; namespace SIL.FieldWorks.XWorks { @@ -738,7 +737,7 @@ protected void DoExport(string outPath, bool fLiftOutput) FxtType ft = m_rgFxtTypes[FxtIndex(fxtPath)]; using (new WaitCursor(this)) { - using (var progressDlg = new ProgressDialogWithTask(this, m_cache.ThreadHelper)) + using (var progressDlg = new ProgressDialogWithTask(this)) { try { @@ -756,7 +755,6 @@ protected void DoExport(string outPath, bool fLiftOutput) progressDlg.Maximum = m_dumper.GetProgressMaximum(); progressDlg.AllowCancel = true; progressDlg.Restartable = true; - progressDlg.ProgressBarStyle = ProgressBarStyle.Continuous; progressDlg.RunTask(true, ExportFxt, outPath, fxtPath, fLiftOutput); break; @@ -775,7 +773,6 @@ protected void DoExport(string outPath, bool fLiftOutput) progressDlg.Minimum = 0; progressDlg.Maximum = m_translatedLists.Count; progressDlg.AllowCancel = true; - progressDlg.ProgressBarStyle = ProgressBarStyle.Continuous; progressDlg.RunTask(true, ExportTranslatedLists, outPath); break; @@ -787,7 +784,6 @@ protected void DoExport(string outPath, bool fLiftOutput) progressDlg.Minimum = 0; progressDlg.Maximum = 1; progressDlg.AllowCancel = true; - progressDlg.ProgressBarStyle = ProgressBarStyle.Continuous; progressDlg.RunTask(true, ExportSemanticDomains, outPath, ft, fxtPath, m_allQuestions); break; @@ -798,7 +794,6 @@ protected void DoExport(string outPath, bool fLiftOutput) progressDlg.Maximum = 1000; progressDlg.AllowCancel = true; progressDlg.Restartable = true; - progressDlg.ProgressBarStyle = ProgressBarStyle.Continuous; progressDlg.RunTask(true, ExportLift, outPath, ft.m_filtered); break; case FxtTypes.kftGrammarSketch: @@ -806,7 +801,6 @@ protected void DoExport(string outPath, bool fLiftOutput) progressDlg.Maximum = 1000; progressDlg.AllowCancel = true; progressDlg.Restartable = true; - progressDlg.ProgressBarStyle = ProgressBarStyle.Continuous; progressDlg.RunTask(true, ExportGrammarSketch, outPath, ft.m_sDataType, ft.m_sXsltFiles); break; } diff --git a/Src/xWorks/FwXWindow.cs b/Src/xWorks/FwXWindow.cs index 2f8fdf4d5b..fcd9ae4f16 100644 --- a/Src/xWorks/FwXWindow.cs +++ b/Src/xWorks/FwXWindow.cs @@ -1911,7 +1911,7 @@ public bool OnImportTranslatedLists(object commandObject) private void ImportTranslatedLists(string filename) { - using (var dlg = new ProgressDialogWithTask(this, Cache.ThreadHelper)) + using (var dlg = new ProgressDialogWithTask(this)) { dlg.AllowCancel = true; dlg.Maximum = 200; diff --git a/Src/xWorks/NotebookExportDialog.cs b/Src/xWorks/NotebookExportDialog.cs index 35e8b779ec..2ad17d1119 100644 --- a/Src/xWorks/NotebookExportDialog.cs +++ b/Src/xWorks/NotebookExportDialog.cs @@ -113,7 +113,7 @@ protected override void DoExport(string outPath) FxtType ft = m_rgFxtTypes[FxtIndex(fxtPath)]; using (new WaitCursor(this)) { - using (var progressDlg = new ProgressDialogWithTask(this, m_cache.ThreadHelper)) + using (var progressDlg = new ProgressDialogWithTask(this)) { try { diff --git a/Src/xWorks/xWorksTests/ExportDialogTests.cs b/Src/xWorks/xWorksTests/ExportDialogTests.cs index 21a1062433..f8b0afb01c 100644 --- a/Src/xWorks/xWorksTests/ExportDialogTests.cs +++ b/Src/xWorks/xWorksTests/ExportDialogTests.cs @@ -20,7 +20,6 @@ using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.FDOTests; using SIL.FieldWorks.FDO.Application.ApplicationServices; -using XCore; using System.Collections.Generic; using SIL.FieldWorks.FDO.Infrastructure; using SIL.Utils; @@ -475,7 +474,7 @@ public class ExportDialogTests : BaseTest public void CreateMockCache() { m_cache = FdoCache.CreateCacheWithNewBlankLangProj( - new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "fr", "en", new ThreadHelper(), new DummyFdoUserAction()); + new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "fr", "en", new DummyFdoUserAction()); var xl = new XmlList(); using (var reader = new StringReader(s_ksSemanticDomainsXml)) xl.ImportList(m_cache.LangProject, "SemanticDomainList", reader, null); @@ -487,7 +486,6 @@ public void CreateMockCache() [TearDown] public void DestroyMockCache() { - m_cache.ThreadHelper.Dispose(); m_cache.Dispose(); m_cache = null; } From 625eb90ef49ee0dd58889bdda5df0ffb54cf083a Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Wed, 4 Dec 2013 11:27:17 +0700 Subject: [PATCH 012/143] removed message boxes from ProjectRestoreService/ProjectBackupService Change-Id: I98a795dba9616dad4a2d7fbaee64d88b200b9985 --- Src/Common/FieldWorks/FieldWorks.cs | 15 +- .../Properties/Resources.Designer.cs | 23 +- .../AppStrings.Designer.cs | 11 +- .../ApplicationServices/AppStrings.resx | 333 +++++++++--------- .../BackupRestore/ProjectBackupService.cs | 32 +- .../BackupRestore/ProjectRestoreService.cs | 60 +--- Src/FDO/Strings.Designer.cs | 36 -- Src/FDO/Strings.resx | 12 - .../BackupRestore/BackupProjectPresenter.cs | 11 +- .../RestoreProjectDlg.Designer.cs | 192 +++++----- .../BackupRestore/RestoreProjectDlg.cs | 51 ++- Src/FwCoreDlgs/FwCoreDlgs.Designer.cs | 11 +- Src/FwCoreDlgs/FwCoreDlgs.resx | 3 + 13 files changed, 389 insertions(+), 401 deletions(-) diff --git a/Src/Common/FieldWorks/FieldWorks.cs b/Src/Common/FieldWorks/FieldWorks.cs index 9ba157c578..938c96e5b4 100644 --- a/Src/Common/FieldWorks/FieldWorks.cs +++ b/Src/Common/FieldWorks/FieldWorks.cs @@ -1846,7 +1846,7 @@ internal static string BackupProject(Form dialogOwner, FwApp fwApp) internal static void RestoreProject(Form dialogOwner, string backupFile) { BackupFileSettings settings = null; - if (!ProjectRestoreService.HandleRestoreFileErrors(null, FwUtils.ksSuiteName, backupFile, + if (!RestoreProjectDlg.HandleRestoreFileErrors(null, FwUtils.ksSuiteName, backupFile, () => settings = new BackupFileSettings(backupFile, true))) { return; @@ -2461,7 +2461,7 @@ private static void RestoreCurrentProject(FwRestoreProjectSettings restoreSettin ProjectRestoreService restoreService = new ProjectRestoreService(restoreSettings.Settings, GetHelpTopicProvider(restoreSettings.FwAppCommandLineAbbrev), s_userAction); Logger.WriteEvent("Restoring from " + restoreSettings.Settings.Backup.File); - if (ProjectRestoreService.HandleRestoreFileErrors(null, ResourceHelper.GetResourceString("ksRestoreFailed"), + if (RestoreProjectDlg.HandleRestoreFileErrors(null, ResourceHelper.GetResourceString("ksRestoreFailed"), restoreSettings.Settings.Backup.File, () => DoRestore(restoreService))) { s_LinkDirChangedTo = restoreService.LinkDirChangedTo; @@ -2479,6 +2479,7 @@ private static void RestoreCurrentProject(FwRestoreProjectSettings restoreSettin } catch (FailedFwRestoreException e) { + MessageBoxUtils.Show(Properties.Resources.ksRestoringOldFwBackupFailed, Properties.Resources.ksFailed); } } while (retry); @@ -2495,7 +2496,7 @@ private static void RestoreCurrentProject(FwRestoreProjectSettings restoreSettin /// ------------------------------------------------------------------------------------ private static void DoRestore(ProjectRestoreService restoreService) { - using (ProgressDialogWithTask progressDlg = new ProgressDialogWithTask(s_threadHelper)) + using (var progressDlg = new ProgressDialogWithTask(s_threadHelper)) restoreService.RestoreProject(progressDlg); } @@ -2529,7 +2530,13 @@ private static bool BackupProjectForRestore(FwRestoreProjectSettings restoreSett settings.AppAbbrev = restoreSettings.FwAppCommandLineAbbrev; ProjectBackupService backupService = new ProjectBackupService(cache, settings); - backupService.BackupProject(progressDlg); + string backupFile; + if (!backupService.BackupProject(progressDlg, out backupFile)) + { + string msg = string.Format(FwCoreDlgs.FwCoreDlgs.ksCouldNotBackupSomeFiles, backupService.FailedFiles.ToString(", ", Path.GetFileName)); + if (MessageBox.Show(msg, FwCoreDlgs.FwCoreDlgs.ksWarning, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) != DialogResult.Yes) + File.Delete(backupFile); + } } catch (FwBackupException e) { diff --git a/Src/Common/FieldWorks/Properties/Resources.Designer.cs b/Src/Common/FieldWorks/Properties/Resources.Designer.cs index 5b79962ab0..6158ad1cde 100644 --- a/Src/Common/FieldWorks/Properties/Resources.Designer.cs +++ b/Src/Common/FieldWorks/Properties/Resources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.296 +// Runtime Version:4.0.30319.18052 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -60,6 +60,9 @@ internal Resources() { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// internal static System.Drawing.Bitmap DatabaseNew { get { object obj = ResourceManager.GetObject("DatabaseNew", resourceCulture); @@ -67,6 +70,9 @@ internal static System.Drawing.Bitmap DatabaseNew { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// internal static System.Drawing.Bitmap Download { get { object obj = ResourceManager.GetObject("Download", resourceCulture); @@ -74,6 +80,9 @@ internal static System.Drawing.Bitmap Download { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// internal static System.Drawing.Bitmap Import { get { object obj = ResourceManager.GetObject("Import", resourceCulture); @@ -81,6 +90,9 @@ internal static System.Drawing.Bitmap Import { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// internal static System.Drawing.Bitmap Info { get { object obj = ResourceManager.GetObject("Info", resourceCulture); @@ -566,6 +578,9 @@ internal static string ksYouCanTryToMoveProjects { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// internal static System.Drawing.Bitmap OpenFile { get { object obj = ResourceManager.GetObject("OpenFile", resourceCulture); @@ -573,6 +588,9 @@ internal static System.Drawing.Bitmap OpenFile { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// internal static System.Drawing.Bitmap Receive { get { object obj = ResourceManager.GetObject("Receive", resourceCulture); @@ -580,6 +598,9 @@ internal static System.Drawing.Bitmap Receive { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// internal static System.Drawing.Bitmap SendReceiveGetArrow32x32 { get { object obj = ResourceManager.GetObject("SendReceiveGetArrow32x32", resourceCulture); diff --git a/Src/FDO/Application/ApplicationServices/AppStrings.Designer.cs b/Src/FDO/Application/ApplicationServices/AppStrings.Designer.cs index 5d263ed8ba..777b206e57 100644 --- a/Src/FDO/Application/ApplicationServices/AppStrings.Designer.cs +++ b/Src/FDO/Application/ApplicationServices/AppStrings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.296 +// Runtime Version:4.0.30319.18052 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -548,15 +548,6 @@ internal static string ksProblemImporting { } } - /// - /// Looks up a localized string similar to Restore Failed. - /// - internal static string ksRestoreDidNotSucceed { - get { - return ResourceManager.GetString("ksRestoreDidNotSucceed", resourceCulture); - } - } - /// /// Looks up a localized string similar to Semantic Domain. /// diff --git a/Src/FDO/Application/ApplicationServices/AppStrings.resx b/Src/FDO/Application/ApplicationServices/AppStrings.resx index 814540a3a5..0c5b98a38e 100644 --- a/Src/FDO/Application/ApplicationServices/AppStrings.resx +++ b/Src/FDO/Application/ApplicationServices/AppStrings.resx @@ -1,302 +1,299 @@  - + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - text/microsoft-resx + text/microsoft-resx - 2.0 + 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Created {0} {1} objects during import from {2} + Created {0} {1} objects during import from {2} - Loading the XML file into the database took {0:F1} seconds. + Loading the XML file into the database took {0:F1} seconds. - This was automatically created to satisfy a Lexical Relation, and it should be checked. + This was automatically created to satisfy a Lexical Relation, and it should be checked. - {0}:{1}: Created an entry for "{2}" to satisfy a Lexical Relation. + {0}:{1}: Created an entry for "{2}" to satisfy a Lexical Relation. - This was automatically created to satisfy a Cross Reference, and it should be checked. + This was automatically created to satisfy a Cross Reference, and it should be checked. - {0}:{1}: Created an entry for "{2}" to satisfy a Cross Reference. + {0}:{1}: Created an entry for "{2}" to satisfy a Cross Reference. - Info: Creating Entry Or Sense Pair Lexical Reference Type with name="{0}" and abbr="{1}". + Info: Creating Entry Or Sense Pair Lexical Reference Type with name="{0}" and abbr="{1}". - Warning: Invalid <Binary> data. + Warning: Invalid <Binary> data. - Warning: Ignoring extra character at the end of <Binary> data. + Warning: Ignoring extra character at the end of <Binary> data. - Warning: Cannot create desired Lexical Reference Type: <Link {0}/>. + Warning: Cannot create desired Lexical Reference Type: <Link {0}/>. - Warning: Cannot resolve a link for a cross reference: <Link {0}/>. + Warning: Cannot resolve a link for a cross reference: <Link {0}/>. - Warning: Cannot resolve a link for a lexical relation: <Link {0}/>. + Warning: Cannot resolve a link for a lexical relation: <Link {0}/>. - Info: Creating new writing system for "{0}". + Info: Creating new writing system for "{0}". - Warning: Media file "{0}" does not exist. + Warning: Media file "{0}" does not exist. - Warning: Picture file "{0}" does not exist. + Warning: Picture file "{0}" does not exist. - Info: Creating new item with ws="{0}", abbr="{1}", and name="{2}" in the {3} list. + Info: Creating new item with ws="{0}", abbr="{1}", and name="{2}" in the {3} list. - Anthropology Categories + Anthropology Categories - Semantic Domain + Semantic Domain - Parts of Speech + Parts of Speech - Location + Location - People + People - Confidence Level + Confidence Level - Warning: Cannot resolve <Link {0}/> + Warning: Cannot resolve <Link {0}/> - Info: Creating Reversal Index for the {0} ("{1}") language. + Info: Creating Reversal Index for the {0} ("{1}") language. - Info: Implicit CmPossibility target in a Link element has name attribute "{0}" which matches an Abbreviation value. + Info: Implicit CmPossibility target in a Link element has name attribute "{0}" which matches an Abbreviation value. - Info: Implicit CmPossibility target in a Link element has abbr attribute "{0}" which matches a Name value. + Info: Implicit CmPossibility target in a Link element has abbr attribute "{0}" which matches a Name value. - Warning: Unexpected {0} element in XML file. + Warning: Unexpected {0} element in XML file. - Warning: Expected <Boolean val="..."/> here. + Warning: Expected <Boolean val="..."/> here. - Warning: Need explicit val attribute for Boolean elements! + Warning: Need explicit val attribute for Boolean elements! - Warning: Expected <Integer val="..."/> here. + Warning: Expected <Integer val="..."/> here. - Warning: Need explicit val attribute for Integer elements! + Warning: Need explicit val attribute for Integer elements! - Warning: Expected <Guid val="..."/> here. + Warning: Expected <Guid val="..."/> here. - Warning: Need explicit val attribute for Guid elements! + Warning: Need explicit val attribute for Guid elements! - Warning: Expected <Time val="..."/> here. + Warning: Expected <Time val="..."/> here. - Warning: Need explicit val attribute for Time elements! + Warning: Need explicit val attribute for Time elements! - Warning: Expected <GenDate val="..."/> here. + Warning: Expected <GenDate val="..."/> here. - Warning: Need explicit val attribute for GenDate elements! + Warning: Need explicit val attribute for GenDate elements! - Warning: Expected <Binary>...</Binary> here. + Warning: Expected <Binary>...</Binary> here. - Warning: Expected <Uni>...</Uni> here. + Warning: Expected <Uni>...</Uni> here. - Warning: Expected <AUni>...</AUni> here. + Warning: Expected <AUni>...</AUni> here. - Warning: Expected <Str>...</Str> here. + Warning: Expected <Str>...</Str> here. - Warning: Expected <AStr>...</AStr> here. + Warning: Expected <AStr>...</AStr> here. - Warning: Expected <Link .../> here. + Warning: Expected <Link .../> here. - Warning: Invalid <Link/> element - must have at least one attribute! + Warning: Invalid <Link/> element - must have at least one attribute! - Warning: Problem importing from {0}. + Warning: Problem importing from {0}. {1} - Import could not merge the custom field named "{0}" from one entry to another. + Import could not merge the custom field named "{0}" from one entry to another. - Warning: Nested XML object elements must reflect owning relationships. + Warning: Nested XML object elements must reflect owning relationships. - Warning: Unrecognized ownerless object class. + Warning: Unrecognized ownerless object class. - This was automatically created to satisfy a Components link, and it should be checked. + This was automatically created to satisfy a Components link, and it should be checked. - This was automatically created to satisfy a Show Subentry Under link, and it should be checked. + This was automatically created to satisfy a Show Subentry Under link, and it should be checked. - This was automatically created to satisfy a link target, and it should be checked. + This was automatically created to satisfy a link target, and it should be checked. - {0}:{1}: Created an entry for "{2}" to satisfy a Components link. + {0}:{1}: Created an entry for "{2}" to satisfy a Components link. - {0}:{1}: Created an entry for "{2}" to satisfy a Show Subentry Under link. + {0}:{1}: Created an entry for "{2}" to satisfy a Show Subentry Under link. - {0}:{1}: Created an entry for "{2}" to satisfy a link target. + {0}:{1}: Created an entry for "{2}" to satisfy a link target. - Info: Lexical reference type in a Link element has name attribute "{0}" which matches an Abbreviation value. + Info: Lexical reference type in a Link element has name attribute "{0}" which matches an Abbreviation value. - Info: Lexical reference type in a Link element has abbr attribute "{0}" which matches a Name value. + Info: Lexical reference type in a Link element has abbr attribute "{0}" which matches a Name value. - and {0} subrecords. + and {0} subrecords. - There was an error trying to create a subfolder of the new project. + There was an error trying to create a subfolder of the new project. The error was: {0} - - Restore Failed - - + Saving migrated data before loading. Message on a progress dialog. Appears after a data migration has completed and before the project is opened by FLEx. diff --git a/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs b/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs index 0193985c3b..3f26b4f4b7 100644 --- a/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs +++ b/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs @@ -15,7 +15,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Windows.Forms; using ICSharpCode.SharpZipLib.Zip; using SIL.CoreImpl; using SIL.FieldWorks.Common.FwUtils; @@ -31,7 +30,7 @@ public class ProjectBackupService { private readonly FdoCache m_cache; private readonly BackupProjectSettings m_settings; - List m_failedFiles = new List(); + private readonly List m_failedFiles = new List(); /// /// Constructor @@ -42,15 +41,26 @@ public ProjectBackupService(FdoCache cache, BackupProjectSettings settings) m_settings = settings; } + /// + /// Gets the failed files. + /// + /// + /// The failed files. + /// + public IEnumerable FailedFiles + { + get { return m_failedFiles; } + } + /// /// Perform a backup of the current project, using specified settings. /// /// The backup file or null if something went wrong. - public string BackupProject(IThreadedProgress progressDlg) + public bool BackupProject(IThreadedProgress progressDlg, out string backupFile) { PersistBackupFileSettings(); - string backupFile = null; + backupFile = null; try { // Make sure any changes we want backup are saved. @@ -65,19 +75,10 @@ public string BackupProject(IThreadedProgress progressDlg) progressDlg.AllowCancel = false; m_failedFiles.Clear(); // I think it's always a new instance, but play safe. backupFile = (string)progressDlg.RunTask(true, BackupTask, filesToZip); - if (m_failedFiles.Count > 0) - { - var msg = string.Format(Strings.ksCouldNotBackupSomeFiles, m_failedFiles.ToString(", ", Path.GetFileName)); - if (MessageBox.Show(progressDlg.Form, msg, Strings.ksWarning, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) != - DialogResult.Yes) - { - File.Delete(backupFile); - } - } if (tempFilePath != null) File.Delete(tempFilePath); // don't leave the extra fwdata file around to confuse things. } - catch(Exception e) + catch (Exception e) { // Something went catastrophically wrong. Don't leave a junk backup around. if (backupFile != null) @@ -86,7 +87,8 @@ public string BackupProject(IThreadedProgress progressDlg) throw e.InnerException; throw new ContinuableErrorException("Backup did not succeed. Code is needed to handle this case.", e); } - return backupFile; + + return m_failedFiles.Count == 0; } /// ------------------------------------------------------------------------------------ diff --git a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs index 517816724e..def642cf52 100644 --- a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs +++ b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs @@ -17,10 +17,8 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Text; -using System.Windows.Forms; using ICSharpCode.SharpZipLib.Zip; using SIL.FieldWorks.Common.FwUtils; -using SIL.FieldWorks.FDO.Application.ApplicationServices; using SIL.Utils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; using XCore; @@ -105,24 +103,19 @@ public void RestoreProject(IThreadedProgress progressDlg) try { - //Import from FW version 6.0 based on the file extension. - var extension = Path.GetExtension(fileSettings.File).ToLowerInvariant(); - if (extension == FwFileExtensions.ksFw60BackupFileExtension || extension == ".xml") - ImportFrom6_0Backup(fileSettings, progressDlg); - else //Restore from FW version 7.0 and newer backup. - RestoreFrom7_0AndNewerBackup(fileSettings); + //Import from FW version 6.0 based on the file extension. + var extension = Path.GetExtension(fileSettings.File).ToLowerInvariant(); + if (extension == FwFileExtensions.ksFw60BackupFileExtension || extension == ".xml") + ImportFrom6_0Backup(fileSettings, progressDlg); + else //Restore from FW version 7.0 and newer backup. + RestoreFrom7_0AndNewerBackup(fileSettings); } - catch(Exception error) + catch (Exception error) { if (error is IOException || error is InvalidBackupFileException || error is UnauthorizedAccessException) { CleanupAfterRestore(false); - // ENHANCE: If/when we have the restore process using a progress dialog so that this code - // runs in the progress dialog thread instead of the main thread, all message boxes should - // be replaced with the ThreadHelper.ShowMessageBox() method so that they will be thread-safe. - MessageBoxUtils.Show(null, error.Message, AppStrings.ksRestoreDidNotSucceed, - MessageBoxButtons.OK, MessageBoxIcon.Information); } throw; } @@ -147,7 +140,6 @@ private void ImportFrom6_0Backup(BackupFileSettings fileSettings, IThreadedProgr throw new MissingOldFwException("Error restoring from FieldWorks 6.0 (or earlier) backup", importer.HaveFwSqlServer, importer.HaveOldFieldWorks); } - MessageBoxUtils.Show(Strings.ksRestoringOldFwBackupFailed, Strings.ksFailed); throw new FailedFwRestoreException("Error restoring from FieldWorks 6.0 (or earlier) backup"); } } @@ -254,44 +246,6 @@ private void CleanupAfterRestore(bool succeeded) #endregion - /// ------------------------------------------------------------------------------------ - /// - /// Performs the requested actions and handles any IO or zip error by reporting them to - /// the user. (Intended for operations that deal directly with a backup zip file. - /// - /// The parent window to use when reporting an error (can be - /// null). - /// Used in title bar of message box when reporting an error - /// (typically the name of the application). - /// - /// The backup zip filename. - /// The action to perform. - /// - /// true if successful (no exception caught); false otherwise - /// - /// ------------------------------------------------------------------------------------ - public static bool HandleRestoreFileErrors(IWin32Window parentWindow, string caption, - string zipFilename, Action action) - { - try - { - action(); - } - catch (Exception error) - { - if (error is IOException || error is InvalidBackupFileException || - error is UnauthorizedAccessException) - { - Logger.WriteError(error); - MessageBoxUtils.Show(parentWindow, error.Message, caption, - MessageBoxButtons.OK, MessageBoxIcon.Information); - return false; - } - throw; - } - return true; - } - #region Private methods /// ------------------------------------------------------------------------------------ /// diff --git a/Src/FDO/Strings.Designer.cs b/Src/FDO/Strings.Designer.cs index 36b65a5013..f27906b750 100644 --- a/Src/FDO/Strings.Designer.cs +++ b/Src/FDO/Strings.Designer.cs @@ -588,15 +588,6 @@ internal static string ksConvertingToShared { } } - /// - /// Looks up a localized string similar to FieldWorks was not able to back up some of the files used by this project. Do you want to keep the backup anyway? The files not backed up were {0}. - /// - internal static string ksCouldNotBackupSomeFiles { - get { - return ResourceManager.GetString("ksCouldNotBackupSomeFiles", resourceCulture); - } - } - /// /// Looks up a localized string similar to Dashed {0} Underline. /// @@ -1049,15 +1040,6 @@ internal static string ksExtractingFromZip { } } - /// - /// Looks up a localized string similar to Failed. - /// - internal static string ksFailed { - get { - return ResourceManager.GetString("ksFailed", resourceCulture); - } - } - /// /// Looks up a localized string similar to Failed to start server: ///{0}. @@ -1888,15 +1870,6 @@ internal static string ksRequiredItem { } } - /// - /// Looks up a localized string similar to Restoring from an old FieldWorks backup failed.. - /// - internal static string ksRestoringOldFwBackupFailed { - get { - return ResourceManager.GetString("ksRestoringOldFwBackupFailed", resourceCulture); - } - } - /// /// Looks up a localized string similar to Restoring {0} to a temporary project. /// @@ -2203,15 +2176,6 @@ internal static string ksUsedXTimesInRules { } } - /// - /// Looks up a localized string similar to Warning. - /// - internal static string ksWarning { - get { - return ResourceManager.GetString("ksWarning", resourceCulture); - } - } - /// /// Looks up a localized string similar to Warning, once you delete this analysis, the following problems may arise:. /// diff --git a/Src/FDO/Strings.resx b/Src/FDO/Strings.resx index 624c64e3dd..e9fbcad403 100644 --- a/Src/FDO/Strings.resx +++ b/Src/FDO/Strings.resx @@ -530,9 +530,6 @@ truncated to the maximum length. Try using the Tools/Guess Word Breaks tool on the baseline text, or insert word breaks into the text manually. - - Warning - The FDOBackendProviderType is not supported. @@ -792,12 +789,6 @@ Your changes to this entry will be discarded when you exit the project. Error restoring from FieldWorks 6.0 (or earlier) backup - - Restoring from an old FieldWorks backup failed. - - - Failed - Could not connect to server. Check that {0} is running on the remote server and that any firewalls are configured to allow connections to it. Parameter is hard-coded service name (FwRemoteDatabaseConnectorService). This is a message targeted primarily at a computer savvy person. @@ -904,9 +895,6 @@ Corrupted Record: Short delay Caption that goes with ksOtherClientsAreWriting - - FieldWorks was not able to back up some of the files used by this project. Do you want to keep the backup anyway? The files not backed up were {0} - Number of other users: {0} The menu command you selected will open a dialog box. If you change any selections or settings in the dialog box, other users who have this project open on their computers will have problems. diff --git a/Src/FwCoreDlgs/BackupRestore/BackupProjectPresenter.cs b/Src/FwCoreDlgs/BackupRestore/BackupProjectPresenter.cs index a13346dfbe..61dce80548 100644 --- a/Src/FwCoreDlgs/BackupRestore/BackupProjectPresenter.cs +++ b/Src/FwCoreDlgs/BackupRestore/BackupProjectPresenter.cs @@ -14,6 +14,7 @@ using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices.BackupRestore; using SIL.FieldWorks.Common.FwUtils; +using SIL.Utils; namespace SIL.FieldWorks.FwCoreDlgs.BackupRestore { @@ -123,7 +124,15 @@ internal string BackupProject(IThreadedProgress progressDlg) settings.AppAbbrev = m_appAbbrev; ProjectBackupService backupService = new ProjectBackupService(m_cache, settings); - return backupService.BackupProject(progressDlg); + string backupFile; + if (!backupService.BackupProject(progressDlg, out backupFile)) + { + string msg = string.Format(FwCoreDlgs.ksCouldNotBackupSomeFiles, backupService.FailedFiles.ToString(", ", Path.GetFileName)); + if (MessageBox.Show(msg, FwCoreDlgs.ksWarning, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) != DialogResult.Yes) + File.Delete(backupFile); + backupFile = null; + } + return backupFile; } } } diff --git a/Src/FwCoreDlgs/BackupRestore/RestoreProjectDlg.Designer.cs b/Src/FwCoreDlgs/BackupRestore/RestoreProjectDlg.Designer.cs index 537cda623b..e8c67b7ca3 100644 --- a/Src/FwCoreDlgs/BackupRestore/RestoreProjectDlg.Designer.cs +++ b/Src/FwCoreDlgs/BackupRestore/RestoreProjectDlg.Designer.cs @@ -1,4 +1,12 @@ -namespace SIL.FieldWorks.FwCoreDlgs.BackupRestore +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.IO; +using System.Windows.Forms; +using SIL.FieldWorks.FDO.DomainServices.BackupRestore; +using SIL.Utils; + +namespace SIL.FieldWorks.FwCoreDlgs.BackupRestore { /// /// @@ -8,7 +16,7 @@ partial class RestoreProjectDlg /// /// Required designer variable. /// - private System.ComponentModel.IContainer components = null; + private IContainer components = null; /// /// Clean up any resources being used. @@ -16,7 +24,7 @@ partial class RestoreProjectDlg /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { - System.Diagnostics.Debug.WriteLineIf(!disposing, "****** Missing Dispose() call for " + GetType().Name + ". ****** "); + Debug.WriteLineIf(!disposing, "****** Missing Dispose() call for " + GetType().Name + ". ****** "); if (disposing) { if (m_openFileDlg != null) @@ -36,52 +44,52 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - System.Windows.Forms.Button m_btnHelp; - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(RestoreProjectDlg)); - System.Windows.Forms.Button m_btnCancel; - System.Windows.Forms.Label label2; - System.Windows.Forms.Label label3; - System.Windows.Forms.Label label4; - System.Windows.Forms.Label label5; - System.Windows.Forms.Label label13; - System.Windows.Forms.Label label16; - this.m_btnBrowse = new System.Windows.Forms.Button(); - this.m_txtOtherProjectName = new System.Windows.Forms.TextBox(); - this.m_configurationSettings = new System.Windows.Forms.CheckBox(); - this.m_linkedFiles = new System.Windows.Forms.CheckBox(); - this.m_supportingFiles = new System.Windows.Forms.CheckBox(); - this.m_gbAlsoRestore = new System.Windows.Forms.GroupBox(); - this.m_spellCheckAdditions = new System.Windows.Forms.CheckBox(); - this.m_btnOk = new System.Windows.Forms.Button(); - this.m_lblOtherBackupIncludes = new System.Windows.Forms.Label(); - this.m_gbBackupProperties = new System.Windows.Forms.GroupBox(); - this.m_pnlDefaultBackupFolder = new System.Windows.Forms.Panel(); - this.m_lstVersions = new System.Windows.Forms.ListView(); - this.colDate = new System.Windows.Forms.ColumnHeader(); - this.colComment = new System.Windows.Forms.ColumnHeader(); - this.m_cboProjects = new System.Windows.Forms.ComboBox(); - this.m_lblDefaultBackupIncludes = new System.Windows.Forms.Label(); - this.label14 = new System.Windows.Forms.Label(); - this.m_pnlAnotherLocation = new System.Windows.Forms.Panel(); - this.m_lblBackupComment = new System.Windows.Forms.Label(); - this.m_lblBackupZipFile = new System.Windows.Forms.Label(); - this.m_lblBackupDate = new System.Windows.Forms.Label(); - this.m_lblBackupProjectName = new System.Windows.Forms.Label(); - this.label6 = new System.Windows.Forms.Label(); - this.m_gbRestoreAs = new System.Windows.Forms.GroupBox(); - this.m_rdoUseOriginalName = new System.Windows.Forms.RadioButton(); - this.m_rdoRestoreToName = new System.Windows.Forms.RadioButton(); - this.m_rdoDefaultFolder = new System.Windows.Forms.RadioButton(); - this.m_rdoAnotherLocation = new System.Windows.Forms.RadioButton(); - this.label1 = new System.Windows.Forms.Label(); - m_btnHelp = new System.Windows.Forms.Button(); - m_btnCancel = new System.Windows.Forms.Button(); - label2 = new System.Windows.Forms.Label(); - label3 = new System.Windows.Forms.Label(); - label4 = new System.Windows.Forms.Label(); - label5 = new System.Windows.Forms.Label(); - label13 = new System.Windows.Forms.Label(); - label16 = new System.Windows.Forms.Label(); + Button m_btnHelp; + ComponentResourceManager resources = new ComponentResourceManager(typeof(RestoreProjectDlg)); + Button m_btnCancel; + Label label2; + Label label3; + Label label4; + Label label5; + Label label13; + Label label16; + this.m_btnBrowse = new Button(); + this.m_txtOtherProjectName = new TextBox(); + this.m_configurationSettings = new CheckBox(); + this.m_linkedFiles = new CheckBox(); + this.m_supportingFiles = new CheckBox(); + this.m_gbAlsoRestore = new GroupBox(); + this.m_spellCheckAdditions = new CheckBox(); + this.m_btnOk = new Button(); + this.m_lblOtherBackupIncludes = new Label(); + this.m_gbBackupProperties = new GroupBox(); + this.m_pnlDefaultBackupFolder = new Panel(); + this.m_lstVersions = new ListView(); + this.colDate = new ColumnHeader(); + this.colComment = new ColumnHeader(); + this.m_cboProjects = new ComboBox(); + this.m_lblDefaultBackupIncludes = new Label(); + this.label14 = new Label(); + this.m_pnlAnotherLocation = new Panel(); + this.m_lblBackupComment = new Label(); + this.m_lblBackupZipFile = new Label(); + this.m_lblBackupDate = new Label(); + this.m_lblBackupProjectName = new Label(); + this.label6 = new Label(); + this.m_gbRestoreAs = new GroupBox(); + this.m_rdoUseOriginalName = new RadioButton(); + this.m_rdoRestoreToName = new RadioButton(); + this.m_rdoDefaultFolder = new RadioButton(); + this.m_rdoAnotherLocation = new RadioButton(); + this.label1 = new Label(); + m_btnHelp = new Button(); + m_btnCancel = new Button(); + label2 = new Label(); + label3 = new Label(); + label4 = new Label(); + label5 = new Label(); + label13 = new Label(); + label16 = new Label(); this.m_gbAlsoRestore.SuspendLayout(); this.m_gbBackupProperties.SuspendLayout(); this.m_pnlDefaultBackupFolder.SuspendLayout(); @@ -94,12 +102,12 @@ private void InitializeComponent() resources.ApplyResources(m_btnHelp, "m_btnHelp"); m_btnHelp.Name = "m_btnHelp"; m_btnHelp.UseVisualStyleBackColor = true; - m_btnHelp.Click += new System.EventHandler(this.m_btnHelp_Click); + m_btnHelp.Click += new EventHandler(this.m_btnHelp_Click); // // m_btnCancel // resources.ApplyResources(m_btnCancel, "m_btnCancel"); - m_btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + m_btnCancel.DialogResult = DialogResult.Cancel; m_btnCancel.Name = "m_btnCancel"; m_btnCancel.UseVisualStyleBackColor = true; // @@ -138,7 +146,7 @@ private void InitializeComponent() resources.ApplyResources(this.m_btnBrowse, "m_btnBrowse"); this.m_btnBrowse.Name = "m_btnBrowse"; this.m_btnBrowse.UseVisualStyleBackColor = true; - this.m_btnBrowse.Click += new System.EventHandler(this.m_btnBrowse_Click); + this.m_btnBrowse.Click += new EventHandler(this.m_btnBrowse_Click); // // m_txtOtherProjectName // @@ -184,7 +192,7 @@ private void InitializeComponent() resources.ApplyResources(this.m_btnOk, "m_btnOk"); this.m_btnOk.Name = "m_btnOk"; this.m_btnOk.UseVisualStyleBackColor = true; - this.m_btnOk.Click += new System.EventHandler(this.m_btnOk_Click); + this.m_btnOk.Click += new EventHandler(this.m_btnOk_Click); // // m_lblOtherBackupIncludes // @@ -213,19 +221,19 @@ private void InitializeComponent() // m_lstVersions // resources.ApplyResources(this.m_lstVersions, "m_lstVersions"); - this.m_lstVersions.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.m_lstVersions.Columns.AddRange(new ColumnHeader[] { this.colDate, this.colComment}); this.m_lstVersions.FullRowSelect = true; - this.m_lstVersions.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None; + this.m_lstVersions.HeaderStyle = ColumnHeaderStyle.None; this.m_lstVersions.HideSelection = false; this.m_lstVersions.MultiSelect = false; this.m_lstVersions.Name = "m_lstVersions"; this.m_lstVersions.ShowGroups = false; this.m_lstVersions.UseCompatibleStateImageBehavior = false; - this.m_lstVersions.View = System.Windows.Forms.View.Details; - this.m_lstVersions.SelectedIndexChanged += new System.EventHandler(this.m_lstVersions_SelectedIndexChanged); - this.m_lstVersions.SizeChanged += new System.EventHandler(this.m_lstVersions_SizeChanged); + this.m_lstVersions.View = View.Details; + this.m_lstVersions.SelectedIndexChanged += new EventHandler(this.m_lstVersions_SelectedIndexChanged); + this.m_lstVersions.SizeChanged += new EventHandler(this.m_lstVersions_SizeChanged); // // colDate // @@ -238,10 +246,10 @@ private void InitializeComponent() // m_cboProjects // resources.ApplyResources(this.m_cboProjects, "m_cboProjects"); - this.m_cboProjects.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.m_cboProjects.DropDownStyle = ComboBoxStyle.DropDownList; this.m_cboProjects.FormattingEnabled = true; this.m_cboProjects.Name = "m_cboProjects"; - this.m_cboProjects.SelectedIndexChanged += new System.EventHandler(this.m_cboProjects_SelectedIndexChanged); + this.m_cboProjects.SelectedIndexChanged += new EventHandler(this.m_cboProjects_SelectedIndexChanged); // // m_lblDefaultBackupIncludes // @@ -316,7 +324,7 @@ private void InitializeComponent() this.m_rdoRestoreToName.Name = "m_rdoRestoreToName"; this.m_rdoRestoreToName.TabStop = true; this.m_rdoRestoreToName.UseVisualStyleBackColor = true; - this.m_rdoRestoreToName.CheckedChanged += new System.EventHandler(this.m_rdoRestoreToName_CheckedChanged); + this.m_rdoRestoreToName.CheckedChanged += new EventHandler(this.m_rdoRestoreToName_CheckedChanged); // // m_rdoDefaultFolder // @@ -325,7 +333,7 @@ private void InitializeComponent() this.m_rdoDefaultFolder.Name = "m_rdoDefaultFolder"; this.m_rdoDefaultFolder.TabStop = true; this.m_rdoDefaultFolder.UseVisualStyleBackColor = true; - this.m_rdoDefaultFolder.CheckedChanged += new System.EventHandler(this.m_rdoDefaultFolder_CheckedChanged); + this.m_rdoDefaultFolder.CheckedChanged += new EventHandler(this.m_rdoDefaultFolder_CheckedChanged); // // m_rdoAnotherLocation // @@ -342,7 +350,7 @@ private void InitializeComponent() // this.AcceptButton = this.m_btnOk; resources.ApplyResources(this, "$this"); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleMode = AutoScaleMode.Font; this.CancelButton = m_btnCancel; this.Controls.Add(this.label1); this.Controls.Add(this.m_gbRestoreAs); @@ -375,34 +383,34 @@ private void InitializeComponent() #endregion - private System.Windows.Forms.Button m_btnBrowse; - private System.Windows.Forms.TextBox m_txtOtherProjectName; - private System.Windows.Forms.CheckBox m_configurationSettings; - private System.Windows.Forms.CheckBox m_linkedFiles; - private System.Windows.Forms.CheckBox m_supportingFiles; - private System.Windows.Forms.GroupBox m_gbAlsoRestore; - private System.Windows.Forms.Button m_btnOk; - private System.Windows.Forms.Label m_lblOtherBackupIncludes; - private System.Windows.Forms.GroupBox m_gbBackupProperties; - private System.Windows.Forms.CheckBox m_spellCheckAdditions; - private System.Windows.Forms.GroupBox m_gbRestoreAs; - private System.Windows.Forms.RadioButton m_rdoUseOriginalName; - private System.Windows.Forms.RadioButton m_rdoRestoreToName; - private System.Windows.Forms.RadioButton m_rdoDefaultFolder; - private System.Windows.Forms.RadioButton m_rdoAnotherLocation; - private System.Windows.Forms.Label label6; - private System.Windows.Forms.Label m_lblBackupComment; - private System.Windows.Forms.Label m_lblBackupDate; - private System.Windows.Forms.Label m_lblBackupProjectName; - private System.Windows.Forms.Label m_lblBackupZipFile; - private System.Windows.Forms.Panel m_pnlAnotherLocation; - private System.Windows.Forms.Label label1; - private System.Windows.Forms.Panel m_pnlDefaultBackupFolder; - private System.Windows.Forms.Label m_lblDefaultBackupIncludes; - private System.Windows.Forms.Label label14; - private System.Windows.Forms.ComboBox m_cboProjects; - private System.Windows.Forms.ListView m_lstVersions; - private System.Windows.Forms.ColumnHeader colDate; - private System.Windows.Forms.ColumnHeader colComment; + private Button m_btnBrowse; + private TextBox m_txtOtherProjectName; + private CheckBox m_configurationSettings; + private CheckBox m_linkedFiles; + private CheckBox m_supportingFiles; + private GroupBox m_gbAlsoRestore; + private Button m_btnOk; + private Label m_lblOtherBackupIncludes; + private GroupBox m_gbBackupProperties; + private CheckBox m_spellCheckAdditions; + private GroupBox m_gbRestoreAs; + private RadioButton m_rdoUseOriginalName; + private RadioButton m_rdoRestoreToName; + private RadioButton m_rdoDefaultFolder; + private RadioButton m_rdoAnotherLocation; + private Label label6; + private Label m_lblBackupComment; + private Label m_lblBackupDate; + private Label m_lblBackupProjectName; + private Label m_lblBackupZipFile; + private Panel m_pnlAnotherLocation; + private Label label1; + private Panel m_pnlDefaultBackupFolder; + private Label m_lblDefaultBackupIncludes; + private Label label14; + private ComboBox m_cboProjects; + private ListView m_lstVersions; + private ColumnHeader colDate; + private ColumnHeader colComment; } } \ No newline at end of file diff --git a/Src/FwCoreDlgs/BackupRestore/RestoreProjectDlg.cs b/Src/FwCoreDlgs/BackupRestore/RestoreProjectDlg.cs index f3aeb9a8f8..620feae6aa 100644 --- a/Src/FwCoreDlgs/BackupRestore/RestoreProjectDlg.cs +++ b/Src/FwCoreDlgs/BackupRestore/RestoreProjectDlg.cs @@ -19,7 +19,6 @@ using SIL.Utils; using SIL.Utils.FileDialog; using XCore; -using System.Diagnostics; namespace SIL.FieldWorks.FwCoreDlgs.BackupRestore { @@ -28,6 +27,42 @@ namespace SIL.FieldWorks.FwCoreDlgs.BackupRestore /// public partial class RestoreProjectDlg : Form { + /// ------------------------------------------------------------------------------------ + /// + /// Performs the requested actions and handles any IO or zip error by reporting them to + /// the user. (Intended for operations that deal directly with a backup zip file. + /// + /// The parent window to use when reporting an error (can be + /// null). + /// Used in title bar of message box when reporting an error + /// (typically the name of the application). + /// + /// The backup zip filename. + /// The action to perform. + /// + /// true if successful (no exception caught); false otherwise + /// + /// ------------------------------------------------------------------------------------ + public static bool HandleRestoreFileErrors(IWin32Window parentWindow, string caption, string zipFilename, Action action) + { + try + { + action(); + } + catch (Exception error) + { + if (error is IOException || error is InvalidBackupFileException || + error is UnauthorizedAccessException) + { + Logger.WriteError(error); + MessageBoxUtils.Show(parentWindow, error.Message, caption, MessageBoxButtons.OK, MessageBoxIcon.Information); + return false; + } + throw; + } + return true; + } + #region Data members private readonly string m_appName; private readonly IHelpTopicProvider m_helpTopicProvider; @@ -97,12 +132,12 @@ private RestoreProjectDlg(string appName, IHelpTopicProvider helpTopicProvider) { m_appName = appName; m_helpTopicProvider = helpTopicProvider; - m_lblOtherBackupIncludes.Text = string.Empty; - m_lblDefaultBackupIncludes.Text = string.Empty; - m_lblBackupZipFile.Text = string.Empty; - m_lblBackupProjectName.Text = string.Empty; - m_lblBackupDate.Text = string.Empty; - m_lblBackupComment.Text = string.Empty; + m_lblOtherBackupIncludes.Text = String.Empty; + m_lblDefaultBackupIncludes.Text = String.Empty; + m_lblBackupZipFile.Text = String.Empty; + m_lblBackupProjectName.Text = String.Empty; + m_lblBackupDate.Text = String.Empty; + m_lblBackupComment.Text = String.Empty; m_fmtUseOriginalName = m_rdoUseOriginalName.Text; m_rdoUseOriginalName.Text = String.Format(m_fmtUseOriginalName, String.Empty); m_settings = new RestoreProjectSettings(); @@ -291,7 +326,7 @@ private void OnBackupVersionChosen() return; } - if (ProjectRestoreService.HandleRestoreFileErrors(this, m_appName, BackupZipFile, + if (HandleRestoreFileErrors(this, m_appName, BackupZipFile, () => BackupFileSettings = new BackupFileSettings(BackupZipFile, true))) { SetOriginalNameFromSettings(); diff --git a/Src/FwCoreDlgs/FwCoreDlgs.Designer.cs b/Src/FwCoreDlgs/FwCoreDlgs.Designer.cs index a23661a6ad..84a2072fa8 100644 --- a/Src/FwCoreDlgs/FwCoreDlgs.Designer.cs +++ b/Src/FwCoreDlgs/FwCoreDlgs.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.1008 +// Runtime Version:4.0.30319.18052 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -383,6 +383,15 @@ public static string ksCopyFile { } } + /// + /// Looks up a localized string similar to FieldWorks was not able to back up some of the files used by this project. Do you want to keep the backup anyway? The files not backed up were {0}. + /// + public static string ksCouldNotBackupSomeFiles { + get { + return ResourceManager.GetString("ksCouldNotBackupSomeFiles", resourceCulture); + } + } + /// /// Looks up a localized string similar to If you want to replace a picture file, you must first delete the current picture.. /// diff --git a/Src/FwCoreDlgs/FwCoreDlgs.resx b/Src/FwCoreDlgs/FwCoreDlgs.resx index 217d244d5d..6ba3c8df47 100644 --- a/Src/FwCoreDlgs/FwCoreDlgs.resx +++ b/Src/FwCoreDlgs/FwCoreDlgs.resx @@ -979,4 +979,7 @@ The error was: Click 'OK' to continue with this project name or 'Cancel' to enter a different name. + + FieldWorks was not able to back up some of the files used by this project. Do you want to keep the backup anyway? The files not backed up were {0} + \ No newline at end of file From 6778fd9a725757237e50bdaaab085b2094a3721d Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Wed, 4 Dec 2013 11:45:15 +0700 Subject: [PATCH 013/143] Move more UI elements out of FDO Add Retry method to IFdoUserAction and implementations. Move various message boxes out of ClientServerServices. Change-Id: I98ddcea0bd2dc4bee3ec9697f904f57f44c8d8b4 --- .../FwControls/ObtainProjectMethod.cs | 18 +-- Src/Common/FieldWorks/FieldWorks.cs | 4 +- .../FieldWorks/PaObjects/PaLexicalInfo.cs | 15 +- .../BackupRestore/ProjectRestoreService.cs | 2 +- .../DomainServices/ClientServerServices.cs | 115 +++++--------- Src/FDO/FDOTests/DummyFdoUserAction.cs | 11 ++ Src/FDO/FDOTests/FdoCacheTests.cs | 6 +- Src/FDO/IFdoUserAction.cs | 8 + Src/FDO/SilentFdoUserAction.cs | 11 ++ Src/FDO/Strings.Designer.cs | 46 +----- Src/FDO/Strings.resx | 19 --- Src/FDO/fdoCache.cs | 36 ++--- Src/FDOBrowser/FdoBrowserUserAction.cs | 12 ++ Src/FdoUi/FdoUserActionWindowsForms.cs | 14 +- Src/FwCoreDlgs/ChooseLangProjectDialog.cs | 11 +- Src/FwCoreDlgs/ClientServerServicesHelper.cs | 59 ++++++++ Src/FwCoreDlgs/FwCoreDlgs.csproj | 10 ++ .../FwCoreDlgsTests/FwNewLangProjectTests.cs | 2 +- Src/FwCoreDlgs/FwNewLangProject.cs | 6 +- Src/FwCoreDlgs/FwProjPropertiesDlg.cs | 2 +- Src/FwCoreDlgs/Strings.Designer.cs | 107 +++++++++++++ Src/FwCoreDlgs/Strings.resx | 140 ++++++++++++++++++ .../WritingSystemPropertiesDialog.cs | 4 +- Src/LexText/Lexicon/FLExBridgeListener.cs | 4 +- Src/xWorks/FwXWindow.cs | 2 +- 25 files changed, 475 insertions(+), 189 deletions(-) create mode 100644 Src/FwCoreDlgs/ClientServerServicesHelper.cs create mode 100644 Src/FwCoreDlgs/Strings.Designer.cs create mode 100644 Src/FwCoreDlgs/Strings.resx diff --git a/Src/Common/Controls/FwControls/ObtainProjectMethod.cs b/Src/Common/Controls/FwControls/ObtainProjectMethod.cs index 2364b688e8..635db8828a 100644 --- a/Src/Common/Controls/FwControls/ObtainProjectMethod.cs +++ b/Src/Common/Controls/FwControls/ObtainProjectMethod.cs @@ -24,8 +24,7 @@ public static class ObtainProjectMethod /// The repo may be a lift or full FW repo, but it can be from any source source, as long as the code can create an FW project from it. /// /// Null if the operation was cancelled or otherwise did not work. The full pathname of an fwdata file, if it did work. - public static string ObtainProjectFromAnySource(Form parent, IHelpTopicProvider helpTopicProvider, - out ObtainedProjectType obtainedProjectType) + public static string ObtainProjectFromAnySource(Form parent, IHelpTopicProvider helpTopicProvider, out ObtainedProjectType obtainedProjectType, IFdoUserAction userAction) { bool dummy; string fwdataFileFullPathname; @@ -46,7 +45,7 @@ public static string ObtainProjectFromAnySource(Form parent, IHelpTopicProvider if (fwdataFileFullPathname.EndsWith("lift")) { - fwdataFileFullPathname = CreateProjectFromLift(parent, helpTopicProvider, fwdataFileFullPathname); + fwdataFileFullPathname = CreateProjectFromLift(parent, helpTopicProvider, fwdataFileFullPathname, userAction); obtainedProjectType = ObtainedProjectType.Lift; } @@ -56,7 +55,7 @@ public static string ObtainProjectFromAnySource(Form parent, IHelpTopicProvider /// /// Create a new Fieldworks project and import a lift file into it. Return the .fwdata path. /// - private static string CreateProjectFromLift(Form parent, IHelpTopicProvider helpTopicProvider, string liftPath) + private static string CreateProjectFromLift(Form parent, IHelpTopicProvider helpTopicProvider, string liftPath, IFdoUserAction userAction) { string projectPath; FdoCache cache; @@ -73,7 +72,7 @@ private static string CreateProjectFromLift(Form parent, IHelpTopicProvider help progressDlg.Title = FwControls.ksCreatingLiftProject; var cacheReceiver = new FdoCache[1]; // a clumsy way of handling an out parameter, consistent with RunTask projectPath = (string)progressDlg.RunTask(true, CreateProjectTask, - new[] { liftPath, parent, anthroListFile, cacheReceiver }); + new[] { liftPath, parent, userAction, anthroListFile, cacheReceiver }); cache = cacheReceiver[0]; } @@ -103,19 +102,20 @@ private static object CreateProjectTask(IThreadedProgress progress, object[] par // Get required parameters. Ideally these would just be the signature of the method, but RunTask requires object[]. var liftPathname = (string) parameters[0]; var synchronizeInvoke = (ISynchronizeInvoke) parameters[1]; - var anthroFile = (string) parameters[2]; - var cacheReceiver = (FdoCache[]) parameters[3]; + var userAction = (IFdoUserAction) parameters[2]; + var anthroFile = (string) parameters[3]; + var cacheReceiver = (FdoCache[]) parameters[4]; IWritingSystem wsVern, wsAnalysis; RetrieveDefaultWritingSystemsFromLift(liftPathname, out wsVern, out wsAnalysis); string projectPath = FdoCache.CreateNewLangProj(progress, Directory.GetParent(Path.GetDirectoryName(liftPathname)).Parent.Name, // Get the new Flex project name from the Lift pathname. - synchronizeInvoke, wsAnalysis, wsVern, null, null, null, anthroFile); + synchronizeInvoke, userAction, wsAnalysis, wsVern, null, null, null, anthroFile); // This is a temporary cache, just to do the import, and AFAIK we have no access to the current // user WS. So create it as "English". Put it in the array to return to the caller. - cacheReceiver[0] = FdoCache.CreateCacheFromLocalProjectFile(projectPath, "en", progress, new SilentFdoUserAction(synchronizeInvoke)); + cacheReceiver[0] = FdoCache.CreateCacheFromLocalProjectFile(projectPath, "en", progress, userAction); return projectPath; } diff --git a/Src/Common/FieldWorks/FieldWorks.cs b/Src/Common/FieldWorks/FieldWorks.cs index 938c96e5b4..0da474f37a 100644 --- a/Src/Common/FieldWorks/FieldWorks.cs +++ b/Src/Common/FieldWorks/FieldWorks.cs @@ -1652,7 +1652,7 @@ private static ProjectId ShowWelcomeDialog(FwAppArgs args, FwApp startingApp, Pr projectToTry = null; // If the user cancels the send/receive, this null will result in a return to the welcome dialog. // Hard to say what Form.ActiveForm is here. The splash and welcome dlgs are both gone. var projectDataPathname = ObtainProjectMethod.ObtainProjectFromAnySource(Form.ActiveForm, - helpTopicProvider, out obtainedProjectType); + helpTopicProvider, out obtainedProjectType, s_userAction); if (!string.IsNullOrEmpty(projectDataPathname)) { projectToTry = new ProjectId(FDOBackendProviderType.kXML, projectDataPathname, null); @@ -1724,7 +1724,7 @@ internal static ProjectId ChooseLangProject(Form dialogOwner, IHelpTopicProvider { return null; } - using (var dlg = new ChooseLangProjectDialog(helpTopicProvider, false)) + using (var dlg = new ChooseLangProjectDialog(helpTopicProvider, false, s_userAction)) { dlg.ShowDialog(dialogOwner); var app = helpTopicProvider as IApp; diff --git a/Src/Common/FieldWorks/PaObjects/PaLexicalInfo.cs b/Src/Common/FieldWorks/PaObjects/PaLexicalInfo.cs index 4c465c0e54..fd96aad110 100644 --- a/Src/Common/FieldWorks/PaObjects/PaLexicalInfo.cs +++ b/Src/Common/FieldWorks/PaObjects/PaLexicalInfo.cs @@ -22,11 +22,14 @@ using System.Linq; using System.Threading; using System.Windows.Forms; +using SIL.FieldWorks.FDO; +using SIL.FieldWorks.FdoUi; using SIL.PaToFdoInterfaces; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FwCoreDlgs; using SIL.Utils; +using XCore; namespace SIL.FieldWorks.PaObjects { @@ -35,6 +38,16 @@ public class PaLexicalInfo : IPaLexicalInfo, IDisposable { private List m_writingSystems; private List m_lexEntries; + private readonly IFdoUserAction m_userAction; + + /// + /// Initializes a new instance of the class. + /// + public PaLexicalInfo() + { + var helpTopicProvider = (IHelpTopicProvider)DynamicLoader.CreateObject(DirectoryFinder.FlexDll, "SIL.FieldWorks.XWorks.LexText.FlexHelpTopicProvider"); + m_userAction = new FdoUserActionWindowsForms(helpTopicProvider, new ThreadHelper()); + } #region Disposable stuff #if DEBUG @@ -86,7 +99,7 @@ public bool ShowOpenProject(Form owner, ref Rectangle dialogBounds, Icu.InitIcuDataDir(); RegistryHelper.ProductName = "FieldWorks"; // inorder to find correct Registry keys - using (var dlg = new ChooseLangProjectDialog(dialogBounds, dialogSplitterPos)) + using (var dlg = new ChooseLangProjectDialog(dialogBounds, dialogSplitterPos, m_userAction)) { if (dlg.ShowDialog(owner) == DialogResult.OK) { diff --git a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs index def642cf52..17d54d39d9 100644 --- a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs +++ b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs @@ -122,7 +122,7 @@ public void RestoreProject(IThreadedProgress progressDlg) // switch to the desired backend (if it's in the projects directory...anything else stays XML for now). if (DirectoryFinder.IsSubFolderOfProjectsDirectory(m_restoreSettings.ProjectPath) && !suppressConversion) - ClientServerServices.Current.Local.ConvertToDb4oBackendIfNeeded(progressDlg, m_restoreSettings.FullProjectPath); + ClientServerServices.Current.Local.ConvertToDb4oBackendIfNeeded(progressDlg, m_restoreSettings.FullProjectPath, m_userAction); CleanupAfterRestore(true); } diff --git a/Src/FDO/DomainServices/ClientServerServices.cs b/Src/FDO/DomainServices/ClientServerServices.cs index 597f66a61d..3c8d295bcc 100644 --- a/Src/FDO/DomainServices/ClientServerServices.cs +++ b/Src/FDO/DomainServices/ClientServerServices.cs @@ -168,22 +168,11 @@ void BeginFindProjects(string host, Action foundProject, IDisposable GetExclusiveModeToken(FdoCache cache, string id); /// - /// Display a warning indicating that it may be dangerous to change things that the user has just - /// asked to change when other users are connected. The warning should only be shown if, in fact, - /// other users are currently connected. The dialog may contain some information about the other - /// users that are connected. Return true to continue, false to discard the changes. This is typically - /// called in response to clicking an OK button in a dialog which changes dangerous user settings. + /// Returns the number of other users currently connected /// - /// - bool WarnOnConfirmingSingleUserChanges(FdoCache cache); - /// - /// Display a warning indicating that it may be dangerous to change things in the dialog that - /// is about to open when other users are connected. The warning should only be shown if, in fact, - /// other users are currently connected. The dialog may contain some information about the other - /// users that are connected. Return true to continue, false to cancel opening the dialog. - /// - /// - bool WarnOnOpeningSingleUserDialog(FdoCache cache); + /// The FDO cache. + /// The number of other users currently connected + int CountOfOtherUsersConnected(FdoCache cache); } #endregion @@ -238,10 +227,11 @@ public interface ILocalClientServerServices /// The progress dialog for getting a message box owner and/or /// ensuring we're invoking on the uI thread. /// The full path of the existing XML file for the project + /// /// The project identifier, typically the path to the converted file (or the /// original, if not configured for the client-server backend) /// ------------------------------------------------------------------------------------ - string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string filename); + string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string filename, IFdoUserAction userAction); /// /// Copies the specified project (assumed to be in the current Projects directory) @@ -475,7 +465,12 @@ public IDisposable GetExclusiveModeToken(FdoCache cache, string id) return null; } - int CountOfOtherUsersConnected(FdoCache cache) + /// + /// Returns the number of other users currently connected + /// + /// The FDO cache. + /// The number of other users currently connected + public int CountOfOtherUsersConnected(FdoCache cache) { if (cache == null) // Can happen when creating a new project when editing the WS properties. (FWR-2981) return 0; @@ -489,41 +484,6 @@ int CountOfOtherUsersConnected(FdoCache cache) return otherUsers.Length - 1; // Assume this is connected! } - /// - /// Display a warning indicating that it may be dangerous to change things that the user has just - /// asked to change when other users are connected. The warning should only be shown if, in fact, - /// other users are currently connected. The dialog may contain some information about the other - /// users that are connected. Return true to continue, false to discard the changes. This is typically - /// called in response to clicking an OK button in a dialog which changes dangerous user settings. - /// - /// - public bool WarnOnConfirmingSingleUserChanges(FdoCache cache) - { - var others = CountOfOtherUsersConnected(cache); - if (others == 0) - return true; - var msg = string.Format(Strings.ksWarnOnConfirmingSingleUserChanges.Replace("\\n", Environment.NewLine), others); - return ThreadHelper.ShowMessageBox(null, msg, Strings.ksNotAdvisableOthersConnectedCaption, - MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes; - } - - /// - /// Display a warning indicating that it may be dangerous to change things in the dialog that - /// is about to open when other users are connected. The warning should only be shown if, in fact, - /// other users are currently connected. The dialog may contain some information about the other - /// users that are connected. Return true to continue, false to cancel opening the dialog. - /// - /// - public bool WarnOnOpeningSingleUserDialog(FdoCache cache) - { - var others = CountOfOtherUsersConnected(cache); - if (others == 0) - return true; - var msg = string.Format(Strings.ksWarnOnOpeningSingleUserDialog.Replace("\\n", Environment.NewLine), others); - return ThreadHelper.ShowMessageBox(null, msg, Strings.ksOthersConnectedCaption, - MessageBoxButtons.OKCancel, MessageBoxIcon.Information) == DialogResult.OK; - } - #region TrivialDisposable class private sealed class TrivialDisposable: IDisposable { @@ -630,10 +590,9 @@ public bool SetProjectSharing(bool fShare, IThreadedProgress progress, IFdoUserA { } } - while ((serverInfo == null && ThreadHelper.ShowMessageBox(progress.Form, - string.Format(Strings.ksLocalConnectorServiceNotStarted, "FwRemoteDatabaseConnectorService"), - fShare ? Strings.ksConvertingToShared : Strings.ksConvertingToNonShared, - MessageBoxButtons.RetryCancel, MessageBoxIcon.None) == DialogResult.Retry)); + while (serverInfo == null && + userAction.Retry(string.Format(Strings.ksLocalConnectorServiceNotStarted, "FwRemoteDatabaseConnectorService"), + fShare ? Strings.ksConvertingToShared : Strings.ksConvertingToNonShared)); if (serverInfo == null || serverInfo.AreProjectShared() == fShare) return false; @@ -644,7 +603,7 @@ public bool SetProjectSharing(bool fShare, IThreadedProgress progress, IFdoUserA if (fShare) { // Turning sharing on. - if (!ConvertAllProjectsToDb4o(progress)) + if (!ConvertAllProjectsToDb4o(progress, userAction)) { LocalDb4OServerInfoConnection.ShareProjects(false); // could not switch return false; @@ -687,7 +646,7 @@ public bool WillProjectBeConverted(string projectPath, string parentDirectory, s /// /// false if clients are still connected. /// ------------------------------------------------------------------------------------ - private static bool EnsureNoClientsAreConnected() + private static bool EnsureNoClientsAreConnected(IFdoUserAction userAction) { var localService = LocalDb4OServerInfoConnection; if (localService == null) @@ -702,8 +661,8 @@ private static bool EnsureNoClientsAreConnected() connectedClientsMsg.AppendFormat("{2}{0} : {1}", client, Dns.GetHostEntry(client).HostName, Environment.NewLine); } - if (MessageBoxUtils.Show(String.Format(Strings.ksAllProjectsMustDisconnectClients, connectedClientsMsg), - Strings.ksAllProjectsMustDisconnectCaption, MessageBoxButtons.RetryCancel) == DialogResult.Cancel) + if (!userAction.Retry(String.Format(Strings.ksAllProjectsMustDisconnectClients, connectedClientsMsg), + Strings.ksAllProjectsMustDisconnectCaption)) return false; connectedClients = localService.ListConnectedClients(); @@ -720,11 +679,11 @@ private static bool EnsureNoClientsAreConnected() /// TODO: prevent new connections while in this shutdown phase. /// TODO: as an enhancement connected clients could be messaged and asked to disconnect. /// - /// The message box owner. /// project name. + /// /// false if clients are still connected. /// ------------------------------------------------------------------------------------ - private static bool EnsureNoClientsAreConnected(Form messageBoxOwner, string projectName) + private static bool EnsureNoClientsAreConnected(string projectName, IFdoUserAction userAction) { Db4oServerInfo localService = LocalDb4OServerInfoConnection; if (localService == null) @@ -736,7 +695,7 @@ private static bool EnsureNoClientsAreConnected(Form messageBoxOwner, string pro foreach (string client in connectedClients) connectedClientsMsg.AppendFormat("{2}{0} : {1}", client, Dns.GetHostEntry(client).HostName, Environment.NewLine); - if (WarnOfOtherConnectedClients(messageBoxOwner, projectName, connectedClientsMsg.ToString()) == DialogResult.Cancel) + if (!WarnOfOtherConnectedClients(projectName, connectedClientsMsg.ToString(), userAction)) return false; connectedClients = localService.ListConnectedClients(projectName); @@ -749,18 +708,17 @@ private static bool EnsureNoClientsAreConnected(Form messageBoxOwner, string pro /// /// Warns the of other connected clients. /// - /// The message box owner. /// Name of the project. /// The message to show about the connected clients. /// + /// /// ------------------------------------------------------------------------------------ - private static DialogResult WarnOfOtherConnectedClients(Form messageBoxOwner, - string projectName, string connectedClientsMsg) + private static bool WarnOfOtherConnectedClients(string projectName, string connectedClientsMsg, IFdoUserAction userAction) { var msg = String.Format(Strings.ksMustDisconnectClients, projectName, connectedClientsMsg); var caption = String.Format(Strings.ksMustDisconnectCaption, projectName); - return ThreadHelper.ShowMessageBox(messageBoxOwner, msg, caption, - MessageBoxButtons.RetryCancel, MessageBoxIcon.None); + + return userAction.Retry(msg, caption); } /// ------------------------------------------------------------------------------------ @@ -772,7 +730,7 @@ private static DialogResult WarnOfOtherConnectedClients(Form messageBoxOwner, /// ------------------------------------------------------------------------------------ private bool ConvertAllProjectsToXml(IThreadedProgress progressDlg, IFdoUserAction userAction) { - if (!EnsureNoClientsAreConnected()) + if (!EnsureNoClientsAreConnected(userAction)) return false; progressDlg.Title = Strings.ksConvertingToNonShared; @@ -819,16 +777,17 @@ private object ConvertAllProjectsToXmlTask(IThreadedProgress progress, IFdoUserA /// Converts all projects to db4o. /// /// The progress dialog box. + /// /// ------------------------------------------------------------------------------------ - private bool ConvertAllProjectsToDb4o(IThreadedProgress progressDlg) + private bool ConvertAllProjectsToDb4o(IThreadedProgress progressDlg, IFdoUserAction userAction) { progressDlg.Title = Strings.ksConvertingToShared; progressDlg.AllowCancel = false; progressDlg.Maximum = Directory.GetDirectories(DirectoryFinder.ProjectsDirectory).Count(); - return (bool)progressDlg.RunTask(true, ConvertAllProjectsToDb4o); + return (bool)progressDlg.RunTask(true, (progress, args) => ConvertAllProjectsToDb4o(progress, userAction, args)); } - private object ConvertAllProjectsToDb4o(IThreadedProgress progress, object[] args) + private object ConvertAllProjectsToDb4o(IThreadedProgress progress, IFdoUserAction userAction, object[] args) { for (; ; ) { @@ -846,9 +805,8 @@ private object ConvertAllProjectsToDb4o(IThreadedProgress progress, object[] arg if (projects.Length == 0) break; projects = projects.Substring(0, projects.Length - ", ".Length); - // ENHANCE (TimS): Showing a message box at this level is not a good idea. - if (ThreadHelper.ShowMessageBox(progress.Form, string.Format(Strings.ksMustCloseProjectsToShare, projects), - Strings.ksConvertingToShared, MessageBoxButtons.RetryCancel, MessageBoxIcon.None) != DialogResult.Retry) + + if (!userAction.Retry(string.Format(Strings.ksMustCloseProjectsToShare, projects), Strings.ksConvertingToShared)) return false; } foreach (string projectFolder in Directory.GetDirectories(DirectoryFinder.ProjectsDirectory)) @@ -861,7 +819,7 @@ private object ConvertAllProjectsToDb4o(IThreadedProgress progress, object[] arg { try { - ConvertToDb4oBackendIfNeeded(progress, projectPath); + ConvertToDb4oBackendIfNeeded(progress, projectPath, userAction); } catch (Exception e) { @@ -899,15 +857,16 @@ private static void ReportConversionError(Form messageBoxOwner, string projectPa /// The progress dialog (for getting a message box owner and/or /// ensuring we're invoking on the UI thread). /// The full path of the existing XML file for the project + /// /// The project identifier, typically the path to the converted file (or the /// original, if not configured for the client-server backend) /// ------------------------------------------------------------------------------------ - public string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string xmlFilename) + public string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string xmlFilename, IFdoUserAction userAction) { if (!ShareMyProjects) return xmlFilename; // no conversion needed. string desiredPath = Path.ChangeExtension(xmlFilename, FwFileExtensions.ksFwDataDb4oFileExtension); - if (!EnsureNoClientsAreConnected(progressDlg.Form, Path.GetFileNameWithoutExtension(desiredPath))) + if (!EnsureNoClientsAreConnected(Path.GetFileNameWithoutExtension(desiredPath), userAction)) return null; // fail try diff --git a/Src/FDO/FDOTests/DummyFdoUserAction.cs b/Src/FDO/FDOTests/DummyFdoUserAction.cs index 5248bb80c4..f7b11d709a 100644 --- a/Src/FDO/FDOTests/DummyFdoUserAction.cs +++ b/Src/FDO/FDOTests/DummyFdoUserAction.cs @@ -128,5 +128,16 @@ public void ReportDuplicateGuids(RegistryKey applicationKey, string emailAddress { throw new NotImplementedException(); } + + /// + /// Present a message to the user and allow the options to Retry or Cancel + /// + /// The message. + /// The caption. + /// True to retry. False otherwise + public bool Retry(string msg, string caption) + { + throw new NotImplementedException(); + } } } diff --git a/Src/FDO/FDOTests/FdoCacheTests.cs b/Src/FDO/FDOTests/FdoCacheTests.cs index ad3fae314d..6023047cad 100644 --- a/Src/FDO/FDOTests/FdoCacheTests.cs +++ b/Src/FDO/FDOTests/FdoCacheTests.cs @@ -87,7 +87,7 @@ public void CreateNewLangProject_DbFilesExist() using (new DummyFileMaker(Path.Combine(DirectoryFinder.ProjectsDirectory, "Gumby", DirectoryFinder.GetXmlDataFileName("Gumby")))) { using (var threadHelper = new ThreadHelper()) - FdoCache.CreateNewLangProj(new DummyProgressDlg(), "Gumby", threadHelper); + FdoCache.CreateNewLangProj(new DummyProgressDlg(), "Gumby", threadHelper, new DummyFdoUserAction()); } } finally @@ -117,7 +117,7 @@ public void CreateNewLangProject_NameWithSingleQuote() { string dbFileName; using (var threadHelper = new ThreadHelper()) - dbFileName = FdoCache.CreateNewLangProj(new DummyProgressDlg(), dbName, threadHelper); + dbFileName = FdoCache.CreateNewLangProj(new DummyProgressDlg(), dbName, threadHelper, new DummyFdoUserAction()); currentDirs = new List(Directory.GetDirectories(DirectoryFinder.ProjectsDirectory)); if (currentDirs.Contains(writingSystemsCommonDir) && !expectedDirs.Contains(writingSystemsCommonDir)) @@ -148,7 +148,7 @@ public void CreateNewLangProject_AnthropologyCategoriesExist() // create project string dbFileName; using (var threadHelper = new ThreadHelper()) - dbFileName = FdoCache.CreateNewLangProj(new DummyProgressDlg(), dbName, threadHelper); + dbFileName = FdoCache.CreateNewLangProj(new DummyProgressDlg(), dbName, threadHelper, new DummyFdoUserAction()); using (var cache = FdoCache.CreateCacheFromLocalProjectFile(dbFileName, "en", new DummyProgressDlg(), m_userAction)) { diff --git a/Src/FDO/IFdoUserAction.cs b/Src/FDO/IFdoUserAction.cs index 96b585d832..0121539216 100644 --- a/Src/FDO/IFdoUserAction.cs +++ b/Src/FDO/IFdoUserAction.cs @@ -82,6 +82,14 @@ public interface IFdoUserAction /// The email address. /// The error text. void ReportDuplicateGuids(RegistryKey applicationKey, string emailAddress, string errorText); + + /// + /// Present a message to the user and allow the options to Retry or Cancel + /// + /// The message. + /// The caption. + /// True to retry. False otherwise + bool Retry(string msg, string caption); } /// diff --git a/Src/FDO/SilentFdoUserAction.cs b/Src/FDO/SilentFdoUserAction.cs index df5a4d91ca..7d7bdc3aad 100644 --- a/Src/FDO/SilentFdoUserAction.cs +++ b/Src/FDO/SilentFdoUserAction.cs @@ -129,5 +129,16 @@ public void ReportDuplicateGuids(RegistryKey applicationKey, string emailAddress { // Informational only } + + /// + /// Present a message to the user and allow the options to Retry or Cancel + /// + /// The message. + /// The caption. + /// True to retry. False otherwise + public bool Retry(string msg, string caption) + { + return false; + } } } diff --git a/Src/FDO/Strings.Designer.cs b/Src/FDO/Strings.Designer.cs index f27906b750..fed133e3d4 100644 --- a/Src/FDO/Strings.Designer.cs +++ b/Src/FDO/Strings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.18052 +// Runtime Version:4.0.30319.1008 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -1582,15 +1582,6 @@ internal static string ksNoSuperSubscript { } } - /// - /// Looks up a localized string similar to Not advisable when other users connected. - /// - internal static string ksNotAdvisableOthersConnectedCaption { - get { - return ResourceManager.GetString("ksNotAdvisableOthersConnectedCaption", resourceCulture); - } - } - /// /// Looks up a localized string similar to Not Bold. /// @@ -1708,15 +1699,6 @@ internal static string ksOtherClientsAreWriting { } } - /// - /// Looks up a localized string similar to Take care - other users connected. - /// - internal static string ksOthersConnectedCaption { - get { - return ResourceManager.GetString("ksOthersConnectedCaption", resourceCulture); - } - } - /// /// Looks up a localized string similar to If you delete the phoneme, it will be removed from:. /// @@ -2203,32 +2185,6 @@ internal static string ksWarningProjectFolderNotFoundOnServer { } } - /// - /// Looks up a localized string similar to Number of other users: {0} - ///When saving changes in this dialog with other users connected, FieldWorks may crash or malfunction for those users. - /// - ///Do you want to make the changes anyway?. - /// - internal static string ksWarnOnConfirmingSingleUserChanges { - get { - return ResourceManager.GetString("ksWarnOnConfirmingSingleUserChanges", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Number of other users: {0} - ///The menu command you selected will open a dialog box. If you change any selections or settings in the dialog box, other users who have this project open on their computers will have problems. - /// - ///If you will only look at selections and settings, click OK. - /// - ///If you need to make changes, tell the other users to close this project before you continue, or click Cancel.. - /// - internal static string ksWarnOnOpeningSingleUserDialog { - get { - return ResourceManager.GetString("ksWarnOnOpeningSingleUserDialog", resourceCulture); - } - } - /// /// Looks up a localized string similar to You cannot delete this wordform because it is used as an occurrence of a biblical term ({0}) in Translation Editor.. /// diff --git a/Src/FDO/Strings.resx b/Src/FDO/Strings.resx index e9fbcad403..3b05cf748e 100644 --- a/Src/FDO/Strings.resx +++ b/Src/FDO/Strings.resx @@ -860,18 +860,6 @@ Your changes to this entry will be discarded when you exit the project. Undo Reset Homograph Numbers - - Number of other users: {0} -When saving changes in this dialog with other users connected, FieldWorks may crash or malfunction for those users. - -Do you want to make the changes anyway? - - - Not advisable when other users connected - - - Take care - other users connected - Cannot Restore Caption for ksCannotRestoreBackup message box @@ -895,13 +883,6 @@ Corrupted Record: Short delay Caption that goes with ksOtherClientsAreWriting - - Number of other users: {0} -The menu command you selected will open a dialog box. If you change any selections or settings in the dialog box, other users who have this project open on their computers will have problems. - -If you will only look at selections and settings, click OK. - -If you need to make changes, tell the other users to close this project before you continue, or click Cancel. FieldWorks was unable to convert the project {0} because it was created by a more recent version of FieldWorks. To convert this project, install the appropriate version of FieldWorks, and turn sharing off then on again. (Note that doing this will upgrade all your projects to the newer version.) diff --git a/Src/FDO/fdoCache.cs b/Src/FDO/fdoCache.cs index e2ce827186..807cb1dac6 100644 --- a/Src/FDO/fdoCache.cs +++ b/Src/FDO/fdoCache.cs @@ -364,26 +364,28 @@ private static bool IsUpdatedWsInUse(StringBuilder updatedWssInUseBuilder) /// One or more parameters, supplied in this order: /// 0. A string containing the name of the project (required); /// 1. An ISynchronizeInvoke used for invoking actions on the main UI thread (required); - /// 2. An IWritingSystem to be used as the default analylis writing system (default: English); - /// 3. An IWritingSystem to be used as the default vernacular writing system (default: French); - /// 4. A string with the ICU locale of the UI writing system (default: "en"). - /// 5. A set of IWritingSystem to provide additional analysis writing systems (default: no more) - /// 6. A set of IWritingSystem to provide additional vernacular writing systems (default: no more) - /// 7. OCM Data filename. (default: OCM-Frame.xml if available; else, null) + /// 2. An IFdoUserAction used for soliciting user feedback during deep FDO processing (required); + /// 3. An IWritingSystem to be used as the default analylis writing system (default: English); + /// 4. An IWritingSystem to be used as the default vernacular writing system (default: French); + /// 5. A string with the ICU locale of the UI writing system (default: "en"). + /// 6. A set of IWritingSystem to provide additional analysis writing systems (default: no more) + /// 7. A set of IWritingSystem to provide additional vernacular writing systems (default: no more) + /// 8. OCM Data filename. (default: OCM-Frame.xml if available; else, null) /// Path of the newly created project file. /// Override DisplayUi to prevent progress dialog from showing. /// ------------------------------------------------------------------------------------ public static string CreateNewLangProj(IThreadedProgress progressDlg, params object[] parameters) { - if (parameters == null || parameters.Length < 2) - throw new ArgumentException("Parameters must include at least a project name and a SynchronizeInvoke object"); + if (parameters == null || parameters.Length < 3) + throw new ArgumentException("Parameters must include at least a project name, a SynchronizeInvoke object, and a FdoUserAction object"); var projectName = (string)parameters[0]; if (string.IsNullOrEmpty(projectName)) throw new ArgumentNullException("parameters", "Cannot be null or empty"); var synchronizeInvoke = (ISynchronizeInvoke) parameters[1]; - IWritingSystem analWrtSys = (parameters.Length > 2) ? (IWritingSystem)parameters[2] : null; - IWritingSystem vernWrtSys = (parameters.Length > 3) ? (IWritingSystem)parameters[3] : null; - var userIcuLocale = (parameters.Length > 4 && parameters[4] != null) ? (string)parameters[4] : "en"; + var userAction = (IFdoUserAction) parameters[2]; + IWritingSystem analWrtSys = (parameters.Length > 3) ? (IWritingSystem)parameters[3] : null; + IWritingSystem vernWrtSys = (parameters.Length > 4) ? (IWritingSystem)parameters[4] : null; + var userIcuLocale = (parameters.Length > 5 && parameters[5] != null) ? (string)parameters[5] : "en"; const int nMax = 10; if (progressDlg != null) { @@ -426,13 +428,13 @@ public static string CreateNewLangProj(IThreadedProgress progressDlg, params obj if (progressDlg != null) progressDlg.Step(0); - var additionalAnalysisWss = (parameters.Length > 5 && parameters[5] != null) - ? (HashSet)parameters[5] + var additionalAnalysisWss = (parameters.Length > 6 && parameters[6] != null) + ? (HashSet)parameters[6] : new HashSet(); foreach (var additionalWs in additionalAnalysisWss) CreateAnalysisWritingSystem(cache, additionalWs, false); - var additionalVernWss = (parameters.Length > 6 && parameters[6] != null) - ? (HashSet)parameters[6] + var additionalVernWss = (parameters.Length > 7 && parameters[7] != null) + ? (HashSet)parameters[7] : new HashSet(); foreach (var additionalWs in additionalVernWss) CreateVernacularWritingSystem(cache, additionalWs, false); @@ -487,7 +489,7 @@ public static string CreateNewLangProj(IThreadedProgress progressDlg, params obj cache.ActionHandlerAccessor.BeginNonUndoableTask(); InitializeAnthroList(cache.LangProject, cache.WritingSystemFactory.GetWsFromStr(analWrtSys != null ? analWrtSys.IcuLocale : userIcuLocale), - (parameters.Length > 7) ? (string)parameters[7] : null); + (parameters.Length > 8) ? (string)parameters[8] : null); ImportLocalizedLists(cache, progressDlg); cache.ActionHandlerAccessor.EndNonUndoableTask(); @@ -517,7 +519,7 @@ public static string CreateNewLangProj(IThreadedProgress progressDlg, params obj cache.SaveAndForceNewestXmlForCmObjectWithoutUnitOfWork(null, cache.m_serviceLocator.ObjectRepository.AllInstances().ToList()); } } - return ClientServerServices.Current.Local.ConvertToDb4oBackendIfNeeded(progressDlg, dbFileName); + return ClientServerServices.Current.Local.ConvertToDb4oBackendIfNeeded(progressDlg, dbFileName, userAction); } /// diff --git a/Src/FDOBrowser/FdoBrowserUserAction.cs b/Src/FDOBrowser/FdoBrowserUserAction.cs index c4cbbc9244..37b82f0f80 100644 --- a/Src/FDOBrowser/FdoBrowserUserAction.cs +++ b/Src/FDOBrowser/FdoBrowserUserAction.cs @@ -138,5 +138,17 @@ public void ReportDuplicateGuids(RegistryKey applicationKey, string emailAddress { System.Windows.Forms.MessageBox.Show(errorText, "Duplicate Guids"); } + + /// + /// Present a message to the user and allow the options to Retry or Cancel + /// + /// The message. + /// The caption. + /// True to retry. False otherwise + public bool Retry(string msg, string caption) + { + return System.Windows.Forms.MessageBox.Show(msg, caption, + MessageBoxButtons.RetryCancel, MessageBoxIcon.None) == DialogResult.Retry; + } } } diff --git a/Src/FdoUi/FdoUserActionWindowsForms.cs b/Src/FdoUi/FdoUserActionWindowsForms.cs index 6dd7643439..20402330bd 100644 --- a/Src/FdoUi/FdoUserActionWindowsForms.cs +++ b/Src/FdoUi/FdoUserActionWindowsForms.cs @@ -51,7 +51,7 @@ public bool ConflictingSave() { using (var dlg = new ConflictingSaveDlg()) { - DialogResult result = dlg.ShowDialog(Form.ActiveForm); + DialogResult result = dlg.ShowDialog(); return result != DialogResult.OK; } } @@ -161,6 +161,18 @@ public void ReportDuplicateGuids(RegistryKey applicationKey, string emailAddress ErrorReporter.ReportDuplicateGuids(applicationKey, emailAddress, null, errorText); } + /// + /// Present a message to the user and allow the options to Retry or Cancel + /// + /// The message. + /// The caption. + /// True to retry. False otherwise + public bool Retry(string msg, string caption) + { + return System.Windows.Forms.MessageBox.Show(msg, caption, + MessageBoxButtons.RetryCancel, MessageBoxIcon.None) == DialogResult.Retry; + } + /// /// This class is a message filter which can be installed in order to track when the user last /// pressed a key or did any mouse action, including moving the mouse. diff --git a/Src/FwCoreDlgs/ChooseLangProjectDialog.cs b/Src/FwCoreDlgs/ChooseLangProjectDialog.cs index d395f0ef0c..6d17c0ec61 100644 --- a/Src/FwCoreDlgs/ChooseLangProjectDialog.cs +++ b/Src/FwCoreDlgs/ChooseLangProjectDialog.cs @@ -46,6 +46,7 @@ public partial class ChooseLangProjectDialog : Form private readonly Rectangle m_initialBounds = Rectangle.Empty; private readonly int m_initialSplitterPosition = -1; private ObtainedProjectType m_obtainedProjectType = ObtainedProjectType.None; + private readonly IFdoUserAction m_userAction; #endregion #region LanguageProjectInfo class @@ -102,8 +103,10 @@ private ChooseLangProjectDialog() /// /// The initial client bounds of the dialog. /// The initial splitter position. + /// /// ------------------------------------------------------------------------------------ - public ChooseLangProjectDialog(Rectangle bounds, int splitterPosition) : this(null, false) + public ChooseLangProjectDialog(Rectangle bounds, int splitterPosition, IFdoUserAction userAction) + : this(null, false, userAction) { m_initialBounds = bounds; m_initialSplitterPosition = splitterPosition; @@ -120,12 +123,14 @@ public ChooseLangProjectDialog(Rectangle bounds, int splitterPosition) : this(nu /// If set to true the dialog will be /// used to assosiate a FieldWorks project with another application (e.g. Paratext). /// + /// /// ------------------------------------------------------------------------------------ public ChooseLangProjectDialog(IHelpTopicProvider helpTopicProvider, - bool openToAssosiateFwProject) + bool openToAssosiateFwProject, IFdoUserAction userAction) : this() { m_helpTopicProvider = helpTopicProvider; + m_userAction = userAction; if (helpTopicProvider == null) m_btnHelp.Enabled = false; @@ -561,7 +566,7 @@ private void OpenFwDataProjectLinkClicked(object sender, LinkLabelLinkClickedEve private void OpenBridgeProjectLinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { // ObtainProjectFromAnySource may return null, empty string, or the full pathname to an fwdata file. - Project = ObtainProjectMethod.ObtainProjectFromAnySource(this, m_helpTopicProvider, out m_obtainedProjectType); + Project = ObtainProjectMethod.ObtainProjectFromAnySource(this, m_helpTopicProvider, out m_obtainedProjectType, m_userAction); Server = null; if (String.IsNullOrEmpty(Project)) return; // Don't close the Open project dialog yet (LT-13187) diff --git a/Src/FwCoreDlgs/ClientServerServicesHelper.cs b/Src/FwCoreDlgs/ClientServerServicesHelper.cs new file mode 100644 index 0000000000..1a30cc5f42 --- /dev/null +++ b/Src/FwCoreDlgs/ClientServerServicesHelper.cs @@ -0,0 +1,59 @@ +// --------------------------------------------------------------------------------------------- +#region // Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Distributable under the terms of either the Common Public License or the +// GNU Lesser General Public License, as specified in the LICENSING.txt file. +// +#endregion +// --------------------------------------------------------------------------------------------- +using System; +using System.Windows.Forms; +using SIL.FieldWorks.FDO; +using SIL.FieldWorks.FDO.DomainServices; +using SIL.Utils; + +namespace SIL.FieldWorks.FwCoreDlgs +{ + /// + /// Provides a common place for calls which utilize FDO's ClientServerServices + /// + public static class ClientServerServicesHelper + { + /// + /// Display a warning indicating that it may be dangerous to change things in the dialog that + /// is about to open when other users are connected. The warning should only be shown if, in fact, + /// other users are currently connected. The dialog may contain some information about the other + /// users that are connected. Return true to continue, false to cancel opening the dialog. + /// + /// + public static bool WarnOnOpeningSingleUserDialog(FdoCache cache) + { + var others = ClientServerServices.Current.CountOfOtherUsersConnected(cache); + if (others == 0) + return true; + var msg = string.Format(Strings.ksWarnOnOpeningSingleUserDialog.Replace("\\n", Environment.NewLine), others); + return ThreadHelper.ShowMessageBox(null, msg, Strings.ksOthersConnectedCaption, + MessageBoxButtons.OKCancel, MessageBoxIcon.Information) == DialogResult.OK; + } + + /// + /// Display a warning indicating that it may be dangerous to change things that the user has just + /// asked to change when other users are connected. The warning should only be shown if, in fact, + /// other users are currently connected. The dialog may contain some information about the other + /// users that are connected. Return true to continue, false to discard the changes. This is typically + /// called in response to clicking an OK button in a dialog which changes dangerous user settings. + /// + /// + public static bool WarnOnConfirmingSingleUserChanges(FdoCache cache) + { + var others = ClientServerServices.Current.CountOfOtherUsersConnected(cache); + if (others == 0) + return true; + var msg = string.Format(Strings.ksWarnOnConfirmingSingleUserChanges.Replace("\\n", Environment.NewLine), others); + return ThreadHelper.ShowMessageBox(null, msg, Strings.ksNotAdvisableOthersConnectedCaption, + MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes; + } + } +} diff --git a/Src/FwCoreDlgs/FwCoreDlgs.csproj b/Src/FwCoreDlgs/FwCoreDlgs.csproj index 0b47007489..af203a4a0f 100644 --- a/Src/FwCoreDlgs/FwCoreDlgs.csproj +++ b/Src/FwCoreDlgs/FwCoreDlgs.csproj @@ -297,6 +297,7 @@ Component + UserControl @@ -441,6 +442,11 @@ Component + + True + True + Strings.resx + Form @@ -614,6 +620,10 @@ RealSplashScreen.cs Designer + + ResXFileCodeGenerator + Strings.Designer.cs + UtilityDlg.cs Designer diff --git a/Src/FwCoreDlgs/FwCoreDlgsTests/FwNewLangProjectTests.cs b/Src/FwCoreDlgs/FwCoreDlgsTests/FwNewLangProjectTests.cs index 21fbd2fb36..7cc43aa2d6 100644 --- a/Src/FwCoreDlgs/FwCoreDlgsTests/FwNewLangProjectTests.cs +++ b/Src/FwCoreDlgs/FwCoreDlgsTests/FwNewLangProjectTests.cs @@ -55,7 +55,7 @@ public void CreateNewLangProj() { CheckDisposed(); - CreateNewLangProjWithProgress(); + CreateNewLangProjWithProgress(new DummyFdoUserAction()); NonAsciiWarningWasActivated = false; SimulatedNonAsciiDialogResult = DialogResult.Cancel; } diff --git a/Src/FwCoreDlgs/FwNewLangProject.cs b/Src/FwCoreDlgs/FwNewLangProject.cs index c7fa25da0a..573d7f9de5 100644 --- a/Src/FwCoreDlgs/FwNewLangProject.cs +++ b/Src/FwCoreDlgs/FwNewLangProject.cs @@ -566,7 +566,7 @@ private void btnOK_Click(object sender, EventArgs e) // // Create new project // - CreateNewLangProjWithProgress(); + CreateNewLangProjWithProgress(m_userAction); } private string RemoveNonAsciiCharsFromProjectName() @@ -673,7 +673,7 @@ private void m_btnNewAnalWrtSys_Click(object sender, EventArgs e) /// Create a new language project showing a progress dialog. /// /// ------------------------------------------------------------------------------------ - protected void CreateNewLangProjWithProgress() + protected void CreateNewLangProjWithProgress(IFdoUserAction userAction) { try { @@ -694,7 +694,7 @@ protected void CreateNewLangProjWithProgress() using (var threadHelper = new ThreadHelper()) { m_dbFile = (string)progressDlg.RunTask(DisplayUi, FdoCache.CreateNewLangProj, - ProjectName, threadHelper, m_cbAnalWrtSys.SelectedItem, + ProjectName, threadHelper, userAction, m_cbAnalWrtSys.SelectedItem, m_cbVernWrtSys.SelectedItem, ((PalasoWritingSystem)m_wsManager.UserWritingSystem).RFC5646, m_newAnalysisWss, m_newVernWss, anthroFile); diff --git a/Src/FwCoreDlgs/FwProjPropertiesDlg.cs b/Src/FwCoreDlgs/FwProjPropertiesDlg.cs index 18098588e9..fc1404a22b 100644 --- a/Src/FwCoreDlgs/FwProjPropertiesDlg.cs +++ b/Src/FwCoreDlgs/FwProjPropertiesDlg.cs @@ -976,7 +976,7 @@ protected void m_btnOK_Click(object sender, EventArgs e) return; } - if (!ClientServerServices.Current.WarnOnConfirmingSingleUserChanges(m_cache)) //if Anything changed, check and warn about DB4o + if (!ClientServerServicesHelper.WarnOnConfirmingSingleUserChanges(m_cache)) //if Anything changed, check and warn about DB4o { NotifyProjectPropsChangedAndClose(); //The user changed something, but when warned decided against it, so do not save just quit return; diff --git a/Src/FwCoreDlgs/Strings.Designer.cs b/Src/FwCoreDlgs/Strings.Designer.cs new file mode 100644 index 0000000000..2a4ae649dc --- /dev/null +++ b/Src/FwCoreDlgs/Strings.Designer.cs @@ -0,0 +1,107 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.1008 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SIL.FieldWorks.FwCoreDlgs { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Strings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Strings() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SIL.FieldWorks.FwCoreDlgs.Strings", typeof(Strings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Not advisable when other users connected. + /// + internal static string ksNotAdvisableOthersConnectedCaption { + get { + return ResourceManager.GetString("ksNotAdvisableOthersConnectedCaption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Take care - other users connected. + /// + internal static string ksOthersConnectedCaption { + get { + return ResourceManager.GetString("ksOthersConnectedCaption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Number of other users: {0} + ///When saving changes in this dialog with other users connected, FieldWorks may crash or malfunction for those users. + /// + ///Do you want to make the changes anyway?. + /// + internal static string ksWarnOnConfirmingSingleUserChanges { + get { + return ResourceManager.GetString("ksWarnOnConfirmingSingleUserChanges", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Number of other users: {0} + ///The menu command you selected will open a dialog box. If you change any selections or settings in the dialog box, other users who have this project open on their computers will have problems. + /// + ///If you will only look at selections and settings, click OK. + /// + ///If you need to make changes, tell the other users to close this project before you continue, or click Cancel.. + /// + internal static string ksWarnOnOpeningSingleUserDialog { + get { + return ResourceManager.GetString("ksWarnOnOpeningSingleUserDialog", resourceCulture); + } + } + } +} diff --git a/Src/FwCoreDlgs/Strings.resx b/Src/FwCoreDlgs/Strings.resx new file mode 100644 index 0000000000..015df49db7 --- /dev/null +++ b/Src/FwCoreDlgs/Strings.resx @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Not advisable when other users connected + + + Take care - other users connected + + + Number of other users: {0} +When saving changes in this dialog with other users connected, FieldWorks may crash or malfunction for those users. + +Do you want to make the changes anyway? + + + Number of other users: {0} +The menu command you selected will open a dialog box. If you change any selections or settings in the dialog box, other users who have this project open on their computers will have problems. + +If you will only look at selections and settings, click OK. + +If you need to make changes, tell the other users to close this project before you continue, or click Cancel. + + \ No newline at end of file diff --git a/Src/FwCoreDlgs/WritingSystemPropertiesDialog.cs b/Src/FwCoreDlgs/WritingSystemPropertiesDialog.cs index 88b6fe7bd0..fa5d8086a0 100644 --- a/Src/FwCoreDlgs/WritingSystemPropertiesDialog.cs +++ b/Src/FwCoreDlgs/WritingSystemPropertiesDialog.cs @@ -155,7 +155,7 @@ public static bool ShowModifyDialog(Form owner, IWritingSystem selectedWs, bool if (addNewForLangOfSelectedWs) wsPropsDlg.AddNewWsForLanguage(); - if (!ClientServerServices.Current.WarnOnOpeningSingleUserDialog(cache)) + if (!ClientServerServicesHelper.WarnOnOpeningSingleUserDialog(cache)) return false; // nothing changed. if (wsPropsDlg.ShowDialog(owner) == DialogResult.OK) @@ -1566,7 +1566,7 @@ private void OnOk(object sender, EventArgs e) if (!CheckOkToChangeContext()) return; - if (ThereAreChanges && ClientServerServices.Current.WarnOnConfirmingSingleUserChanges(m_cache)) + if (ThereAreChanges && ClientServerServicesHelper.WarnOnConfirmingSingleUserChanges(m_cache)) SaveChanges(); DialogResult = DialogResult.OK; diff --git a/Src/LexText/Lexicon/FLExBridgeListener.cs b/Src/LexText/Lexicon/FLExBridgeListener.cs index 671949cf68..eb7fc317e3 100644 --- a/Src/LexText/Lexicon/FLExBridgeListener.cs +++ b/Src/LexText/Lexicon/FLExBridgeListener.cs @@ -181,11 +181,11 @@ public bool OnDisplayObtainAnyFlexBridgeProject(object parameters, ref UIItemDis /// /// Handle the S/R "_Get Project from Colleague" menu option. /// - public bool OnObtainAnyFlexBridgeProject(object commandObject) + public bool OnObtainAnyFlexBridgeProject(object commandObject, IFdoUserAction userAction) { ObtainedProjectType obtainedProjectType; var newprojectPathname = ObtainProjectMethod.ObtainProjectFromAnySource(_parentForm, _mediator.HelpTopicProvider, - out obtainedProjectType); + out obtainedProjectType, userAction); if (string.IsNullOrEmpty(newprojectPathname)) return true; // We dealt with it. _mediator.PropertyTable.SetProperty("LastBridgeUsed", obtainedProjectType == ObtainedProjectType.Lift ? "LiftBridge" : "FLExBridge", diff --git a/Src/xWorks/FwXWindow.cs b/Src/xWorks/FwXWindow.cs index 387719d9ee..051c911316 100644 --- a/Src/xWorks/FwXWindow.cs +++ b/Src/xWorks/FwXWindow.cs @@ -1230,7 +1230,7 @@ public bool OnExitApplication(object param) /// ------------------------------------------------------------------------------------ private void LaunchProjPropertiesDlg(bool startOnWSPage) { - if (!ClientServerServices.Current.WarnOnOpeningSingleUserDialog(Cache)) + if (!ClientServerServicesHelper.WarnOnOpeningSingleUserDialog(Cache)) return; FdoCache cache = Cache; bool fDbRenamed = false; From 6b915ca1310b8ff1e266956ddac915e561a9c113 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Wed, 4 Dec 2013 14:32:02 +0700 Subject: [PATCH 014/143] Move more UI elements out of FDO Add Retry method to IFdoUserAction and implementations. Move various message boxes out of ClientServerServices. Change-Id: I81c2db15cbaeb336c1f3e36341d89c2b7a551dc9 --- Src/FDO/Strings.resx | 1 - 1 file changed, 1 deletion(-) diff --git a/Src/FDO/Strings.resx b/Src/FDO/Strings.resx index 3b05cf748e..8fc71604d1 100644 --- a/Src/FDO/Strings.resx +++ b/Src/FDO/Strings.resx @@ -883,7 +883,6 @@ Corrupted Record: Short delay Caption that goes with ksOtherClientsAreWriting - FieldWorks was unable to convert the project {0} because it was created by a more recent version of FieldWorks. To convert this project, install the appropriate version of FieldWorks, and turn sharing off then on again. (Note that doing this will upgrade all your projects to the newer version.) From 4f938164053e4a34c33fd4138f5fffeca8cd6b72 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Wed, 4 Dec 2013 14:45:34 +0700 Subject: [PATCH 015/143] removed WinForms references from some classes in FDO -FdoCache -CmObjectSurrogate -XMLBackendProvider Change-Id: I01c5ef946a2b55bc73021b0b1e61f1d2dc339c3e --- Src/Common/FieldWorks/FieldWorks.cs | 48 ++++ .../FieldWorksTests/FieldWorksTests.cs | 82 ++++++ .../Properties/Resources.Designer.cs | 18 ++ .../FieldWorks/Properties/Resources.resx | 8 + Src/FDO/FDOTests/DummyFdoUserAction.cs | 21 +- Src/FDO/FDOTests/FdoCacheTests.cs | 85 ------ Src/FDO/IFdoUserAction.cs | 34 ++- .../Infrastructure/Impl/CmObjectSurrogate.cs | 10 +- .../Infrastructure/Impl/XMLBackendProvider.cs | 14 +- Src/FDO/Properties/Resources.Designer.cs | 20 +- Src/FDO/Properties/Resources.resx | 254 +++++++++--------- Src/FDO/SilentFdoUserAction.cs | 23 +- Src/FDO/Strings.Designer.cs | 18 -- Src/FDO/Strings.resx | 8 - Src/FDO/fdoCache.cs | 49 ---- Src/FDOBrowser/FDOBrowser.csproj | 5 +- Src/FDOBrowser/FDOBrowserForm.cs | 6 +- Src/FDOBrowser/FDOClassList.cs | 5 +- Src/FDOBrowser/FdoBrowserUserAction.cs | 154 ----------- Src/FDOBrowser/ModelWnd.cs | 8 +- Src/FdoUi/FdoUiStrings.Designer.cs | 20 +- Src/FdoUi/FdoUiStrings.resx | 7 + Src/FdoUi/FdoUserActionWindowsForms.cs | 48 +++- 23 files changed, 434 insertions(+), 511 deletions(-) delete mode 100644 Src/FDOBrowser/FdoBrowserUserAction.cs diff --git a/Src/Common/FieldWorks/FieldWorks.cs b/Src/Common/FieldWorks/FieldWorks.cs index 0da474f37a..856b632f80 100644 --- a/Src/Common/FieldWorks/FieldWorks.cs +++ b/Src/Common/FieldWorks/FieldWorks.cs @@ -49,6 +49,7 @@ using SIL.FieldWorks.Resources; using SIL.FieldWorks.LexicalProvider; using SIL.Utils; +using SIL.Utils.FileDialog; using XCore; using SIL.CoreImpl; using ConfigurationException = SIL.Utils.ConfigurationException; @@ -806,6 +807,7 @@ private static FdoCache CreateCache(ProjectId projectId) using (var progressDlg = new ProgressDialogWithTask(owner)) { FdoCache cache = FdoCache.CreateCacheFromExistingData(projectId, s_sWsUser, progressDlg, s_userAction); + EnsureValidLinkedFilesFolder(cache); cache.ProjectNameChanged += ProjectNameChanged; cache.ServiceLocator.GetInstance().OnSave += FieldWorks_OnSave; @@ -814,6 +816,52 @@ private static FdoCache CreateCache(ProjectId projectId) } } + /// + /// Ensure a valid folder for LangProject.LinkedFilesRootDir. When moving projects + /// between systems, the stored value may become hopelessly invalid. See FWNX-1005 + /// for an example of the havoc than can ensue. + /// + /// This method gets called when we open the FDO cache. + private static void EnsureValidLinkedFilesFolder(FdoCache cache) + { + if (MiscUtils.RunningTests) + return; + + var linkedFilesFolder = cache.LangProject.LinkedFilesRootDir; + var defaultFolder = DirectoryFinder.GetDefaultLinkedFilesDir(cache.ProjectId.ProjectFolder); + EnsureValidLinkedFilesFolderCore(linkedFilesFolder, defaultFolder); + + if (!Directory.Exists(linkedFilesFolder)) + { + if (!Directory.Exists(defaultFolder)) + defaultFolder = cache.ProjectId.ProjectFolder; + MessageBox.Show(String.Format(Properties.Resources.ksInvalidLinkedFilesFolder, linkedFilesFolder), Properties.Resources.ksErrorCaption); + while (!Directory.Exists(linkedFilesFolder)) + { + using (var folderBrowserDlg = new FolderBrowserDialogAdapter()) + { + folderBrowserDlg.Description = Properties.Resources.ksLinkedFilesFolder; + folderBrowserDlg.RootFolder = Environment.SpecialFolder.Desktop; + folderBrowserDlg.SelectedPath = defaultFolder; + if (folderBrowserDlg.ShowDialog() == DialogResult.OK) + linkedFilesFolder = folderBrowserDlg.SelectedPath; + } + } + NonUndoableUnitOfWorkHelper.DoUsingNewOrCurrentUOW(cache.ActionHandlerAccessor, () => + { cache.LangProject.LinkedFilesRootDir = linkedFilesFolder; }); + } + } + + /// + /// Just make the directory if it's the default. + /// See FWNX-1092, LT-14491. + /// + internal static void EnsureValidLinkedFilesFolderCore(string linkedFilesFolder, string defaultLinkedFilesFolder) + { + if (linkedFilesFolder == defaultLinkedFilesFolder) + FileUtils.EnsureDirectoryExists(defaultLinkedFilesFolder); + } + /// ------------------------------------------------------------------------------------ /// /// When non-trivial (user-visible) changes are saved for a project, we want to record diff --git a/Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.cs b/Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.cs index a2124a0775..843a9f3caa 100644 --- a/Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.cs +++ b/Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.cs @@ -11,6 +11,7 @@ // File: FieldWorksTests.cs // Responsibility: FW Team // --------------------------------------------------------------------------------------------- +using System; using NUnit.Framework; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Test.TestUtils; @@ -120,5 +121,86 @@ public void GetProjectMatchStatus_SingleProcessMode() #endregion + /// + [Test] + public void EnsureValidLinkedFilesFolderCore_IfUsingDefaultDir_CreatesDirIfNotExist() + { + EnsureValidLinkedFilesFolderCore_TestHelper(defaultFolder => { + var configuredFolder = defaultFolder; + Assert.That(FileUtils.DirectoryExists(configuredFolder), Is.False, "Unit test not testing what it's supposed to"); + FieldWorks.EnsureValidLinkedFilesFolderCore(configuredFolder, defaultFolder); + Assert.That(FileUtils.DirectoryExists(configuredFolder), Is.True, "Should have created directory"); + }); + } + + /// + [Test] + public void EnsureValidLinkedFilesFolderCore_IfUsingDefaultDirAndItExists_DoesntCrashOrAnything() + { + EnsureValidLinkedFilesFolderCore_TestHelper(defaultFolder => { + var configuredFolder = defaultFolder; + + // Make default linked files directory already exist + FileUtils.EnsureDirectoryExists(defaultFolder); + + Assert.That(FileUtils.DirectoryExists(configuredFolder), Is.True, "Unit test not testing what it's supposed to"); + // Not crash or anything + FieldWorks.EnsureValidLinkedFilesFolderCore(configuredFolder, defaultFolder); + }); + } + + /// + [Test] + public void EnsureValidLinkedFilesFolderCore_NonDefaultLocation_NotCreateNonExistentDir() + { + EnsureValidLinkedFilesFolderCore_TestHelper(defaultFolder => { + var configuredFolder = FileUtils.ChangePathToPlatform("/nondefaultAndNonexistentPath"); + + Assert.That(defaultFolder, Is.Not.EqualTo(configuredFolder), "Unit test not set up right"); + Assert.That(FileUtils.DirectoryExists(configuredFolder), Is.False, "Unit test not testing what it's supposed to"); + + FieldWorks.EnsureValidLinkedFilesFolderCore(configuredFolder, defaultFolder); + Assert.That(FileUtils.DirectoryExists(configuredFolder), Is.False, "Shouldn't have just made the nondefault directory"); + }); + } + + /// + [Test] + public void EnsureValidLinkedFilesFolderCore_NonDefaultLocationAndExists_DoesntCrashOrAnything() + { + EnsureValidLinkedFilesFolderCore_TestHelper(defaultFolder => { + var configuredFolder = FileUtils.ChangePathToPlatform("/nondefaultPath"); + + // Make linked files directory already exist + FileUtils.EnsureDirectoryExists(configuredFolder); + + Assert.That(defaultFolder, Is.Not.EqualTo(configuredFolder), "Unit test not set up right"); + Assert.That(FileUtils.DirectoryExists(configuredFolder), Is.True, "Unit test not testing what it's supposed to"); + + // Not crash or anything + FieldWorks.EnsureValidLinkedFilesFolderCore(configuredFolder, defaultFolder); + }); + } + + /// + /// Unit test helper to set up environment in which to test EnsureValidLinkedFilesFolderCore. + /// testToExecute takes (string defaultFolder, FdoCache cache). + /// + public void EnsureValidLinkedFilesFolderCore_TestHelper(Action testToExecute) + { + var defaultFolder = FileUtils.ChangePathToPlatform("/ProjectDir/LinkedFiles"); + + var fileOs = new MockFileOS(); + try + { + FileUtils.Manager.SetFileAdapter(fileOs); + + testToExecute(defaultFolder); + } + finally + { + FileUtils.Manager.Reset(); + } + } } } diff --git a/Src/Common/FieldWorks/Properties/Resources.Designer.cs b/Src/Common/FieldWorks/Properties/Resources.Designer.cs index 6158ad1cde..cc4579cf6c 100644 --- a/Src/Common/FieldWorks/Properties/Resources.Designer.cs +++ b/Src/Common/FieldWorks/Properties/Resources.Designer.cs @@ -210,6 +210,24 @@ internal static string ksInsufficientPrivilegesToUpdateProjectLocationText { } } + /// + /// Looks up a localized string similar to {0} is not a valid directory for linked files. Please select a valid directory.. + /// + internal static string ksInvalidLinkedFilesFolder { + get { + return ResourceManager.GetString("ksInvalidLinkedFilesFolder", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Linked Files Folder. + /// + internal static string ksLinkedFilesFolder { + get { + return ResourceManager.GetString("ksLinkedFilesFolder", resourceCulture); + } + } + /// /// Looks up a localized string similar to Migrate projects. /// diff --git a/Src/Common/FieldWorks/Properties/Resources.resx b/Src/Common/FieldWorks/Properties/Resources.resx index 2fe644bee5..44c45ac29a 100644 --- a/Src/Common/FieldWorks/Properties/Resources.resx +++ b/Src/Common/FieldWorks/Properties/Resources.resx @@ -327,4 +327,12 @@ We have sometimes seen cases where installing other software leaves the machine We don't know why this happens. If you have any idea what recently changed on your computer to cause it, please pass this on to the developers. This message should never be seen. Some users however have gotten into a weird state we don't understand where they have to run-as-administrator in order to access required local-machine keys. + + {0} is not a valid directory for linked files. Please select a valid directory. + Error message for accessing an invalid LangProject.LinkedFilesRootDir value + + + Linked Files Folder + Caption for folder dialog, when setting a new LangProject.LinkedFilesRootDir value + \ No newline at end of file diff --git a/Src/FDO/FDOTests/DummyFdoUserAction.cs b/Src/FDO/FDOTests/DummyFdoUserAction.cs index f7b11d709a..bd9800b840 100644 --- a/Src/FDO/FDOTests/DummyFdoUserAction.cs +++ b/Src/FDO/FDOTests/DummyFdoUserAction.cs @@ -98,7 +98,11 @@ public YesNoCancel CannotRestoreLinkedFilesToOriginalLocation() /// /// Displays information to the user /// - public void MessageBox() + /// + /// + /// + /// + public void DisplayMessage(MessageType type, string message, string caption) { throw new NotImplementedException(); } @@ -111,11 +115,10 @@ public void MessageBox() /// false. /// True if the error was lethal and the user chose to exit the application, /// false otherwise. - public bool ReportException(Exception error, bool isLethal) + public void ReportException(Exception error, bool isLethal) { // Store the message so we can check it later ErrorMessage = error.Message; - return isLethal; } /// @@ -129,6 +132,18 @@ public void ReportDuplicateGuids(RegistryKey applicationKey, string emailAddress throw new NotImplementedException(); } + /// + /// Ask user if they wish to restore an XML project from a backup project file. + /// + /// The project path. + /// The backup path. + /// + /// + public bool OfferToRestore(string projectPath, string backupPath) + { + throw new NotImplementedException(); + } + /// /// Present a message to the user and allow the options to Retry or Cancel /// diff --git a/Src/FDO/FDOTests/FdoCacheTests.cs b/Src/FDO/FDOTests/FdoCacheTests.cs index 6023047cad..f13c60ef1d 100644 --- a/Src/FDO/FDOTests/FdoCacheTests.cs +++ b/Src/FDO/FDOTests/FdoCacheTests.cs @@ -327,91 +327,6 @@ public void ChangingLangProjDefaultPronunciationWs_ChangesCacheDefaultPronunciat Assert.That(cache.DefaultPronunciationWs, Is.EqualTo(wsObjSpanish.Handle)); } } - - /// - /// Unit test helper to set up environment in which to test EnsureValidLinkedFilesFolderCore. - /// testToExecute takes (string defaultFolder, FdoCache cache). - /// - public void EnsureValidLinkedFilesFolderCore_TestHelper(Action testToExecute) - { - using (var cache = new FdoCache()) - { - var defaultFolder = FileUtils.ChangePathToPlatform("/ProjectDir/LinkedFiles"); - - var m_fileOs = new MockFileOS(); - try - { - FileUtils.Manager.SetFileAdapter(m_fileOs); - - testToExecute(defaultFolder, cache); - } - finally - { - FileUtils.Manager.Reset(); - } - } - } - - /// - [Test] - public void EnsureValidLinkedFilesFolderCore_IfUsingDefaultDir_CreatesDirIfNotExist() - { - EnsureValidLinkedFilesFolderCore_TestHelper((defaultFolder, cache) => { - var configuredFolder = defaultFolder; - Assert.That(FileUtils.DirectoryExists(configuredFolder), Is.False, "Unit test not testing what it's supposed to"); - cache.EnsureValidLinkedFilesFolderCore(configuredFolder, defaultFolder); - Assert.That(FileUtils.DirectoryExists(configuredFolder), Is.True, "Should have created directory"); - }); - } - - /// - [Test] - public void EnsureValidLinkedFilesFolderCore_IfUsingDefaultDirAndItExists_DoesntCrashOrAnything() - { - EnsureValidLinkedFilesFolderCore_TestHelper((defaultFolder, cache) => { - var configuredFolder = defaultFolder; - - // Make default linked files directory already exist - FileUtils.EnsureDirectoryExists(defaultFolder); - - Assert.That(FileUtils.DirectoryExists(configuredFolder), Is.True, "Unit test not testing what it's supposed to"); - // Not crash or anything - cache.EnsureValidLinkedFilesFolderCore(configuredFolder, defaultFolder); - }); - } - - /// - [Test] - public void EnsureValidLinkedFilesFolderCore_NonDefaultLocation_NotCreateNonExistentDir() - { - EnsureValidLinkedFilesFolderCore_TestHelper((defaultFolder, cache) => { - var configuredFolder = FileUtils.ChangePathToPlatform("/nondefaultAndNonexistentPath"); - - Assert.That(defaultFolder, Is.Not.EqualTo(configuredFolder), "Unit test not set up right"); - Assert.That(FileUtils.DirectoryExists(configuredFolder), Is.False, "Unit test not testing what it's supposed to"); - - cache.EnsureValidLinkedFilesFolderCore(configuredFolder, defaultFolder); - Assert.That(FileUtils.DirectoryExists(configuredFolder), Is.False, "Shouldn't have just made the nondefault directory"); - }); - } - - /// - [Test] - public void EnsureValidLinkedFilesFolderCore_NonDefaultLocationAndExists_DoesntCrashOrAnything() - { - EnsureValidLinkedFilesFolderCore_TestHelper((defaultFolder, cache) => { - var configuredFolder = FileUtils.ChangePathToPlatform("/nondefaultPath"); - - // Make linked files directory already exist - FileUtils.EnsureDirectoryExists(configuredFolder); - - Assert.That(defaultFolder, Is.Not.EqualTo(configuredFolder), "Unit test not set up right"); - Assert.That(FileUtils.DirectoryExists(configuredFolder), Is.True, "Unit test not testing what it's supposed to"); - - // Not crash or anything - cache.EnsureValidLinkedFilesFolderCore(configuredFolder, defaultFolder); - }); - } } /// ---------------------------------------------------------------------------------------- diff --git a/Src/FDO/IFdoUserAction.cs b/Src/FDO/IFdoUserAction.cs index 0121539216..74201dfd88 100644 --- a/Src/FDO/IFdoUserAction.cs +++ b/Src/FDO/IFdoUserAction.cs @@ -63,7 +63,7 @@ public interface IFdoUserAction /// /// Displays information to the user /// - void MessageBox(); + void DisplayMessage(MessageType type, string message, string caption); /// /// Show a dialog or output to the error log, as appropriate. @@ -71,9 +71,7 @@ public interface IFdoUserAction /// the exception you want to report /// set to true if the error is lethal, otherwise /// false. - /// True if the error was lethal and the user chose to exit the application, - /// false otherwise. - bool ReportException(Exception error, bool isLethal); + void ReportException(Exception error, bool isLethal); /// /// Reports duplicate guids to the user @@ -90,6 +88,34 @@ public interface IFdoUserAction /// The caption. /// True to retry. False otherwise bool Retry(string msg, string caption); + + /// + /// Ask user if they wish to restore an XML project from a backup project file. + /// + /// The project path. + /// The backup path. + /// + bool OfferToRestore(string projectPath, string backupPath); + + } + + /// + /// Message type + /// + public enum MessageType + { + /// + /// Information message + /// + Info, + /// + /// Warning message + /// + Warning, + /// + /// Error message + /// + Error } /// diff --git a/Src/FDO/Infrastructure/Impl/CmObjectSurrogate.cs b/Src/FDO/Infrastructure/Impl/CmObjectSurrogate.cs index f278985bf3..fa36978624 100644 --- a/Src/FDO/Infrastructure/Impl/CmObjectSurrogate.cs +++ b/Src/FDO/Infrastructure/Impl/CmObjectSurrogate.cs @@ -7,9 +7,7 @@ using System.Linq; using System.Reflection; using System.Text; -using System.Windows.Forms; using System.Xml.Linq; -using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; using System.Threading; @@ -549,11 +547,9 @@ ICmObject ICmObjectOrSurrogate.Object const int nLines = 40; if (lines.Length > nLines) msg = String.Join("\n", lines.Take(nLines).ToArray()) + "\n..."; - m_cache.ServiceLocator.GetInstance().SynchronizeInvoke.Invoke(() => - { - MessageBox.Show(null, msg, Strings.ksErrorCaption, MessageBoxButtons.OK, MessageBoxIcon.Error); - m_cache.ServiceLocator.GetInstance().ReportException(new Exception(fullMsg, e), true); - }); + var userAction = m_cache.ServiceLocator.GetInstance(); + userAction.DisplayMessage(MessageType.Error, msg, Strings.ksErrorCaption); + userAction.ReportException(new Exception(fullMsg, e), true); } return m_object; } diff --git a/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs b/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs index 5269c8ab11..6191b2425a 100644 --- a/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs @@ -13,7 +13,6 @@ using System.IO; using System.Linq; using System.Text; -using System.Windows.Forms; using System.Xml; using System.Xml.Linq; using SIL.FieldWorks.FDO.DomainServices.DataMigration; @@ -347,11 +346,7 @@ private void OfferToRestore(string message) string backupFilePath = Path.ChangeExtension(ProjectId.Path, "bak"); if (File.Exists(backupFilePath)) { - if (ThreadHelper.ShowMessageBox(null, - String.Format(Properties.Resources.kstidOfferToRestore, ProjectId.Path, File.GetLastWriteTime(ProjectId.Path), - backupFilePath, File.GetLastWriteTime(backupFilePath)), - Properties.Resources.kstidProblemOpeningFile, MessageBoxButtons.YesNo, - MessageBoxIcon.Error) == DialogResult.Yes) + if (m_userAction.OfferToRestore(ProjectId.Path, backupFilePath)) { string badFilePath = Path.ChangeExtension(ProjectId.Path, "bad"); if (File.Exists(badFilePath)) @@ -488,7 +483,7 @@ public override void CompleteAllCommits() m_thread.WaitUntilIdle(); } - private static void ReportProblem(string message, string tempPath) + private void ReportProblem(string message, string tempPath) { if (File.Exists(tempPath)) { @@ -501,8 +496,7 @@ private static void ReportProblem(string message, string tempPath) // Can't even clean up. Sigh. } } - ThreadHelper.ShowMessageBox(null, message, Strings.ksProblemWritingFile, - MessageBoxButtons.OK, MessageBoxIcon.Error); + m_userAction.DisplayMessage(MessageType.Error, message, Strings.ksProblemWritingFile); } /// @@ -1105,7 +1099,7 @@ public void Dispose() /// protected virtual void Dispose(bool fDisposing) { - System.Diagnostics.Debug.WriteLineIf(!fDisposing, "****** Missing Dispose() call for " + GetType().Name + ". ****** "); + Debug.WriteLineIf(!fDisposing, "****** Missing Dispose() call for " + GetType().Name + ". ****** "); if (fDisposing && !IsDisposed) { // dispose managed and unmanaged objects diff --git a/Src/FDO/Properties/Resources.Designer.cs b/Src/FDO/Properties/Resources.Designer.cs index e9a934a37d..617a9f9e80 100644 --- a/Src/FDO/Properties/Resources.Designer.cs +++ b/Src/FDO/Properties/Resources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.1008 +// Runtime Version:4.0.30319.18052 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -132,24 +132,6 @@ internal static string kstidLockFileLocked { } } - /// - /// Looks up a localized string similar to There was a problem opening the current version of the file {0}, dated {1}. Would you like to open the automatic backup, {2}, dated {3}?. - /// - internal static string kstidOfferToRestore { - get { - return ResourceManager.GetString("kstidOfferToRestore", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Problem opening file. - /// - internal static string kstidProblemOpeningFile { - get { - return ResourceManager.GetString("kstidProblemOpeningFile", resourceCulture); - } - } - /// /// Looks up a localized string similar to This project is for a newer version of FieldWorks. /// diff --git a/Src/FDO/Properties/Resources.resx b/Src/FDO/Properties/Resources.resx index b85563cc10..17ee344fb4 100644 --- a/Src/FDO/Properties/Resources.resx +++ b/Src/FDO/Properties/Resources.resx @@ -1,168 +1,160 @@  - + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - text/microsoft-resx + text/microsoft-resx - 2.0 + 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Creating new database... - Displayed in the progress dialog box when creating a new FieldWorks project + Creating new database... + Displayed in the progress dialog box when creating a new FieldWorks project - Initializing new database... - Displayed in the progress dialog box when creating a new FieldWorks project + Initializing new database... + Displayed in the progress dialog box when creating a new FieldWorks project - Loading the Semantic Domain List + Loading the Semantic Domain List - File is not a valid FieldWorks project file. - Error message when the user attempts to load a file as a FW project when it isn't. + File is not a valid FieldWorks project file. + Error message when the user attempts to load a file as a FW project when it isn't. - {0} has {1} entries referenced by {2} senses. - format for creating the deletion text for a ReversalIndex object - - - There was a problem opening the current version of the file {0}, dated {1}. Would you like to open the automatic backup, {2}, dated {3}? + {0} has {1} entries referenced by {2} senses. + format for creating the deletion text for a ReversalIndex object - Loading the initial Grammatical Categories - - - Problem opening file - Caption for error dialog + Loading the initial Grammatical Categories - - This project is for a newer version of FieldWorks. + This project is for a newer version of FieldWorks. To open this project, click Close, and then install the newer version of FieldWorks. To revert to a version of this project which is compatible with this version of FieldWorks, click Restore a Project. - FieldWorks 6.0 (or earlier) backup - Comment associated with a backup from FieldWorks 6.0 or earlier (shown in Restore a Project dialog box) + FieldWorks 6.0 (or earlier) backup + Comment associated with a backup from FieldWorks 6.0 or earlier (shown in Restore a Project dialog box) - FieldWorks 6.0 XML file - Comment associated with an XML backup from FieldWorks 6.0 (shown in Restore a Project dialog box) + FieldWorks 6.0 XML file + Comment associated with an XML backup from FieldWorks 6.0 (shown in Restore a Project dialog box) - FieldWorks cannot open the project {0} because another program is using it. Please close the other program and try again. Note: this can sometimes occur when there appears to be no other program using the file. The simplest way to fix this is to log off and on again. Other options are discussed in Help. - Must contain {0} which is a project name + FieldWorks cannot open the project {0} because another program is using it. Please close the other program and try again. Note: this can sometimes occur when there appears to be no other program using the file. The simplest way to fix this is to log off and on again. Other options are discussed in Help. + Must contain {0} which is a project name \ No newline at end of file diff --git a/Src/FDO/SilentFdoUserAction.cs b/Src/FDO/SilentFdoUserAction.cs index 7d7bdc3aad..d34de816e8 100644 --- a/Src/FDO/SilentFdoUserAction.cs +++ b/Src/FDO/SilentFdoUserAction.cs @@ -101,7 +101,10 @@ public YesNoCancel CannotRestoreLinkedFilesToOriginalLocation() /// /// Displays information to the user /// - public void MessageBox() + /// + /// + /// + public void DisplayMessage(MessageType type, string message, string caption) { // Informational only } @@ -112,11 +115,9 @@ public void MessageBox() /// the exception you want to report /// set to true if the error is lethal, otherwise /// false. - /// True if the error was lethal and the user chose to exit the application, - /// false otherwise. - public bool ReportException(Exception error, bool isLethal) + public void ReportException(Exception error, bool isLethal) { - return isLethal; + // Informational only } /// @@ -130,6 +131,18 @@ public void ReportDuplicateGuids(RegistryKey applicationKey, string emailAddress // Informational only } + /// + /// Ask user if they wish to restore an XML project from a backup project file. + /// + /// The project path. + /// The backup path. + /// + /// + public bool OfferToRestore(string projectPath, string backupPath) + { + return true; + } + /// /// Present a message to the user and allow the options to Retry or Cancel /// diff --git a/Src/FDO/Strings.Designer.cs b/Src/FDO/Strings.Designer.cs index fed133e3d4..a74fcf941e 100644 --- a/Src/FDO/Strings.Designer.cs +++ b/Src/FDO/Strings.Designer.cs @@ -1141,15 +1141,6 @@ internal static string ksInvalidForm0Trailing1 { } } - /// - /// Looks up a localized string similar to {0} is not a valid directory for linked files. Please select a valid directory.. - /// - internal static string ksInvalidLinkedFilesFolder { - get { - return ResourceManager.GetString("ksInvalidLinkedFilesFolder", resourceCulture); - } - } - /// /// Looks up a localized string similar to Invalid unmarked form ({0}).. /// @@ -1375,15 +1366,6 @@ internal static string ksLexRelation { } } - /// - /// Looks up a localized string similar to Linked Files Folder. - /// - internal static string ksLinkedFilesFolder { - get { - return ResourceManager.GetString("ksLinkedFilesFolder", resourceCulture); - } - } - /// /// Looks up a localized string similar to , . /// diff --git a/Src/FDO/Strings.resx b/Src/FDO/Strings.resx index 8fc71604d1..4e142bf14d 100644 --- a/Src/FDO/Strings.resx +++ b/Src/FDO/Strings.resx @@ -900,14 +900,6 @@ Corrupted Record: Loading list member names Caption for progress dialog, when a new writing system is added - - Linked Files Folder - Caption for folder dialog, when setting a new LangProject.LinkedFilesRootDir value - - - {0} is not a valid directory for linked files. Please select a valid directory. - Error message for accessing an invalid LangProject.LinkedFilesRootDir value - Parts of Speech for {0} Reversal Index diff --git a/Src/FDO/fdoCache.cs b/Src/FDO/fdoCache.cs index 807cb1dac6..14b27d7bd1 100644 --- a/Src/FDO/fdoCache.cs +++ b/Src/FDO/fdoCache.cs @@ -19,7 +19,6 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Windows.Forms; using System.Xml; using System.Runtime.InteropServices; using System.ComponentModel; @@ -35,7 +34,6 @@ using SIL.FieldWorks.FDO.Infrastructure; using SIL.CoreImpl; using SIL.FieldWorks.FDO.Infrastructure.Impl; -using SIL.Utils.FileDialog; namespace SIL.FieldWorks.FDO { @@ -270,7 +268,6 @@ private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, servLoc.WritingSystemManager.UserWritingSystem = wsUser; } - createdCache.EnsureValidLinkedFilesFolder(); return createdCache; } @@ -1427,52 +1424,6 @@ public string GetText(int hvo, int flid, XmlNode frag, out bool fTypeFound) return itype.ToString(); } } - - /// - /// Ensure a valid folder for LangProject.LinkedFilesRootDir. When moving projects - /// between systems, the stored value may become hopelessly invalid. See FWNX-1005 - /// for an example of the havoc than can ensue. - /// - /// This method gets called when we open the FDO cache. - private void EnsureValidLinkedFilesFolder() - { - if (MiscUtils.RunningTests) - return; - - var linkedFilesFolder = LangProject.LinkedFilesRootDir; - var defaultFolder = DirectoryFinder.GetDefaultLinkedFilesDir(ProjectId.ProjectFolder); - EnsureValidLinkedFilesFolderCore(linkedFilesFolder, defaultFolder); - - if (!Directory.Exists(linkedFilesFolder)) - { - if (!Directory.Exists(defaultFolder)) - defaultFolder = ProjectId.ProjectFolder; - MessageBox.Show(String.Format(Strings.ksInvalidLinkedFilesFolder, linkedFilesFolder), Strings.ksErrorCaption); - while (!Directory.Exists(linkedFilesFolder)) - { - using (var folderBrowserDlg = new FolderBrowserDialogAdapter()) - { - folderBrowserDlg.Description = Strings.ksLinkedFilesFolder; - folderBrowserDlg.RootFolder = Environment.SpecialFolder.Desktop; - folderBrowserDlg.SelectedPath = defaultFolder; - if (folderBrowserDlg.ShowDialog() == DialogResult.OK) - linkedFilesFolder = folderBrowserDlg.SelectedPath; - } - } - NonUndoableUnitOfWorkHelper.DoUsingNewOrCurrentUOW(ActionHandlerAccessor, () => - { LangProject.LinkedFilesRootDir = linkedFilesFolder; }); - } - } - - /// - /// Just make the directory if it's the default. - /// See FWNX-1092, LT-14491. - /// - internal void EnsureValidLinkedFilesFolderCore(string linkedFilesFolder, string defaultLinkedFilesFolder) - { - if (linkedFilesFolder == defaultLinkedFilesFolder) - FileUtils.EnsureDirectoryExists(defaultLinkedFilesFolder); - } #endregion Public methods #endregion Public interface diff --git a/Src/FDOBrowser/FDOBrowser.csproj b/Src/FDOBrowser/FDOBrowser.csproj index c2d50e58c3..169a893115 100644 --- a/Src/FDOBrowser/FDOBrowser.csproj +++ b/Src/FDOBrowser/FDOBrowser.csproj @@ -85,6 +85,10 @@ False ..\..\Output\Debug\FDO.dll + + False + ..\..\Output\Debug\FdoUi.dll + False @@ -154,7 +158,6 @@ - Form diff --git a/Src/FDOBrowser/FDOBrowserForm.cs b/Src/FDOBrowser/FDOBrowserForm.cs index 4d1151807b..9c71320c4a 100644 --- a/Src/FDOBrowser/FDOBrowserForm.cs +++ b/Src/FDOBrowser/FDOBrowserForm.cs @@ -15,6 +15,7 @@ using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.Application; using SIL.FieldWorks.FDO.Infrastructure; +using SIL.FieldWorks.FdoUi; using SIL.FieldWorks.Resources; using SIL.ObjectBrowser; using WeifenLuo.WinFormsUI.Docking; @@ -375,13 +376,14 @@ protected override void OpenFile(string fileName) // Init backend data provider // TODO: Get the correct ICU local for the user writing system + var userAction = new FdoUserActionWindowsForms(this, this); if (isMemoryBEP) - m_cache = FdoCache.CreateCacheWithNewBlankLangProj(new BrowserProjectId(bepType, null), "en", "en", "en", new FdoBrowserUserAction(this)); + m_cache = FdoCache.CreateCacheWithNewBlankLangProj(new BrowserProjectId(bepType, null), "en", "en", "en", userAction); else { using (var progressDlg = new ProgressDialogWithTask(this)) { - m_cache = FdoCache.CreateCacheFromExistingData(new BrowserProjectId(bepType, fileName), "en", progressDlg, new FdoBrowserUserAction(this)); + m_cache = FdoCache.CreateCacheFromExistingData(new BrowserProjectId(bepType, fileName), "en", progressDlg, userAction); } } // var v = m_cache. diff --git a/Src/FDOBrowser/FDOClassList.cs b/Src/FDOBrowser/FDOClassList.cs index d77e58e907..fe71b5bf4b 100644 --- a/Src/FDOBrowser/FDOClassList.cs +++ b/Src/FDOBrowser/FDOClassList.cs @@ -1,13 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Reflection; using System.Xml.Serialization; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.FDO; -using System.Collections; using System.IO; using SIL.Utils; @@ -139,7 +137,8 @@ private static void LoadFDOClassNames() if (s_allFDOClassNames != null) return; - using (FdoCache cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", new FdoBrowserUserAction(null))) + using (var threadHelper = new ThreadHelper()) + using (FdoCache cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", new SilentFdoUserAction(threadHelper))) { IFwMetaDataCacheManaged mdc = (IFwMetaDataCacheManaged)cache.MainCacheAccessor.MetaDataCache; s_allFDOClassNames = new List(); diff --git a/Src/FDOBrowser/FdoBrowserUserAction.cs b/Src/FDOBrowser/FdoBrowserUserAction.cs deleted file mode 100644 index 37b82f0f80..0000000000 --- a/Src/FDOBrowser/FdoBrowserUserAction.cs +++ /dev/null @@ -1,154 +0,0 @@ -// --------------------------------------------------------------------------------------------- -#region // Copyright (c) 2013, SIL International. All Rights Reserved. -// -// Copyright (c) 2013, SIL International. All Rights Reserved. -// -// Distributable under the terms of either the Common Public License or the -// GNU Lesser General Public License, as specified in the LICENSING.txt file. -// -#endregion -// --------------------------------------------------------------------------------------------- -using System; -using System.ComponentModel; -using System.Windows.Forms; -using Microsoft.Win32; -using SIL.FieldWorks.FDO; - -namespace FDOBrowser -{ - class FdoBrowserUserAction : IFdoUserAction - { - private readonly ISynchronizeInvoke m_synchronizeInvoke; - - public FdoBrowserUserAction(ISynchronizeInvoke synchronizeInvoke) - { - m_synchronizeInvoke = synchronizeInvoke; - } - - /// - /// Gets the object that is used to invoke methods on the main UI thread. - /// - public ISynchronizeInvoke SynchronizeInvoke - { - get { return m_synchronizeInvoke; } - } - - /// - /// Check with user regarding conflicting changes - /// - /// True if user wishes to revert to saved state. False otherwise. - public bool ConflictingSave() - { - DialogResult dialogResult = System.Windows.Forms.MessageBox.Show("There are conflicting changes from another user. Do you want to load the latest saved version?", "Conflicting Changes", MessageBoxButtons.YesNo); - return dialogResult == DialogResult.Yes; - } - - /// - /// Inform the user of a lost connection - /// - /// True if user wishes to attempt reconnect. False otherwise. - public bool ConnectionLost() - { - DialogResult dialogResult = System.Windows.Forms.MessageBox.Show("The connection has been lost. Do you wish to attempt a reconnect?", "Connection Lost", MessageBoxButtons.YesNo); - return dialogResult == DialogResult.Yes; - } - - public FileSelection ChooseFilesToUse() - { - DialogResult dialogResult = System.Windows.Forms.MessageBox.Show("Some files are newer than the files to be restored. Use these newer files?", "Files To Restore Are Older", MessageBoxButtons.YesNoCancel); - switch (dialogResult) - { - case DialogResult.Yes: - return FileSelection.OkKeepNewer; - case DialogResult.No: - return FileSelection.OkUseOlder; - case DialogResult.Cancel: - default: - return FileSelection.Cancel; - } - } - - /// - /// Check with user regarding restoring linked files in the project folder or original path - /// - /// True if user wishes to restore linked files in project folder. False to leave them in the original location. - public bool RestoreLinkedFilesInProjectFolder() - { - DialogResult dialogResult = System.Windows.Forms.MessageBox.Show("During restore, do you want to move linked files from their current location to the project folder?", "Restore Linked Files", MessageBoxButtons.YesNo); - return dialogResult == DialogResult.Yes; - } - - /// - /// Cannot restore linked files to original path. - /// Check with user regarding restoring linked files in the project folder or not at all - /// - /// OkYes to restore to project folder, OkNo to skip restoring linked files, Cancel otherwise - public YesNoCancel CannotRestoreLinkedFilesToOriginalLocation() - { - DialogResult dialogResult = System.Windows.Forms.MessageBox.Show("Linked files cannot stay in original location and will be moved to project folder. Restore linked files?", "Cannot Restore in Original Location", MessageBoxButtons.YesNoCancel); - switch (dialogResult) - { - case DialogResult.Yes: - return YesNoCancel.OkYes; - case DialogResult.No: - return YesNoCancel.OkNo; - case DialogResult.Cancel: - default: - return YesNoCancel.Cancel; - } - } - - /// - /// Displays information to the user - /// - public void MessageBox() - { - throw new NotImplementedException(); - } - - /// - /// Gets the last time that there was user activity. - /// - public DateTime LastActivityTime - { - get { return DateTime.Now; } - } - - /// - /// Show a dialog or output to the error log, as appropriate. - /// - /// the exception you want to report - /// set to true if the error is lethal, otherwise - /// false. - /// True if the error was lethal and the user chose to exit the application, - /// false otherwise. - public bool ReportException(Exception error, bool isLethal) - { - DialogResult dialogResult = System.Windows.Forms.MessageBox.Show("Close application? Error: " + error.Message, "Application Error", MessageBoxButtons.YesNo); - return dialogResult == DialogResult.Yes; - } - - /// - /// Reports duplicate guids to the user - /// - /// The application key. - /// The email address. - /// The error text. - public void ReportDuplicateGuids(RegistryKey applicationKey, string emailAddress, string errorText) - { - System.Windows.Forms.MessageBox.Show(errorText, "Duplicate Guids"); - } - - /// - /// Present a message to the user and allow the options to Retry or Cancel - /// - /// The message. - /// The caption. - /// True to retry. False otherwise - public bool Retry(string msg, string caption) - { - return System.Windows.Forms.MessageBox.Show(msg, caption, - MessageBoxButtons.RetryCancel, MessageBoxIcon.None) == DialogResult.Retry; - } - } -} diff --git a/Src/FDOBrowser/ModelWnd.cs b/Src/FDOBrowser/ModelWnd.cs index a45fa36e9d..4d9b0d86a5 100644 --- a/Src/FDOBrowser/ModelWnd.cs +++ b/Src/FDOBrowser/ModelWnd.cs @@ -5,10 +5,12 @@ using System.Windows.Forms; using SIL.CoreImpl; using SIL.FieldWorks.Common.FwUtils; +using SIL.FieldWorks.FdoUi; using SIL.Utils; using WeifenLuo.WinFormsUI.Docking; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.Infrastructure; +using XCore; namespace FDOBrowser { @@ -29,7 +31,7 @@ public partial class ModelWnd : DockContent /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// ------------------------------------------------------------------------------------ public ModelWnd() @@ -40,7 +42,7 @@ public ModelWnd() m_lvModel.Font = SystemFonts.MenuFont; // Add model browsing cache (no data, just model browsing). - m_cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", new FdoBrowserUserAction(this)); + m_cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", new SilentFdoUserAction(this)); m_mdc = (IFwMetaDataCacheManaged)m_cache.MainCacheAccessor.MetaDataCache; PopulateModelTree(); @@ -71,7 +73,7 @@ public ModelWnd() /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// ------------------------------------------------------------------------------------ public ModelWnd(ToolStripStatusLabel statuslabel) : this() diff --git a/Src/FdoUi/FdoUiStrings.Designer.cs b/Src/FdoUi/FdoUiStrings.Designer.cs index 7d26a6e528..a08d152f95 100644 --- a/Src/FdoUi/FdoUiStrings.Designer.cs +++ b/Src/FdoUi/FdoUiStrings.Designer.cs @@ -1,4 +1,4 @@ -//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.18052 @@ -538,6 +538,24 @@ internal static string kstidFindRelWordsTitle { } } + /// + /// Looks up a localized string similar to There was a problem opening the current version of the file {0}, dated {1}. Would you like to open the automatic backup, {2}, dated {3}?. + /// + internal static string kstidOfferToRestore { + get { + return ResourceManager.GetString("kstidOfferToRestore", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Problem opening file. + /// + internal static string kstidProblemOpeningFile { + get { + return ResourceManager.GetString("kstidProblemOpeningFile", resourceCulture); + } + } + /// /// Looks up a localized string similar to Undo Bulk Edit Inflection Class. /// diff --git a/Src/FdoUi/FdoUiStrings.resx b/Src/FdoUi/FdoUiStrings.resx index 9c2c05a38d..00c862eb0b 100644 --- a/Src/FdoUi/FdoUiStrings.resx +++ b/Src/FdoUi/FdoUiStrings.resx @@ -330,4 +330,11 @@ Without these, we cannot find related entries. Warning + + There was a problem opening the current version of the file {0}, dated {1}. Would you like to open the automatic backup, {2}, dated {3}? + + + Problem opening file + Caption for error dialog + \ No newline at end of file diff --git a/Src/FdoUi/FdoUserActionWindowsForms.cs b/Src/FdoUi/FdoUserActionWindowsForms.cs index 20402330bd..c6db0af946 100644 --- a/Src/FdoUi/FdoUserActionWindowsForms.cs +++ b/Src/FdoUi/FdoUserActionWindowsForms.cs @@ -11,6 +11,7 @@ using System; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; +using System.IO; using System.Windows.Forms; using Microsoft.Win32; using SIL.FieldWorks.FDO; @@ -128,11 +129,28 @@ public YesNoCancel CannotRestoreLinkedFilesToOriginalLocation() } /// - /// Displays information to the user + /// Displays the message. /// - public void MessageBox() + /// The type. + /// The message. + /// The caption. + /// + public void DisplayMessage(MessageType type, string message, string caption) { - //System.Windows.Forms.MessageBox.Show(); + var icon = MessageBoxIcon.Information; + switch (type) + { + case MessageType.Error: + icon = MessageBoxIcon.Error; + break; + case MessageType.Info: + icon = MessageBoxIcon.Information; + break; + case MessageType.Warning: + icon = MessageBoxIcon.Warning; + break; + } + m_synchronizeInvoke.Invoke(() => MessageBox.Show(message, caption, MessageBoxButtons.OK, icon)); } /// @@ -141,11 +159,9 @@ public void MessageBox() /// the exception you want to report /// set to true if the error is lethal, otherwise /// false. - /// True if the error was lethal and the user chose to exit the application, - /// false otherwise. - public bool ReportException(Exception error, bool isLethal) + public void ReportException(Exception error, bool isLethal) { - return ErrorReporter.ReportException(error, null, null, null, isLethal); + m_synchronizeInvoke.Invoke(() => ErrorReporter.ReportException(error, null, null, null, isLethal)); } public DateTime LastActivityTime { get; private set; } @@ -158,7 +174,23 @@ public bool ReportException(Exception error, bool isLethal) /// The error text. public void ReportDuplicateGuids(RegistryKey applicationKey, string emailAddress, string errorText) { - ErrorReporter.ReportDuplicateGuids(applicationKey, emailAddress, null, errorText); + m_synchronizeInvoke.Invoke(() => ErrorReporter.ReportDuplicateGuids(applicationKey, emailAddress, null, errorText)); + } + + /// + /// Ask user if they wish to restore an XML project from a backup project file. + /// + /// The project path. + /// The backup path. + /// + /// + public bool OfferToRestore(string projectPath, string backupPath) + { + return m_synchronizeInvoke.Invoke(() => MessageBox.Show( + String.Format(FdoUiStrings.kstidOfferToRestore, projectPath, File.GetLastWriteTime(projectPath), + backupPath, File.GetLastWriteTime(backupPath)), + FdoUiStrings.kstidProblemOpeningFile, MessageBoxButtons.YesNo, + MessageBoxIcon.Error) == DialogResult.Yes); } /// From 11ce06721ceca10340dc2843e48a044a76837a6e Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Wed, 4 Dec 2013 16:31:49 +0700 Subject: [PATCH 016/143] removed WinForms references from some FDO classes -ScrSfFileList -Db40ClientServerBackendProvider -ClientServerServices Change-Id: I96793d106b6a98e583cfc014520ad7cffde5a005 --- .../FwControls/ObtainProjectMethod.cs | 10 +-- .../TestColumnConfigureDialog.cs | 2 +- Src/Common/FieldWorks/FieldWorks.cs | 20 ++--- .../FieldWorks/PaObjects/PaLexicalInfo.cs | 21 +++-- Src/FDO/DomainImpl/ScrImportSet.cs | 22 +---- .../BackupRestore/ProjectRestoreService.cs | 16 ++-- .../DomainServices/ClientServerServices.cs | 87 +++++++++---------- .../DataStoreInitializationServices.cs | 2 +- .../DomainServices/DomainObjectServices.cs | 4 +- Src/FDO/DomainServices/FwStyleSheet.cs | 2 +- Src/FDO/DomainServices/ScrSfFileList.cs | 14 ++- Src/FDO/FDO.csproj | 4 +- Src/FDO/FDOTests/ClientServerServicesTests.cs | 16 ++-- .../{DummyFdoUserAction.cs => DummyFdoUI.cs} | 15 +++- Src/FDO/FDOTests/FDOTests.csproj | 2 +- Src/FDO/FDOTests/FdoCacheTests.cs | 30 +++---- Src/FDO/FDOTests/FdoScriptureTests.cs | 6 +- Src/FDO/FDOTests/FdoTestBase.cs | 4 +- .../PersistingBackendProviderTests.cs | 4 +- .../PersistingLayerTests.BEPPortTests.cs | 8 +- Src/FDO/FDOTests/XmlImportDataTests.cs | 2 +- Src/FDO/FDOTests/XmlListTests.cs | 2 +- Src/FDO/FDOTests/XmlTranslatedListsTests.cs | 2 +- Src/FDO/FdoInterfaceAdditions.cs | 10 --- Src/FDO/{IFdoUserAction.cs => IFdoUI.cs} | 12 ++- Src/FDO/IOC/FdoServiceLocatorFactory.cs | 12 +-- .../Impl/ClientServerBackendProvider.cs | 2 +- .../Infrastructure/Impl/CmObjectSurrogate.cs | 4 +- .../Impl/Db4oClientServerBackendProvider.cs | 16 ++-- .../Infrastructure/Impl/FDOBackendProvider.cs | 10 +-- .../Impl/MemoryOnlyBackendProvider.cs | 4 +- Src/FDO/Infrastructure/Impl/UndoStack.cs | 8 +- .../Infrastructure/Impl/UnitOfWorkService.cs | 18 ++-- .../Infrastructure/Impl/XMLBackendProvider.cs | 10 +-- ...{SilentFdoUserAction.cs => SilentFdoUI.cs} | 17 +++- Src/FDO/fdoCache.cs | 54 ++++++------ Src/FDOBrowser/FDOBrowserForm.cs | 2 +- Src/FDOBrowser/FDOClassList.cs | 2 +- Src/FDOBrowser/ModelWnd.cs | 2 +- Src/FdoUi/FdoUi.csproj | 2 +- ...doUserActionWindowsForms.cs => FwFdoUI.cs} | 39 ++++++--- Src/FwCoreDlgs/ChooseLangProjectDialog.cs | 16 ++-- .../FwCoreDlgsTests/FwNewLangProjectTests.cs | 6 +- Src/FwCoreDlgs/FwNewLangProject.cs | 12 +-- .../LexTextControlsTests/LiftExportTests.cs | 2 +- Src/LexText/Lexicon/FLExBridgeListener.cs | 4 +- Src/TE/TeImportExport/TeImportManager.cs | 1 - Src/xWorks/xWorksTests/ExportDialogTests.cs | 2 +- 48 files changed, 285 insertions(+), 277 deletions(-) rename Src/FDO/FDOTests/{DummyFdoUserAction.cs => DummyFdoUI.cs} (95%) rename Src/FDO/{IFdoUserAction.cs => IFdoUI.cs} (96%) rename Src/FDO/{SilentFdoUserAction.cs => SilentFdoUI.cs} (93%) rename Src/FdoUi/{FdoUserActionWindowsForms.cs => FwFdoUI.cs} (88%) diff --git a/Src/Common/Controls/FwControls/ObtainProjectMethod.cs b/Src/Common/Controls/FwControls/ObtainProjectMethod.cs index 635db8828a..45a10fd42f 100644 --- a/Src/Common/Controls/FwControls/ObtainProjectMethod.cs +++ b/Src/Common/Controls/FwControls/ObtainProjectMethod.cs @@ -24,7 +24,7 @@ public static class ObtainProjectMethod /// The repo may be a lift or full FW repo, but it can be from any source source, as long as the code can create an FW project from it. /// /// Null if the operation was cancelled or otherwise did not work. The full pathname of an fwdata file, if it did work. - public static string ObtainProjectFromAnySource(Form parent, IHelpTopicProvider helpTopicProvider, out ObtainedProjectType obtainedProjectType, IFdoUserAction userAction) + public static string ObtainProjectFromAnySource(Form parent, IHelpTopicProvider helpTopicProvider, out ObtainedProjectType obtainedProjectType, IFdoUI ui) { bool dummy; string fwdataFileFullPathname; @@ -45,7 +45,7 @@ public static string ObtainProjectFromAnySource(Form parent, IHelpTopicProvider if (fwdataFileFullPathname.EndsWith("lift")) { - fwdataFileFullPathname = CreateProjectFromLift(parent, helpTopicProvider, fwdataFileFullPathname, userAction); + fwdataFileFullPathname = CreateProjectFromLift(parent, helpTopicProvider, fwdataFileFullPathname, ui); obtainedProjectType = ObtainedProjectType.Lift; } @@ -55,7 +55,7 @@ public static string ObtainProjectFromAnySource(Form parent, IHelpTopicProvider /// /// Create a new Fieldworks project and import a lift file into it. Return the .fwdata path. /// - private static string CreateProjectFromLift(Form parent, IHelpTopicProvider helpTopicProvider, string liftPath, IFdoUserAction userAction) + private static string CreateProjectFromLift(Form parent, IHelpTopicProvider helpTopicProvider, string liftPath, IFdoUI ui) { string projectPath; FdoCache cache; @@ -72,7 +72,7 @@ private static string CreateProjectFromLift(Form parent, IHelpTopicProvider help progressDlg.Title = FwControls.ksCreatingLiftProject; var cacheReceiver = new FdoCache[1]; // a clumsy way of handling an out parameter, consistent with RunTask projectPath = (string)progressDlg.RunTask(true, CreateProjectTask, - new[] { liftPath, parent, userAction, anthroListFile, cacheReceiver }); + new[] { liftPath, parent, ui, anthroListFile, cacheReceiver }); cache = cacheReceiver[0]; } @@ -102,7 +102,7 @@ private static object CreateProjectTask(IThreadedProgress progress, object[] par // Get required parameters. Ideally these would just be the signature of the method, but RunTask requires object[]. var liftPathname = (string) parameters[0]; var synchronizeInvoke = (ISynchronizeInvoke) parameters[1]; - var userAction = (IFdoUserAction) parameters[2]; + var userAction = (IFdoUI) parameters[2]; var anthroFile = (string) parameters[3]; var cacheReceiver = (FdoCache[]) parameters[4]; diff --git a/Src/Common/Controls/XMLViews/XMLViewsTests/TestColumnConfigureDialog.cs b/Src/Common/Controls/XMLViews/XMLViewsTests/TestColumnConfigureDialog.cs index 05e8e44faf..3888706df4 100644 --- a/Src/Common/Controls/XMLViews/XMLViewsTests/TestColumnConfigureDialog.cs +++ b/Src/Common/Controls/XMLViews/XMLViewsTests/TestColumnConfigureDialog.cs @@ -36,7 +36,7 @@ public void SetUp() m_mediator = new Mediator(); m_mediator.StringTbl = new StringTable("../../DistFiles/Language Explorer/Configuration"); m_cache = FdoCache.CreateCacheWithNewBlankLangProj( - new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "en", "en", new DummyFdoUserAction()); + new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "en", "en", new DummyFdoUI()); m_mediator.PropertyTable.SetProperty("cache", m_cache); } diff --git a/Src/Common/FieldWorks/FieldWorks.cs b/Src/Common/FieldWorks/FieldWorks.cs index 856b632f80..3e10a31a47 100644 --- a/Src/Common/FieldWorks/FieldWorks.cs +++ b/Src/Common/FieldWorks/FieldWorks.cs @@ -131,7 +131,7 @@ private enum StartupStatus // true if we have no previous reporting settings, typically the first time a version of FLEx that // supports usage reporting has been run. private static bool s_noPreviousReportingSettings; - private static IFdoUserAction s_userAction; + private static IFdoUI s_ui; #endregion #region Main Method and Initialization Methods @@ -242,7 +242,7 @@ static int Main(string[] rgArgs) s_noUserInterface = appArgs.NoUserInterface; s_appServerMode = appArgs.AppServerMode; - s_userAction = new FdoUserActionWindowsForms(GetHelpTopicProvider(appArgs.AppAbbrev), s_threadHelper); + s_ui = new FwFdoUI(GetHelpTopicProvider(appArgs.AppAbbrev), s_threadHelper); if (Settings.Default.CallUpgrade) { @@ -806,7 +806,7 @@ private static FdoCache CreateCache(ProjectId projectId) Form owner = s_splashScreen != null ? s_splashScreen.Form : Form.ActiveForm; using (var progressDlg = new ProgressDialogWithTask(owner)) { - FdoCache cache = FdoCache.CreateCacheFromExistingData(projectId, s_sWsUser, progressDlg, s_userAction); + FdoCache cache = FdoCache.CreateCacheFromExistingData(projectId, s_sWsUser, progressDlg, s_ui); EnsureValidLinkedFilesFolder(cache); cache.ProjectNameChanged += ProjectNameChanged; cache.ServiceLocator.GetInstance().OnSave += FieldWorks_OnSave; @@ -1700,7 +1700,7 @@ private static ProjectId ShowWelcomeDialog(FwAppArgs args, FwApp startingApp, Pr projectToTry = null; // If the user cancels the send/receive, this null will result in a return to the welcome dialog. // Hard to say what Form.ActiveForm is here. The splash and welcome dlgs are both gone. var projectDataPathname = ObtainProjectMethod.ObtainProjectFromAnySource(Form.ActiveForm, - helpTopicProvider, out obtainedProjectType, s_userAction); + helpTopicProvider, out obtainedProjectType, s_ui); if (!string.IsNullOrEmpty(projectDataPathname)) { projectToTry = new ProjectId(FDOBackendProviderType.kXML, projectDataPathname, null); @@ -1772,7 +1772,7 @@ internal static ProjectId ChooseLangProject(Form dialogOwner, IHelpTopicProvider { return null; } - using (var dlg = new ChooseLangProjectDialog(helpTopicProvider, false, s_userAction)) + using (var dlg = new ChooseLangProjectDialog(helpTopicProvider, false, s_ui)) { dlg.ShowDialog(dialogOwner); var app = helpTopicProvider as IApp; @@ -1804,7 +1804,7 @@ internal static ProjectId ChooseLangProject(Form dialogOwner, IHelpTopicProvider /// ------------------------------------------------------------------------------------ internal static ProjectId CreateNewProject(Form dialogOwner, FwApp app, IHelpTopicProvider helpTopicProvider) { - using (var dlg = new FwNewLangProject(s_userAction)) + using (var dlg = new FwNewLangProject(s_ui)) { dlg.SetDialogProperties(helpTopicProvider); switch (dlg.DisplayDialog(dialogOwner)) @@ -2034,7 +2034,7 @@ private static bool UpdateProjectsSharing(bool fShareProjects, Form dialogOwner // Both these setters check and do nothing if not changed. using (var progressDlg = new ProgressDialogWithTask(s_threadHelper)) { - return ClientServerServices.Current.Local.SetProjectSharing(fShareProjects, progressDlg, s_userAction); + return ClientServerServices.Current.Local.SetProjectSharing(fShareProjects, progressDlg, s_ui); } } @@ -2043,7 +2043,7 @@ private static bool UpdateProjectsSharing(bool fShareProjects, Form dialogOwner { using (var progressDlg = new ProgressDialogWithTask(s_threadHelper)) { - fSuccess = ClientServerServices.Current.Local.SetProjectSharing(fShareProjects, progressDlg, s_userAction); + fSuccess = ClientServerServices.Current.Local.SetProjectSharing(fShareProjects, progressDlg, s_ui); } return new ProjectId(ClientServerServices.Current.Local.IdForLocalProject(Path.GetFileNameWithoutExtension(projectPath)), null); }); @@ -2507,7 +2507,7 @@ private static void RestoreCurrentProject(FwRestoreProjectSettings restoreSettin try { ProjectRestoreService restoreService = new ProjectRestoreService(restoreSettings.Settings, - GetHelpTopicProvider(restoreSettings.FwAppCommandLineAbbrev), s_userAction); + GetHelpTopicProvider(restoreSettings.FwAppCommandLineAbbrev), s_ui); Logger.WriteEvent("Restoring from " + restoreSettings.Settings.Backup.File); if (RestoreProjectDlg.HandleRestoreFileErrors(null, ResourceHelper.GetResourceString("ksRestoreFailed"), restoreSettings.Settings.Backup.File, () => DoRestore(restoreService))) @@ -2569,7 +2569,7 @@ private static bool BackupProjectForRestore(FwRestoreProjectSettings restoreSett { FdoCache cache = existingCache ?? FdoCache.CreateCacheFromExistingData( new ProjectId(restoreSettings.Settings.FullProjectPath, null), - s_sWsUser, progressDlg, s_userAction); + s_sWsUser, progressDlg, s_ui); try { diff --git a/Src/Common/FieldWorks/PaObjects/PaLexicalInfo.cs b/Src/Common/FieldWorks/PaObjects/PaLexicalInfo.cs index fd96aad110..b03a5a6203 100644 --- a/Src/Common/FieldWorks/PaObjects/PaLexicalInfo.cs +++ b/Src/Common/FieldWorks/PaObjects/PaLexicalInfo.cs @@ -19,7 +19,6 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Drawing; -using System.Linq; using System.Threading; using System.Windows.Forms; using SIL.FieldWorks.FDO; @@ -38,15 +37,17 @@ public class PaLexicalInfo : IPaLexicalInfo, IDisposable { private List m_writingSystems; private List m_lexEntries; - private readonly IFdoUserAction m_userAction; + private ThreadHelper m_threadHelper; + private readonly IFdoUI m_ui; /// /// Initializes a new instance of the class. /// public PaLexicalInfo() { - var helpTopicProvider = (IHelpTopicProvider)DynamicLoader.CreateObject(DirectoryFinder.FlexDll, "SIL.FieldWorks.XWorks.LexText.FlexHelpTopicProvider"); - m_userAction = new FdoUserActionWindowsForms(helpTopicProvider, new ThreadHelper()); + m_threadHelper = new ThreadHelper(); + var helpTopicProvider = (IHelpTopicProvider) DynamicLoader.CreateObject(DirectoryFinder.FlexDll, "SIL.FieldWorks.XWorks.LexText.FlexHelpTopicProvider"); + m_ui = new FwFdoUI(helpTopicProvider, m_threadHelper); } #region Disposable stuff @@ -71,7 +72,7 @@ public void Dispose() /// protected virtual void Dispose(bool fDisposing) { - System.Diagnostics.Debug.WriteLineIf(!fDisposing, "****** Missing Dispose() call for " + GetType().ToString() + " *******"); + Debug.WriteLineIf(!fDisposing, "****** Missing Dispose() call for " + GetType() + " *******"); if (fDisposing && !IsDisposed) { // dispose managed and unmanaged objects @@ -80,9 +81,13 @@ protected virtual void Dispose(bool fDisposing) if (m_writingSystems != null) m_writingSystems.Clear(); + + if (m_threadHelper != null) + m_threadHelper.Dispose(); } m_lexEntries = null; m_writingSystems = null; + m_threadHelper = null; IsDisposed = true; } #endregion @@ -99,7 +104,7 @@ public bool ShowOpenProject(Form owner, ref Rectangle dialogBounds, Icu.InitIcuDataDir(); RegistryHelper.ProductName = "FieldWorks"; // inorder to find correct Registry keys - using (var dlg = new ChooseLangProjectDialog(dialogBounds, dialogSplitterPos, m_userAction)) + using (var dlg = new ChooseLangProjectDialog(dialogBounds, dialogSplitterPos, m_ui)) { if (dlg.ShowDialog(owner) == DialogResult.OK) { @@ -259,7 +264,7 @@ private bool LoadFwDataForPa(PaRemoteRequest requestor, string name, string serv /// ------------------------------------------------------------------------------------ public IEnumerable LexEntries { - get { return m_lexEntries.Cast(); } + get { return m_lexEntries; } } /// ------------------------------------------------------------------------------------ @@ -269,7 +274,7 @@ public IEnumerable LexEntries /// ------------------------------------------------------------------------------------ public IEnumerable WritingSystems { - get { return m_writingSystems.Cast(); } + get { return m_writingSystems; } } #endregion diff --git a/Src/FDO/DomainImpl/ScrImportSet.cs b/Src/FDO/DomainImpl/ScrImportSet.cs index e2223e50e6..d2df3ced09 100644 --- a/Src/FDO/DomainImpl/ScrImportSet.cs +++ b/Src/FDO/DomainImpl/ScrImportSet.cs @@ -71,8 +71,6 @@ internal partial class ScrImportSet private bool m_fImportAnnotations; private BCVRef m_startRef; private BCVRef m_endRef; - - private string m_helpFile; #endregion #region Construction & initialization @@ -155,7 +153,7 @@ private void LoadInMemoryFileLists() { m_scrFileInfoList = new ScrSfFileList((ScrImportSFFiles)source, m_scrMappingsList, ImportDomain.Main, - (ImportTypeEnum == TypeOfImport.Paratext5), m_helpFile); + (ImportTypeEnum == TypeOfImport.Paratext5)); m_scrFileInfoList.OverlappingFileResolver = m_resolver; break; } @@ -170,7 +168,7 @@ private void LoadInMemoryFileLists() string wsId = source.WritingSystem ?? string.Empty; m_btFileInfoLists[wsId] = new ScrSfFileList((ScrImportSFFiles)source, m_scrMappingsList, ImportDomain.BackTrans, - (ImportTypeEnum == TypeOfImport.Paratext5), m_helpFile); + (ImportTypeEnum == TypeOfImport.Paratext5)); } } @@ -183,7 +181,7 @@ private void LoadInMemoryFileLists() ((ScrImportSFFiles)source).NoteTypeRA); m_notesFileInfoLists[key] = new ScrSfFileList((ScrImportSFFiles)source, m_notesMappingsList, ImportDomain.Annotations, - (ImportTypeEnum == TypeOfImport.Paratext5), m_helpFile); + (ImportTypeEnum == TypeOfImport.Paratext5)); } } } @@ -680,20 +678,6 @@ public IVwStylesheet StyleSheet } } } - - /// ------------------------------------------------------------------------------------ - /// - /// Sets the help file used in a message box if an error occurs. - /// - /// ------------------------------------------------------------------------------------ - public string HelpFile - { - set - { - lock (SyncRoot) - m_helpFile = value; - } - } #endregion #region Public Methods diff --git a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs index 17d54d39d9..cedcae59bc 100644 --- a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs +++ b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs @@ -37,7 +37,7 @@ public class ProjectRestoreService private bool m_fRestoreOverProject; private readonly IHelpTopicProvider m_helpTopicProvider; private string m_sLinkDirChangedTo; - private readonly IFdoUserAction m_userAction; + private readonly IFdoUI m_ui; #endregion #region Constructor @@ -47,13 +47,13 @@ public class ProjectRestoreService /// /// The restore settings. /// - /// + /// /// ------------------------------------------------------------------------------------ - public ProjectRestoreService(RestoreProjectSettings settings, IHelpTopicProvider helpTopicProvider, IFdoUserAction userAction) + public ProjectRestoreService(RestoreProjectSettings settings, IHelpTopicProvider helpTopicProvider, IFdoUI ui) { m_restoreSettings = settings; m_helpTopicProvider = helpTopicProvider; - m_userAction = userAction; + m_ui = ui; } /// ------------------------------------------------------------------------------------ @@ -122,7 +122,7 @@ public void RestoreProject(IThreadedProgress progressDlg) // switch to the desired backend (if it's in the projects directory...anything else stays XML for now). if (DirectoryFinder.IsSubFolderOfProjectsDirectory(m_restoreSettings.ProjectPath) && !suppressConversion) - ClientServerServices.Current.Local.ConvertToDb4oBackendIfNeeded(progressDlg, m_restoreSettings.FullProjectPath, m_userAction); + ClientServerServices.Current.Local.ConvertToDb4oBackendIfNeeded(progressDlg, m_restoreSettings.FullProjectPath, m_ui); CleanupAfterRestore(true); } @@ -333,7 +333,7 @@ private void RestoreLinkedFiles(BackupFileSettings fileSettings) /// Protected so we can subclass in tests. protected virtual bool CanRestoreLinkedFilesToProjectsFolder() { - return m_userAction.RestoreLinkedFilesInProjectFolder(); + return m_ui.RestoreLinkedFilesInProjectFolder(); } /// @@ -392,7 +392,7 @@ private void ExternalLinksDirectoryExits(string linkedFilesPathPersisted, string { //Some files in the zip file are older than the ones on disk. Therefore find out if the user wants //to keep the newer files on disk. - FileSelection fileSelection = m_userAction.ChooseFilesToUse(); + FileSelection fileSelection = m_ui.ChooseFilesToUse(); if (fileSelection == FileSelection.OkKeepNewer) { var newList = RemoveFilesThatAreOlderThanThoseOnDisk(filesContainedInLinkdFilesFolder, @@ -423,7 +423,7 @@ private void ExternalLinksDirectoryExits(string linkedFilesPathPersisted, string /// protected virtual void CouldNotRestoreLinkedFilesToOriginalLocation(string linkedFilesPathPersisted, Dictionary filesContainedInLinkdFilesFolder) { - YesNoCancel userSelection = m_userAction.CannotRestoreLinkedFilesToOriginalLocation(); + YesNoCancel userSelection = m_ui.CannotRestoreLinkedFilesToOriginalLocation(); if (userSelection == YesNoCancel.OkYes) { m_sLinkDirChangedTo = DirectoryFinder.GetDefaultLinkedFilesDir(m_restoreSettings.ProjectPath); diff --git a/Src/FDO/DomainServices/ClientServerServices.cs b/Src/FDO/DomainServices/ClientServerServices.cs index 3c8d295bcc..a848a964c8 100644 --- a/Src/FDO/DomainServices/ClientServerServices.cs +++ b/Src/FDO/DomainServices/ClientServerServices.cs @@ -21,13 +21,11 @@ using System.Net.NetworkInformation; using System.Net.Sockets; using System.Text; -using System.Windows.Forms; using FwRemoteDatabaseConnector; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.FDO.Infrastructure.Impl; using SIL.FieldWorks.Resources; -using SIL.Utils; namespace SIL.FieldWorks.FDO.DomainServices { @@ -207,9 +205,9 @@ public interface ILocalClientServerServices /// /// if set to true, turn sharing on. /// The progress dialog. - /// + /// /// Indication of whether the request was performed successfully. - bool SetProjectSharing(bool fShare, IThreadedProgress progress, IFdoUserAction userAction); + bool SetProjectSharing(bool fShare, IThreadedProgress progress, IFdoUI ui); /// /// Return true if the specified project (in the specified parent directory) will be @@ -227,11 +225,11 @@ public interface ILocalClientServerServices /// The progress dialog for getting a message box owner and/or /// ensuring we're invoking on the uI thread. /// The full path of the existing XML file for the project - /// + /// /// The project identifier, typically the path to the converted file (or the /// original, if not configured for the client-server backend) /// ------------------------------------------------------------------------------------ - string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string filename, IFdoUserAction userAction); + string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string filename, IFdoUI ui); /// /// Copies the specified project (assumed to be in the current Projects directory) @@ -575,9 +573,9 @@ public bool ShareMyProjects /// /// if set to true, turn sharing on. /// The progress dialog. - /// + /// /// ------------------------------------------------------------------------------------ - public bool SetProjectSharing(bool fShare, IThreadedProgress progress, IFdoUserAction userAction) + public bool SetProjectSharing(bool fShare, IThreadedProgress progress, IFdoUI ui) { Db4oServerInfo serverInfo = null; do @@ -591,7 +589,7 @@ public bool SetProjectSharing(bool fShare, IThreadedProgress progress, IFdoUserA } } while (serverInfo == null && - userAction.Retry(string.Format(Strings.ksLocalConnectorServiceNotStarted, "FwRemoteDatabaseConnectorService"), + ui.Retry(string.Format(Strings.ksLocalConnectorServiceNotStarted, "FwRemoteDatabaseConnectorService"), fShare ? Strings.ksConvertingToShared : Strings.ksConvertingToNonShared)); if (serverInfo == null || serverInfo.AreProjectShared() == fShare) @@ -603,7 +601,7 @@ public bool SetProjectSharing(bool fShare, IThreadedProgress progress, IFdoUserA if (fShare) { // Turning sharing on. - if (!ConvertAllProjectsToDb4o(progress, userAction)) + if (!ConvertAllProjectsToDb4o(progress, ui)) { LocalDb4OServerInfoConnection.ShareProjects(false); // could not switch return false; @@ -611,7 +609,7 @@ public bool SetProjectSharing(bool fShare, IThreadedProgress progress, IFdoUserA } else { - if (!ConvertAllProjectsToXml(progress, userAction)) + if (!ConvertAllProjectsToXml(progress, ui)) { // If ConvertAllProjectsToXml failed then leave sharing on. LocalDb4OServerInfoConnection.ShareProjects(true); @@ -646,7 +644,7 @@ public bool WillProjectBeConverted(string projectPath, string parentDirectory, s /// /// false if clients are still connected. /// ------------------------------------------------------------------------------------ - private static bool EnsureNoClientsAreConnected(IFdoUserAction userAction) + private static bool EnsureNoClientsAreConnected(IFdoUI ui) { var localService = LocalDb4OServerInfoConnection; if (localService == null) @@ -661,7 +659,7 @@ private static bool EnsureNoClientsAreConnected(IFdoUserAction userAction) connectedClientsMsg.AppendFormat("{2}{0} : {1}", client, Dns.GetHostEntry(client).HostName, Environment.NewLine); } - if (!userAction.Retry(String.Format(Strings.ksAllProjectsMustDisconnectClients, connectedClientsMsg), + if (!ui.Retry(String.Format(Strings.ksAllProjectsMustDisconnectClients, connectedClientsMsg), Strings.ksAllProjectsMustDisconnectCaption)) return false; @@ -680,10 +678,10 @@ private static bool EnsureNoClientsAreConnected(IFdoUserAction userAction) /// TODO: as an enhancement connected clients could be messaged and asked to disconnect. /// /// project name. - /// + /// /// false if clients are still connected. /// ------------------------------------------------------------------------------------ - private static bool EnsureNoClientsAreConnected(string projectName, IFdoUserAction userAction) + private static bool EnsureNoClientsAreConnected(string projectName, IFdoUI ui) { Db4oServerInfo localService = LocalDb4OServerInfoConnection; if (localService == null) @@ -695,7 +693,7 @@ private static bool EnsureNoClientsAreConnected(string projectName, IFdoUserActi foreach (string client in connectedClients) connectedClientsMsg.AppendFormat("{2}{0} : {1}", client, Dns.GetHostEntry(client).HostName, Environment.NewLine); - if (!WarnOfOtherConnectedClients(projectName, connectedClientsMsg.ToString(), userAction)) + if (!WarnOfOtherConnectedClients(projectName, connectedClientsMsg.ToString(), ui)) return false; connectedClients = localService.ListConnectedClients(projectName); @@ -711,14 +709,14 @@ private static bool EnsureNoClientsAreConnected(string projectName, IFdoUserActi /// Name of the project. /// The message to show about the connected clients. /// - /// + /// /// ------------------------------------------------------------------------------------ - private static bool WarnOfOtherConnectedClients(string projectName, string connectedClientsMsg, IFdoUserAction userAction) + private static bool WarnOfOtherConnectedClients(string projectName, string connectedClientsMsg, IFdoUI ui) { var msg = String.Format(Strings.ksMustDisconnectClients, projectName, connectedClientsMsg); var caption = String.Format(Strings.ksMustDisconnectCaption, projectName); - return userAction.Retry(msg, caption); + return ui.Retry(msg, caption); } /// ------------------------------------------------------------------------------------ @@ -728,20 +726,21 @@ private static bool WarnOfOtherConnectedClients(string projectName, string conne /// true if successful; false if other clients are connected, /// which prevents conversion of shared projects. /// ------------------------------------------------------------------------------------ - private bool ConvertAllProjectsToXml(IThreadedProgress progressDlg, IFdoUserAction userAction) + private bool ConvertAllProjectsToXml(IThreadedProgress progressDlg, IFdoUI ui) { - if (!EnsureNoClientsAreConnected(userAction)) + if (!EnsureNoClientsAreConnected(ui)) return false; progressDlg.Title = Strings.ksConvertingToNonShared; progressDlg.AllowCancel = false; progressDlg.Maximum = Directory.GetDirectories(DirectoryFinder.ProjectsDirectory).Count(); - progressDlg.RunTask(true, (progress, args) => ConvertAllProjectsToXmlTask(progress, userAction, args)); + progressDlg.RunTask(true, ConvertAllProjectsToXmlTask, ui); return true; } - private object ConvertAllProjectsToXmlTask(IThreadedProgress progress, IFdoUserAction userAction, object[] args) + private object ConvertAllProjectsToXmlTask(IThreadedProgress progress, object[] args) { + var userAction = (IFdoUI) args[0]; foreach (var projectFolder in Directory.GetDirectories(DirectoryFinder.ProjectsDirectory)) { var projectName = Path.GetFileName(projectFolder); @@ -764,7 +763,7 @@ private object ConvertAllProjectsToXmlTask(IThreadedProgress progress, IFdoUserA } catch (Exception e) { - ReportConversionError(progress.Form, projectPath, e); + ReportConversionError(userAction, projectPath, e); } } progress.Step(1); @@ -777,18 +776,19 @@ private object ConvertAllProjectsToXmlTask(IThreadedProgress progress, IFdoUserA /// Converts all projects to db4o. /// /// The progress dialog box. - /// + /// /// ------------------------------------------------------------------------------------ - private bool ConvertAllProjectsToDb4o(IThreadedProgress progressDlg, IFdoUserAction userAction) + private bool ConvertAllProjectsToDb4o(IThreadedProgress progressDlg, IFdoUI ui) { progressDlg.Title = Strings.ksConvertingToShared; progressDlg.AllowCancel = false; progressDlg.Maximum = Directory.GetDirectories(DirectoryFinder.ProjectsDirectory).Count(); - return (bool)progressDlg.RunTask(true, (progress, args) => ConvertAllProjectsToDb4o(progress, userAction, args)); + return (bool)progressDlg.RunTask(true, ConvertAllProjectsToDb4o, ui); } - private object ConvertAllProjectsToDb4o(IThreadedProgress progress, IFdoUserAction userAction, object[] args) + private object ConvertAllProjectsToDb4o(IThreadedProgress progress, object[] args) { + var userAction = (IFdoUI) args[0]; for (; ; ) { string projects = ""; @@ -817,21 +817,21 @@ private object ConvertAllProjectsToDb4o(IThreadedProgress progress, IFdoUserActi progress.Message = Path.GetFileNameWithoutExtension(projectPath); if (File.Exists(projectPath) && !File.Exists(suppressPath)) { - try - { + try + { ConvertToDb4oBackendIfNeeded(progress, projectPath, userAction); - } - catch (Exception e) - { - ReportConversionError(progress.Form, projectPath, e); - } + } + catch (Exception e) + { + ReportConversionError(userAction, projectPath, e); + } } progress.Step(1); } return true; } - private static void ReportConversionError(Form messageBoxOwner, string projectPath, Exception e) + private static void ReportConversionError(IFdoUI ui, string projectPath, Exception e) { string message; if (e is FwNewerVersionException) @@ -844,8 +844,7 @@ private static void ReportConversionError(Form messageBoxOwner, string projectPa message = string.Format(Strings.ksConvertFailedDetails, Path.GetFileName(projectPath), Path.GetDirectoryName(projectPath), e.Message); } - ThreadHelper.ShowMessageBox(messageBoxOwner, message, Strings.ksCannotConvert, - MessageBoxButtons.OK, MessageBoxIcon.Error); + ui.DisplayMessage(MessageType.Error, message, Strings.ksCannotConvert, null); } /// ------------------------------------------------------------------------------------ @@ -857,29 +856,29 @@ private static void ReportConversionError(Form messageBoxOwner, string projectPa /// The progress dialog (for getting a message box owner and/or /// ensuring we're invoking on the UI thread). /// The full path of the existing XML file for the project - /// + /// /// The project identifier, typically the path to the converted file (or the /// original, if not configured for the client-server backend) /// ------------------------------------------------------------------------------------ - public string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string xmlFilename, IFdoUserAction userAction) + public string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string xmlFilename, IFdoUI ui) { if (!ShareMyProjects) return xmlFilename; // no conversion needed. string desiredPath = Path.ChangeExtension(xmlFilename, FwFileExtensions.ksFwDataDb4oFileExtension); - if (!EnsureNoClientsAreConnected(Path.GetFileNameWithoutExtension(desiredPath), userAction)) + if (!EnsureNoClientsAreConnected(Path.GetFileNameWithoutExtension(desiredPath), ui)) return null; // fail try { using (var tempCache = FdoCache.CreateCacheFromExistingData(new SimpleProjectId(FDOBackendProviderType.kXML, xmlFilename), - "en", progressDlg, new SilentFdoUserAction(progressDlg.SynchronizeInvoke))) + "en", progressDlg, new SilentFdoUI(progressDlg.SynchronizeInvoke))) { // The zero in the object array is for db4o and causes it not to open a port. // This is fine since we aren't yet trying to start up on this restored database. // The null says we are creating the file on the local host. using (var copyCache = FdoCache.CreateCacheCopy(new SimpleProjectId(FDOBackendProviderType.kDb4oClientServer, desiredPath), - "en", tempCache, new SilentFdoUserAction(progressDlg.SynchronizeInvoke))) + "en", tempCache, new SilentFdoUI(progressDlg.SynchronizeInvoke))) { copyCache.ServiceLocator.GetInstance().Commit(new HashSet(), new HashSet(), new HashSet()); // Enhance JohnT: how can we tell this succeeded? @@ -920,7 +919,7 @@ public string CopyToXmlFile(FdoCache source, string destDir) try { using (var copyCache = FdoCache.CreateCacheCopy( - new SimpleProjectId(FDOBackendProviderType.kXML, newFilePath), "en", source, source.ServiceLocator.GetInstance())) + new SimpleProjectId(FDOBackendProviderType.kXML, newFilePath), "en", source, source.ServiceLocator.GetInstance())) { copyCache.ServiceLocator.GetInstance().Commit( new HashSet(), diff --git a/Src/FDO/DomainServices/DataStoreInitializationServices.cs b/Src/FDO/DomainServices/DataStoreInitializationServices.cs index ddd4df8fc7..20cb3d0c23 100644 --- a/Src/FDO/DomainServices/DataStoreInitializationServices.cs +++ b/Src/FDO/DomainServices/DataStoreInitializationServices.cs @@ -386,7 +386,7 @@ private static void FixSegmentsForScriptureParas(FdoCache cache) if (hadError) { // Tell the user that something bad happened - cache.ServiceLocator.GetInstance().ReportException(new Exception("Error during resegmentation"), false); + cache.ServiceLocator.GetInstance().ReportException(new Exception("Error during resegmentation"), false); } } diff --git a/Src/FDO/DomainServices/DomainObjectServices.cs b/Src/FDO/DomainServices/DomainObjectServices.cs index 1ed7984857..f12d04a377 100644 --- a/Src/FDO/DomainServices/DomainObjectServices.cs +++ b/Src/FDO/DomainServices/DomainObjectServices.cs @@ -478,7 +478,7 @@ internal static void AdjustObjectsInArchivedBook(IScrBook book, IScrBook archive BCVRef.MakeReferenceString(startRef, endRef, ":", "-") + " with guid " + guid + " does not have a corresponding footnote object owned by " + book.BookId + " or refers to a footnote that is owned by another ORC that occurs earlier."; - serviceLocator.GetInstance().ReportException(new Exception(sMsg), false); + serviceLocator.GetInstance().ReportException(new Exception(sMsg), false); break; } Logger.WriteEvent("Footnotes out of order in " + book.BookId + ". Expected footnote with guid " + guid + @@ -532,7 +532,7 @@ internal static void AdjustObjectsInArchivedBook(IScrBook book, IScrBook archive { string sMsg = (archivedBook.FootnotesOS.Count - iFootnote) + " footnote(s) in " + book.BookId + " did not correspond to any owned footnotes in the vernacular text of that book. They have been moved to the end of the footnote sequence."; - serviceLocator.GetInstance().ReportException(new Exception(sMsg), false); + serviceLocator.GetInstance().ReportException(new Exception(sMsg), false); } } diff --git a/Src/FDO/DomainServices/FwStyleSheet.cs b/Src/FDO/DomainServices/FwStyleSheet.cs index b64c286070..5a57324ed7 100644 --- a/Src/FDO/DomainServices/FwStyleSheet.cs +++ b/Src/FDO/DomainServices/FwStyleSheet.cs @@ -927,7 +927,7 @@ private LgCharRenderProps GetStyleChrps(string stylename, int ws, ILgWritingSyst // that the property store does not implement IVwPropertyStore. See FWR-1918. // Some more sophisticated trick may be needed if it is ever the case that the stylesheet // is NOT created on the main UI thread. - return m_fdoCache.ServiceLocator.GetInstance().SynchronizeInvoke.Invoke(() => GetChrps(ws, ttp, wsf)); + return m_fdoCache.ServiceLocator.GetInstance().SynchronizeInvoke.Invoke(() => GetChrps(ws, ttp, wsf)); } /// ------------------------------------------------------------------------------------ diff --git a/Src/FDO/DomainServices/ScrSfFileList.cs b/Src/FDO/DomainServices/ScrSfFileList.cs index d84ae41e50..6bb9a991aa 100644 --- a/Src/FDO/DomainServices/ScrSfFileList.cs +++ b/Src/FDO/DomainServices/ScrSfFileList.cs @@ -16,10 +16,8 @@ using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; -using System.Windows.Forms; using SIL.FieldWorks.Common.ScriptureUtils; using SILUBS.SharedScrUtils; -using SIL.Utils; namespace SIL.FieldWorks.FDO.DomainServices { @@ -87,7 +85,6 @@ public class ScrSfFileList : ArrayList /// An Overlapping File Resolver /// ------------------------------------------------------------------------------------ public ScrSfFileList(IOverlappingFileResolver resolver) - : base() { m_resolver = resolver; } @@ -105,13 +102,12 @@ public ScrSfFileList(IOverlappingFileResolver resolver) /// in the middle of lines. (Toolbox dictates that fields tagged with backslash markers /// must start on a new line, but Paratext considers all backslashes in the data to be /// SF markers.) - /// The path of the application help file. /// ------------------------------------------------------------------------------------ public ScrSfFileList(IScrImportSFFiles source, ScrMappingList mappingList, - ImportDomain importDomain, bool scanInlineBackslashMarkers, string helpFile) + ImportDomain importDomain, bool scanInlineBackslashMarkers) : this(null) { - List deleteList = new List(); + var deleteList = new List(); // Load the files into an in-memory list foreach (ICmFile file in source.FilesOC) { @@ -123,8 +119,10 @@ public ScrSfFileList(IScrImportSFFiles source, ScrMappingList mappingList, } catch (ScriptureUtilsException e) { - MessageBoxUtils.Show(string.Format(ScrFdoResources.kstidImportBadFile, e.Message), "", MessageBoxButtons.OK, - MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, 0, helpFile, HelpNavigator.Topic, e.HelpTopic); + var userAction = source.Services.GetInstance(); + userAction.DisplayMessage(MessageType.Error, string.Format(ScrFdoResources.kstidImportBadFile, e.Message), Strings.ksErrorCaption, e.HelpTopic); + //MessageBoxUtils.Show(, "", MessageBoxButtons.OK, + // MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, 0, helpFile, HelpNavigator.Topic, e.HelpTopic); deleteList.Add(file); } } diff --git a/Src/FDO/FDO.csproj b/Src/FDO/FDO.csproj index 98eb94c80f..6924b4d0ab 100644 --- a/Src/FDO/FDO.csproj +++ b/Src/FDO/FDO.csproj @@ -375,8 +375,8 @@ - - + + diff --git a/Src/FDO/FDOTests/ClientServerServicesTests.cs b/Src/FDO/FDOTests/ClientServerServicesTests.cs index 78e8f3d47e..b9b0ed84fa 100644 --- a/Src/FDO/FDOTests/ClientServerServicesTests.cs +++ b/Src/FDO/FDOTests/ClientServerServicesTests.cs @@ -25,7 +25,7 @@ public class ClientServerServicesTests : BaseTest private IThreadedProgress m_progress; - private IFdoUserAction m_userAction; + private IFdoUI m_ui; /// [SetUp] @@ -48,7 +48,7 @@ public void StartFwRemoteDatabaseConnector() m_progress = new DummyProgressDlg(); - m_userAction = new DummyFdoUserAction(); + m_ui = new DummyFdoUI(); } /// @@ -82,7 +82,7 @@ public void ProjectNames_NullServer_ThrowsArgumentExeception() [Test] public void ProjectNames_LocalhostServiceIsRunning_ProjectsReturned() { - ClientServerServices.Current.Local.SetProjectSharing(true, m_progress, m_userAction); + ClientServerServices.Current.Local.SetProjectSharing(true, m_progress, m_ui); using (var db4OServerFile = new TemporaryDb4OServerFile(m_db4OServerInfo)) { @@ -99,9 +99,9 @@ public void ProjectNames_LocalhostServiceIsRunning_ProjectsReturned() [Test] public void ShareMyProjects_TurningShareMyProjectOff_ShareMyProjectsReturnedFalse() { - ClientServerServices.Current.Local.SetProjectSharing(true, m_progress, m_userAction); + ClientServerServices.Current.Local.SetProjectSharing(true, m_progress, m_ui); - Assert.IsTrue(ClientServerServices.Current.Local.SetProjectSharing(false, m_progress, m_userAction)); + Assert.IsTrue(ClientServerServices.Current.Local.SetProjectSharing(false, m_progress, m_ui)); Assert.AreEqual(false, ClientServerServices.Current.Local.ShareMyProjects); } @@ -109,9 +109,9 @@ public void ShareMyProjects_TurningShareMyProjectOff_ShareMyProjectsReturnedFals [Test] public void ShareMyProjects_TurningShareMyProjectOn_ShareMyProjectsReturnedTrue() { - ClientServerServices.Current.Local.SetProjectSharing(false, m_progress, m_userAction); + ClientServerServices.Current.Local.SetProjectSharing(false, m_progress, m_ui); - Assert.IsTrue(ClientServerServices.Current.Local.SetProjectSharing(true, m_progress, m_userAction)); + Assert.IsTrue(ClientServerServices.Current.Local.SetProjectSharing(true, m_progress, m_ui)); Assert.IsTrue(Db4OLocalClientServerServices.LocalDb4OServerInfoConnection.AreProjectShared()); Assert.IsFalse(ClientServerServices.Current.Local.ShareMyProjects, "ShareMyProjects should not be true unless HKCU projects dir same as HKLM"); var temp = DirectoryFinder.ProjectsDirectory; @@ -131,7 +131,7 @@ public void ConvertToCurrentBackend_ConvertFromFwDataToClientServer_ValidFwDataF [Test] public void IdForLocalProject_SimpleNameProjectsAreNotShared_ReturnedFilenameHasFwdataExtenstionAndExistsInProjectDirectory() { - ClientServerServices.Current.Local.SetProjectSharing(false, m_progress, m_userAction); + ClientServerServices.Current.Local.SetProjectSharing(false, m_progress, m_ui); string filename = ClientServerServices.Current.Local.IdForLocalProject("tom"); // Assert ends with .fwdata diff --git a/Src/FDO/FDOTests/DummyFdoUserAction.cs b/Src/FDO/FDOTests/DummyFdoUI.cs similarity index 95% rename from Src/FDO/FDOTests/DummyFdoUserAction.cs rename to Src/FDO/FDOTests/DummyFdoUI.cs index bd9800b840..178f6d09cd 100644 --- a/Src/FDO/FDOTests/DummyFdoUserAction.cs +++ b/Src/FDO/FDOTests/DummyFdoUI.cs @@ -21,7 +21,7 @@ namespace SIL.FieldWorks.FDO.FDOTests /// [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", Justification="m_threadHelper is a singleton and disposed by the SingletonsContainer")] - public class DummyFdoUserAction : IFdoUserAction + public class DummyFdoUI : IFdoUI { private readonly ThreadHelper m_threadHelper = SingletonsContainer.Get(); @@ -101,8 +101,8 @@ public YesNoCancel CannotRestoreLinkedFilesToOriginalLocation() /// /// /// - /// - public void DisplayMessage(MessageType type, string message, string caption) + /// + public void DisplayMessage(MessageType type, string message, string caption, string helpTopic) { throw new NotImplementedException(); } @@ -144,6 +144,15 @@ public bool OfferToRestore(string projectPath, string backupPath) throw new NotImplementedException(); } + /// + /// Exits the application. + /// + /// + public void Exit() + { + throw new NotImplementedException(); + } + /// /// Present a message to the user and allow the options to Retry or Cancel /// diff --git a/Src/FDO/FDOTests/FDOTests.csproj b/Src/FDO/FDOTests/FDOTests.csproj index 1ee3c244e4..efb2be7775 100644 --- a/Src/FDO/FDOTests/FDOTests.csproj +++ b/Src/FDO/FDOTests/FDOTests.csproj @@ -299,7 +299,7 @@ - + diff --git a/Src/FDO/FDOTests/FdoCacheTests.cs b/Src/FDO/FDOTests/FdoCacheTests.cs index f13c60ef1d..c7a974bf06 100644 --- a/Src/FDO/FDOTests/FdoCacheTests.cs +++ b/Src/FDO/FDOTests/FdoCacheTests.cs @@ -35,7 +35,7 @@ namespace SIL.FieldWorks.FDO.CoreTests.FdoCacheTests public class FdoCacheTests : MemoryOnlyBackendProviderTestBase { private string m_oldProjectDirectory; - private IFdoUserAction m_userAction; + private IFdoUI m_ui; /// Setup for db4o client server tests. public override void FixtureSetup() @@ -46,7 +46,7 @@ public override void FixtureSetup() DirectoryFinder.ProjectsDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); Directory.CreateDirectory(DirectoryFinder.ProjectsDirectory); - m_userAction = new DummyFdoUserAction(); + m_ui = new DummyFdoUI(); try { @@ -87,7 +87,7 @@ public void CreateNewLangProject_DbFilesExist() using (new DummyFileMaker(Path.Combine(DirectoryFinder.ProjectsDirectory, "Gumby", DirectoryFinder.GetXmlDataFileName("Gumby")))) { using (var threadHelper = new ThreadHelper()) - FdoCache.CreateNewLangProj(new DummyProgressDlg(), "Gumby", threadHelper, new DummyFdoUserAction()); + FdoCache.CreateNewLangProj(new DummyProgressDlg(), "Gumby", threadHelper, new DummyFdoUI()); } } finally @@ -117,7 +117,7 @@ public void CreateNewLangProject_NameWithSingleQuote() { string dbFileName; using (var threadHelper = new ThreadHelper()) - dbFileName = FdoCache.CreateNewLangProj(new DummyProgressDlg(), dbName, threadHelper, new DummyFdoUserAction()); + dbFileName = FdoCache.CreateNewLangProj(new DummyProgressDlg(), dbName, threadHelper, new DummyFdoUI()); currentDirs = new List(Directory.GetDirectories(DirectoryFinder.ProjectsDirectory)); if (currentDirs.Contains(writingSystemsCommonDir) && !expectedDirs.Contains(writingSystemsCommonDir)) @@ -148,9 +148,9 @@ public void CreateNewLangProject_AnthropologyCategoriesExist() // create project string dbFileName; using (var threadHelper = new ThreadHelper()) - dbFileName = FdoCache.CreateNewLangProj(new DummyProgressDlg(), dbName, threadHelper, new DummyFdoUserAction()); + dbFileName = FdoCache.CreateNewLangProj(new DummyProgressDlg(), dbName, threadHelper, new DummyFdoUI()); - using (var cache = FdoCache.CreateCacheFromLocalProjectFile(dbFileName, "en", new DummyProgressDlg(), m_userAction)) + using (var cache = FdoCache.CreateCacheFromLocalProjectFile(dbFileName, "en", new DummyProgressDlg(), m_ui)) { Assert.AreEqual(Strings.ksAnthropologyCategories, cache.LangProject.AnthroListOA.Name.UiString, "Anthropology Categories list was not properly initialized."); @@ -220,7 +220,7 @@ public void ChangingLangProjDefaultVernWs_ChangesCacheDefaultVernWs() { using ( var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", m_userAction)) + "en", "fr", "en", m_ui)) { var wsFr = cache.DefaultVernWs; Assert.That(cache.LangProject.DefaultVernacularWritingSystem.Handle, Is.EqualTo(wsFr)); @@ -253,7 +253,7 @@ public void ChangingLangProjDefaultAnalysisWs_ChangesCacheDefaultAnalWs() { using ( var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", m_userAction)) + "en", "fr", "en", m_ui)) { var wsEn = cache.DefaultAnalWs; Assert.That(cache.LangProject.DefaultAnalysisWritingSystem.Handle, Is.EqualTo(wsEn)); @@ -287,7 +287,7 @@ public void ChangingLangProjDefaultPronunciationWs_ChangesCacheDefaultPronunciat { using ( var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", m_userAction)) + "en", "fr", "en", m_ui)) { var wsFr = cache.DefaultPronunciationWs; Assert.That(cache.LangProject.DefaultPronunciationWritingSystem.Handle, Is.EqualTo(wsFr)); @@ -337,7 +337,7 @@ public void ChangingLangProjDefaultPronunciationWs_ChangesCacheDefaultPronunciat [TestFixture] public class FdoCacheDisposedTests: BaseTest { - private readonly IFdoUserAction m_userAction = new DummyFdoUserAction(); + private readonly IFdoUI m_ui = new DummyFdoUI(); /// /// Make sure the CheckDisposed method works. @@ -348,7 +348,7 @@ public void CacheCheckDisposedTest() { // This can't be in the minimalist class, because it disposes the cache. var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", m_userAction); + "en", "fr", "en", m_ui); // Init backend data provider var dataSetup = cache.ServiceLocator.GetInstance(); dataSetup.LoadDomain(BackendBulkLoadDomain.All); @@ -364,7 +364,7 @@ public void CacheIsDisposedTest() { // This can't be in the minimalist class, because it disposes the cache. var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", m_userAction); + "en", "fr", "en", m_ui); // Init backend data provider var dataSetup = cache.ServiceLocator.GetInstance(); dataSetup.LoadDomain(BackendBulkLoadDomain.All); @@ -380,7 +380,7 @@ public void CacheIsDisposedTest() public void CacheDisposedForFDOObject() { var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", m_userAction); + "en", "fr", "en", m_ui); // Init backend data provider var dataSetup = cache.ServiceLocator.GetInstance(); dataSetup.LoadDomain(BackendBulkLoadDomain.All); @@ -396,7 +396,7 @@ public void CacheDisposedForFDOObject() public void FDOObjectDeleted() { using (var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", m_userAction)) + "en", "fr", "en", m_ui)) { // Init backend data provider var dataSetup = cache.ServiceLocator.GetInstance(); @@ -419,7 +419,7 @@ public void NumberOfRemoteClients_NotClientServer_ReturnsZero() { using ( var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", m_userAction)) + "en", "fr", "en", m_ui)) { Assert.AreEqual(0, cache.NumberOfRemoteClients); } diff --git a/Src/FDO/FDOTests/FdoScriptureTests.cs b/Src/FDO/FDOTests/FdoScriptureTests.cs index f5fb39648e..69d3b29b37 100644 --- a/Src/FDO/FDOTests/FdoScriptureTests.cs +++ b/Src/FDO/FDOTests/FdoScriptureTests.cs @@ -2587,9 +2587,9 @@ public void SavedVersion_BogusUnownedFootnoteORC() Assert.AreEqual(StringUtils.kChObject, sOrc[0]); // Expecting error to have been thrown in ScriptureServices.AdjustObjectsInArchivedBook, so now we make sure the error is the one expected. - var userAction = Cache.ServiceLocator.GetInstance(); - Assert.IsTrue(userAction is DummyFdoUserAction); - string sWarningMessage = ((DummyFdoUserAction)userAction).ErrorMessage; + var userAction = Cache.ServiceLocator.GetInstance(); + Assert.IsTrue(userAction is DummyFdoUI); + string sWarningMessage = ((DummyFdoUI)userAction).ErrorMessage; Assert.AreEqual("1 footnote(s) in HEB did not correspond to any owned footnotes in the vernacular text of that book. They have been moved to the end of the footnote sequence.", sWarningMessage); } diff --git a/Src/FDO/FDOTests/FdoTestBase.cs b/Src/FDO/FDOTests/FdoTestBase.cs index 9e79d19bdb..574579ca4a 100644 --- a/Src/FDO/FDOTests/FdoTestBase.cs +++ b/Src/FDO/FDOTests/FdoTestBase.cs @@ -174,8 +174,8 @@ public virtual void TestTearDown() /// a working FdoCache protected FdoCache BootstrapSystem(IProjectIdentifier projectId, BackendBulkLoadDomain loadType) { - var retval = m_internalRestart ? FdoCache.CreateCacheFromExistingData(projectId, "en", new DummyProgressDlg(), new DummyFdoUserAction()) : - FdoCache.CreateCacheWithNewBlankLangProj(projectId, "en", "fr", "en", new DummyFdoUserAction()); + var retval = m_internalRestart ? FdoCache.CreateCacheFromExistingData(projectId, "en", new DummyProgressDlg(), new DummyFdoUI()) : + FdoCache.CreateCacheWithNewBlankLangProj(projectId, "en", "fr", "en", new DummyFdoUI()); var dataSetup = retval.ServiceLocator.GetInstance(); dataSetup.LoadDomain(loadType); return retval; diff --git a/Src/FDO/FDOTests/PersistingBackendProviderTests.cs b/Src/FDO/FDOTests/PersistingBackendProviderTests.cs index c303286c09..81723e0344 100644 --- a/Src/FDO/FDOTests/PersistingBackendProviderTests.cs +++ b/Src/FDO/FDOTests/PersistingBackendProviderTests.cs @@ -614,7 +614,7 @@ public void OnlyOneCacheAllowed() private FdoCache OpenExistingFile(string filename) { return FdoCache.CreateCacheFromExistingData( - new TestProjectId(FDOBackendProviderType.kXMLWithMemoryOnlyWsMgr, filename), "en", new DummyProgressDlg(), new DummyFdoUserAction()); + new TestProjectId(FDOBackendProviderType.kXMLWithMemoryOnlyWsMgr, filename), "en", new DummyProgressDlg(), new DummyFdoUI()); } /// ------------------------------------------------------------------------------------ @@ -750,7 +750,7 @@ internal class MockXMLBackendProvider : XMLBackendProvider public MockXMLBackendProvider(FdoCache cache, string projName): base(cache, new IdentityMap((IFwMetaDataCacheManaged)cache.MetaDataCache), new CmObjectSurrogateFactory(cache), (IFwMetaDataCacheManagedInternal)cache.MetaDataCache, - new FdoDataMigrationManager(), new DummyFdoUserAction()) + new FdoDataMigrationManager(), new DummyFdoUI()) { Project = projName; Cache = cache; diff --git a/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs b/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs index 99aeeb6f68..5a56f71135 100644 --- a/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs +++ b/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs @@ -206,7 +206,7 @@ public void PortAllBEPsTestsUsingAnAlreadyOpenedSource( var sourceGuids = new List(); using (var sourceCache = FdoCache.CreateCacheWithNewBlankLangProj( new TestProjectId(sourceBackendStartupParameters.ProjectId.Type, - sourceBackendStartupParameters.ProjectId.Path), "en", "fr", "en", new DummyFdoUserAction())) + sourceBackendStartupParameters.ProjectId.Path), "en", "fr", "en", new DummyFdoUI())) { // BEP is a singleton, so we shouldn't call Dispose on it. This will be done // by service locator. @@ -221,7 +221,7 @@ public void PortAllBEPsTestsUsingAnAlreadyOpenedSource( // Migrate source data to new BEP. using (var targetCache = FdoCache.CreateCacheCopy( new TestProjectId(targetBackendStartupParameters.ProjectId.Type, - targetBackendStartupParameters.ProjectId.Path), "en", sourceCache, new DummyFdoUserAction())) + targetBackendStartupParameters.ProjectId.Path), "en", sourceCache, new DummyFdoUI())) { // BEP is a singleton, so we shouldn't call Dispose on it. This will be done // by service locator. @@ -270,7 +270,7 @@ public void PortAllBEPsTestsUsingAnUnopenedSource( sourceBackendStartupParameters.ProjectId.Path); IThreadedProgress progressDlg = new DummyProgressDlg(); using (FdoCache sourceCache = FdoCache.CreateCacheWithNewBlankLangProj( - projId, "en", "fr", "en", new DummyFdoUserAction())) + projId, "en", "fr", "en", new DummyFdoUI())) { // BEP is a singleton, so we shouldn't call Dispose on it. This will be done // by service locator. @@ -284,7 +284,7 @@ public void PortAllBEPsTestsUsingAnUnopenedSource( // Migrate source data to new BEP. progressDlg = new DummyProgressDlg(); using (var targetCache = FdoCache.CreateCacheWithNoLangProj( - new TestProjectId(targetBackendStartupParameters.ProjectId.Type, null), "en", new DummyFdoUserAction())) + new TestProjectId(targetBackendStartupParameters.ProjectId.Type, null), "en", new DummyFdoUI())) { // BEP is a singleton, so we shouldn't call Dispose on it. This will be done // by service locator. diff --git a/Src/FDO/FDOTests/XmlImportDataTests.cs b/Src/FDO/FDOTests/XmlImportDataTests.cs index cee95ea23e..6b4e81f977 100644 --- a/Src/FDO/FDOTests/XmlImportDataTests.cs +++ b/Src/FDO/FDOTests/XmlImportDataTests.cs @@ -54,7 +54,7 @@ public void CreateTestCache() { m_now = DateTime.Now; m_cache = FdoCache.CreateCacheWithNewBlankLangProj( - new TestProjectId(FDOBackendProviderType.kMemoryOnly, "MemoryOnly.mem"), "en", "fr", "en", new DummyFdoUserAction()); + new TestProjectId(FDOBackendProviderType.kMemoryOnly, "MemoryOnly.mem"), "en", "fr", "en", new DummyFdoUI()); IDataSetup dataSetup = m_cache.ServiceLocator.GetInstance(); dataSetup.LoadDomain(BackendBulkLoadDomain.All); if (m_cache.LangProject != null) diff --git a/Src/FDO/FDOTests/XmlListTests.cs b/Src/FDO/FDOTests/XmlListTests.cs index 3a38a5b942..c3960de1a0 100644 --- a/Src/FDO/FDOTests/XmlListTests.cs +++ b/Src/FDO/FDOTests/XmlListTests.cs @@ -599,7 +599,7 @@ public class XmlListTests : BaseTest public void CreateMockCache() { m_cache = FdoCache.CreateCacheWithNewBlankLangProj( - new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "es", "en", new DummyFdoUserAction()); + new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "es", "en", new DummyFdoUI()); } /// diff --git a/Src/FDO/FDOTests/XmlTranslatedListsTests.cs b/Src/FDO/FDOTests/XmlTranslatedListsTests.cs index 6de8400bdf..64af184643 100644 --- a/Src/FDO/FDOTests/XmlTranslatedListsTests.cs +++ b/Src/FDO/FDOTests/XmlTranslatedListsTests.cs @@ -644,7 +644,7 @@ public class XmlTranslatedListsTests : BaseTest public void CreateMockCache() { m_cache = FdoCache.CreateCacheWithNewBlankLangProj( - new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "es", "en", new DummyFdoUserAction()); + new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "es", "en", new DummyFdoUI()); var xl = new XmlList(); using (var reader = new StringReader(XmlListTests.s_ksPartsOfSpeechXml)) diff --git a/Src/FDO/FdoInterfaceAdditions.cs b/Src/FDO/FdoInterfaceAdditions.cs index 23e0f9a54f..848698b142 100644 --- a/Src/FDO/FdoInterfaceAdditions.cs +++ b/Src/FDO/FdoInterfaceAdditions.cs @@ -4399,16 +4399,6 @@ IVwStylesheet StyleSheet set; } - /// ------------------------------------------------------------------------------------ - /// - /// Sets the help file used in a message box if an error occurs. - /// - /// ------------------------------------------------------------------------------------ - string HelpFile - { - set; - } - /// ------------------------------------------------------------------------------------ /// /// Sets the Overlapping File Resolver diff --git a/Src/FDO/IFdoUserAction.cs b/Src/FDO/IFdoUI.cs similarity index 96% rename from Src/FDO/IFdoUserAction.cs rename to Src/FDO/IFdoUI.cs index 74201dfd88..4e2e9b9bd6 100644 --- a/Src/FDO/IFdoUserAction.cs +++ b/Src/FDO/IFdoUI.cs @@ -15,9 +15,9 @@ namespace SIL.FieldWorks.FDO { /// - /// Used for getting user feedback while processing FDO requests + /// This interface abstracts the UI from FDO. /// - public interface IFdoUserAction + public interface IFdoUI { /// /// Gets the object that is used to invoke methods on the main UI thread. @@ -63,7 +63,7 @@ public interface IFdoUserAction /// /// Displays information to the user /// - void DisplayMessage(MessageType type, string message, string caption); + void DisplayMessage(MessageType type, string message, string caption, string helpTopic); /// /// Show a dialog or output to the error log, as appropriate. @@ -88,7 +88,7 @@ public interface IFdoUserAction /// The caption. /// True to retry. False otherwise bool Retry(string msg, string caption); - + /// /// Ask user if they wish to restore an XML project from a backup project file. /// @@ -97,6 +97,10 @@ public interface IFdoUserAction /// bool OfferToRestore(string projectPath, string backupPath); + /// + /// Exits the application. + /// + void Exit(); } /// diff --git a/Src/FDO/IOC/FdoServiceLocatorFactory.cs b/Src/FDO/IOC/FdoServiceLocatorFactory.cs index 8730924ca2..99dc9de820 100644 --- a/Src/FDO/IOC/FdoServiceLocatorFactory.cs +++ b/Src/FDO/IOC/FdoServiceLocatorFactory.cs @@ -38,18 +38,18 @@ namespace SIL.FieldWorks.FDO.IOC internal sealed partial class FdoServiceLocatorFactory : IServiceLocatorBootstrapper { private readonly FDOBackendProviderType m_backendProviderType; - private readonly IFdoUserAction m_userAction; + private readonly IFdoUI m_ui; /// /// Constructor /// /// Type of backend provider to create. - /// The user action implementation + /// The user action implementation /// ------------------------------------------------------------------------------------ - internal FdoServiceLocatorFactory(FDOBackendProviderType backendProviderType, IFdoUserAction userAction) + internal FdoServiceLocatorFactory(FDOBackendProviderType backendProviderType, IFdoUI ui) { m_backendProviderType = backendProviderType; - m_userAction = userAction; + m_ui = ui; } #region Implementation of IServiceLocatorBootstrapper @@ -247,8 +247,8 @@ public IServiceLocator CreateServiceLocator() .Use(c => c.GetInstance().Singleton); registry - .For() - .Use(m_userAction); + .For() + .Use(m_ui); // ================================================================================= // Don't add COM object to the registry. StructureMap does not properly release COM diff --git a/Src/FDO/Infrastructure/Impl/ClientServerBackendProvider.cs b/Src/FDO/Infrastructure/Impl/ClientServerBackendProvider.cs index 797a635184..0442eaba66 100644 --- a/Src/FDO/Infrastructure/Impl/ClientServerBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/ClientServerBackendProvider.cs @@ -24,7 +24,7 @@ protected ClientServerBackendProvider(FdoCache cache, ICmObjectSurrogateFactory surrogateFactory, IFwMetaDataCacheManagedInternal mdc, IDataMigrationManager dataMigrationManager, - IFdoUserAction userAction) : base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager, userAction) + IFdoUI ui) : base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager, ui) { } diff --git a/Src/FDO/Infrastructure/Impl/CmObjectSurrogate.cs b/Src/FDO/Infrastructure/Impl/CmObjectSurrogate.cs index fa36978624..a34b553f91 100644 --- a/Src/FDO/Infrastructure/Impl/CmObjectSurrogate.cs +++ b/Src/FDO/Infrastructure/Impl/CmObjectSurrogate.cs @@ -547,8 +547,8 @@ ICmObject ICmObjectOrSurrogate.Object const int nLines = 40; if (lines.Length > nLines) msg = String.Join("\n", lines.Take(nLines).ToArray()) + "\n..."; - var userAction = m_cache.ServiceLocator.GetInstance(); - userAction.DisplayMessage(MessageType.Error, msg, Strings.ksErrorCaption); + var userAction = m_cache.ServiceLocator.GetInstance(); + userAction.DisplayMessage(MessageType.Error, msg, Strings.ksErrorCaption, null); userAction.ReportException(new Exception(fullMsg, e), true); } return m_object; diff --git a/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs b/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs index a37dd19f3c..1a2b8d5af3 100644 --- a/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs @@ -18,7 +18,6 @@ using System.Net.Sockets; using System.Runtime.Remoting; using System.Threading; -using System.Windows.Forms; using Db4objects.Db4o; using Db4objects.Db4o.Config; using Db4objects.Db4o.Config.Encoding; @@ -87,15 +86,15 @@ internal class Db4oClientServerBackendProvider : ClientServerBackendProvider /// /// /// - /// + /// public Db4oClientServerBackendProvider( FdoCache cache, IdentityMap identityMap, ICmObjectSurrogateFactory surrogateFactory, IFwMetaDataCacheManagedInternal mdc, IDataMigrationManager dataMigrationManager, - IFdoUserAction userAction) - : base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager, userAction) + IFdoUI ui) + : base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager, ui) { } @@ -521,10 +520,7 @@ private bool GetCommitLock(bool fWaitForCommitLock) while (!m_dbStore.Ext().SetSemaphore(kCommitLock, 3000)) { if (fWaitForCommitLock) - { - ThreadHelper.ShowMessageBox(null, Strings.ksOtherClientsAreWriting, Strings.ksShortDelayCaption, - MessageBoxButtons.OK, MessageBoxIcon.None); - } + m_ui.DisplayMessage(MessageType.Info, Strings.ksOtherClientsAreWriting, Strings.ksShortDelayCaption, null); else return false; } @@ -745,7 +741,7 @@ private bool ResumeDb4oConnectionAskingUser() return true; } - while (m_userAction.ConnectionLost()) + while (m_ui.ConnectionLost()) { // if re-connection failed allow user to keep retrying as many times as they want. if (ResumeDb4oConnection()) @@ -753,7 +749,7 @@ private bool ResumeDb4oConnectionAskingUser() } if (m_dbStore == null) - System.Windows.Forms.Application.Exit(); + m_ui.Exit(); // return true if connection re-established return (m_dbStore != null); diff --git a/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs b/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs index 85bbf6b898..79e7ae0386 100644 --- a/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs @@ -38,7 +38,7 @@ internal abstract partial class FDOBackendProvider : IDataSetup, IDataReader, ID protected readonly FdoCache m_cache; protected readonly IFwMetaDataCacheManagedInternal m_mdcInternal; private readonly IDataMigrationManager m_dataMigrationManager; - protected readonly IFdoUserAction m_userAction; + protected readonly IFdoUI m_ui; protected readonly Dictionary m_extantCustomFields = new Dictionary(); protected int m_modelVersionOverride = ModelVersion; private readonly List m_loadDomainThreads = new List(); @@ -50,13 +50,13 @@ internal abstract partial class FDOBackendProvider : IDataSetup, IDataReader, ID /// protected FDOBackendProvider(FdoCache cache, IdentityMap identityMap, ICmObjectSurrogateFactory surrogateFactory, IFwMetaDataCacheManagedInternal mdc, IDataMigrationManager dataMigrationManager, - IFdoUserAction userAction) + IFdoUI ui) { if (cache == null) throw new ArgumentNullException("cache"); if (identityMap == null) throw new ArgumentNullException("identityMap"); if (surrogateFactory == null) throw new ArgumentNullException("surrogateFactory"); if (dataMigrationManager == null) throw new ArgumentNullException("dataMigrationManager"); - if (userAction == null) throw new ArgumentNullException("userAction"); + if (ui == null) throw new ArgumentNullException("ui"); m_cache = cache; m_cache.Disposing += OnCacheDisposing; @@ -64,7 +64,7 @@ protected FDOBackendProvider(FdoCache cache, IdentityMap identityMap, m_surrogateFactory = surrogateFactory; m_mdcInternal = mdc; m_dataMigrationManager = dataMigrationManager; - m_userAction = userAction; + m_ui = ui; } @@ -820,7 +820,7 @@ public void InitializeFromSource(IProjectIdentifier projectId, // 3. Startup source BEP, but without instantiating any FDO objects (surrogates, are loaded). using (var sourceCache = FdoCache.CreateCacheFromExistingData(sourceDataStore.ProjectId, - userWsIcuLocale, progressDlg, m_userAction)) + userWsIcuLocale, progressDlg, m_ui)) { // 4. Do the port. var sourceCacheServLoc = sourceCache.ServiceLocator; diff --git a/Src/FDO/Infrastructure/Impl/MemoryOnlyBackendProvider.cs b/Src/FDO/Infrastructure/Impl/MemoryOnlyBackendProvider.cs index defa13179e..5f28588392 100644 --- a/Src/FDO/Infrastructure/Impl/MemoryOnlyBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/MemoryOnlyBackendProvider.cs @@ -27,8 +27,8 @@ internal sealed class MemoryOnlyBackendProvider : FDOBackendProvider /// Constructor. /// internal MemoryOnlyBackendProvider(FdoCache cache, IdentityMap identityMap, ICmObjectSurrogateFactory surrogateFactory, - IFwMetaDataCacheManagedInternal mdc, IDataMigrationManager dataMigrationManager, IFdoUserAction userAction) - : base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager, userAction) + IFwMetaDataCacheManagedInternal mdc, IDataMigrationManager dataMigrationManager, IFdoUI ui) + : base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager, ui) { } diff --git a/Src/FDO/Infrastructure/Impl/UndoStack.cs b/Src/FDO/Infrastructure/Impl/UndoStack.cs index f7e87f8171..6b7332bc5b 100644 --- a/Src/FDO/Infrastructure/Impl/UndoStack.cs +++ b/Src/FDO/Infrastructure/Impl/UndoStack.cs @@ -96,7 +96,7 @@ internal sealed class UndoStack : IActionHandler, IActionHandlerExtensions private bool m_createMarkIfNeeded; internal FdoUnitOfWork m_currentBundle; private readonly UnitOfWorkService m_uowService; - private readonly IFdoUserAction m_userAction; + private readonly IFdoUI m_ui; // Positive values count unsaved bundles in m_undoBundles. // Negative values count unsaved bundles in m_redoBundles, that is, things Undone since the last Save. private int m_countUnsavedBundles; @@ -105,10 +105,10 @@ internal sealed class UndoStack : IActionHandler, IActionHandlerExtensions #endregion #region Constructor - public UndoStack(UnitOfWorkService uowService, IFdoUserAction userAction) + public UndoStack(UnitOfWorkService uowService, IFdoUI ui) { m_uowService = uowService; - m_userAction = userAction; + m_ui = ui; m_undoBundles = new Stack(); m_redoBundles = new Stack(); m_currentBundle = null; @@ -371,7 +371,7 @@ private void EndUndoTaskCommon(bool updateDateModified) /// ------------------------------------------------------------------------------------ private void DoTasksForEndOfPropChanged(FdoUnitOfWork uow, bool fromUndoRedo) { - m_userAction.SynchronizeInvoke.Invoke(() => + m_ui.SynchronizeInvoke.Invoke(() => { if (!fromUndoRedo) { diff --git a/Src/FDO/Infrastructure/Impl/UnitOfWorkService.cs b/Src/FDO/Infrastructure/Impl/UnitOfWorkService.cs index 3057147ed0..1d64cad15f 100644 --- a/Src/FDO/Infrastructure/Impl/UnitOfWorkService.cs +++ b/Src/FDO/Infrastructure/Impl/UnitOfWorkService.cs @@ -108,7 +108,7 @@ internal enum FdoBusinessTransactionState private readonly IDataStorer m_dataStorer; private readonly IdentityMap m_identityMap; - private readonly IFdoUserAction m_userAction; + private readonly IFdoUI m_ui; internal ICmObjectRepositoryInternal ObjectRepository { get; @@ -157,24 +157,24 @@ internal FdoBusinessTransactionState CurrentProcessingState { /// /// Constructor. /// - internal UnitOfWorkService(IDataStorer dataStorer, IdentityMap identityMap, ICmObjectRepositoryInternal objectRepository, IFdoUserAction userAction) + internal UnitOfWorkService(IDataStorer dataStorer, IdentityMap identityMap, ICmObjectRepositoryInternal objectRepository, IFdoUI ui) { if (dataStorer == null) throw new ArgumentNullException("dataStorer"); if (identityMap == null) throw new ArgumentNullException("identityMap"); if (objectRepository == null) throw new ArgumentNullException("objectRepository"); - if (userAction == null) throw new ArgumentNullException("userAction"); + if (ui == null) throw new ArgumentNullException("ui"); m_dataStorer = dataStorer; m_identityMap = identityMap; ObjectRepository = objectRepository; - m_userAction = userAction; + m_ui = ui; CurrentProcessingState = FdoBusinessTransactionState.ReadyForBeginTask; NonUndoableStack = (UndoStack)CreateUndoStack(); // Make a separate stack as the initial default. This should be mainly used in tests. // It serves to keep undoable UOWs separate from non-undoable ones, the only things ever put on the NonUndoableStack. m_currentUndoStack = m_activeUndoStack = (UndoStack)CreateUndoStack(); - m_saveTimer.SynchronizingObject = userAction.SynchronizeInvoke; + m_saveTimer.SynchronizingObject = ui.SynchronizeInvoke; m_saveTimer.Interval = 1000; m_saveTimer.Elapsed += SaveOnIdle; m_saveTimer.Start(); @@ -250,7 +250,7 @@ void SaveOnIdle(object sender, ElapsedEventArgs e) if (DateTime.Now - m_lastSave < TimeSpan.FromSeconds(10.0)) return; // Nor if it's been less than 2s since the user did something. We don't want to interrupt continuous activity. - if (DateTime.Now - m_userAction.LastActivityTime < TimeSpan.FromSeconds(2.0)) + if (DateTime.Now - m_ui.LastActivityTime < TimeSpan.FromSeconds(2.0)) return; SaveInternal(); @@ -374,7 +374,7 @@ private void SaveInternal() /// ------------------------------------------------------------------------------------ private void GetUserInputOnConflictingSave() { - if (m_userAction.ConflictingSave()) + if (m_ui.ConflictingSave()) { RevertToSavedState(); } @@ -532,7 +532,7 @@ internal void SendPropChangedNotifications(IEnumerable change // This is very likely to modify the UI, so if the UOW is not being done on the UI thread, we need // to do at least this part on that thread. One known case is a task being done in the background // thread of ProgressDialogWithTask. - m_userAction.SynchronizeInvoke.Invoke(() => + m_ui.SynchronizeInvoke.Invoke(() => { var subscribers = m_changeWatchers.ToArray(); var changes = changesEnum.ToList(); @@ -945,7 +945,7 @@ public void EndReadTask() /// public IActionHandler CreateUndoStack() { - var result = new UndoStack(this, m_userAction); + var result = new UndoStack(this, m_ui); m_undoStacks.Add(result); return result; } diff --git a/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs b/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs index 6191b2425a..e338a9cab4 100644 --- a/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs @@ -124,8 +124,8 @@ public void Combine(CommitWork work) /// internal XMLBackendProvider(FdoCache cache, IdentityMap identityMap, ICmObjectSurrogateFactory surrogateFactory, IFwMetaDataCacheManagedInternal mdc, - IDataMigrationManager dataMigrationManager, IFdoUserAction userAction) : - base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager, userAction) + IDataMigrationManager dataMigrationManager, IFdoUI ui) : + base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager, ui) { } @@ -304,7 +304,7 @@ internal virtual void ReportDuplicateGuidsIfTheyExist() sb.AppendLine(String.Format(Strings.ksDuplicateGuidsMsg2, guid)); sb.AppendLine(); } - m_cache.ServiceLocator.GetInstance().ReportDuplicateGuids(FwRegistryHelper.FieldWorksRegistryKey, "FLExErrors@sil.org", sb.ToString()); + m_cache.ServiceLocator.GetInstance().ReportDuplicateGuids(FwRegistryHelper.FieldWorksRegistryKey, "FLExErrors@sil.org", sb.ToString()); } } @@ -346,7 +346,7 @@ private void OfferToRestore(string message) string backupFilePath = Path.ChangeExtension(ProjectId.Path, "bak"); if (File.Exists(backupFilePath)) { - if (m_userAction.OfferToRestore(ProjectId.Path, backupFilePath)) + if (m_ui.OfferToRestore(ProjectId.Path, backupFilePath)) { string badFilePath = Path.ChangeExtension(ProjectId.Path, "bad"); if (File.Exists(badFilePath)) @@ -496,7 +496,7 @@ private void ReportProblem(string message, string tempPath) // Can't even clean up. Sigh. } } - m_userAction.DisplayMessage(MessageType.Error, message, Strings.ksProblemWritingFile); + m_ui.DisplayMessage(MessageType.Error, message, Strings.ksProblemWritingFile, null); } /// diff --git a/Src/FDO/SilentFdoUserAction.cs b/Src/FDO/SilentFdoUI.cs similarity index 93% rename from Src/FDO/SilentFdoUserAction.cs rename to Src/FDO/SilentFdoUI.cs index d34de816e8..a7ff8bd5e0 100644 --- a/Src/FDO/SilentFdoUserAction.cs +++ b/Src/FDO/SilentFdoUI.cs @@ -18,15 +18,15 @@ namespace SIL.FieldWorks.FDO /// Silent implementation of FdoUserAction with reasonable defaults for /// actions which should not require user intervention /// - public class SilentFdoUserAction : IFdoUserAction + public class SilentFdoUI : IFdoUI { private readonly ISynchronizeInvoke m_synchronizeInvoke; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The synchronize invoke. - public SilentFdoUserAction(ISynchronizeInvoke synchronizeInvoke) + public SilentFdoUI(ISynchronizeInvoke synchronizeInvoke) { m_synchronizeInvoke = synchronizeInvoke; } @@ -104,7 +104,8 @@ public YesNoCancel CannotRestoreLinkedFilesToOriginalLocation() /// /// /// - public void DisplayMessage(MessageType type, string message, string caption) + /// + public void DisplayMessage(MessageType type, string message, string caption, string helpTopic) { // Informational only } @@ -143,6 +144,14 @@ public bool OfferToRestore(string projectPath, string backupPath) return true; } + /// + /// Exits the application. + /// + public void Exit() + { + Environment.Exit(0); + } + /// /// Present a message to the user and allow the options to Retry or Cancel /// diff --git a/Src/FDO/fdoCache.cs b/Src/FDO/fdoCache.cs index 14b27d7bd1..5659af807a 100644 --- a/Src/FDO/fdoCache.cs +++ b/Src/FDO/fdoCache.cs @@ -95,12 +95,12 @@ public sealed partial class FdoCache /// /// Identifies the new project to create. /// The ICU locale of the default user WS. - /// + /// /// ------------------------------------------------------------------------------------ public static FdoCache CreateCacheWithNoLangProj(IProjectIdentifier projectId, - string userWsIcuLocale, IFdoUserAction userAction) + string userWsIcuLocale, IFdoUI ui) { - FdoCache createdCache = CreateCacheInternal(projectId, userAction); + FdoCache createdCache = CreateCacheInternal(projectId, ui); createdCache.FullyInitializedAndReadyToRock = true; return createdCache; } @@ -120,14 +120,14 @@ public static FdoCache CreateCacheWithNoLangProj(IProjectIdentifier projectId, /// system. /// The ICU locale of the default user writing /// system. - /// + /// /// ------------------------------------------------------------------------------------ public static FdoCache CreateCacheWithNewBlankLangProj(IProjectIdentifier projectId, string analWsIcuLocale, string vernWsIcuLocale, string userWsIcuLocale, - IFdoUserAction userAction) + IFdoUI ui) { FdoCache createdCache = CreateCacheInternal(projectId, userWsIcuLocale, - dataSetup => dataSetup.CreateNewLanguageProject(projectId), userAction); + dataSetup => dataSetup.CreateNewLanguageProject(projectId), ui); NonUndoableUnitOfWorkHelper.Do(createdCache.ActionHandlerAccessor, () => { createdCache.ServiceLocator.WritingSystems.DefaultAnalysisWritingSystem = @@ -146,14 +146,14 @@ public static FdoCache CreateCacheWithNewBlankLangProj(IProjectIdentifier projec /// Identifies the project to load. /// The ICU locale of the default user WS. /// The progress dialog box - /// + /// /// ------------------------------------------------------------------------------------ public static FdoCache CreateCacheFromExistingData(IProjectIdentifier projectId, - string userWsIcuLocale, IThreadedProgress progressDlg, IFdoUserAction userAction) + string userWsIcuLocale, IThreadedProgress progressDlg, IFdoUI ui) { return CreateCacheInternal(projectId, userWsIcuLocale, dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg), - cache => cache.Initialize(userWsIcuLocale), userAction); + cache => cache.Initialize(userWsIcuLocale), ui); } /// ------------------------------------------------------------------------------------ @@ -164,15 +164,15 @@ public static FdoCache CreateCacheFromExistingData(IProjectIdentifier projectId, /// /// /// The progress dialog box - /// + /// /// ------------------------------------------------------------------------------------ public static FdoCache CreateCacheFromLocalProjectFile(string projectPath, - string userWsIcuLocale, IThreadedProgress progressDlg, IFdoUserAction userAction) + string userWsIcuLocale, IThreadedProgress progressDlg, IFdoUI ui) { var projectId = new SimpleProjectId(FDOBackendProviderType.kXML, projectPath); return CreateCacheInternal(projectId, userWsIcuLocale, dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg), - cache => cache.Initialize(userWsIcuLocale), userAction); + cache => cache.Initialize(userWsIcuLocale), ui); } /// ------------------------------------------------------------------------------------ @@ -183,13 +183,13 @@ public static FdoCache CreateCacheFromLocalProjectFile(string projectPath, /// Identifies the project to create (i.e., the copy). /// The ICU locale of the default user WS. /// The FdoCache to copy - /// + /// /// ------------------------------------------------------------------------------------ public static FdoCache CreateCacheCopy(IProjectIdentifier projectId, - string userWsIcuLocale, FdoCache sourceCache, IFdoUserAction userAction) + string userWsIcuLocale, FdoCache sourceCache, IFdoUI ui) { return CreateCacheInternal(projectId, userWsIcuLocale, - dataSetup => dataSetup.InitializeFromSource(projectId, sourceCache), userAction); + dataSetup => dataSetup.InitializeFromSource(projectId, sourceCache), ui); } /// ------------------------------------------------------------------------------------ @@ -197,15 +197,15 @@ public static FdoCache CreateCacheCopy(IProjectIdentifier projectId, /// Creates a new FdoCache that uses a specified data provider. /// /// Identifies the project to create or load. - /// + /// /// ------------------------------------------------------------------------------------ - private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, IFdoUserAction userAction) + private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, IFdoUI ui) { FDOBackendProviderType providerType = projectId.Type; if (providerType == FDOBackendProviderType.kXMLWithMemoryOnlyWsMgr) providerType = FDOBackendProviderType.kXML; - var iocFactory = new FdoServiceLocatorFactory(providerType, userAction); + var iocFactory = new FdoServiceLocatorFactory(providerType, ui); var servLoc = (IFdoServiceLocator)iocFactory.CreateServiceLocator(); var createdCache = servLoc.GetInstance(); createdCache.m_serviceLocator = servLoc; @@ -220,12 +220,12 @@ private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, IFdoUs /// Identifies the project to create or load. /// The ICU locale of the default user WS. /// The data setup action to perform. - /// + /// /// ------------------------------------------------------------------------------------ private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, - string userWsIcuLocale, Action doThe, IFdoUserAction userAction) + string userWsIcuLocale, Action doThe, IFdoUI ui) { - return CreateCacheInternal(projectId, userWsIcuLocale, doThe, null, userAction); + return CreateCacheInternal(projectId, userWsIcuLocale, doThe, null, ui); } /// ------------------------------------------------------------------------------------ @@ -236,17 +236,17 @@ private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, /// The ICU locale of the default user WS. /// The data setup action to perform. /// The initialization step to perfrom (can be null). - /// + /// /// The newly created cache /// ------------------------------------------------------------------------------------ private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, string userWsIcuLocale, Action doThe, - Action initialize, IFdoUserAction userAction) + Action initialize, IFdoUI ui) { FDOBackendProviderType providerType = projectId.Type; bool useMemoryWsManager = (providerType == FDOBackendProviderType.kMemoryOnly || providerType == FDOBackendProviderType.kXMLWithMemoryOnlyWsMgr); - FdoCache createdCache = CreateCacheInternal(projectId, userAction); + FdoCache createdCache = CreateCacheInternal(projectId, ui); // Init backend data provider var dataSetup = createdCache.ServiceLocator.GetInstance(); @@ -361,7 +361,7 @@ private static bool IsUpdatedWsInUse(StringBuilder updatedWssInUseBuilder) /// One or more parameters, supplied in this order: /// 0. A string containing the name of the project (required); /// 1. An ISynchronizeInvoke used for invoking actions on the main UI thread (required); - /// 2. An IFdoUserAction used for soliciting user feedback during deep FDO processing (required); + /// 2. An IFdoUI used for soliciting user feedback during deep FDO processing (required); /// 3. An IWritingSystem to be used as the default analylis writing system (default: English); /// 4. An IWritingSystem to be used as the default vernacular writing system (default: French); /// 5. A string with the ICU locale of the UI writing system (default: "en"). @@ -379,7 +379,7 @@ public static string CreateNewLangProj(IThreadedProgress progressDlg, params obj if (string.IsNullOrEmpty(projectName)) throw new ArgumentNullException("parameters", "Cannot be null or empty"); var synchronizeInvoke = (ISynchronizeInvoke) parameters[1]; - var userAction = (IFdoUserAction) parameters[2]; + var userAction = (IFdoUI) parameters[2]; IWritingSystem analWrtSys = (parameters.Length > 3) ? (IWritingSystem)parameters[3] : null; IWritingSystem vernWrtSys = (parameters.Length > 4) ? (IWritingSystem)parameters[4] : null; var userIcuLocale = (parameters.Length > 5 && parameters[5] != null) ? (string)parameters[5] : "en"; @@ -403,7 +403,7 @@ public static string CreateNewLangProj(IThreadedProgress progressDlg, params obj var projectId = new SimpleProjectId(FDOBackendProviderType.kXML, dbFileName); using (var cache = CreateCacheInternal(projectId, userIcuLocale, - dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg), new SilentFdoUserAction(synchronizeInvoke))) + dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg), new SilentFdoUI(synchronizeInvoke))) { if (progressDlg != null) { diff --git a/Src/FDOBrowser/FDOBrowserForm.cs b/Src/FDOBrowser/FDOBrowserForm.cs index 9c71320c4a..887580b109 100644 --- a/Src/FDOBrowser/FDOBrowserForm.cs +++ b/Src/FDOBrowser/FDOBrowserForm.cs @@ -376,7 +376,7 @@ protected override void OpenFile(string fileName) // Init backend data provider // TODO: Get the correct ICU local for the user writing system - var userAction = new FdoUserActionWindowsForms(this, this); + var userAction = new FwFdoUI(this, this); if (isMemoryBEP) m_cache = FdoCache.CreateCacheWithNewBlankLangProj(new BrowserProjectId(bepType, null), "en", "en", "en", userAction); else diff --git a/Src/FDOBrowser/FDOClassList.cs b/Src/FDOBrowser/FDOClassList.cs index fe71b5bf4b..7c1c05d8ab 100644 --- a/Src/FDOBrowser/FDOClassList.cs +++ b/Src/FDOBrowser/FDOClassList.cs @@ -138,7 +138,7 @@ private static void LoadFDOClassNames() return; using (var threadHelper = new ThreadHelper()) - using (FdoCache cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", new SilentFdoUserAction(threadHelper))) + using (FdoCache cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", new SilentFdoUI(threadHelper))) { IFwMetaDataCacheManaged mdc = (IFwMetaDataCacheManaged)cache.MainCacheAccessor.MetaDataCache; s_allFDOClassNames = new List(); diff --git a/Src/FDOBrowser/ModelWnd.cs b/Src/FDOBrowser/ModelWnd.cs index 4d9b0d86a5..a8460719bd 100644 --- a/Src/FDOBrowser/ModelWnd.cs +++ b/Src/FDOBrowser/ModelWnd.cs @@ -42,7 +42,7 @@ public ModelWnd() m_lvModel.Font = SystemFonts.MenuFont; // Add model browsing cache (no data, just model browsing). - m_cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", new SilentFdoUserAction(this)); + m_cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", new SilentFdoUI(this)); m_mdc = (IFwMetaDataCacheManaged)m_cache.MainCacheAccessor.MetaDataCache; PopulateModelTree(); diff --git a/Src/FdoUi/FdoUi.csproj b/Src/FdoUi/FdoUi.csproj index 029c968d54..62d3c61a5a 100644 --- a/Src/FdoUi/FdoUi.csproj +++ b/Src/FdoUi/FdoUi.csproj @@ -245,7 +245,7 @@ True True - + Code diff --git a/Src/FdoUi/FdoUserActionWindowsForms.cs b/Src/FdoUi/FwFdoUI.cs similarity index 88% rename from Src/FdoUi/FdoUserActionWindowsForms.cs rename to Src/FdoUi/FwFdoUI.cs index c6db0af946..eadc7e398c 100644 --- a/Src/FdoUi/FdoUserActionWindowsForms.cs +++ b/Src/FdoUi/FwFdoUI.cs @@ -22,14 +22,14 @@ namespace SIL.FieldWorks.FdoUi { /// - /// Implementation of IFdoUserAction which uses Windows Forms + /// The implementation of IFdoUI for FieldWorks apps. /// - public class FdoUserActionWindowsForms : IFdoUserAction + public class FwFdoUI : IFdoUI { private readonly IHelpTopicProvider m_helpTopicProvider; private readonly ISynchronizeInvoke m_synchronizeInvoke; - public FdoUserActionWindowsForms(IHelpTopicProvider helpTopicProvider, ISynchronizeInvoke synchronizeInvoke) + public FwFdoUI(IHelpTopicProvider helpTopicProvider, ISynchronizeInvoke synchronizeInvoke) { m_helpTopicProvider = helpTopicProvider; m_synchronizeInvoke = synchronizeInvoke; @@ -134,8 +134,8 @@ public YesNoCancel CannotRestoreLinkedFilesToOriginalLocation() /// The type. /// The message. /// The caption. - /// - public void DisplayMessage(MessageType type, string message, string caption) + /// The help topic. + public void DisplayMessage(MessageType type, string message, string caption, string helpTopic) { var icon = MessageBoxIcon.Information; switch (type) @@ -150,7 +150,14 @@ public void DisplayMessage(MessageType type, string message, string caption) icon = MessageBoxIcon.Warning; break; } - m_synchronizeInvoke.Invoke(() => MessageBox.Show(message, caption, MessageBoxButtons.OK, icon)); + m_synchronizeInvoke.Invoke(() => + { + if (string.IsNullOrEmpty(helpTopic)) + MessageBox.Show(message, caption, MessageBoxButtons.OK, icon); + else + MessageBox.Show(message, caption, MessageBoxButtons.OK, icon, MessageBoxDefaultButton.Button1, + 0, m_helpTopicProvider.HelpFile, HelpNavigator.Topic, helpTopic); + }); } /// @@ -193,6 +200,14 @@ public bool OfferToRestore(string projectPath, string backupPath) MessageBoxIcon.Error) == DialogResult.Yes); } + /// + /// Exits the application. + /// + public void Exit() + { + Application.Exit(); + } + /// /// Present a message to the user and allow the options to Retry or Cancel /// @@ -201,7 +216,7 @@ public bool OfferToRestore(string projectPath, string backupPath) /// True to retry. False otherwise public bool Retry(string msg, string caption) { - return System.Windows.Forms.MessageBox.Show(msg, caption, + return MessageBox.Show(msg, caption, MessageBoxButtons.RetryCancel, MessageBoxIcon.None) == DialogResult.Retry; } @@ -212,11 +227,11 @@ public bool Retry(string msg, string caption) [SuppressMessage("Gendarme.Rules.Design", "TypesWithNativeFieldsShouldBeDisposableRule", Justification="No unmanaged resources to release")] class UserActivityMonitor : IMessageFilter { - private readonly FdoUserActionWindowsForms m_userAction; + private readonly FwFdoUI m_ui; - public UserActivityMonitor(FdoUserActionWindowsForms userAction) + public UserActivityMonitor(FwFdoUI ui) { - m_userAction = userAction; + m_ui = ui; } private IntPtr m_lastMousePosition; @@ -228,7 +243,7 @@ public bool PreFilterMessage(ref Message m) // For mouse move, we get spurious ones when it didn't really move. So check the actual position. if (m.LParam != m_lastMousePosition) { - m_userAction.LastActivityTime = DateTime.Now; + m_ui.LastActivityTime = DateTime.Now; m_lastMousePosition = m.LParam; // Enhance JohnT: suppress ones where it doesn't move?? } @@ -237,7 +252,7 @@ public bool PreFilterMessage(ref Message m) if ((m.Msg >= (int)Win32.WinMsgs.WM_MOUSE_Min && m.Msg <= (int)Win32.WinMsgs.WM_MOUSE_Max) || (m.Msg >= (int)Win32.WinMsgs.WM_KEY_Min && m.Msg <= (int)Win32.WinMsgs.WM_KEY_Max)) { - m_userAction.LastActivityTime = DateTime.Now; + m_ui.LastActivityTime = DateTime.Now; } return false; // don't want to block any messages. } diff --git a/Src/FwCoreDlgs/ChooseLangProjectDialog.cs b/Src/FwCoreDlgs/ChooseLangProjectDialog.cs index 6d17c0ec61..3e8712e90c 100644 --- a/Src/FwCoreDlgs/ChooseLangProjectDialog.cs +++ b/Src/FwCoreDlgs/ChooseLangProjectDialog.cs @@ -46,7 +46,7 @@ public partial class ChooseLangProjectDialog : Form private readonly Rectangle m_initialBounds = Rectangle.Empty; private readonly int m_initialSplitterPosition = -1; private ObtainedProjectType m_obtainedProjectType = ObtainedProjectType.None; - private readonly IFdoUserAction m_userAction; + private readonly IFdoUI m_ui; #endregion #region LanguageProjectInfo class @@ -103,10 +103,10 @@ private ChooseLangProjectDialog() /// /// The initial client bounds of the dialog. /// The initial splitter position. - /// + /// /// ------------------------------------------------------------------------------------ - public ChooseLangProjectDialog(Rectangle bounds, int splitterPosition, IFdoUserAction userAction) - : this(null, false, userAction) + public ChooseLangProjectDialog(Rectangle bounds, int splitterPosition, IFdoUI ui) + : this(null, false, ui) { m_initialBounds = bounds; m_initialSplitterPosition = splitterPosition; @@ -123,14 +123,14 @@ public ChooseLangProjectDialog(Rectangle bounds, int splitterPosition, IFdoUserA /// If set to true the dialog will be /// used to assosiate a FieldWorks project with another application (e.g. Paratext). /// - /// + /// /// ------------------------------------------------------------------------------------ public ChooseLangProjectDialog(IHelpTopicProvider helpTopicProvider, - bool openToAssosiateFwProject, IFdoUserAction userAction) + bool openToAssosiateFwProject, IFdoUI ui) : this() { m_helpTopicProvider = helpTopicProvider; - m_userAction = userAction; + m_ui = ui; if (helpTopicProvider == null) m_btnHelp.Enabled = false; @@ -566,7 +566,7 @@ private void OpenFwDataProjectLinkClicked(object sender, LinkLabelLinkClickedEve private void OpenBridgeProjectLinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { // ObtainProjectFromAnySource may return null, empty string, or the full pathname to an fwdata file. - Project = ObtainProjectMethod.ObtainProjectFromAnySource(this, m_helpTopicProvider, out m_obtainedProjectType, m_userAction); + Project = ObtainProjectMethod.ObtainProjectFromAnySource(this, m_helpTopicProvider, out m_obtainedProjectType, m_ui); Server = null; if (String.IsNullOrEmpty(Project)) return; // Don't close the Open project dialog yet (LT-13187) diff --git a/Src/FwCoreDlgs/FwCoreDlgsTests/FwNewLangProjectTests.cs b/Src/FwCoreDlgs/FwCoreDlgsTests/FwNewLangProjectTests.cs index 7cc43aa2d6..837cc1f6ce 100644 --- a/Src/FwCoreDlgs/FwCoreDlgsTests/FwNewLangProjectTests.cs +++ b/Src/FwCoreDlgs/FwCoreDlgsTests/FwNewLangProjectTests.cs @@ -39,7 +39,7 @@ public class DummyFwNewLangProject : FwNewLangProject /// /// Default parameterless constructor /// - public DummyFwNewLangProject() : base(new DummyFdoUserAction()) + public DummyFwNewLangProject() : base(new DummyFdoUI()) { } @@ -55,7 +55,7 @@ public void CreateNewLangProj() { CheckDisposed(); - CreateNewLangProjWithProgress(new DummyFdoUserAction()); + CreateNewLangProjWithProgress(new DummyFdoUI()); NonAsciiWarningWasActivated = false; SimulatedNonAsciiDialogResult = DialogResult.Cancel; } @@ -141,7 +141,7 @@ public void CreateNewLangProject() // despite of the name is DummyProgressDlg no real dialog (doesn't derive from Control), so // we don't need a 'using' cache = FdoCache.CreateCacheFromExistingData( - new TestProjectId(FDOBackendProviderType.kXML, DbFilename(dbName)), "en", new DummyProgressDlg(), new DummyFdoUserAction()); + new TestProjectId(FDOBackendProviderType.kXML, DbFilename(dbName)), "en", new DummyProgressDlg(), new DummyFdoUI()); CheckInitialSetOfPartsOfSpeech(cache); Assert.AreEqual(1, cache.ServiceLocator.WritingSystems.AnalysisWritingSystems.Count); diff --git a/Src/FwCoreDlgs/FwNewLangProject.cs b/Src/FwCoreDlgs/FwNewLangProject.cs index 573d7f9de5..215ceb0795 100644 --- a/Src/FwCoreDlgs/FwNewLangProject.cs +++ b/Src/FwCoreDlgs/FwNewLangProject.cs @@ -62,7 +62,7 @@ public class FwNewLangProject : Form, IFWDisposable private Label m_lblSpecifyWrtSys; private HelpProvider helpProvider1; private string m_dbFile; - private IFdoUserAction m_userAction; + private IFdoUI m_ui; #endregion #region Properties @@ -177,9 +177,9 @@ private void FixLabelFont(Label lbl) /// Constructs a new instance of the class. /// /// ----------------------------------------------------------------------------------- - public FwNewLangProject(IFdoUserAction userAction) : this() + public FwNewLangProject(IFdoUI ui) : this() { - m_userAction = userAction; + m_ui = ui; } /// @@ -566,7 +566,7 @@ private void btnOK_Click(object sender, EventArgs e) // // Create new project // - CreateNewLangProjWithProgress(m_userAction); + CreateNewLangProjWithProgress(m_ui); } private string RemoveNonAsciiCharsFromProjectName() @@ -673,7 +673,7 @@ private void m_btnNewAnalWrtSys_Click(object sender, EventArgs e) /// Create a new language project showing a progress dialog. /// /// ------------------------------------------------------------------------------------ - protected void CreateNewLangProjWithProgress(IFdoUserAction userAction) + protected void CreateNewLangProjWithProgress(IFdoUI ui) { try { @@ -694,7 +694,7 @@ protected void CreateNewLangProjWithProgress(IFdoUserAction userAction) using (var threadHelper = new ThreadHelper()) { m_dbFile = (string)progressDlg.RunTask(DisplayUi, FdoCache.CreateNewLangProj, - ProjectName, threadHelper, userAction, m_cbAnalWrtSys.SelectedItem, + ProjectName, threadHelper, ui, m_cbAnalWrtSys.SelectedItem, m_cbVernWrtSys.SelectedItem, ((PalasoWritingSystem)m_wsManager.UserWritingSystem).RFC5646, m_newAnalysisWss, m_newVernWss, anthroFile); diff --git a/Src/LexText/LexTextControls/LexTextControlsTests/LiftExportTests.cs b/Src/LexText/LexTextControls/LexTextControlsTests/LiftExportTests.cs index d780670a44..e362ee2c0f 100644 --- a/Src/LexText/LexTextControls/LexTextControlsTests/LiftExportTests.cs +++ b/Src/LexText/LexTextControls/LexTextControlsTests/LiftExportTests.cs @@ -490,7 +490,7 @@ public void CreateMockCache() MockProjectFolder = Path.Combine(Path.GetTempPath(), mockProjectName); var mockProjectPath = Path.Combine(MockProjectFolder, mockProjectName + ".fwdata"); m_cache = FdoCache.CreateCacheWithNewBlankLangProj( - new TestProjectId(FDOBackendProviderType.kMemoryOnly, mockProjectPath), "en", "fr", "en", new DummyFdoUserAction()); + new TestProjectId(FDOBackendProviderType.kMemoryOnly, mockProjectPath), "en", "fr", "en", new DummyFdoUI()); MockLinkedFilesFolder = Path.Combine(MockProjectFolder, DirectoryFinder.ksLinkedFilesDir); Directory.CreateDirectory(MockLinkedFilesFolder); //m_cache.LangProject.LinkedFilesRootDir = MockLinkedFilesFolder; this is already the default. diff --git a/Src/LexText/Lexicon/FLExBridgeListener.cs b/Src/LexText/Lexicon/FLExBridgeListener.cs index eb7fc317e3..168574b93e 100644 --- a/Src/LexText/Lexicon/FLExBridgeListener.cs +++ b/Src/LexText/Lexicon/FLExBridgeListener.cs @@ -181,11 +181,11 @@ public bool OnDisplayObtainAnyFlexBridgeProject(object parameters, ref UIItemDis /// /// Handle the S/R "_Get Project from Colleague" menu option. /// - public bool OnObtainAnyFlexBridgeProject(object commandObject, IFdoUserAction userAction) + public bool OnObtainAnyFlexBridgeProject(object commandObject, IFdoUI ui) { ObtainedProjectType obtainedProjectType; var newprojectPathname = ObtainProjectMethod.ObtainProjectFromAnySource(_parentForm, _mediator.HelpTopicProvider, - out obtainedProjectType, userAction); + out obtainedProjectType, ui); if (string.IsNullOrEmpty(newprojectPathname)) return true; // We dealt with it. _mediator.PropertyTable.SetProperty("LastBridgeUsed", obtainedProjectType == ObtainedProjectType.Lift ? "LiftBridge" : "FLExBridge", diff --git a/Src/TE/TeImportExport/TeImportManager.cs b/Src/TE/TeImportExport/TeImportManager.cs index 2f7c36ab3b..75a9bb995a 100644 --- a/Src/TE/TeImportExport/TeImportManager.cs +++ b/Src/TE/TeImportExport/TeImportManager.cs @@ -288,7 +288,6 @@ protected IScrImportSet GetImportSettings() scr.FindOrCreateDefaultImportSettings(TypeOfImport.Unknown); }); importSettings.StyleSheet = m_styleSheet; - importSettings.HelpFile = m_helpTopicProvider.HelpFile; importSettings.OverlappingFileResolver = new ConfirmOverlappingFileReplaceDialog(m_helpTopicProvider); if (!importSettings.BasicSettingsExist) diff --git a/Src/xWorks/xWorksTests/ExportDialogTests.cs b/Src/xWorks/xWorksTests/ExportDialogTests.cs index f8b0afb01c..eed71eb6e6 100644 --- a/Src/xWorks/xWorksTests/ExportDialogTests.cs +++ b/Src/xWorks/xWorksTests/ExportDialogTests.cs @@ -474,7 +474,7 @@ public class ExportDialogTests : BaseTest public void CreateMockCache() { m_cache = FdoCache.CreateCacheWithNewBlankLangProj( - new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "fr", "en", new DummyFdoUserAction()); + new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "fr", "en", new DummyFdoUI()); var xl = new XmlList(); using (var reader = new StringReader(s_ksSemanticDomainsXml)) xl.ImportList(m_cache.LangProject, "SemanticDomainList", reader, null); From d05584de91492e490ed769ea357577eb2a9bb1af Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Wed, 4 Dec 2013 17:10:44 +0700 Subject: [PATCH 017/143] Move more UI elements out of FDO Throw exceptions in ImportFrom6_0 instead of showing message boxes in low-level code. Change-Id: Ic2e188bd8cb7ef0066bd7678ed32b50b868009aa --- Src/Common/FieldWorks/FieldWorks.cs | 5 + .../BackupRestore/ProjectRestoreService.cs | 26 +- .../DataMigration/ImportFrom6_0.cs | 91 +++-- Src/MigrateSqlDbs/MigrateProjects.cs | 112 ++--- .../Properties/Resources.Designer.cs | 383 +++++++++--------- Src/MigrateSqlDbs/Properties/Resources.resx | 271 +++++++------ 6 files changed, 479 insertions(+), 409 deletions(-) diff --git a/Src/Common/FieldWorks/FieldWorks.cs b/Src/Common/FieldWorks/FieldWorks.cs index 3e10a31a47..9526f2bee9 100644 --- a/Src/Common/FieldWorks/FieldWorks.cs +++ b/Src/Common/FieldWorks/FieldWorks.cs @@ -41,6 +41,7 @@ using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.DomainServices.BackupRestore; +using SIL.FieldWorks.FDO.DomainServices.DataMigration; using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.FdoUi; using SIL.FieldWorks.FwCoreDlgs; @@ -2517,6 +2518,10 @@ private static void RestoreCurrentProject(FwRestoreProjectSettings restoreSettin new ProjectId(ClientServerServices.Current.Local.IdForLocalProject(restoreSettings.Settings.ProjectName), null); } } + catch (CannotConvertException e) + { + MessageBoxUtils.Show(e.Message, ResourceHelper.GetResourceString("ksRestoreFailed")); + } catch (MissingOldFwException e) { using (var dlg = new MissingOldFieldWorksDlg(restoreSettings.Settings, diff --git a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs index cedcae59bc..e6dec3ff4e 100644 --- a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs +++ b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs @@ -129,12 +129,22 @@ public void RestoreProject(IThreadedProgress progressDlg) private void ImportFrom6_0Backup(BackupFileSettings fileSettings, IThreadedProgress progressDlg) { - ImportFrom6_0 importer = new ImportFrom6_0(progressDlg); - string projFile; - if (!importer.Import(fileSettings.File, m_restoreSettings.ProjectName, out projFile)) + var importer = new ImportFrom6_0(progressDlg); + bool importSuccessful; + try + { + string projFile; + importSuccessful = importer.Import(fileSettings.File, m_restoreSettings.ProjectName, out projFile); + } + catch (CannotConvertException e) + { + FailedImportCleanUp(importer); + throw; + } + if (!importSuccessful) { - ExceptionHelper.LogAndIgnoreErrors(() => CleanupFrom6_0FailedRestore(importer)); - ExceptionHelper.LogAndIgnoreErrors(() => CleanupAfterRestore(false)); + FailedImportCleanUp(importer); + if (!importer.HaveOldFieldWorks || !importer.HaveFwSqlServer) { throw new MissingOldFwException("Error restoring from FieldWorks 6.0 (or earlier) backup", @@ -144,6 +154,12 @@ private void ImportFrom6_0Backup(BackupFileSettings fileSettings, IThreadedProgr } } + private void FailedImportCleanUp(ImportFrom6_0 importer) + { + ExceptionHelper.LogAndIgnoreErrors(() => CleanupFrom6_0FailedRestore(importer)); + ExceptionHelper.LogAndIgnoreErrors(() => CleanupAfterRestore(false)); + } + private void RestoreFrom7_0AndNewerBackup(BackupFileSettings fileSettings) { // Get rid of any saved settings, since they may not be consistent with something about the data diff --git a/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs b/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs index a34b44137c..5c201c53de 100644 --- a/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs +++ b/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs @@ -89,11 +89,7 @@ public bool Import(string pathname, string projectName, out string projectFile) if (extension == ".xml") { if (!IsValid6_0Xml(pathname)) - { - MessageBoxUtils.Show(m_progressDlg.Form, Strings.ksBackupXMLFileTooOld, - Strings.ksCannotConvert); - return false; - } + throw new CannotConvertException(Strings.ksBackupXMLFileTooOld); var result1 = ImportFrom6_0Xml(pathname, folderName, projectFile); return result1; } @@ -129,9 +125,16 @@ public bool Import(string pathname, string projectName, out string projectFile) else continue; } - // Next step is to run the converter. It should be in the same directory as FDO.dll - var result = ImportFrom6_0Xml(tempPath, folderName, projectFile); - File.Delete(tempPath); + bool result; + try + { + // Next step is to run the converter. It should be in the same directory as FDO.dll + result = ImportFrom6_0Xml(tempPath, folderName, projectFile); + } + finally + { + File.Delete(tempPath); + } return result; } if (entry.Name.ToLowerInvariant().EndsWith(".bak") && entry.IsFile) @@ -142,10 +145,7 @@ public bool Import(string pathname, string projectName, out string projectFile) } } if (!fHasBak) - { - MessageBoxUtils.Show(m_progressDlg.Form, Strings.ksZipNotFieldWorksBackup, Strings.ksCannotConvert); - return false; - } + throw new CannotConvertException(Strings.ksZipNotFieldWorksBackup); if (HaveFwSqlServer && HaveOldFieldWorks) { foreach (ZipEntry entry in zipFile) @@ -179,15 +179,23 @@ public bool Import(string pathname, string projectName, out string projectFile) proj, "{0}", "{1}"); if (!DumpDatabaseAsXml(TempDatabaseName, tempXmlPath, msg3, errMsgFmt3)) return false; - // Next step is to run the converter. It should be in the same directory as FDO.dll - var result = ImportFrom6_0Xml(tempXmlPath, folderName, projectFile); - File.Delete(tempXmlPath); - DeleteTempDatabase(); + + bool result; + try + { + // Next step is to run the converter. It should be in the same directory as FDO.dll + result = ImportFrom6_0Xml(tempXmlPath, folderName, projectFile); + } + finally + { + File.Delete(tempXmlPath); + DeleteTempDatabase(); + } return result; } } // Should never get here, but ... - MessageBoxUtils.Show(m_progressDlg.Form, Strings.ksZipNotFieldWorksBackup, Strings.ksCannotConvert); + throw new CannotConvertException(Strings.ksZipNotFieldWorksBackup); } return false; } @@ -532,8 +540,7 @@ private bool CallDbProgram(string args, string progressMsg, string errorMsgFmt) if (process.ExitCode != 0 || !string.IsNullOrEmpty(m_errorMessages)) { var msg = string.Format(errorMsgFmt, process.ExitCode, m_errorMessages); - MessageBoxUtils.Show(m_progressDlg.Form, msg, Strings.ksCannotConvert); - return false; + throw new CannotConvertException(msg); } return true; } @@ -558,8 +565,7 @@ public bool DumpDatabaseAsXml(string dbName, string tempXmlPath, string progress if (process.ExitCode != 0 || !string.IsNullOrEmpty(m_errorMessages)) { var msg = string.Format(errorMsgFmt, process.ExitCode, m_errorMessages); - MessageBoxUtils.Show(m_progressDlg.Form, msg, Strings.ksCannotConvert); - return false; + throw new CannotConvertException(msg); } return true; } @@ -675,19 +681,12 @@ public bool ImportFrom6_0Xml(string pathname, string folderName, string projectF else if (process.ExitCode != 0 || !String.IsNullOrEmpty(m_errorMessages)) { message = String.Format(Strings.ksConversionProcessFailed, process.ExitCode, m_errorMessages); - // ENHANCE (TimS): We should not be showing a message box at this level. If we - // really need to show it here, we should pass in the owning form instead of relying on - // Form.ActiveForm since it can return null if no .Net forms have focus. - MessageBoxUtils.Show(Form.ActiveForm, message, Strings.ksCannotConvert); - retval = false; + BackOutCleanUp(projectFile, fCreateFolder, folderName, replacedProj); + throw new CannotConvertException(message); } if (retval == false) { - File.Delete(projectFile); - if (fCreateFolder) - Directory.Delete(folderName); - else if (replacedProj != null) - File.Move(replacedProj, projectFile); + BackOutCleanUp(projectFile, fCreateFolder, folderName, replacedProj); } else { @@ -712,6 +711,15 @@ public bool ImportFrom6_0Xml(string pathname, string folderName, string projectF } } + private void BackOutCleanUp(string projectFile, bool fCreateFolder, string folderName, string replacedProj) + { + File.Delete(projectFile); + if (fCreateFolder) + Directory.Delete(folderName); + else if (replacedProj != null) + File.Move(replacedProj, projectFile); + } + /// /// Create a process and initialize it according to our standard way of doing things. /// @@ -803,4 +811,25 @@ void process_OutputDataReceived(object sender, DataReceivedEventArgs e) m_stdoutBldr.AppendLine(e.Data); } } + + #region class CannotConvertException + /// ---------------------------------------------------------------------------------------- + /// + /// Exception type to encapsulate a problem while running the conversion + /// + /// ---------------------------------------------------------------------------------------- + public class CannotConvertException : Exception + { + /// ------------------------------------------------------------------------------------ + /// + /// Initializes a new instance of the class. + /// + /// The message. + /// ------------------------------------------------------------------------------------ + public CannotConvertException(string message) + : base(message) + { + } + } + #endregion } diff --git a/Src/MigrateSqlDbs/MigrateProjects.cs b/Src/MigrateSqlDbs/MigrateProjects.cs index fe99bef6cc..6b99093418 100644 --- a/Src/MigrateSqlDbs/MigrateProjects.cs +++ b/Src/MigrateSqlDbs/MigrateProjects.cs @@ -222,70 +222,78 @@ enum MigrateStatus private MigrateStatus ConvertProject(string proj) { bool fOk; - string dbName = proj; - // 1. Check database version number. If >= 200260, goto step 4. - int version = GetDbVersion(proj); - if (version < 200260) + try { - // 2. Make a temporary copy of the project. - // 3. Migrate that temporary copy. - if (m_fTempMigrationDbExists) + string dbName = proj; + // 1. Check database version number. If >= 200260, goto step 4. + int version = GetDbVersion(proj); + if (version < 200260) { - fOk = m_importer.DeleteTempDatabase(); + // 2. Make a temporary copy of the project. + // 3. Migrate that temporary copy. + if (m_fTempMigrationDbExists) + { + fOk = m_importer.DeleteTempDatabase(); + if (!fOk) + return MigrateStatus.Failed; + m_fTempMigrationDbExists = false; + } + string msg = String.Format(Properties.Resources.ksCreatingATemporaryCopy, proj); + string sErrorMsgFmt = String.Format(Properties.Resources.ksCreatingATemporaryCopyFailed, + proj, "{0}", "{1}"); + fOk = m_importer.CopyToTempDatabase(proj, msg, sErrorMsgFmt); + if (!fOk) + return MigrateStatus.Failed; + m_fTempMigrationDbExists = true; + string msg2 = String.Format(Properties.Resources.ksMigratingTheCopy, proj); + string errMsgFmt2 = String.Format(Properties.Resources.ksMigratingTheCopyFailed, + proj, "{0}", "{1}"); + fOk = m_importer.MigrateTempDatabase(msg2, errMsgFmt2); if (!fOk) return MigrateStatus.Failed; - m_fTempMigrationDbExists = false; + dbName = ImportFrom6_0.TempDatabaseName; + } + // 4. Dump XML for project (or for the temporary project copy) + string projDir = Path.Combine(DirectoryFinder.ProjectsDirectory, proj); + string projName = proj; + if (Directory.Exists(projDir)) + { + using (var dlg = new ExistingProjectDlg(proj)) + { + if (dlg.ShowDialog(this) == DialogResult.Cancel) + return MigrateStatus.Canceled; + projName = dlg.TargetProjectName; + } + projDir = Path.Combine(DirectoryFinder.ProjectsDirectory, projName); + if (!Directory.Exists(projDir)) + Directory.CreateDirectory(projDir); + } + else + { + Directory.CreateDirectory(projDir); } - string msg = String.Format(Properties.Resources.ksCreatingATemporaryCopy, proj); - string sErrorMsgFmt = String.Format(Properties.Resources.ksCreatingATemporaryCopyFailed, + string projXml = Path.Combine(projDir, "tempProj.xml"); + string msgDump = String.Format(Properties.Resources.ksWritingFw60XML, proj); + string msgDumpErrorFmt = String.Format(Properties.Resources.ksWritingFw60XMLFailed, proj, "{0}", "{1}"); - fOk = m_importer.CopyToTempDatabase(proj, msg, sErrorMsgFmt); - if (!fOk) - return MigrateStatus.Failed; - m_fTempMigrationDbExists = true; - string msg2 = String.Format(Properties.Resources.ksMigratingTheCopy, proj); - string errMsgFmt2 = String.Format(Properties.Resources.ksMigratingTheCopyFailed, + if (dbName != proj) + { + msgDump = String.Format(Properties.Resources.ksWritingCopyAsFw60XML, proj); ; + msgDumpErrorFmt = String.Format(Properties.Resources.ksWritingCopyAsFw60XMLFailed, proj, "{0}", "{1}"); - fOk = m_importer.MigrateTempDatabase(msg2, errMsgFmt2); + } + fOk = m_importer.DumpDatabaseAsXml(dbName, projXml, msgDump, msgDumpErrorFmt); if (!fOk) return MigrateStatus.Failed; - dbName = ImportFrom6_0.TempDatabaseName; - } - // 4. Dump XML for project (or for the temporary project copy) - string projDir = Path.Combine(DirectoryFinder.ProjectsDirectory, proj); - string projName = proj; - if (Directory.Exists(projDir)) - { - using (var dlg = new ExistingProjectDlg(proj)) - { - if (dlg.ShowDialog(this) == DialogResult.Cancel) - return MigrateStatus.Canceled; - projName = dlg.TargetProjectName; - } - projDir = Path.Combine(DirectoryFinder.ProjectsDirectory, projName); - if (!Directory.Exists(projDir)) - Directory.CreateDirectory(projDir); - } - else - { - Directory.CreateDirectory(projDir); + // 5. Convert FW 6.0 XML to FW 7.0 XML + string projFile = Path.Combine(projDir, projName + FwFileExtensions.ksFwDataXmlFileExtension); + fOk = m_importer.ImportFrom6_0Xml(projXml, projDir, projFile); } - string projXml = Path.Combine(projDir, "tempProj.xml"); - string msgDump = String.Format(Properties.Resources.ksWritingFw60XML, proj); - string msgDumpErrorFmt = String.Format(Properties.Resources.ksWritingFw60XMLFailed, - proj, "{0}", "{1}"); - if (dbName != proj) + catch (CannotConvertException e) { - msgDump = String.Format(Properties.Resources.ksWritingCopyAsFw60XML, proj); ; - msgDumpErrorFmt = String.Format(Properties.Resources.ksWritingCopyAsFw60XMLFailed, - proj, "{0}", "{1}"); + fOk = false; + MessageBox.Show(e.Message, Properties.Resources.ksCannotConvert); } - fOk = m_importer.DumpDatabaseAsXml(dbName, projXml, msgDump, msgDumpErrorFmt); - if (!fOk) - return MigrateStatus.Failed; - // 5. Convert FW 6.0 XML to FW 7.0 XML - string projFile = Path.Combine(projDir, projName + FwFileExtensions.ksFwDataXmlFileExtension); - fOk = m_importer.ImportFrom6_0Xml(projXml, projDir, projFile); return fOk ? MigrateStatus.OK : MigrateStatus.Failed; } diff --git a/Src/MigrateSqlDbs/Properties/Resources.Designer.cs b/Src/MigrateSqlDbs/Properties/Resources.Designer.cs index 96332964c9..0c93c130b0 100644 --- a/Src/MigrateSqlDbs/Properties/Resources.Designer.cs +++ b/Src/MigrateSqlDbs/Properties/Resources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.239 +// Runtime Version:4.0.30319.1008 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -9,190 +9,199 @@ //------------------------------------------------------------------------------ namespace SIL.FieldWorks.MigrateSqlDbs.MigrateProjects.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SIL.FieldWorks.MigrateSqlDbs.MigrateProjects.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to Cancel. - /// - internal static string ksCancel { - get { - return ResourceManager.GetString("ksCancel", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Preparing for migration - Creating a temporary copy of {0}.. - /// - internal static string ksCreatingATemporaryCopy { - get { - return ResourceManager.GetString("ksCreatingATemporaryCopy", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Creating a temporary copy of {0} failed. The copy process returned error code {1} and error message {2}.. - /// - internal static string ksCreatingATemporaryCopyFailed { - get { - return ResourceManager.GetString("ksCreatingATemporaryCopyFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The following projects did not migrate successfully:. - /// - internal static string ksFollowingProjectsFailed { - get { - return ResourceManager.GetString("ksFollowingProjectsFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to {0} (already exists). - /// - internal static string ksMarkAsExisting { - get { - return ResourceManager.GetString("ksMarkAsExisting", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to {0} (failed migration). - /// - internal static string ksMarkAsFailed { - get { - return ResourceManager.GetString("ksMarkAsFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to {0} (migrated). - /// - internal static string ksMarkAsMigrated { - get { - return ResourceManager.GetString("ksMarkAsMigrated", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Preparing for migration - Migrating the copy of {0} to FieldWorks 6.0. - /// - internal static string ksMigratingTheCopy { - get { - return ResourceManager.GetString("ksMigratingTheCopy", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Migrating the copy of {0} to FieldWorks 6.0 failed. The migration process returned error code {1} and error message {2}.. - /// - internal static string ksMigratingTheCopyFailed { - get { - return ResourceManager.GetString("ksMigratingTheCopyFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Skip. - /// - internal static string ksSkip { - get { - return ResourceManager.GetString("ksSkip", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Warning. - /// - internal static string ksWarning { - get { - return ResourceManager.GetString("ksWarning", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Preparing for migration - Writing the copy of {0} as FieldWorks 6.0 XML.. - /// - internal static string ksWritingCopyAsFw60XML { - get { - return ResourceManager.GetString("ksWritingCopyAsFw60XML", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Writing the copy of {0} as FieldWorks 6.0 XML failed. The writing process returned error code {1} and error message {2}.. - /// - internal static string ksWritingCopyAsFw60XMLFailed { - get { - return ResourceManager.GetString("ksWritingCopyAsFw60XMLFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Preparing for migration - Writing {0} as FieldWorks 6.0 XML.. - /// - internal static string ksWritingFw60XML { - get { - return ResourceManager.GetString("ksWritingFw60XML", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Writing {0} as FieldWorks 6.0 XML failed. The writing process returned error code {1} and error message {2}.. - /// - internal static string ksWritingFw60XMLFailed { - get { - return ResourceManager.GetString("ksWritingFw60XMLFailed", resourceCulture); - } - } - } + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SIL.FieldWorks.MigrateSqlDbs.MigrateProjects.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Cancel. + /// + internal static string ksCancel { + get { + return ResourceManager.GetString("ksCancel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot Convert. + /// + internal static string ksCannotConvert { + get { + return ResourceManager.GetString("ksCannotConvert", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Preparing for migration - Creating a temporary copy of {0}.. + /// + internal static string ksCreatingATemporaryCopy { + get { + return ResourceManager.GetString("ksCreatingATemporaryCopy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Creating a temporary copy of {0} failed. The copy process returned error code {1} and error message {2}.. + /// + internal static string ksCreatingATemporaryCopyFailed { + get { + return ResourceManager.GetString("ksCreatingATemporaryCopyFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The following projects did not migrate successfully:. + /// + internal static string ksFollowingProjectsFailed { + get { + return ResourceManager.GetString("ksFollowingProjectsFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} (already exists). + /// + internal static string ksMarkAsExisting { + get { + return ResourceManager.GetString("ksMarkAsExisting", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} (failed migration). + /// + internal static string ksMarkAsFailed { + get { + return ResourceManager.GetString("ksMarkAsFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} (migrated). + /// + internal static string ksMarkAsMigrated { + get { + return ResourceManager.GetString("ksMarkAsMigrated", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Preparing for migration - Migrating the copy of {0} to FieldWorks 6.0. + /// + internal static string ksMigratingTheCopy { + get { + return ResourceManager.GetString("ksMigratingTheCopy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Migrating the copy of {0} to FieldWorks 6.0 failed. The migration process returned error code {1} and error message {2}.. + /// + internal static string ksMigratingTheCopyFailed { + get { + return ResourceManager.GetString("ksMigratingTheCopyFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Skip. + /// + internal static string ksSkip { + get { + return ResourceManager.GetString("ksSkip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Warning. + /// + internal static string ksWarning { + get { + return ResourceManager.GetString("ksWarning", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Preparing for migration - Writing the copy of {0} as FieldWorks 6.0 XML.. + /// + internal static string ksWritingCopyAsFw60XML { + get { + return ResourceManager.GetString("ksWritingCopyAsFw60XML", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Writing the copy of {0} as FieldWorks 6.0 XML failed. The writing process returned error code {1} and error message {2}.. + /// + internal static string ksWritingCopyAsFw60XMLFailed { + get { + return ResourceManager.GetString("ksWritingCopyAsFw60XMLFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Preparing for migration - Writing {0} as FieldWorks 6.0 XML.. + /// + internal static string ksWritingFw60XML { + get { + return ResourceManager.GetString("ksWritingFw60XML", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Writing {0} as FieldWorks 6.0 XML failed. The writing process returned error code {1} and error message {2}.. + /// + internal static string ksWritingFw60XMLFailed { + get { + return ResourceManager.GetString("ksWritingFw60XMLFailed", resourceCulture); + } + } + } } diff --git a/Src/MigrateSqlDbs/Properties/Resources.resx b/Src/MigrateSqlDbs/Properties/Resources.resx index 23a66e2ee1..5de1b0b97d 100644 --- a/Src/MigrateSqlDbs/Properties/Resources.resx +++ b/Src/MigrateSqlDbs/Properties/Resources.resx @@ -1,178 +1,181 @@  - + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - text/microsoft-resx + text/microsoft-resx - 2.0 + 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - The following projects did not migrate successfully: - message heading (list of projects will appear on lines below this message) + The following projects did not migrate successfully: + message heading (list of projects will appear on lines below this message) - Warning - heading for message box + Warning + heading for message box - {0} (migrated) - {0} is a project name + {0} (migrated) + {0} is a project name - {0} (failed migration) - {0} is a project name + {0} (failed migration) + {0} is a project name - Preparing for migration - Creating a temporary copy of {0}. - {0} is a project name + Preparing for migration - Creating a temporary copy of {0}. + {0} is a project name - Creating a temporary copy of {0} failed. The copy process returned error code {1} and error message {2}. - {0} is a project name + Creating a temporary copy of {0} failed. The copy process returned error code {1} and error message {2}. + {0} is a project name - Preparing for migration - Migrating the copy of {0} to FieldWorks 6.0 - {0} is a project name + Preparing for migration - Migrating the copy of {0} to FieldWorks 6.0 + {0} is a project name - Migrating the copy of {0} to FieldWorks 6.0 failed. The migration process returned error code {1} and error message {2}. - {0} is a project name + Migrating the copy of {0} to FieldWorks 6.0 failed. The migration process returned error code {1} and error message {2}. + {0} is a project name - Preparing for migration - Writing {0} as FieldWorks 6.0 XML. - {0} is a project name + Preparing for migration - Writing {0} as FieldWorks 6.0 XML. + {0} is a project name - Writing {0} as FieldWorks 6.0 XML failed. The writing process returned error code {1} and error message {2}. - {0} is a project name + Writing {0} as FieldWorks 6.0 XML failed. The writing process returned error code {1} and error message {2}. + {0} is a project name - Preparing for migration - Writing the copy of {0} as FieldWorks 6.0 XML. - {0} is a project name + Preparing for migration - Writing the copy of {0} as FieldWorks 6.0 XML. + {0} is a project name - Writing the copy of {0} as FieldWorks 6.0 XML failed. The writing process returned error code {1} and error message {2}. - {0} is a project name + Writing the copy of {0} as FieldWorks 6.0 XML failed. The writing process returned error code {1} and error message {2}. + {0} is a project name - Cancel + Cancel - {0} (already exists) - {0} is a project name + {0} (already exists) + {0} is a project name - Skip + Skip + + + Cannot Convert \ No newline at end of file From befe36ea2646bbde3fbfeb2a571aebd24d52750f Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Wed, 4 Dec 2013 17:44:49 +0700 Subject: [PATCH 018/143] Remove WinForms references from some FDO classes Mostly unused using directives. Change-Id: I86197262db61de0381208f4e1dbaba2bc1a9a516 --- Src/FDO/DomainImpl/OverridesLing_Lex.cs | 1 - Src/FDO/DomainServices/BootstrapNewLanguageProject.cs | 6 ------ .../DomainServices/DataMigration/DataMigration7000024.cs | 3 --- .../DomainServices/DataMigration/DataMigration7000026.cs | 6 ------ .../DomainServices/DataMigration/DataMigration7000029.cs | 4 ---- .../DomainServices/DataMigration/DataMigration7000030.cs | 5 ----- Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs | 6 ------ Src/FDO/DomainServices/WfiWordformServices.cs | 2 -- Src/FDO/FDO.csproj | 7 +------ Src/FDO/FdoInterfaceAdditions.cs | 1 - Src/FDO/Infrastructure/Impl/FdoRepositoryAdditions.cs | 1 - Src/MigrateSqlDbs/MigrateProjects.cs | 1 - 12 files changed, 1 insertion(+), 42 deletions(-) diff --git a/Src/FDO/DomainImpl/OverridesLing_Lex.cs b/Src/FDO/DomainImpl/OverridesLing_Lex.cs index bbded7a42f..ca401ea7c3 100644 --- a/Src/FDO/DomainImpl/OverridesLing_Lex.cs +++ b/Src/FDO/DomainImpl/OverridesLing_Lex.cs @@ -21,7 +21,6 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; -using System.Windows.Forms; using System.Collections.Generic; using System.Collections.Specialized; using System.Xml; // XMLWriter diff --git a/Src/FDO/DomainServices/BootstrapNewLanguageProject.cs b/Src/FDO/DomainServices/BootstrapNewLanguageProject.cs index 4ebff7aead..4fd2a4454a 100644 --- a/Src/FDO/DomainServices/BootstrapNewLanguageProject.cs +++ b/Src/FDO/DomainServices/BootstrapNewLanguageProject.cs @@ -1,16 +1,10 @@ using System; -using System.Collections.Generic; using System.Diagnostics; -using System.IO; -using System.Net; -using System.Text; -using System.Windows.Forms; using Microsoft.Practices.ServiceLocation; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.FDO.DomainImpl; using SIL.FieldWorks.FDO.Infrastructure; using SIL.CoreImpl; -using SIL.FieldWorks.FDO.Infrastructure.Impl; namespace SIL.FieldWorks.FDO.DomainServices { diff --git a/Src/FDO/DomainServices/DataMigration/DataMigration7000024.cs b/Src/FDO/DomainServices/DataMigration/DataMigration7000024.cs index 6da3894791..bd5b4c9b81 100644 --- a/Src/FDO/DomainServices/DataMigration/DataMigration7000024.cs +++ b/Src/FDO/DomainServices/DataMigration/DataMigration7000024.cs @@ -15,13 +15,10 @@ // // --------------------------------------------------------------------------------------------- using System; -using System.Collections; using System.Collections.Generic; -using System.Windows.Forms; using System.Xml.Linq; using System.Linq; using System.Xml.XPath; -using SIL.FieldWorks.FDO.DomainImpl; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration { diff --git a/Src/FDO/DomainServices/DataMigration/DataMigration7000026.cs b/Src/FDO/DomainServices/DataMigration/DataMigration7000026.cs index 3522df207a..912bd90f4a 100644 --- a/Src/FDO/DomainServices/DataMigration/DataMigration7000026.cs +++ b/Src/FDO/DomainServices/DataMigration/DataMigration7000026.cs @@ -14,14 +14,8 @@ // // // --------------------------------------------------------------------------------------------- -using System; -using System.Collections; -using System.Collections.Generic; -using System.Windows.Forms; using System.Xml.Linq; using System.Linq; -using System.Xml.XPath; -using SIL.FieldWorks.FDO.DomainImpl; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration { diff --git a/Src/FDO/DomainServices/DataMigration/DataMigration7000029.cs b/Src/FDO/DomainServices/DataMigration/DataMigration7000029.cs index d3e3208854..0d8e2a8d71 100644 --- a/Src/FDO/DomainServices/DataMigration/DataMigration7000029.cs +++ b/Src/FDO/DomainServices/DataMigration/DataMigration7000029.cs @@ -15,15 +15,11 @@ // // --------------------------------------------------------------------------------------------- using System; -using System.Collections; -using System.Collections.Generic; using System.IO; -using System.Windows.Forms; using System.Xml.Linq; using System.Linq; using System.Xml.XPath; using SIL.FieldWorks.Common.FwUtils; -using SIL.FieldWorks.FDO.DomainImpl; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration { diff --git a/Src/FDO/DomainServices/DataMigration/DataMigration7000030.cs b/Src/FDO/DomainServices/DataMigration/DataMigration7000030.cs index e283a97ff8..0cc88ea4b1 100644 --- a/Src/FDO/DomainServices/DataMigration/DataMigration7000030.cs +++ b/Src/FDO/DomainServices/DataMigration/DataMigration7000030.cs @@ -15,18 +15,13 @@ // // --------------------------------------------------------------------------------------------- using System; -using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; -using System.Windows.Forms; -using System.Xml; using System.Xml.Linq; using System.Xml.XPath; -using SIL.CoreImpl; using SIL.FieldWorks.Common.FwUtils; -using SIL.FieldWorks.FDO.DomainImpl; using SIL.Utils; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration diff --git a/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs b/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs index 5c201c53de..fea07bb635 100644 --- a/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs +++ b/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs @@ -13,7 +13,6 @@ using System.IO; using System.ServiceProcess; using System.Text; -using System.Windows.Forms; using ICSharpCode.SharpZipLib.Zip; using Microsoft.Win32; @@ -52,11 +51,6 @@ public class ImportFrom6_0 private readonly IThreadedProgress m_progressDlg; #endregion - /// - /// provides parent form for progress dialog - /// - public Form ParentForm { get; set; } - #region Constructors /// /// Constructor for run-time debugging. diff --git a/Src/FDO/DomainServices/WfiWordformServices.cs b/Src/FDO/DomainServices/WfiWordformServices.cs index d6ce8cc1f4..c4890cf616 100644 --- a/Src/FDO/DomainServices/WfiWordformServices.cs +++ b/Src/FDO/DomainServices/WfiWordformServices.cs @@ -18,12 +18,10 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using System.Windows.Forms; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.Common.FwUtils; using SIL.CoreImpl; using SIL.FieldWorks.FDO.DomainImpl; -using Sharpen.Util; namespace SIL.FieldWorks.FDO.DomainServices { diff --git a/Src/FDO/FDO.csproj b/Src/FDO/FDO.csproj index 6924b4d0ab..1c19c84265 100644 --- a/Src/FDO/FDO.csproj +++ b/Src/FDO/FDO.csproj @@ -101,6 +101,7 @@ + COMInterfaces @@ -114,9 +115,6 @@ System.Drawing - - System.Windows.Forms - System.XML @@ -158,9 +156,6 @@ ..\..\Output\Debug\PhraseTranslationHelper.dll - - ..\..\Output\Debug\Reporting.dll - ..\..\Output\Debug\ScrUtilsInterfaces.dll diff --git a/Src/FDO/FdoInterfaceAdditions.cs b/Src/FDO/FdoInterfaceAdditions.cs index 848698b142..dd3eea3b3f 100644 --- a/Src/FDO/FdoInterfaceAdditions.cs +++ b/Src/FDO/FdoInterfaceAdditions.cs @@ -19,7 +19,6 @@ using System; using System.Collections.Generic; using System.Xml; -using System.Windows.Forms; using System.Collections; using System.Collections.Specialized; diff --git a/Src/FDO/Infrastructure/Impl/FdoRepositoryAdditions.cs b/Src/FDO/Infrastructure/Impl/FdoRepositoryAdditions.cs index 14e1ab9910..779d048416 100644 --- a/Src/FDO/Infrastructure/Impl/FdoRepositoryAdditions.cs +++ b/Src/FDO/Infrastructure/Impl/FdoRepositoryAdditions.cs @@ -21,7 +21,6 @@ using System.Diagnostics; using System.Linq; using System.Text; -using System.Windows.Forms; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainImpl; diff --git a/Src/MigrateSqlDbs/MigrateProjects.cs b/Src/MigrateSqlDbs/MigrateProjects.cs index 6b99093418..ab7e3430b9 100644 --- a/Src/MigrateSqlDbs/MigrateProjects.cs +++ b/Src/MigrateSqlDbs/MigrateProjects.cs @@ -150,7 +150,6 @@ public MigrateProjects(ImportFrom6_0 importer, string version, List proj : this() { m_importer = importer; - m_importer.ParentForm = this; m_projects = projects; m_fAutoClose = fAutoClose; if (m_fAutoClose) From 0982cf914edb531adab6550fbf37aaa76b1943ac Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 6 Dec 2013 10:43:41 +0700 Subject: [PATCH 019/143] removed message boxes from some FDO classes -XmlImportData -ProjectRestoreService -Db4)ServerFinder -FdoCache Change-Id: Ib1f99e50f4da501bf1257ee4e4fbfbbf938351e3 --- Src/Common/FieldWorks/FieldWorks.cs | 3 +- .../ApplicationServices/XmlImportData.cs | 19 ++-- .../BackupRestore/ProjectRestoreService.cs | 10 +- .../DomainServices/ClientServerServices.cs | 4 +- Src/FDO/DomainServices/Db4OServerFinder.cs | 92 ++++++++----------- Src/FDO/DomainServices/ScrSfFileList.cs | 2 - Src/FDO/fdoCache.cs | 2 - Src/FdoUi/FwFdoUI.cs | 5 + Src/FwCoreDlgs/ChooseLangProjectDialog.cs | 17 +++- Src/FwCoreDlgs/FwCoreDlgs.Designer.cs | 9 ++ Src/FwCoreDlgs/FwCoreDlgs.resx | 3 + Src/LexText/Interlinear/LinguaLinksImport.cs | 5 +- Src/LexText/LexTextControls/LexImport.cs | 24 +++-- 13 files changed, 100 insertions(+), 95 deletions(-) diff --git a/Src/Common/FieldWorks/FieldWorks.cs b/Src/Common/FieldWorks/FieldWorks.cs index 9526f2bee9..df2ec13bfe 100644 --- a/Src/Common/FieldWorks/FieldWorks.cs +++ b/Src/Common/FieldWorks/FieldWorks.cs @@ -2507,8 +2507,7 @@ private static void RestoreCurrentProject(FwRestoreProjectSettings restoreSettin retry = false; try { - ProjectRestoreService restoreService = new ProjectRestoreService(restoreSettings.Settings, - GetHelpTopicProvider(restoreSettings.FwAppCommandLineAbbrev), s_ui); + var restoreService = new ProjectRestoreService(restoreSettings.Settings, s_ui); Logger.WriteEvent("Restoring from " + restoreSettings.Settings.Backup.File); if (RestoreProjectDlg.HandleRestoreFileErrors(null, ResourceHelper.GetResourceString("ksRestoreFailed"), restoreSettings.Settings.Backup.File, () => DoRestore(restoreService))) diff --git a/Src/FDO/Application/ApplicationServices/XmlImportData.cs b/Src/FDO/Application/ApplicationServices/XmlImportData.cs index 5130f07981..b8efe35aea 100644 --- a/Src/FDO/Application/ApplicationServices/XmlImportData.cs +++ b/Src/FDO/Application/ApplicationServices/XmlImportData.cs @@ -212,7 +212,7 @@ public XmlImportData(FdoCache cache) /// /// true if successful, false if an error occurs /// ------------------------------------------------------------------------------------ - public bool ImportData(string sFilename, IProgress progress) + public void ImportData(string sFilename, IProgress progress) { DateTime dtBegin = DateTime.Now; m_sFilename = sFilename; @@ -221,19 +221,18 @@ public bool ImportData(string sFilename, IProgress progress) if (idx >= 0) sLogFile = sLogFile.Substring(0, idx); sLogFile = sLogFile + "-Import.log"; - bool fRetVal = false; var streamReader = new StreamReader(sFilename, Encoding.UTF8); try { - fRetVal = ImportData(streamReader, + ImportData(streamReader, new StreamWriter(sLogFile, false, Encoding.UTF8), progress); - DateTime dtEnd = DateTime.Now; - TimeSpan span = new TimeSpan(dtEnd.Ticks - dtBegin.Ticks); - LogFinalCounts(Path.GetFileName(sFilename), span); } finally { + DateTime dtEnd = DateTime.Now; + var span = new TimeSpan(dtEnd.Ticks - dtBegin.Ticks); + LogFinalCounts(Path.GetFileName(sFilename), span); if (m_wrtrLog != null) { m_wrtrLog.Close(); @@ -241,7 +240,6 @@ public bool ImportData(string sFilename, IProgress progress) } streamReader.Dispose(); } - return fRetVal; } private void LogFinalCounts(string sFilename, TimeSpan span) @@ -294,7 +292,7 @@ private void LogMessage(string sMsg) /// /// true if successful, false if an error occurs /// ------------------------------------------------------------------------------------ - public bool ImportData(TextReader rdr, TextWriter wrtrLog, IProgress progress) + public void ImportData(TextReader rdr, TextWriter wrtrLog, IProgress progress) { bool fRetVal = true; m_progress = progress; @@ -333,9 +331,7 @@ public bool ImportData(TextReader rdr, TextWriter wrtrLog, IProgress progress) m_sFilename, e.Message); int line = LineNumber(xrdr); LogMessage(sMsg, line); - string sTitle = String.Format("Error on line {0}", line); - MessageBoxUtils.Show(sMsg, sTitle); - fRetVal = false; + throw; } finally { @@ -343,7 +339,6 @@ public bool ImportData(TextReader rdr, TextWriter wrtrLog, IProgress progress) xrdr.Close(); m_cache.MainCacheAccessor.EndNonUndoableTask(); } - return fRetVal; } ILexSenseFactory m_factLexSense; diff --git a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs index e6dec3ff4e..52da82ca77 100644 --- a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs +++ b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs @@ -21,7 +21,6 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; -using XCore; using SIL.FieldWorks.Resources; namespace SIL.FieldWorks.FDO.DomainServices.BackupRestore @@ -35,7 +34,6 @@ public class ProjectRestoreService private readonly RestoreProjectSettings m_restoreSettings; private String m_tempBackupFolder; private bool m_fRestoreOverProject; - private readonly IHelpTopicProvider m_helpTopicProvider; private string m_sLinkDirChangedTo; private readonly IFdoUI m_ui; #endregion @@ -46,13 +44,11 @@ public class ProjectRestoreService /// Constructor /// /// The restore settings. - /// /// /// ------------------------------------------------------------------------------------ - public ProjectRestoreService(RestoreProjectSettings settings, IHelpTopicProvider helpTopicProvider, IFdoUI ui) + public ProjectRestoreService(RestoreProjectSettings settings, IFdoUI ui) { m_restoreSettings = settings; - m_helpTopicProvider = helpTopicProvider; m_ui = ui; } @@ -662,7 +658,7 @@ private void UnzipFileToRestoreFolder(ZipInputStream zipIn, string fileName, { Debug.WriteLine("Failed to create directory {0}; {1}", dir, e.Message); var msg = string.Format(Strings.ksCannotRestoreLinkedFilesToDir, dir); - MessageBoxUtils.Show(msg, Strings.ksCannotRestore); + m_ui.DisplayMessage(MessageType.Warning, msg, Strings.ksCannotRestore, null); return; } if (FileUtils.TrySimilarFileExists(newFileName, out newFileName)) @@ -702,7 +698,7 @@ private void UnzipFileToRestoreFolder(ZipInputStream zipIn, string fileName, { Debug.WriteLine("Failed to restore file {0}; {1}", newFileName, e.Message); var msg = string.Format(Strings.ksCannotRestoreBackup, newFileName); - MessageBoxUtils.Show(msg, Strings.ksCannotRestore); + m_ui.DisplayMessage(MessageType.Warning, msg, Strings.ksCannotRestore, null); return; } } diff --git a/Src/FDO/DomainServices/ClientServerServices.cs b/Src/FDO/DomainServices/ClientServerServices.cs index a848a964c8..01149ae194 100644 --- a/Src/FDO/DomainServices/ClientServerServices.cs +++ b/Src/FDO/DomainServices/ClientServerServices.cs @@ -311,9 +311,9 @@ internal Db4OClientServerServices() /// ------------------------------------------------------------------------------------ public void BeginFindServers(Action foundServer) { - if (m_serverFinder != null) + if (m_serverFinder != null && !m_serverFinder.IsCompleted) throw new InvalidOperationException("Can not start a new find servers before the previous one finishes."); - m_serverFinder = new Db4OServerFinder(foundServer, () => m_serverFinder = null); + m_serverFinder = new Db4OServerFinder(foundServer); } /// ------------------------------------------------------------------------------------ diff --git a/Src/FDO/DomainServices/Db4OServerFinder.cs b/Src/FDO/DomainServices/Db4OServerFinder.cs index b243b391c3..57922f1523 100644 --- a/Src/FDO/DomainServices/Db4OServerFinder.cs +++ b/Src/FDO/DomainServices/Db4OServerFinder.cs @@ -32,10 +32,9 @@ internal class Db4OServerFinder private readonly int HostDiscoveryBroadcastReplyPort = Db4OPorts.ReplyPort; private readonly Thread m_hostListenerThread; - private volatile Socket m_hostListenerSocket; + private Socket m_hostListenerSocket; private readonly object m_syncRoot = new object(); private readonly Action m_foundServerCallback; - private readonly Action m_onCompletedCallback; #endregion #region Constructor @@ -45,12 +44,14 @@ internal class Db4OServerFinder /// /// The method to call when a server is found /// (string parameter is the IP address of the found server) - /// Callback to run when the search is completed. /// ------------------------------------------------------------------------------------ - public Db4OServerFinder(Action foundServerCallback, Action onCompletedCallback) + public Db4OServerFinder(Action foundServerCallback) { m_foundServerCallback = foundServerCallback; - m_onCompletedCallback = onCompletedCallback; + + m_hostListenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) {Blocking = false}; + EndPoint ep = new IPEndPoint(IPAddress.Any, HostDiscoveryBroadcastReplyPort); + m_hostListenerSocket.Bind(ep); // Start the thread that collects responses from our broadcast. m_hostListenerThread = new Thread(ThreadStartListenForServers); @@ -69,11 +70,6 @@ public Db4OServerFinder(Action foundServerCallback, Action onCompletedCa /// ------------------------------------------------------------------------------------ private void BroadcastToFindHosts() { - // Ensure the thread is listening before doing the broadcast - // as it could return before we are listening for it. - while (m_hostListenerThread.IsAlive && (m_hostListenerSocket == null || !m_hostListenerSocket.IsBound)) - Thread.Sleep(80); - // On Windows 7, this silently fails if the computer isn't connected to the network. // On Windows XP, it eventually (after timeout?) throws a SocketException "A socket // operation was attempted to an unreachable host". @@ -82,11 +78,11 @@ private void BroadcastToFindHosts() // Send the broadcast. using (Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) { - sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); - EndPoint iep = new IPEndPoint(IPAddress.Broadcast, HostDiscoveryBroadcastPort); + sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); + EndPoint iep = new IPEndPoint(IPAddress.Broadcast, HostDiscoveryBroadcastPort); - sock.SendTo(new byte[] { 0 }, iep); - } + sock.SendTo(new byte[] { 0 }, iep); + } } catch (SocketException) { @@ -102,54 +98,44 @@ private void BroadcastToFindHosts() /// ------------------------------------------------------------------------------------ private void ThreadStartListenForServers() { - m_hostListenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - try - { - m_hostListenerSocket.Blocking = false; - EndPoint ep = new IPEndPoint(IPAddress.Any, HostDiscoveryBroadcastReplyPort); try { - m_hostListenerSocket.Bind(ep); - } - catch (SocketException e) - { - MessageBoxUtils.Show(String.Format("Unable to bind to port {0} because {1}", HostDiscoveryBroadcastReplyPort, e)); - return; - } - - byte[] data = new byte[1024]; - int cVainAttempts = 0; - while (true) // keep listening until thread is killed. - { - int recv = 0; - lock (m_syncRoot) - { - if (m_hostListenerSocket == null) // another thread can set this to null. - break; - if (m_hostListenerSocket.Available > 0) - ExceptionHelper.LogAndIgnoreErrors(() => recv = m_hostListenerSocket.ReceiveFrom(data, ref ep)); - } - if (recv > 0) + byte[] data = new byte[1024]; + int cVainAttempts = 0; + while (true) // keep listening until thread is killed. { + EndPoint ep = new IPEndPoint(IPAddress.Any, 0); + int recv = 0; lock (m_syncRoot) - m_foundServerCallback(((IPEndPoint)ep).Address.ToString()); - cVainAttempts = 0; - } - else - { - if (cVainAttempts++ > 50) - break; // if no server has pinged us for 5 seconds, let's hang it up. - Thread.Sleep(100); + { + if (m_hostListenerSocket == null) // another thread can set this to null. + break; + if (m_hostListenerSocket.Available > 0) + ExceptionHelper.LogAndIgnoreErrors(() => recv = m_hostListenerSocket.ReceiveFrom(data, ref ep)); + } + if (recv > 0) + { + lock (m_syncRoot) + m_foundServerCallback(((IPEndPoint)ep).Address.ToString()); + cVainAttempts = 0; + } + else + { + if (cVainAttempts++ > 50) + break; // if no server has pinged us for 5 seconds, let's hang it up. + Thread.Sleep(100); + } } } - - if (m_hostListenerSocket != null && m_onCompletedCallback != null) - m_onCompletedCallback(); - } finally { - CloseSocket(); + CloseSocket(); + } } + + public bool IsCompleted + { + get { return !m_hostListenerThread.IsAlive; } } /// ------------------------------------------------------------------------------------ diff --git a/Src/FDO/DomainServices/ScrSfFileList.cs b/Src/FDO/DomainServices/ScrSfFileList.cs index 6bb9a991aa..d1d694f891 100644 --- a/Src/FDO/DomainServices/ScrSfFileList.cs +++ b/Src/FDO/DomainServices/ScrSfFileList.cs @@ -121,8 +121,6 @@ public ScrSfFileList(IScrImportSFFiles source, ScrMappingList mappingList, { var userAction = source.Services.GetInstance(); userAction.DisplayMessage(MessageType.Error, string.Format(ScrFdoResources.kstidImportBadFile, e.Message), Strings.ksErrorCaption, e.HelpTopic); - //MessageBoxUtils.Show(, "", MessageBoxButtons.OK, - // MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, 0, helpFile, HelpNavigator.Topic, e.HelpTopic); deleteList.Add(file); } } diff --git a/Src/FDO/fdoCache.cs b/Src/FDO/fdoCache.cs index 5659af807a..bf9509faa5 100644 --- a/Src/FDO/fdoCache.cs +++ b/Src/FDO/fdoCache.cs @@ -743,8 +743,6 @@ internal static void CreateProjectSubfolders(string dbDirName) } catch (Exception e) { - MessageBoxUtils.Show(String.Format(AppStrings.ksCreateNewProjectSubfoldersError, - e.Message)); throw new ApplicationException(e.Message, e); } diff --git a/Src/FdoUi/FwFdoUI.cs b/Src/FdoUi/FwFdoUI.cs index eadc7e398c..597a0c69be 100644 --- a/Src/FdoUi/FwFdoUI.cs +++ b/Src/FdoUi/FwFdoUI.cs @@ -152,11 +152,16 @@ public void DisplayMessage(MessageType type, string message, string caption, str } m_synchronizeInvoke.Invoke(() => { +#if __MonoCS__ + // Mono doesn't support Help + MessageBox.Show(message, caption, MessageBoxButtons.OK, icon); +#else if (string.IsNullOrEmpty(helpTopic)) MessageBox.Show(message, caption, MessageBoxButtons.OK, icon); else MessageBox.Show(message, caption, MessageBoxButtons.OK, icon, MessageBoxDefaultButton.Button1, 0, m_helpTopicProvider.HelpFile, HelpNavigator.Topic, helpTopic); +#endif }); } diff --git a/Src/FwCoreDlgs/ChooseLangProjectDialog.cs b/Src/FwCoreDlgs/ChooseLangProjectDialog.cs index 3e8712e90c..0e69f64de1 100644 --- a/Src/FwCoreDlgs/ChooseLangProjectDialog.cs +++ b/Src/FwCoreDlgs/ChooseLangProjectDialog.cs @@ -233,8 +233,15 @@ protected override void OnShown(EventArgs e) } } - // Asynchronously search for other Servers. - ClientServerServices.Current.BeginFindServers(AddHost1); + try + { + // Asynchronously search for other Servers. + ClientServerServices.Current.BeginFindServers(AddHost1); + } + catch (Exception) + { + MessageBox.Show(FwCoreDlgs.ksFindServersError, FwCoreDlgs.ksError, MessageBoxButtons.OK, MessageBoxIcon.Error); + } m_lstLanguageProjects.SelectedIndexChanged += LanguageProjectsListSelectedIndexChanged; @@ -285,9 +292,6 @@ internal bool AddHost(string ipAddress) return false; } - // store the HostName -> ipaddress mapping. - m_hostIpAddressMap[entry.HostName] = ipAddress; - AddHostInternal(entry); return true; @@ -312,6 +316,9 @@ private void AddHostInternal(IPHostEntry entry) if (IsDisposed || m_networkNeighborhood.Nodes.ContainsKey((entry.HostName))) return; + // store the HostName -> ipaddress mapping. + m_hostIpAddressMap[entry.HostName] = entry.AddressList[0].ToString(); + // if list of associated addresses in entry matches list of associated addresses of any item in hostsTreeView // then ignore as its the same host. try diff --git a/Src/FwCoreDlgs/FwCoreDlgs.Designer.cs b/Src/FwCoreDlgs/FwCoreDlgs.Designer.cs index 84a2072fa8..e10b03c8db 100644 --- a/Src/FwCoreDlgs/FwCoreDlgs.Designer.cs +++ b/Src/FwCoreDlgs/FwCoreDlgs.Designer.cs @@ -482,6 +482,15 @@ public static string ksFindConvMappingFile { } } + /// + /// Looks up a localized string similar to Unable to search for remote servers.. + /// + public static string ksFindServersError { + get { + return ResourceManager.GetString("ksFindServersError", resourceCulture); + } + } + /// /// Looks up a localized string similar to Find Spec file for unknown mapping type. /// diff --git a/Src/FwCoreDlgs/FwCoreDlgs.resx b/Src/FwCoreDlgs/FwCoreDlgs.resx index 6ba3c8df47..e205cfed67 100644 --- a/Src/FwCoreDlgs/FwCoreDlgs.resx +++ b/Src/FwCoreDlgs/FwCoreDlgs.resx @@ -982,4 +982,7 @@ The error was: FieldWorks was not able to back up some of the files used by this project. Do you want to keep the backup anyway? The files not backed up were {0} + + Unable to search for remote servers. + \ No newline at end of file diff --git a/Src/LexText/Interlinear/LinguaLinksImport.cs b/Src/LexText/Interlinear/LinguaLinksImport.cs index 754f0353e4..b54f5ee346 100644 --- a/Src/LexText/Interlinear/LinguaLinksImport.cs +++ b/Src/LexText/Interlinear/LinguaLinksImport.cs @@ -1577,14 +1577,15 @@ private bool Convert6() try { XmlImportData xid = new XmlImportData(m_cache); - return xid.ImportData(m_nextInput, m_progress); + xid.ImportData(m_nextInput, m_progress); + return true; } catch { string sLogFile = Path.Combine(m_sTempDir, m_nextInput); ReportError(string.Format(ITextStrings.ksFailedLoadingLL, m_LinguaLinksXmlFileName, m_cache.ProjectId.Name, - System.Environment.NewLine, sLogFile), + Environment.NewLine, sLogFile), ITextStrings.ksLLImportFailed); return false; } diff --git a/Src/LexText/LexTextControls/LexImport.cs b/Src/LexText/LexTextControls/LexImport.cs index 268e178d90..ee287573ae 100644 --- a/Src/LexText/LexTextControls/LexImport.cs +++ b/Src/LexText/LexTextControls/LexImport.cs @@ -98,7 +98,6 @@ public object Import(IThreadedProgress dlg, object[] parameters) string sErrorMsg = LexTextControls.ksTransformProblem_X; bool fAttemptedXml = false; - bool fXmlOk = false; string processedInputFile = databaseFileName; string sPhase1Output = Path.Combine(m_sTempDir, s_sPhase1FileName); string sPhase2Output = Path.Combine(m_sTempDir, s_sPhase2FileName); @@ -111,11 +110,20 @@ public object Import(IThreadedProgress dlg, object[] parameters) // if starting with a phase file, rename the phase file with the input file switch (startPhase) { - case 1: sPhase1Output = databaseFileName; break; - case 2: sPhase2Output = databaseFileName; break; - case 3: sPhase3Output = databaseFileName; break; - case 4: m_sPhase4Output = databaseFileName; break; - default: break; // no renaming needed + case 1: + sPhase1Output = databaseFileName; + break; + case 2: + sPhase2Output = databaseFileName; + break; + case 3: + sPhase3Output = databaseFileName; + break; + case 4: + m_sPhase4Output = databaseFileName; + break; + default: + break; // no renaming needed } if (startPhase < 2) @@ -167,7 +175,7 @@ public object Import(IThreadedProgress dlg, object[] parameters) fAttemptedXml = true; if (startPhase == 4 && processedInputFile.Length == 0) processedInputFile = m_sPhase4Output; - fXmlOk = xid.ImportData(m_sPhase4Output, dlg); + xid.ImportData(m_sPhase4Output, dlg); sErrorMsg = LexTextControls.ksLogFileProblem5_X; ProcessLogFile(processedInputFile, startPhase, xid); return true; @@ -179,7 +187,7 @@ public object Import(IThreadedProgress dlg, object[] parameters) ReportError(string.Format(sErrorMsg, ex.Message), LexTextControls.ksUnhandledError); - if (fAttemptedXml && !fXmlOk) + if (fAttemptedXml) { // We want to see the log file even (especially) if the Xml blows up. ProcessLogFile(processedInputFile, startPhase, xid); From 068b691773debfe1ba454582b2357c45b23fd71f Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 6 Dec 2013 11:15:36 +0700 Subject: [PATCH 020/143] suppress Gendarme errors caused by previous revision Change-Id: Id50f30811405de1c5cd76e6bb0e99bbf82e74965 --- .../ApplicationServices/XmlImportData.cs | 3 +++ Src/FDO/DomainServices/Db4OServerFinder.cs | 3 +++ Src/FDO/FDOTests/XmlImportDataTests.cs | 13 ++++--------- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Src/FDO/Application/ApplicationServices/XmlImportData.cs b/Src/FDO/Application/ApplicationServices/XmlImportData.cs index b8efe35aea..fc2e8f0c0e 100644 --- a/Src/FDO/Application/ApplicationServices/XmlImportData.cs +++ b/Src/FDO/Application/ApplicationServices/XmlImportData.cs @@ -14,6 +14,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Text; @@ -292,6 +293,8 @@ private void LogMessage(string sMsg) /// /// true if successful, false if an error occurs /// ------------------------------------------------------------------------------------ + [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", + Justification = "xrdr is disposed when closed.")] public void ImportData(TextReader rdr, TextWriter wrtrLog, IProgress progress) { bool fRetVal = true; diff --git a/Src/FDO/DomainServices/Db4OServerFinder.cs b/Src/FDO/DomainServices/Db4OServerFinder.cs index 57922f1523..d409223d74 100644 --- a/Src/FDO/DomainServices/Db4OServerFinder.cs +++ b/Src/FDO/DomainServices/Db4OServerFinder.cs @@ -12,6 +12,7 @@ // Responsibility: FW Team // --------------------------------------------------------------------------------------------- using System; +using System.Diagnostics.CodeAnalysis; using System.Net; using System.Net.Sockets; using System.Threading; @@ -24,6 +25,8 @@ namespace SIL.FieldWorks.FDO.DomainServices /// In a separate thread, finds any DB4o servers on the network. /// /// ---------------------------------------------------------------------------------------- + [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", + Justification = "m_hostListenerSocket is disposed when closed.")] internal class Db4OServerFinder { #region Data members diff --git a/Src/FDO/FDOTests/XmlImportDataTests.cs b/Src/FDO/FDOTests/XmlImportDataTests.cs index 6b4e81f977..ef6591b86d 100644 --- a/Src/FDO/FDOTests/XmlImportDataTests.cs +++ b/Src/FDO/FDOTests/XmlImportDataTests.cs @@ -27,7 +27,6 @@ using SIL.FieldWorks.FDO.Application.ApplicationServices; using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.Test.TestUtils; -using SIL.Utils; namespace SIL.FieldWorks.FDO.FDOTests { @@ -166,8 +165,7 @@ public void ImportData1() Assert.AreEqual(0, m_cache.LangProject.AnthroListOA.PossibilitiesOS.Count); Assert.AreEqual(0, m_cache.LangProject.SemanticDomainListOA.PossibilitiesOS.Count); Assert.AreEqual(0, m_cache.LangProject.PartsOfSpeechOA.PossibilitiesOS.Count); - bool fOk = xid.ImportData(rdr, new StringWriter(sbLog), null); - Assert.IsTrue(fOk, "Import of one lexical entry succeeded."); + xid.ImportData(rdr, new StringWriter(sbLog), null); DateTime dtLexNew = m_cache.LangProject.LexDbOA.DateCreated; DateTime dt2 = new DateTime(1995, 12, 19, 10, 31, 25); Assert.AreEqual(dt2, dtLexNew, "LexDb DateCreated changed to reflect import value."); @@ -390,8 +388,7 @@ public void ImportData2() )) { StringBuilder sbLog = new StringBuilder(); - bool fOk = xid.ImportData(rdr, new StringWriter(sbLog), null); - Assert.IsTrue(fOk, "Import of one LexEntry, one RreversalIndexEntry, and two WfiWordforms succeeded."); + xid.ImportData(rdr, new StringWriter(sbLog), null); IWritingSystem wsEn = m_cache.ServiceLocator.WritingSystemManager.Get("en"); Assert.AreEqual(1, m_cache.LangProject.LexDbOA.ReversalIndexesOC.Count); IReversalIndex revIdx = m_cache.LangProject.LexDbOA.ReversalIndexesOC.ToArray()[0]; @@ -873,8 +870,7 @@ public void ImportData3() )) { StringBuilder sbLog = new StringBuilder(); - bool fOk = xid.ImportData(rdr, new StringWriter(sbLog), null); - Assert.IsTrue(fOk, "Import of a bunch of stuff succeeded."); + xid.ImportData(rdr, new StringWriter(sbLog), null); int wsEn = m_cache.WritingSystemFactory.GetWsFromStr("en"); int wsAme = m_cache.WritingSystemFactory.GetWsFromStr("qaa-x-ame"); Assert.AreEqual(0, m_cache.LangProject.LexDbOA.ReversalIndexesOC.Count); @@ -1378,8 +1374,7 @@ public void ImportData4() Assert.AreEqual(0, m_cache.LangProject.SemanticDomainListOA.PossibilitiesOS.Count); Assert.AreEqual(0, m_cache.LangProject.PartsOfSpeechOA.PossibilitiesOS.Count); StringBuilder sbLog = new StringBuilder(); - bool fOk = xid.ImportData(rdr, new StringWriter(sbLog), null); - Assert.IsTrue(fOk, "Import of one lexical entry succeeded."); + xid.ImportData(rdr, new StringWriter(sbLog), null); Assert.AreEqual(1, m_cache.LangProject.LexDbOA.Entries.Count()); ILexEntry le = m_cache.LangProject.LexDbOA.Entries.ToArray()[0]; int wsKal = m_cache.WritingSystemFactory.GetWsFromStr("qaa-x-kal"); From 398f278021dcdd02aa69735d75c9ff8b27803b17 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Fri, 6 Dec 2013 10:52:48 +0700 Subject: [PATCH 021/143] Move more message boxes out of FDO Change-Id: I9ed150d011aa4a78d8ab7f07ccce0e977d4b635b --- Src/Common/FieldWorks/FieldWorks.cs | 11 +- .../ApplicationServices/XmlList.cs | 196 ++++++++---------- .../ApplicationServices/XmlTranslatedLists.cs | 40 ++-- Src/FDO/DomainServices/FwStyleSheet.cs | 25 ++- .../Infrastructure/Impl/FDOBackendProvider.cs | 6 - Src/FDO/Strings.Designer.cs | 9 - Src/FDO/Strings.resx | 58 +++--- Src/FwCoreDlgs/FwNewLangProject.cs | 10 + Src/FwCoreDlgs/FwStylesDlg.cs | 13 +- Src/FwResources/FwStrings.Designer.cs | 9 + Src/FwResources/FwStrings.resx | 58 +++--- 11 files changed, 219 insertions(+), 216 deletions(-) diff --git a/Src/Common/FieldWorks/FieldWorks.cs b/Src/Common/FieldWorks/FieldWorks.cs index df2ec13bfe..88e6d2cc04 100644 --- a/Src/Common/FieldWorks/FieldWorks.cs +++ b/Src/Common/FieldWorks/FieldWorks.cs @@ -3102,7 +3102,7 @@ private static bool InitializeFirstApp(FwApp app, ProjectId projectId) sparkle.AboutToExitForInstallerRun += delegate(object sender, CancelEventArgs args) { CloseAllMainWindows(); - if(app.ActiveMainWindow != null) + if (app.ActiveMainWindow != null) { args.Cancel = true; } @@ -3113,6 +3113,15 @@ private static bool InitializeFirstApp(FwApp app, ProjectId projectId) return true; } } + catch (UnauthorizedAccessException uae) + { + if (MiscUtils.IsUnix) + { + // Tell Mono user he/she needs to logout and log back in + MessageBoxUtils.Show(ResourceHelper.GetResourceString("ksNeedToJoinFwGroup")); + } + throw; + } finally { CloseSplashScreen(); diff --git a/Src/FDO/Application/ApplicationServices/XmlList.cs b/Src/FDO/Application/ApplicationServices/XmlList.cs index 4216df829f..4a91f8ea8c 100644 --- a/Src/FDO/Application/ApplicationServices/XmlList.cs +++ b/Src/FDO/Application/ApplicationServices/XmlList.cs @@ -63,15 +63,8 @@ public void ImportList(ICmObject owner, string sFieldName, string sFile, IProgre #if DEBUG DateTime dtBegin = DateTime.Now; #endif - try - { - using (var reader = new StreamReader(sFile, Encoding.UTF8)) - ImportList(owner, sFieldName, reader, progress); - } - catch (Exception e) - { - MessageBoxUtils.Show(e.Message); - } + using (var reader = new StreamReader(sFile, Encoding.UTF8)) + ImportList(owner, sFieldName, reader, progress); #if DEBUG DateTime dtEnd = DateTime.Now; TimeSpan span = new TimeSpan(dtEnd.Ticks - dtBegin.Ticks); @@ -89,110 +82,103 @@ public void ImportList(ICmObject owner, string sFieldName, TextReader reader, IP m_wsf = m_cache.WritingSystemFactory; m_progress = progress; - try - { - NonUndoableUnitOfWorkHelper.DoUsingNewOrCurrentUOW(m_cache.ActionHandlerAccessor, () => + NonUndoableUnitOfWorkHelper.DoUsingNewOrCurrentUOW(m_cache.ActionHandlerAccessor, () => + { + int flidList = m_mdc.GetFieldId(owner.ClassName, sFieldName, true); + if (flidList == 0) + throw new Exception(String.Format("Invalid list fieldname (programming error): {0}", sFieldName)); + using (var xrdr = XmlReader.Create(reader)) { - int flidList = m_mdc.GetFieldId(owner.ClassName, sFieldName, true); - if (flidList == 0) - throw new Exception(String.Format("Invalid list fieldname (programming error): {0}", sFieldName)); - using (var xrdr = XmlReader.Create(reader)) - { - xrdr.MoveToContent(); - if (xrdr.Name != owner.ClassName) - throw new Exception(String.Format("Unexpected outer element: {0}", xrdr.Name)); + xrdr.MoveToContent(); + if (xrdr.Name != owner.ClassName) + throw new Exception(String.Format("Unexpected outer element: {0}", xrdr.Name)); - if (!xrdr.ReadToDescendant(sFieldName)) - throw new Exception(String.Format("Unexpected second element: {0}", xrdr.Name)); + if (!xrdr.ReadToDescendant(sFieldName)) + throw new Exception(String.Format("Unexpected second element: {0}", xrdr.Name)); - if (!xrdr.ReadToDescendant("CmPossibilityList")) - throw new Exception(String.Format("Unexpected third element: {0}", xrdr.Name)); + if (!xrdr.ReadToDescendant("CmPossibilityList")) + throw new Exception(String.Format("Unexpected third element: {0}", xrdr.Name)); - ICmPossibilityList list; - int hvo = m_cache.MainCacheAccessor.get_ObjectProp(owner.Hvo, flidList); - if (hvo == 0) - hvo = m_cache.MainCacheAccessor.MakeNewObject(CmPossibilityListTags.kClassId, owner.Hvo, flidList, -2); - ICmPossibilityListRepository repo = m_cache.ServiceLocator.GetInstance(); - list = repo.GetObject(hvo); - string sItemClassName = "CmPossibility"; - xrdr.Read(); - while (xrdr.Depth == 3) + ICmPossibilityList list; + int hvo = m_cache.MainCacheAccessor.get_ObjectProp(owner.Hvo, flidList); + if (hvo == 0) + hvo = m_cache.MainCacheAccessor.MakeNewObject(CmPossibilityListTags.kClassId, owner.Hvo, flidList, -2); + ICmPossibilityListRepository repo = m_cache.ServiceLocator.GetInstance(); + list = repo.GetObject(hvo); + string sItemClassName = "CmPossibility"; + xrdr.Read(); + while (xrdr.Depth == 3) + { + xrdr.MoveToContent(); + if (xrdr.Depth < 3) + break; + switch (xrdr.Name) { - xrdr.MoveToContent(); - if (xrdr.Depth < 3) + case "Description": + SetMultiStringFromXml(xrdr, list.Description); break; - switch (xrdr.Name) - { - case "Description": - SetMultiStringFromXml(xrdr, list.Description); - break; - case "Name": - SetMultiUnicodeFromXml(xrdr, list.Name); - break; - case "Abbreviation": - SetMultiUnicodeFromXml(xrdr, list.Abbreviation); - break; - case "Depth": - list.Depth = ReadIntFromXml(xrdr); - break; - case "DisplayOption": - list.DisplayOption = ReadIntFromXml(xrdr); - break; - case "HelpFile": - list.HelpFile = ReadUnicodeFromXml(xrdr); - break; - case "IsClosed": - list.IsClosed = ReadBoolFromXml(xrdr); - break; - case "IsSorted": - list.IsSorted = ReadBoolFromXml(xrdr); - break; - case "IsVernacular": - list.IsVernacular = ReadBoolFromXml(xrdr); - break; - case "ItemClsid": - list.ItemClsid = ReadIntFromXml(xrdr); - sItemClassName = m_mdc.GetClassName(list.ItemClsid); - break; - case "ListVersion": - list.ListVersion = ReadGuidFromXml(xrdr); - break; - case "PreventChoiceAboveLevel": - list.PreventChoiceAboveLevel = ReadIntFromXml(xrdr); - break; - case "PreventDuplicates": - list.PreventDuplicates = ReadBoolFromXml(xrdr); - break; - case "PreventNodeChoices": - list.PreventNodeChoices = ReadBoolFromXml(xrdr); - break; - case "UseExtendedFields": - list.UseExtendedFields = ReadBoolFromXml(xrdr); - break; - case "WsSelector": - list.WsSelector = ReadIntFromXml(xrdr); - break; - case "Possibilities": - LoadPossibilitiesFromXml(xrdr, list, sItemClassName); - break; - case "HeaderFooterSets": - throw new Exception("We don't (yet?) handle HeaderFooterSets for CmPossibilityList (programming issue)"); - case "Publications": - throw new Exception("We don't (yet?) handle Publications for CmPossibilityList (programming issue)"); - default: - throw new Exception(String.Format("Unknown field element in CmPossibilityList: {0}", xrdr.Name)); - } + case "Name": + SetMultiUnicodeFromXml(xrdr, list.Name); + break; + case "Abbreviation": + SetMultiUnicodeFromXml(xrdr, list.Abbreviation); + break; + case "Depth": + list.Depth = ReadIntFromXml(xrdr); + break; + case "DisplayOption": + list.DisplayOption = ReadIntFromXml(xrdr); + break; + case "HelpFile": + list.HelpFile = ReadUnicodeFromXml(xrdr); + break; + case "IsClosed": + list.IsClosed = ReadBoolFromXml(xrdr); + break; + case "IsSorted": + list.IsSorted = ReadBoolFromXml(xrdr); + break; + case "IsVernacular": + list.IsVernacular = ReadBoolFromXml(xrdr); + break; + case "ItemClsid": + list.ItemClsid = ReadIntFromXml(xrdr); + sItemClassName = m_mdc.GetClassName(list.ItemClsid); + break; + case "ListVersion": + list.ListVersion = ReadGuidFromXml(xrdr); + break; + case "PreventChoiceAboveLevel": + list.PreventChoiceAboveLevel = ReadIntFromXml(xrdr); + break; + case "PreventDuplicates": + list.PreventDuplicates = ReadBoolFromXml(xrdr); + break; + case "PreventNodeChoices": + list.PreventNodeChoices = ReadBoolFromXml(xrdr); + break; + case "UseExtendedFields": + list.UseExtendedFields = ReadBoolFromXml(xrdr); + break; + case "WsSelector": + list.WsSelector = ReadIntFromXml(xrdr); + break; + case "Possibilities": + LoadPossibilitiesFromXml(xrdr, list, sItemClassName); + break; + case "HeaderFooterSets": + throw new Exception("We don't (yet?) handle HeaderFooterSets for CmPossibilityList (programming issue)"); + case "Publications": + throw new Exception("We don't (yet?) handle Publications for CmPossibilityList (programming issue)"); + default: + throw new Exception(String.Format("Unknown field element in CmPossibilityList: {0}", xrdr.Name)); } - xrdr.Close(); - if (m_mapRelatedDomains.Count > 0) - SetRelatedDomainsLinks(); } - }); - } - catch (Exception e) - { - MessageBoxUtils.Show(e.Message); - } + xrdr.Close(); + if (m_mapRelatedDomains.Count > 0) + SetRelatedDomainsLinks(); + } + }); } Guid EnsureGuid(Guid guid) diff --git a/Src/FDO/Application/ApplicationServices/XmlTranslatedLists.cs b/Src/FDO/Application/ApplicationServices/XmlTranslatedLists.cs index e79309360a..b831608f00 100644 --- a/Src/FDO/Application/ApplicationServices/XmlTranslatedLists.cs +++ b/Src/FDO/Application/ApplicationServices/XmlTranslatedLists.cs @@ -52,30 +52,23 @@ public bool ImportTranslatedLists(string filename, FdoCache cache, IProgress pro #if DEBUG DateTime dtBegin = DateTime.Now; #endif - try + using (var inputStream = FileUtils.OpenStreamForRead(filename)) { - using (var inputStream = FileUtils.OpenStreamForRead(filename)) + var type = Path.GetExtension(filename).ToLowerInvariant(); + if (type == ".zip") { - var type = Path.GetExtension(filename).ToLowerInvariant(); - if (type == ".zip") - { - using (var zipStream = new ZipInputStream(inputStream)) - { - var entry = zipStream.GetNextEntry(); // advances it to where we can read the one zipped file. - using (var reader = new StreamReader(zipStream, Encoding.UTF8)) - ImportTranslatedLists(reader, cache, progress); - } - } - else + using (var zipStream = new ZipInputStream(inputStream)) { - using (var reader = new StreamReader(inputStream, Encoding.UTF8)) + var entry = zipStream.GetNextEntry(); // advances it to where we can read the one zipped file. + using (var reader = new StreamReader(zipStream, Encoding.UTF8)) ImportTranslatedLists(reader, cache, progress); } } - } - catch (Exception e) - { - MessageBoxUtils.Show(e.Message); + else + { + using (var reader = new StreamReader(inputStream, Encoding.UTF8)) + ImportTranslatedLists(reader, cache, progress); + } } #if DEBUG DateTime dtEnd = DateTime.Now; @@ -101,16 +94,9 @@ public bool ImportTranslatedLists(TextReader reader, FdoCache cache, IProgress p Debug.Assert(m_wsEn != 0); m_progress = progress; - try - { - using (var xreader = XmlReader.Create(reader)) + using (var xreader = XmlReader.Create(reader)) Import(xreader); - } - catch (Exception e) - { - MessageBoxUtils.Show(e.Message, "Import Error"); - return false; - } + return true; } diff --git a/Src/FDO/DomainServices/FwStyleSheet.cs b/Src/FDO/DomainServices/FwStyleSheet.cs index 5a57324ed7..2a3a2bbb75 100644 --- a/Src/FDO/DomainServices/FwStyleSheet.cs +++ b/Src/FDO/DomainServices/FwStyleSheet.cs @@ -993,10 +993,8 @@ public virtual IStStyle FindStyle(string name) /// called for a style already known to exist in the stylesheet. /// /// The style info table, containing 0 or more new styles - /// Name of the application calling this (or whatever - /// string you want to appear in a message box if we happen to show one). /// ------------------------------------------------------------------------------------ - public void CheckForDuplicates(StyleInfoTable styleInfoTable, string applicationName) + public void CheckForDuplicates(StyleInfoTable styleInfoTable) { bool fStylesheetReloaded = false; @@ -1023,11 +1021,10 @@ public void CheckForDuplicates(StyleInfoTable styleInfoTable, string application basedOn.Structure != style.Structure || basedOn.Function != style.Function) { - string sMsg = string.Format( - ResourceHelper.GetResourceString("kstidIncompatibleStyleExists"), - style.Name); - MessageBoxUtils.Show(sMsg, applicationName); styleInfo.IsValid = false; + throw new IncompatibleStyleExistsException(string.Format( + ResourceHelper.GetResourceString("kstidIncompatibleStyleExists"), + style.Name)); } else { @@ -1584,4 +1581,18 @@ public override void Delete(int hvoStyle) } #endregion } + + /// + /// Exception for handling case when an incompatible style already exists + /// + public class IncompatibleStyleExistsException : Exception + { + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + public IncompatibleStyleExistsException(string message) : base(message) + { + } + } } diff --git a/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs b/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs index 79e7ae0386..badd7ca750 100644 --- a/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs @@ -750,12 +750,6 @@ public void StartupExtantLanguageProject(IProjectIdentifier projectId, bool fBoo } catch (System.UnauthorizedAccessException e) { - if (MiscUtils.IsUnix) - { - // Tell Mono user he/she needs to logout and log back in - MessageBoxUtils.Show(Strings.ksNeedToJoinFwGroup); - } - // Release any resources. ShutdownInternal(); throw; diff --git a/Src/FDO/Strings.Designer.cs b/Src/FDO/Strings.Designer.cs index a74fcf941e..0ccce2dfba 100644 --- a/Src/FDO/Strings.Designer.cs +++ b/Src/FDO/Strings.Designer.cs @@ -1519,15 +1519,6 @@ internal static string ksNatClassUsedHere { } } - /// - /// Looks up a localized string similar to FieldWorks has encountered a problem setting up the writing systems. It may be that you need to first log out and then back in. If that doesn't fix it, you can also try asking an administrator to add you to the fieldworks group by using the command: $ sudo adduser 'yourusername' fieldworks. - /// - internal static string ksNeedToJoinFwGroup { - get { - return ResourceManager.GetString("ksNeedToJoinFwGroup", resourceCulture); - } - } - /// /// Looks up a localized string similar to No ({0}) Underline. /// diff --git a/Src/FDO/Strings.resx b/Src/FDO/Strings.resx index 4e142bf14d..22afdc0783 100644 --- a/Src/FDO/Strings.resx +++ b/Src/FDO/Strings.resx @@ -1,17 +1,17 @@ - @@ -373,10 +373,6 @@ - separate name and abbreviation (space dash space) - - FieldWorks has encountered a problem setting up the writing systems. It may be that you need to first log out and then back in. If that doesn't fix it, you can also try asking an administrator to add you to the fieldworks group by using the command: $ sudo adduser 'yourusername' fieldworks - Used in Linux version if the user forgets to logout and back in after New Install. - No ({0}) Underline nonsense, but a possibility diff --git a/Src/FwCoreDlgs/FwNewLangProject.cs b/Src/FwCoreDlgs/FwNewLangProject.cs index 215ceb0795..737854c82d 100644 --- a/Src/FwCoreDlgs/FwNewLangProject.cs +++ b/Src/FwCoreDlgs/FwNewLangProject.cs @@ -25,6 +25,7 @@ using SIL.FieldWorks.Common.Drawing; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices; +using SIL.FieldWorks.Resources; using SIL.Utils; using XCore; using SIL.FieldWorks.Common.RootSites; @@ -702,6 +703,15 @@ protected void CreateNewLangProjWithProgress(IFdoUI ui) } } } + catch (UnauthorizedAccessException uae) + { + if (MiscUtils.IsUnix) + { + // Tell Mono user he/she needs to logout and log back in + MessageBoxUtils.Show(ResourceHelper.GetResourceString("ksNeedToJoinFwGroup")); + } + throw; + } catch (WorkerThreadException wex) { Exception e = wex.InnerException; diff --git a/Src/FwCoreDlgs/FwStylesDlg.cs b/Src/FwCoreDlgs/FwStylesDlg.cs index c507d029ce..47e93d309d 100644 --- a/Src/FwCoreDlgs/FwStylesDlg.cs +++ b/Src/FwCoreDlgs/FwStylesDlg.cs @@ -814,9 +814,16 @@ private void m_btnOk_Click(object sender, EventArgs e) UpdateChanges(styleInfo); } - // Check to make sure new styles are not going to result in duplicates - // in the database - m_styleSheet.CheckForDuplicates(m_styleTable, m_app.ApplicationName); + try + { + // Check to make sure new styles are not going to result in duplicates + // in the database + m_styleSheet.CheckForDuplicates(m_styleTable); + } + catch (IncompatibleStyleExistsException isee) + { + MessageBoxUtils.Show(isee.Message, m_app.ApplicationName); + } foreach (StyleInfo style in m_styleTable.Values) { diff --git a/Src/FwResources/FwStrings.Designer.cs b/Src/FwResources/FwStrings.Designer.cs index 8f3a25b232..1008cd15f1 100644 --- a/Src/FwResources/FwStrings.Designer.cs +++ b/Src/FwResources/FwStrings.Designer.cs @@ -91,6 +91,15 @@ internal static string ksInvalidFwBackupFile { } } + /// + /// Looks up a localized string similar to FieldWorks has encountered a problem setting up the writing systems. It may be that you need to first log out and then back in. If that doesn't fix it, you can also try asking an administrator to add you to the fieldworks group by using the command: $ sudo adduser 'yourusername' fieldworks. + /// + internal static string ksNeedToJoinFwGroup { + get { + return ResourceManager.GetString("ksNeedToJoinFwGroup", resourceCulture); + } + } + /// /// Looks up a localized string similar to No guid attribute on factory style [{0}]. /// diff --git a/Src/FwResources/FwStrings.resx b/Src/FwResources/FwStrings.resx index 6471a490e3..55b84165ee 100644 --- a/Src/FwResources/FwStrings.resx +++ b/Src/FwResources/FwStrings.resx @@ -1,17 +1,17 @@ - @@ -1445,4 +1445,8 @@ To restore from this backup, install version {1} of FieldWorks. Adding FieldWorks project Used in Archive with RAMP dialog box + + FieldWorks has encountered a problem setting up the writing systems. It may be that you need to first log out and then back in. If that doesn't fix it, you can also try asking an administrator to add you to the fieldworks group by using the command: $ sudo adduser 'yourusername' fieldworks + Used in Linux version if the user forgets to logout and back in after New Install. + \ No newline at end of file From 8866119e03c18ac4ae0b24be34afbeda70aa8838 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Fri, 6 Dec 2013 13:51:46 +0700 Subject: [PATCH 022/143] Remove some references to FwResources from FDO Create FDO's own file extension class for containing file extension constants to remove dependencies on FwResources. Change-Id: Ic0f2717ae37e8012b2c9cbc9d42d415999896bcb --- .../BackupRestore/BackupFileRepository.cs | 5 +-- .../BackupRestore/BackupFileSettings.cs | 4 +- .../BackupRestore/BackupProjectSettings.cs | 4 +- .../BackupRestore/ProjectRestoreService.cs | 5 +-- .../DomainServices/ClientServerServices.cs | 7 ++-- .../DataMigration/ImportFrom6_0.cs | 3 +- Src/FDO/DomainServices/FwProjectFinder.cs | 4 +- Src/FDO/FDO.csproj | 1 + .../BackupFileRepositoryTests.cs | 4 +- .../BackupRestoreSettingsTests.cs | 9 ++-- .../ProjectRestoreServiceTests.cs | 2 +- Src/FDO/FDOTests/ClientServerServicesTests.cs | 5 +-- Src/FDO/FDOTests/Db4oServerInfoTests.cs | 3 +- Src/FDO/FdoFileExtensions.cs | 42 +++++++++++++++++++ Src/FDO/Infrastructure/Impl/Db4oServerInfo.cs | 6 +-- .../Infrastructure/Impl/XMLBackendProvider.cs | 2 +- Src/FwResources/FwFileExtensions.cs | 30 ++++++++----- 17 files changed, 85 insertions(+), 51 deletions(-) create mode 100644 Src/FDO/FdoFileExtensions.cs diff --git a/Src/FDO/DomainServices/BackupRestore/BackupFileRepository.cs b/Src/FDO/DomainServices/BackupRestore/BackupFileRepository.cs index f15520015b..d80408172e 100644 --- a/Src/FDO/DomainServices/BackupRestore/BackupFileRepository.cs +++ b/Src/FDO/DomainServices/BackupRestore/BackupFileRepository.cs @@ -16,7 +16,6 @@ using System.Text.RegularExpressions; using SIL.FieldWorks.Common.FwUtils; using System.Collections.Generic; -using SIL.FieldWorks.Resources; using SIL.Utils; using System.Globalization; @@ -58,7 +57,7 @@ public BackupFileRepository() foreach (string backup in backups) { string ext = Path.GetExtension(backup); - if (ext != FwFileExtensions.ksFwBackupFileExtension && ext != FwFileExtensions.ksFw60BackupFileExtension) + if (ext != FdoFileExtensions.ksFwBackupFileExtension && ext != FdoFileExtensions.ksFw60BackupFileExtension) continue; string filename = Path.GetFileNameWithoutExtension(backup); MatchCollection matches = regex.Matches(filename); @@ -80,7 +79,7 @@ public BackupFileRepository() { SortedDictionary versions = GetOrCreateProjectVersions(projectName); string comment; - if (ext == FwFileExtensions.ksFw60BackupFileExtension) + if (ext == FdoFileExtensions.ksFw60BackupFileExtension) comment = Properties.Resources.kstidFw60OrEarlierBackupComment; else { diff --git a/Src/FDO/DomainServices/BackupRestore/BackupFileSettings.cs b/Src/FDO/DomainServices/BackupRestore/BackupFileSettings.cs index dd19463327..deb0515ea7 100644 --- a/Src/FDO/DomainServices/BackupRestore/BackupFileSettings.cs +++ b/Src/FDO/DomainServices/BackupRestore/BackupFileSettings.cs @@ -397,7 +397,7 @@ private void PopulateSettingsFromZipFileIfNeeded() return; string extension = Path.GetExtension(m_sZipFileName).ToLowerInvariant(); - if (extension == FwFileExtensions.ksFw60BackupFileExtension) + if (extension == FdoFileExtensions.ksFw60BackupFileExtension) { ProcessOldZipFile(); return; @@ -431,7 +431,7 @@ private void PopulateSettingsFromZipFileIfNeeded() foundBackupSettingsFile = true; InitializeFromStream(zipIn); } - else if (Path.GetExtension(fileName) == FwFileExtensions.ksFwDataXmlFileExtension) + else if (Path.GetExtension(fileName) == FdoFileExtensions.ksFwDataXmlFileExtension) { if (dataFileName != null) throw new InvalidOperationException("Zip file " + m_sZipFileName + diff --git a/Src/FDO/DomainServices/BackupRestore/BackupProjectSettings.cs b/Src/FDO/DomainServices/BackupRestore/BackupProjectSettings.cs index f7831d788b..d59480315e 100644 --- a/Src/FDO/DomainServices/BackupRestore/BackupProjectSettings.cs +++ b/Src/FDO/DomainServices/BackupRestore/BackupProjectSettings.cs @@ -14,10 +14,8 @@ using System; using System.IO; using SIL.FieldWorks.Common.FwUtils; -using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.FDO.Infrastructure.Impl; using System.Reflection; -using SIL.FieldWorks.Resources; using SIL.Utils; namespace SIL.FieldWorks.FDO.DomainServices.BackupRestore @@ -155,7 +153,7 @@ public string AdjustedComment private string MakeBackupFileName(string comment) { return ProjectName + " " + BackupTime.ToString(ksBackupDateFormat) + - comment + FwFileExtensions.ksFwBackupFileExtension; + comment + FdoFileExtensions.ksFwBackupFileExtension; } /// ------------------------------------------------------------------------------------ diff --git a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs index 52da82ca77..7cae893341 100644 --- a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs +++ b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs @@ -21,7 +21,6 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; -using SIL.FieldWorks.Resources; namespace SIL.FieldWorks.FDO.DomainServices.BackupRestore { @@ -101,7 +100,7 @@ public void RestoreProject(IThreadedProgress progressDlg) { //Import from FW version 6.0 based on the file extension. var extension = Path.GetExtension(fileSettings.File).ToLowerInvariant(); - if (extension == FwFileExtensions.ksFw60BackupFileExtension || extension == ".xml") + if (extension == FdoFileExtensions.ksFw60BackupFileExtension || extension == ".xml") ImportFrom6_0Backup(fileSettings, progressDlg); else //Restore from FW version 7.0 and newer backup. RestoreFrom7_0AndNewerBackup(fileSettings); @@ -293,7 +292,7 @@ private void UncompressDataFiles() m_restoreSettings.ProjectPath, entry.DateTime); } string bakFile = Path.Combine(m_restoreSettings.ProjectPath, m_restoreSettings.ProjectName) - + FwFileExtensions.ksFwDataFallbackFileExtension; + + FdoFileExtensions.ksFwDataFallbackFileExtension; if (FileUtils.TrySimilarFileExists(bakFile, out bakFile)) { FileUtils.Delete(bakFile); // TODO: do something about the .Lock file....... diff --git a/Src/FDO/DomainServices/ClientServerServices.cs b/Src/FDO/DomainServices/ClientServerServices.cs index 01149ae194..77a4fbfef9 100644 --- a/Src/FDO/DomainServices/ClientServerServices.cs +++ b/Src/FDO/DomainServices/ClientServerServices.cs @@ -25,7 +25,6 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.FDO.Infrastructure.Impl; -using SIL.FieldWorks.Resources; namespace SIL.FieldWorks.FDO.DomainServices { @@ -78,8 +77,8 @@ public static string GetExtension(this FDOBackendProviderType type) { switch (type) { - case FDOBackendProviderType.kDb4oClientServer: return FwFileExtensions.ksFwDataDb4oFileExtension; - case FDOBackendProviderType.kXML: return FwFileExtensions.ksFwDataXmlFileExtension; + case FDOBackendProviderType.kDb4oClientServer: return FdoFileExtensions.ksFwDataDb4oFileExtension; + case FDOBackendProviderType.kXML: return FdoFileExtensions.ksFwDataXmlFileExtension; default: throw new InvalidEnumArgumentException("type", (int)type, typeof(FDOBackendProviderType)); } } @@ -864,7 +863,7 @@ public string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string { if (!ShareMyProjects) return xmlFilename; // no conversion needed. - string desiredPath = Path.ChangeExtension(xmlFilename, FwFileExtensions.ksFwDataDb4oFileExtension); + string desiredPath = Path.ChangeExtension(xmlFilename, FdoFileExtensions.ksFwDataDb4oFileExtension); if (!EnsureNoClientsAreConnected(Path.GetFileNameWithoutExtension(desiredPath), ui)) return null; // fail diff --git a/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs b/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs index fea07bb635..39d10bcfc3 100644 --- a/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs +++ b/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs @@ -17,7 +17,6 @@ using Microsoft.Win32; using SIL.FieldWorks.Common.FwUtils; -using SIL.FieldWorks.Resources; using SIL.Utils; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration @@ -76,7 +75,7 @@ public bool Import(string pathname, string projectName, out string projectFile) { var destFolder = DirectoryFinder.ProjectsDirectory; var folderName = Path.Combine(destFolder, projectName); - projectFile = Path.Combine(folderName, projectName + FwFileExtensions.ksFwDataXmlFileExtension); + projectFile = Path.Combine(folderName, projectName + FdoFileExtensions.ksFwDataXmlFileExtension); string extension = Path.GetExtension(pathname); if (extension != null) extension = extension.ToLowerInvariant(); diff --git a/Src/FDO/DomainServices/FwProjectFinder.cs b/Src/FDO/DomainServices/FwProjectFinder.cs index acca22b552..7a9068c35e 100644 --- a/Src/FDO/DomainServices/FwProjectFinder.cs +++ b/Src/FDO/DomainServices/FwProjectFinder.cs @@ -13,10 +13,8 @@ // --------------------------------------------------------------------------------------------- using System; using System.IO; -using System.Net; using System.Threading; using SIL.FieldWorks.Common.FwUtils; -using SIL.FieldWorks.Resources; using SIL.Utils; namespace SIL.FieldWorks.FDO.DomainServices @@ -95,7 +93,7 @@ private void FindProjects() if (!FileUtils.SimilarFileExists(db4oFile)) { // See if there is a .bak file - string backupFile = Path.ChangeExtension(file, FwFileExtensions.ksFwDataFallbackFileExtension); + string backupFile = Path.ChangeExtension(file, FdoFileExtensions.ksFwDataFallbackFileExtension); //NOTE: RickM I think this probably should be changed to TrySimilarFileExists but don't want to try this //on a release build. if (FileUtils.SimilarFileExists(backupFile)) diff --git a/Src/FDO/FDO.csproj b/Src/FDO/FDO.csproj index 1c19c84265..9bc3349c27 100644 --- a/Src/FDO/FDO.csproj +++ b/Src/FDO/FDO.csproj @@ -370,6 +370,7 @@ + diff --git a/Src/FDO/FDOTests/BackupRestore/BackupFileRepositoryTests.cs b/Src/FDO/FDOTests/BackupRestore/BackupFileRepositoryTests.cs index 24f45fa59e..e0d8f6380a 100644 --- a/Src/FDO/FDOTests/BackupRestore/BackupFileRepositoryTests.cs +++ b/Src/FDO/FDOTests/BackupRestore/BackupFileRepositoryTests.cs @@ -18,8 +18,6 @@ using NUnit.Framework; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.BackupRestore; -using SIL.FieldWorks.FDO.Infrastructure; -using SIL.FieldWorks.Resources; using SIL.FieldWorks.Test.TestUtils; using SIL.Utils; @@ -191,7 +189,7 @@ public void BackupHasOldStyleDatetimeFormat() DummyBackupProjectSettings backupSettings = new DummyBackupProjectSettings("monkey", "Floozy", null, FDOBackendProviderType.kXML); string backupFileName1 = Path.Combine(DirectoryFinder.DefaultBackupDirectory, - Path.ChangeExtension("Floozy 2010-8-21-0506", FwFileExtensions.ksFwBackupFileExtension)); + Path.ChangeExtension("Floozy 2010-8-21-0506", FdoFileExtensions.ksFwBackupFileExtension)); m_fileOs.AddExistingFile(backupFileName1); BackupFileRepository repo = new BackupFileRepository(); diff --git a/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs b/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs index 048e72550d..74c397c11e 100644 --- a/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs +++ b/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs @@ -17,9 +17,6 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.BackupRestore; -using SIL.FieldWorks.FDO.Infrastructure; -using SIL.FieldWorks.Resources; -using SIL.Utils; namespace SIL.FieldWorks.FDO.FDOTests.BackupRestore { @@ -85,7 +82,7 @@ public void RestoreProjectSettings_VerifyExistenceOfProject() RestoreProjectSettings restoreSettings = new RestoreProjectSettings() { Backup = new BackupFileSettings(Path.Combine(restoreTestsZipFileDir, - Path.ChangeExtension("TestRestoreFWProject", FwFileExtensions.ksFwBackupFileExtension))), + Path.ChangeExtension("TestRestoreFWProject", FdoFileExtensions.ksFwBackupFileExtension))), IncludeConfigurationSettings = false, IncludeLinkedFiles = false, IncludeSupportingFiles = true, @@ -125,7 +122,7 @@ public void RestoreProjectSettings_VerifyExistenceOfHgRepo() RestoreProjectSettings restoreSettings = new RestoreProjectSettings() { Backup = new BackupFileSettings(Path.Combine(restoreTestsZipFileDir, - Path.ChangeExtension("TestRestoreFWProject", FwFileExtensions.ksFwBackupFileExtension))), + Path.ChangeExtension("TestRestoreFWProject", FdoFileExtensions.ksFwBackupFileExtension))), IncludeConfigurationSettings = false, IncludeLinkedFiles = false, IncludeSupportingFiles = true, @@ -223,7 +220,7 @@ public void RestoreProjectSettings_CreateFromCommandLineOptions() public void BackupFileSettings_InitializeFromZipfileMetadata() { string zipFilePath = Path.Combine(Path.Combine(DirectoryFinder.FwSourceDirectory, "FDO/FDOTests/BackupRestore/RestoreProjectPresenterTests"), - Path.ChangeExtension("RestoreProjectPresenterTests", FwFileExtensions.ksFwBackupFileExtension)); + Path.ChangeExtension("RestoreProjectPresenterTests", FdoFileExtensions.ksFwBackupFileExtension)); BackupFileSettings backupSettings = new BackupFileSettings(zipFilePath); Assert.AreEqual("BackupOnlyCoreFiles", backupSettings.Comment); diff --git a/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs b/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs index f263830f3f..5348750517 100644 --- a/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs +++ b/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs @@ -69,7 +69,7 @@ public void Initialize() m_restoreSettings = new RestoreProjectSettings() { Backup = new BackupFileSettings(Path.Combine(restoreTestsZipFileDir, - Path.ChangeExtension("TestRestoreFWProject", FwFileExtensions.ksFwBackupFileExtension))), + Path.ChangeExtension("TestRestoreFWProject", FdoFileExtensions.ksFwBackupFileExtension))), IncludeConfigurationSettings = false, IncludeLinkedFiles = false, IncludeSupportingFiles = false, diff --git a/Src/FDO/FDOTests/ClientServerServicesTests.cs b/Src/FDO/FDOTests/ClientServerServicesTests.cs index b9b0ed84fa..961822d255 100644 --- a/Src/FDO/FDOTests/ClientServerServicesTests.cs +++ b/Src/FDO/FDOTests/ClientServerServicesTests.cs @@ -1,13 +1,10 @@ using System; using System.IO; -using System.Windows.Forms; using FwRemoteDatabaseConnector; using NUnit.Framework; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices; -using SIL.FieldWorks.Resources; using SIL.FieldWorks.Test.TestUtils; -using SIL.Utils; namespace SIL.FieldWorks.FDO.FDOTests { @@ -135,7 +132,7 @@ public void IdForLocalProject_SimpleNameProjectsAreNotShared_ReturnedFilenameHas string filename = ClientServerServices.Current.Local.IdForLocalProject("tom"); // Assert ends with .fwdata - Assert.AreEqual(FwFileExtensions.ksFwDataXmlFileExtension, Path.GetExtension(filename)); + Assert.AreEqual(FdoFileExtensions.ksFwDataXmlFileExtension, Path.GetExtension(filename)); // Check file is in ProjectDirectory. Assert.That(filename, Is.SubPath(DirectoryFinder.ProjectsDirectory)); diff --git a/Src/FDO/FDOTests/Db4oServerInfoTests.cs b/Src/FDO/FDOTests/Db4oServerInfoTests.cs index e7657fd15c..45cc819110 100644 --- a/Src/FDO/FDOTests/Db4oServerInfoTests.cs +++ b/Src/FDO/FDOTests/Db4oServerInfoTests.cs @@ -10,7 +10,6 @@ using NUnit.Framework; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices; -using SIL.FieldWorks.Resources; using SIL.FieldWorks.Test.TestUtils; namespace SIL.FieldWorks.FDO.FDOTests @@ -203,7 +202,7 @@ public void StopFwRemoteDatabaseConnector() [Test] public void ListServers_UnknownNumberOfServers_ReturnsAllServersInProjectsDirectory() { - int projectsCount = Directory.GetFiles(DirectoryFinder.ProjectsDirectory, "*" + FwFileExtensions.ksFwDataDb4oFileExtension, + int projectsCount = Directory.GetFiles(DirectoryFinder.ProjectsDirectory, "*" + FdoFileExtensions.ksFwDataDb4oFileExtension, SearchOption.AllDirectories).Count(); m_db4OServerInfo.RefreshServerList(); diff --git a/Src/FDO/FdoFileExtensions.cs b/Src/FDO/FdoFileExtensions.cs new file mode 100644 index 0000000000..d5deb1e016 --- /dev/null +++ b/Src/FDO/FdoFileExtensions.cs @@ -0,0 +1,42 @@ +// -------------------------------------------------------------------------------------------- +#region // Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Distributable under the terms of either the Common Public License or the +// GNU Lesser General Public License, as specified in the LICENSING.txt file. +// +#endregion +// +// File: FdoFileExtensions.cs +// -------------------------------------------------------------------------------------------- + +namespace SIL.FieldWorks.FDO +{ + /// ---------------------------------------------------------------------------------------- + /// + /// Static class to hold a few constant FDO file extensions. + /// + /// ---------------------------------------------------------------------------------------- + internal static class FdoFileExtensions + { + /* + * The following extensions are also defined in FwFileExtensions + * as a temporary stopgap. + * The idea is that eventually, those will be removed + * and all references will use FdoFileExtensions. + * + * If a change is made here, it should be made in FwFileExtensions as well. + */ + /// Default extension for FieldWorks XML data files (with the period) + internal const string ksFwDataXmlFileExtension = ".fwdata"; + /// Default extension for FieldWorks DB4o data files (with the period) + internal const string ksFwDataDb4oFileExtension = ".fwdb"; + /// Default extension for FieldWorks backup files (with the period). + internal const string ksFwBackupFileExtension = ".fwbackup"; + /// Default extension for FieldWorks 6.0 and earlier backup files (with the period). + internal const string ksFw60BackupFileExtension = ".zip"; + /// Default extension for FieldWorks TEMPORARY fallback data files (with the period). + internal const string ksFwDataFallbackFileExtension = ".bak"; + } +} diff --git a/Src/FDO/Infrastructure/Impl/Db4oServerInfo.cs b/Src/FDO/Infrastructure/Impl/Db4oServerInfo.cs index f7b674ba4c..bf732fe5ed 100644 --- a/Src/FDO/Infrastructure/Impl/Db4oServerInfo.cs +++ b/Src/FDO/Infrastructure/Impl/Db4oServerInfo.cs @@ -29,9 +29,7 @@ using Db4objects.Db4o; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; -using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.FDO.Infrastructure.Impl; -using SIL.FieldWorks.Resources; using SIL.FieldWorks.FDO.DomainServices; using System.Runtime.Remoting.Channels; @@ -98,14 +96,14 @@ internal void PopulateServerList() if (!Directory.Exists(DirectoryFinder.ProjectsDirectory)) throw new DirectoryNotFoundException(String.Format(Strings.ksWarningProjectFolderNotFoundOnServer, DirectoryFinder.ProjectsDirectory)); - string[] files = Directory.GetFiles(DirectoryFinder.ProjectsDirectory, "*" + FwFileExtensions.ksFwDataDb4oFileExtension); + string[] files = Directory.GetFiles(DirectoryFinder.ProjectsDirectory, "*" + FdoFileExtensions.ksFwDataDb4oFileExtension); m_allServers.AddRange(files); // search sub dirs string[] dirs = Directory.GetDirectories(DirectoryFinder.ProjectsDirectory); foreach (var dir in dirs) { - files = Directory.GetFiles(dir, "*" + FwFileExtensions.ksFwDataDb4oFileExtension); + files = Directory.GetFiles(dir, "*" + FdoFileExtensions.ksFwDataDb4oFileExtension); m_allServers.AddRange(files); } } diff --git a/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs b/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs index e338a9cab4..abf2eba539 100644 --- a/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs @@ -413,7 +413,7 @@ internal void UnlockProject() //protected override void RestoreWithoutMigration(string xmlBepPathname) //{ // // Copy original file to backup. - // var bakPathname = m_databasePath + FwFileExtensions.ksFwDataFallbackFileExtension; + // var bakPathname = m_databasePath + FdoFileExtensions.ksFwDataFallbackFileExtension; // if (File.Exists(bakPathname)) // File.Delete(bakPathname); // File.Copy(m_databasePath, bakPathname); diff --git a/Src/FwResources/FwFileExtensions.cs b/Src/FwResources/FwFileExtensions.cs index 4a287d863d..77196a9cd0 100644 --- a/Src/FwResources/FwFileExtensions.cs +++ b/Src/FwResources/FwFileExtensions.cs @@ -20,14 +20,6 @@ namespace SIL.FieldWorks.Resources /// ---------------------------------------------------------------------------------------- public static class FwFileExtensions { - /// Default extension for FieldWorks XML data files (with the period) - public const string ksFwDataXmlFileExtension = ".fwdata"; - /// Default extension for FieldWorks DB4o data files (with the period) - public const string ksFwDataDb4oFileExtension = ".fwdb"; - /// Default extension for FieldWorks backup files (with the period). - public const string ksFwBackupFileExtension = ".fwbackup"; - /// Default extension for FieldWorks 6.0 and earlier backup files (with the period). - public const string ksFw60BackupFileExtension = ".zip"; /// Default extension for Scripture XML (Open XML for Editing Scripture) files (with the period). public const string ksOpenXmlForEditingScripture = ".oxes"; /// Default extension for Scripture annotations XML (Open XML for Exchanging Scripture Annotations) files (with the period). @@ -36,9 +28,27 @@ public static class FwFileExtensions public const string ksOpenXmlForExchangingKeyTerms = ".oxekt"; /// Default extension for Lexicon Interchange FormaT files (with the period). public const string ksLexiconInterchangeFormat = ".lift"; - /// Default extension for FieldWorks TEMPORARY fallback data files (with the period). - public const string ksFwDataFallbackFileExtension = ".bak"; /// Default extension for FlexText format interlinear texts. public const string ksFLexText = ".flextext"; + + + /* + * The following extensions are also defined in FdoFileExtensions. + * They are defined here as a temporary stopgap. + * The idea is that eventually, these will be removed + * from here and all references will use FdoFileExtensions. + * + * If a change is made here, it should be made in FdoFileExtensions as well. + */ + /// Default extension for FieldWorks XML data files (with the period) + public const string ksFwDataXmlFileExtension = ".fwdata"; + /// Default extension for FieldWorks DB4o data files (with the period) + public const string ksFwDataDb4oFileExtension = ".fwdb"; + /// Default extension for FieldWorks backup files (with the period). + public const string ksFwBackupFileExtension = ".fwbackup"; + /// Default extension for FieldWorks 6.0 and earlier backup files (with the period). + public const string ksFw60BackupFileExtension = ".zip"; + /// Default extension for FieldWorks TEMPORARY fallback data files (with the period). + public const string ksFwDataFallbackFileExtension = ".bak"; } } From 6349825479d28d0bbf008ddc336ceee7c79e76c4 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Fri, 6 Dec 2013 14:26:31 +0700 Subject: [PATCH 023/143] Move some FwUtil code into FDO Remove dependencies of FDO upon FwUtil. Moved IProjectIdentifier and TestProjectId. Change-Id: I68da701502838655f1361dcbe56f1d0aefae475a --- Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.cs | 2 +- Src/Common/FieldWorks/FieldWorksTests/ProjectIDTests.cs | 1 + Src/Common/FieldWorks/WelcomeToFieldWorksDlg.cs | 3 +-- Src/Common/FwUtils/FwUtils.csproj | 1 - Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj | 1 - Src/FDO/FDO.csproj | 1 + Src/FDO/FDOTests/FDOTests.csproj | 1 + .../FwUtilsTests => FDO/FDOTests}/TestProjectId.cs | 8 ++++---- Src/{Common/FwUtils => FDO}/IProjectIdentifier.cs | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) rename Src/{Common/FwUtils/FwUtilsTests => FDO/FDOTests}/TestProjectId.cs (96%) rename Src/{Common/FwUtils => FDO}/IProjectIdentifier.cs (99%) diff --git a/Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.cs b/Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.cs index 843a9f3caa..59c4fd709f 100644 --- a/Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.cs +++ b/Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.cs @@ -13,7 +13,7 @@ // --------------------------------------------------------------------------------------------- using System; using NUnit.Framework; -using SIL.FieldWorks.Common.FwUtils; +using SIL.FieldWorks.FDO; using SIL.FieldWorks.Test.TestUtils; using SIL.Utils; diff --git a/Src/Common/FieldWorks/FieldWorksTests/ProjectIDTests.cs b/Src/Common/FieldWorks/FieldWorksTests/ProjectIDTests.cs index dd8e56caeb..4ffd763cc8 100644 --- a/Src/Common/FieldWorks/FieldWorksTests/ProjectIDTests.cs +++ b/Src/Common/FieldWorks/FieldWorksTests/ProjectIDTests.cs @@ -16,6 +16,7 @@ using NUnit.Framework; using Rhino.Mocks; using SIL.FieldWorks.Common.FwUtils; +using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.Test.TestUtils; using SIL.Utils; diff --git a/Src/Common/FieldWorks/WelcomeToFieldWorksDlg.cs b/Src/Common/FieldWorks/WelcomeToFieldWorksDlg.cs index cfa8581494..7eb6f7272b 100644 --- a/Src/Common/FieldWorks/WelcomeToFieldWorksDlg.cs +++ b/Src/Common/FieldWorks/WelcomeToFieldWorksDlg.cs @@ -14,9 +14,8 @@ using System.ComponentModel; using System.Diagnostics; using System.Windows.Forms; -using Palaso.Reporting; -using SIL.CoreImpl.Properties; using SIL.FieldWorks.Common.FwUtils; +using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices; using SIL.Utils; using XCore; diff --git a/Src/Common/FwUtils/FwUtils.csproj b/Src/Common/FwUtils/FwUtils.csproj index 9b731f79d1..f90d16c47c 100644 --- a/Src/Common/FwUtils/FwUtils.csproj +++ b/Src/Common/FwUtils/FwUtils.csproj @@ -178,7 +178,6 @@ - diff --git a/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj b/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj index 0b8a84df8c..fefe6781c3 100644 --- a/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj +++ b/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj @@ -168,7 +168,6 @@ - diff --git a/Src/FDO/FDO.csproj b/Src/FDO/FDO.csproj index 9bc3349c27..ae0826da14 100644 --- a/Src/FDO/FDO.csproj +++ b/Src/FDO/FDO.csproj @@ -372,6 +372,7 @@ + diff --git a/Src/FDO/FDOTests/FDOTests.csproj b/Src/FDO/FDOTests/FDOTests.csproj index efb2be7775..8659dc2915 100644 --- a/Src/FDO/FDOTests/FDOTests.csproj +++ b/Src/FDO/FDOTests/FDOTests.csproj @@ -381,6 +381,7 @@ + diff --git a/Src/Common/FwUtils/FwUtilsTests/TestProjectId.cs b/Src/FDO/FDOTests/TestProjectId.cs similarity index 96% rename from Src/Common/FwUtils/FwUtilsTests/TestProjectId.cs rename to Src/FDO/FDOTests/TestProjectId.cs index 05a83eaacd..ed221e6a78 100644 --- a/Src/Common/FwUtils/FwUtilsTests/TestProjectId.cs +++ b/Src/FDO/FDOTests/TestProjectId.cs @@ -11,9 +11,9 @@ // File: TestProjectId.cs // Responsibility: FW Team // --------------------------------------------------------------------------------------------- -using SysPath = System.IO.Path; +using SIL.FieldWorks.Common.FwUtils; -namespace SIL.FieldWorks.Common.FwUtils +namespace SIL.FieldWorks.FDO.FDOTests { /// ---------------------------------------------------------------------------------------- /// @@ -84,7 +84,7 @@ public string PipeHandle /// ------------------------------------------------------------------------------------ public string Name { - get { return SysPath.GetFileNameWithoutExtension(Path); } + get { return System.IO.Path.GetFileNameWithoutExtension(Path); } } /// ------------------------------------------------------------------------------------ @@ -95,7 +95,7 @@ public string Name /// ------------------------------------------------------------------------------------ public string ProjectFolder { - get { return SysPath.GetDirectoryName(Path); } + get { return System.IO.Path.GetDirectoryName(Path); } } /// ------------------------------------------------------------------------------------ diff --git a/Src/Common/FwUtils/IProjectIdentifier.cs b/Src/FDO/IProjectIdentifier.cs similarity index 99% rename from Src/Common/FwUtils/IProjectIdentifier.cs rename to Src/FDO/IProjectIdentifier.cs index 570269c133..4681752164 100644 --- a/Src/Common/FwUtils/IProjectIdentifier.cs +++ b/Src/FDO/IProjectIdentifier.cs @@ -13,7 +13,7 @@ // --------------------------------------------------------------------------------------------- using System; -namespace SIL.FieldWorks.Common.FwUtils +namespace SIL.FieldWorks.FDO { #region FDOBackendProviderType enum /// From 3f4be61eb510e5e1903cdfb5fc615eaa50a7f680 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Fri, 6 Dec 2013 15:29:43 +0700 Subject: [PATCH 024/143] Move some FwUtil code into BasicUtil Remove dependencies of FDO upon FwUtil. Moved IProgress. Change-Id: I3cbee27bf8e9455ed04a9194ad56708fee7ab2e4 --- Src/Common/FwUtils/FwUtils.csproj | 1 - Src/Common/FwUtils/IThreadedProgress.cs | 1 + Src/Common/FwUtils/ValidationProgress.cs | 1 + Src/FDO/DomainServices/WfiWordformServices.cs | 1 + Src/FDO/FdoRepositoryInterfaceAdditions.cs | 1 + Src/FdoUi/ProgressBarWrapper.cs | 1 + Src/FwCoreDlgs/FwSplashScreen.cs | 1 + .../LexTextDll/FlexStylesXmlAccessor.cs | 1 + Src/TE/DiffView/Cluster.cs | 1 + Src/TE/DiffView/DiffView.csproj | 573 +++++++++--------- .../TeDialogsTests/TeDialogsTests.csproj | 21 +- .../TeDialogsTests/ToolsOptionsDialogTests.cs | 1 + Src/TE/TeScrInitializer/TeScrBookRefsInit.cs | 1 + .../TeKeyTermsInitTests.cs | 1 + .../TeScrNoteCategoriesInitTests.cs | 1 + .../TeScrNoteCategoriesInit.cs | 1 + Src/TE/TeStylesXml/TeStylesXmlAccessor.cs | 1 + .../TeStylesXmlAccessorTests.cs | 1 + Src/Utilities/BasicUtils/BasicUtils.csproj | 1 + .../BasicUtils}/IProgress.cs | 4 +- Src/Utilities/FixFwData/FixFwData.csproj | 6 +- Src/Utilities/FixFwData/Program.cs | 2 +- .../FixFwDataDllTests.csproj | 4 + Src/Utilities/FixFwDataDll/FwDataFixer.cs | 1 + Src/xWorks/xWorksTests/XWorksAppTestBase.cs | 1 + 25 files changed, 332 insertions(+), 297 deletions(-) rename Src/{Common/FwUtils => Utilities/BasicUtils}/IProgress.cs (95%) diff --git a/Src/Common/FwUtils/FwUtils.csproj b/Src/Common/FwUtils/FwUtils.csproj index f90d16c47c..683ef5a5ee 100644 --- a/Src/Common/FwUtils/FwUtils.csproj +++ b/Src/Common/FwUtils/FwUtils.csproj @@ -194,7 +194,6 @@ - diff --git a/Src/Common/FwUtils/IThreadedProgress.cs b/Src/Common/FwUtils/IThreadedProgress.cs index e70589cc9f..910467625a 100644 --- a/Src/Common/FwUtils/IThreadedProgress.cs +++ b/Src/Common/FwUtils/IThreadedProgress.cs @@ -11,6 +11,7 @@ // File: IThreadedProgress.cs // --------------------------------------------------------------------------------------------- using System; +using SIL.Utils; namespace SIL.FieldWorks.Common.FwUtils { diff --git a/Src/Common/FwUtils/ValidationProgress.cs b/Src/Common/FwUtils/ValidationProgress.cs index d4362320bf..8949b25a3f 100644 --- a/Src/Common/FwUtils/ValidationProgress.cs +++ b/Src/Common/FwUtils/ValidationProgress.cs @@ -16,6 +16,7 @@ // --------------------------------------------------------------------------------------------- using System; using Palaso.Lift.Validation; +using SIL.Utils; namespace SIL.FieldWorks.Common.FwUtils { diff --git a/Src/FDO/DomainServices/WfiWordformServices.cs b/Src/FDO/DomainServices/WfiWordformServices.cs index c4890cf616..59a0ca9b09 100644 --- a/Src/FDO/DomainServices/WfiWordformServices.cs +++ b/Src/FDO/DomainServices/WfiWordformServices.cs @@ -22,6 +22,7 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.CoreImpl; using SIL.FieldWorks.FDO.DomainImpl; +using SIL.Utils; namespace SIL.FieldWorks.FDO.DomainServices { diff --git a/Src/FDO/FdoRepositoryInterfaceAdditions.cs b/Src/FDO/FdoRepositoryInterfaceAdditions.cs index 4f4e387d1d..9aa98de26f 100644 --- a/Src/FDO/FdoRepositoryInterfaceAdditions.cs +++ b/Src/FDO/FdoRepositoryInterfaceAdditions.cs @@ -18,6 +18,7 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.DomainServices.SemanticDomainSearch; +using SIL.Utils; namespace SIL.FieldWorks.FDO { diff --git a/Src/FdoUi/ProgressBarWrapper.cs b/Src/FdoUi/ProgressBarWrapper.cs index 8385bd1665..e50c187e24 100644 --- a/Src/FdoUi/ProgressBarWrapper.cs +++ b/Src/FdoUi/ProgressBarWrapper.cs @@ -14,6 +14,7 @@ using System.Diagnostics.CodeAnalysis; using System.Windows.Forms; using SIL.FieldWorks.Common.FwUtils; +using SIL.Utils; namespace SIL.FieldWorks.FdoUi { diff --git a/Src/FwCoreDlgs/FwSplashScreen.cs b/Src/FwCoreDlgs/FwSplashScreen.cs index 93619a27e0..4201a15512 100644 --- a/Src/FwCoreDlgs/FwSplashScreen.cs +++ b/Src/FwCoreDlgs/FwSplashScreen.cs @@ -19,6 +19,7 @@ using System.Windows.Forms; using SIL.FieldWorks.Common.FwUtils; +using SIL.Utils; namespace SIL.FieldWorks.FwCoreDlgs { diff --git a/Src/LexText/LexTextDll/FlexStylesXmlAccessor.cs b/Src/LexText/LexTextDll/FlexStylesXmlAccessor.cs index 8fc0637d2e..80cddd9718 100644 --- a/Src/LexText/LexTextDll/FlexStylesXmlAccessor.cs +++ b/Src/LexText/LexTextDll/FlexStylesXmlAccessor.cs @@ -2,6 +2,7 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.Common.Framework; +using SIL.Utils; namespace SIL.FieldWorks.XWorks.LexText { diff --git a/Src/TE/DiffView/Cluster.cs b/Src/TE/DiffView/Cluster.cs index a1fb530caa..c06cb28a91 100644 --- a/Src/TE/DiffView/Cluster.cs +++ b/Src/TE/DiffView/Cluster.cs @@ -21,6 +21,7 @@ using System.Linq; using SIL.FieldWorks.FDO; using System.Diagnostics; +using SIL.Utils; using SILUBS.SharedScrUtils; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices; diff --git a/Src/TE/DiffView/DiffView.csproj b/Src/TE/DiffView/DiffView.csproj index 962393704e..68122dc605 100644 --- a/Src/TE/DiffView/DiffView.csproj +++ b/Src/TE/DiffView/DiffView.csproj @@ -1,302 +1,305 @@ - + - Local - 9.0.30729 - 2.0 - {12D8342D-1E00-4B53-92DA-4CBB17B63590} - - - - Debug - AnyCPU - - - - - DiffView - - - JScript - Grid - IE50 - false - Library - SIL.FieldWorks.TE - OnBuildSuccess - - - - - - - - - 3.5 - v4.0 - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - + Local + 9.0.30729 + 2.0 + {12D8342D-1E00-4B53-92DA-4CBB17B63590} + + + + + + + Debug + AnyCPU + + + + + DiffView + + + JScript + Grid + IE50 + false + Library + SIL.FieldWorks.TE + OnBuildSuccess + + + + + + + + + 3.5 + v4.0 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + - ..\..\..\Output\Debug\ - false - 285212672 - false - - - DEBUG;TRACE - ..\..\..\Output\Debug\DiffView.xml - true - 4096 - false - 168,169,219,414,649,1635,1702,1701 - false - false - false - true - 4 - full - prompt - AllRules.ruleset - x86 + ..\..\..\Output\Debug\ + false + 285212672 + false + + + DEBUG;TRACE + ..\..\..\Output\Debug\DiffView.xml + true + 4096 + false + 168,169,219,414,649,1635,1702,1701 + false + false + false + true + 4 + full + prompt + AllRules.ruleset + x86 - ..\..\..\Output\Release\ - false - 285212672 - false - - - TRACE - - - true - 4096 - false - 168,169,219,414,649,1635,1702,1701 - true - false - false - false - 4 - full - prompt - AllRules.ruleset - x86 + ..\..\..\Output\Release\ + false + 285212672 + false + + + TRACE + + + true + 4096 + false + 168,169,219,414,649,1635,1702,1701 + true + false + false + false + 4 + full + prompt + AllRules.ruleset + x86 - - ..\..\..\Output\Debug\BasicUtils.dll - False - - - COMInterfaces - ..\..\..\Output\Debug\COMInterfaces.dll - - - False - ..\..\..\Output\Debug\CoreImpl.dll - - - FDO - ..\..\..\Output\Debug\FDO.dll - - - Framework - ..\..\..\Output\Debug\Framework.dll - - - FwControls - ..\..\..\Output\Debug\FwControls.dll - - - False - ..\..\..\Output\Debug\FwCoreDlgs.dll - - - FwResources - ..\..\..\Output\Debug\FwResources.dll - - - FwUtils - ..\..\..\Output\Debug\FwUtils.dll - - - False - ..\..\..\Output\Debug\ITextDll.dll - - - False - ..\..\..\DistFiles\Microsoft.Practices.ServiceLocation.dll - - - ..\..\..\Output\Debug\PrintLayout.dll - False - - - RootSite - ..\..\..\Output\Debug\RootSite.dll - - - ScriptureUtils - ..\..\..\Output\Debug\ScriptureUtils.dll - - - ScrUtilsInterfaces - ..\..\..\Output\Debug\ScrUtilsInterfaces.dll - - - False - ..\..\..\Output\Debug\SharedScrUtils.dll - - - ..\..\..\Output\Debug\SilUtils.dll - False - - - SimpleRootSite - ..\..\..\Output\Debug\SimpleRootSite.dll - - - False - ..\..\..\Output\Debug\SplitGridView.dll - - - System - - - - System.Data - - - System.Drawing - - - System.Windows.Forms - - - System.XML - - - False - ..\..\..\Output\Debug\TeEditing.dll - - - TeResources - ..\..\..\Output\Debug\TeResources.dll - - - TeViewConstructors - ..\..\..\Output\Debug\TeViewConstructors.dll - - - UIAdapterInterfaces - ..\..\..\Output\Debug\UIAdapterInterfaces.dll - - - xCoreInterfaces - ..\..\..\Output\Debug\xCoreInterfaces.dll - + + ..\..\..\Output\Debug\BasicUtils.dll + False + + + COMInterfaces + ..\..\..\Output\Debug\COMInterfaces.dll + + + False + ..\..\..\Output\Debug\CoreImpl.dll + + + FDO + ..\..\..\Output\Debug\FDO.dll + + + Framework + ..\..\..\Output\Debug\Framework.dll + + + FwControls + ..\..\..\Output\Debug\FwControls.dll + + + False + ..\..\..\Output\Debug\FwCoreDlgs.dll + + + FwResources + ..\..\..\Output\Debug\FwResources.dll + + + FwUtils + ..\..\..\Output\Debug\FwUtils.dll + + + False + ..\..\..\Output\Debug\ITextDll.dll + + + False + ..\..\..\DistFiles\Microsoft.Practices.ServiceLocation.dll + + + ..\..\..\Output\Debug\PrintLayout.dll + False + + + RootSite + ..\..\..\Output\Debug\RootSite.dll + + + ScriptureUtils + ..\..\..\Output\Debug\ScriptureUtils.dll + + + ScrUtilsInterfaces + ..\..\..\Output\Debug\ScrUtilsInterfaces.dll + + + False + ..\..\..\Output\Debug\SharedScrUtils.dll + + + ..\..\..\Output\Debug\SilUtils.dll + False + + + SimpleRootSite + ..\..\..\Output\Debug\SimpleRootSite.dll + + + False + ..\..\..\Output\Debug\SplitGridView.dll + + + System + + + + System.Data + + + System.Drawing + + + System.Windows.Forms + + + System.XML + + + False + ..\..\..\Output\Debug\TeEditing.dll + + + TeResources + ..\..\..\Output\Debug\TeResources.dll + + + TeViewConstructors + ..\..\..\Output\Debug\TeViewConstructors.dll + + + UIAdapterInterfaces + ..\..\..\Output\Debug\UIAdapterInterfaces.dll + + + xCoreInterfaces + ..\..\..\Output\Debug\xCoreInterfaces.dll + - - CommonAssemblyInfo.cs - - - Code - - - Code - - - - - - Form - - - Code - - - Code - - - UserControl - - - UserControl - - - - - Code - - - Component - - - - True - True - TeDiffViewResources.resx - - - Code - - - DiffDialog.cs - Designer - - - Difference.cs - Designer - - - DiffView.cs - Designer - - - Designer - ResXFileCodeGenerator - TeDiffViewResources.Designer.cs - + + CommonAssemblyInfo.cs + + + Code + + + Code + + + + + + Form + + + Code + + + Code + + + UserControl + + + UserControl + + + + + Code + + + Component + + + + True + True + TeDiffViewResources.resx + + + Code + + + DiffDialog.cs + Designer + + + Difference.cs + Designer + + + DiffView.cs + Designer + + + Designer + ResXFileCodeGenerator + TeDiffViewResources.Designer.cs + - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + - - - - + + + + \ No newline at end of file diff --git a/Src/TE/TeDialogs/TeDialogsTests/TeDialogsTests.csproj b/Src/TE/TeDialogs/TeDialogsTests/TeDialogsTests.csproj index 0dcd90cf25..002b4d1e2f 100644 --- a/Src/TE/TeDialogs/TeDialogsTests/TeDialogsTests.csproj +++ b/Src/TE/TeDialogs/TeDialogsTests/TeDialogsTests.csproj @@ -1,4 +1,4 @@ - + Local @@ -206,13 +206,21 @@ SetupFixtureClass.cs - - - + + Form + + + Form + + + Form + - + + Form + @@ -233,8 +241,7 @@ - ../../../../DistFiles - + \ No newline at end of file diff --git a/Src/TE/TeDialogs/TeDialogsTests/ToolsOptionsDialogTests.cs b/Src/TE/TeDialogs/TeDialogsTests/ToolsOptionsDialogTests.cs index 6a756cec76..e6e71eb934 100644 --- a/Src/TE/TeDialogs/TeDialogsTests/ToolsOptionsDialogTests.cs +++ b/Src/TE/TeDialogs/TeDialogsTests/ToolsOptionsDialogTests.cs @@ -19,6 +19,7 @@ using SIL.FieldWorks.Common.RootSites; using NUnit.Framework; using SIL.FieldWorks.Test.TestUtils; +using SIL.Utils; using XCore; using SIL.CoreImpl; using System.Collections.Generic; diff --git a/Src/TE/TeScrInitializer/TeScrBookRefsInit.cs b/Src/TE/TeScrInitializer/TeScrBookRefsInit.cs index cfad98d02c..32204af138 100644 --- a/Src/TE/TeScrInitializer/TeScrBookRefsInit.cs +++ b/Src/TE/TeScrInitializer/TeScrBookRefsInit.cs @@ -22,6 +22,7 @@ using SIL.FieldWorks.Common.Framework; using SIL.FieldWorks.FDO; using SIL.FieldWorks.Common.FwUtils; +using SIL.Utils; using SILUBS.SharedScrUtils; namespace SIL.FieldWorks.TE diff --git a/Src/TE/TeScrInitializer/TeScrInitializerTests/TeKeyTermsInitTests.cs b/Src/TE/TeScrInitializer/TeScrInitializerTests/TeKeyTermsInitTests.cs index 71be0edceb..23b32c9776 100644 --- a/Src/TE/TeScrInitializer/TeScrInitializerTests/TeKeyTermsInitTests.cs +++ b/Src/TE/TeScrInitializer/TeScrInitializerTests/TeKeyTermsInitTests.cs @@ -25,6 +25,7 @@ using SIL.FieldWorks.FDO.FDOTests; using SIL.FieldWorks.FDO.Infrastructure; using System.Text; +using SIL.Utils; using SILUBS.SharedScrUtils; namespace SIL.FieldWorks.TE diff --git a/Src/TE/TeScrInitializer/TeScrInitializerTests/TeScrNoteCategoriesInitTests.cs b/Src/TE/TeScrInitializer/TeScrInitializerTests/TeScrNoteCategoriesInitTests.cs index f2ff042d40..363f03a278 100644 --- a/Src/TE/TeScrInitializer/TeScrInitializerTests/TeScrNoteCategoriesInitTests.cs +++ b/Src/TE/TeScrInitializer/TeScrInitializerTests/TeScrNoteCategoriesInitTests.cs @@ -21,6 +21,7 @@ using SIL.FieldWorks.FDO; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.FDOTests; +using SIL.Utils; namespace SIL.FieldWorks.TE { diff --git a/Src/TE/TeScrInitializer/TeScrNoteCategoriesInit.cs b/Src/TE/TeScrInitializer/TeScrNoteCategoriesInit.cs index 057020774a..fc4d15cc1d 100644 --- a/Src/TE/TeScrInitializer/TeScrNoteCategoriesInit.cs +++ b/Src/TE/TeScrInitializer/TeScrNoteCategoriesInit.cs @@ -25,6 +25,7 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices; +using SIL.Utils; namespace SIL.FieldWorks.TE { diff --git a/Src/TE/TeStylesXml/TeStylesXmlAccessor.cs b/Src/TE/TeStylesXml/TeStylesXmlAccessor.cs index 233ee0cf2b..bcd932dc46 100644 --- a/Src/TE/TeStylesXml/TeStylesXmlAccessor.cs +++ b/Src/TE/TeStylesXml/TeStylesXmlAccessor.cs @@ -22,6 +22,7 @@ using SIL.FieldWorks.Common.ScriptureUtils; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Resources; +using SIL.Utils; using XCore; namespace SIL.FieldWorks.TE diff --git a/Src/TE/TeStylesXml/TeStylesXmlTests/TeStylesXmlAccessorTests.cs b/Src/TE/TeStylesXml/TeStylesXmlTests/TeStylesXmlAccessorTests.cs index 6bd53d6058..7ddc98330c 100644 --- a/Src/TE/TeStylesXml/TeStylesXmlTests/TeStylesXmlAccessorTests.cs +++ b/Src/TE/TeStylesXml/TeStylesXmlTests/TeStylesXmlAccessorTests.cs @@ -27,6 +27,7 @@ using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.Common.ScriptureUtils; using SIL.FieldWorks.Common.FwUtils; +using SIL.Utils; namespace SIL.FieldWorks.TE { diff --git a/Src/Utilities/BasicUtils/BasicUtils.csproj b/Src/Utilities/BasicUtils/BasicUtils.csproj index a7bbe2314e..4914bd1b98 100644 --- a/Src/Utilities/BasicUtils/BasicUtils.csproj +++ b/Src/Utilities/BasicUtils/BasicUtils.csproj @@ -80,6 +80,7 @@ Properties\CommonAssemblyInfo.cs + diff --git a/Src/Common/FwUtils/IProgress.cs b/Src/Utilities/BasicUtils/IProgress.cs similarity index 95% rename from Src/Common/FwUtils/IProgress.cs rename to Src/Utilities/BasicUtils/IProgress.cs index 8d7b7ad81a..ccaecc0d7a 100644 --- a/Src/Common/FwUtils/IProgress.cs +++ b/Src/Utilities/BasicUtils/IProgress.cs @@ -1,4 +1,4 @@ -// --------------------------------------------------------------------------------------------- +// --------------------------------------------------------------------------------------------- #region // Copyright (c) 2011, SIL International. All Rights Reserved. // // Copyright (c) 2011, SIL International. All Rights Reserved. @@ -12,7 +12,7 @@ // --------------------------------------------------------------------------------------------- using System.ComponentModel; -namespace SIL.FieldWorks.Common.FwUtils +namespace SIL.Utils { /// -------------------------------------------------------------------------------------------- /// diff --git a/Src/Utilities/FixFwData/FixFwData.csproj b/Src/Utilities/FixFwData/FixFwData.csproj index 1bfddac15b..ead71fa31b 100644 --- a/Src/Utilities/FixFwData/FixFwData.csproj +++ b/Src/Utilities/FixFwData/FixFwData.csproj @@ -59,6 +59,10 @@ + + False + ..\..\..\Output\Debug\BasicUtils.dll + False ..\..\..\Output\Debug\FixFwDataDll.dll @@ -119,4 +123,4 @@ - + \ No newline at end of file diff --git a/Src/Utilities/FixFwData/Program.cs b/Src/Utilities/FixFwData/Program.cs index 2f42647042..64569aa174 100644 --- a/Src/Utilities/FixFwData/Program.cs +++ b/Src/Utilities/FixFwData/Program.cs @@ -16,9 +16,9 @@ using System.Diagnostics.CodeAnalysis; using System.Windows.Forms; using Palaso.Reporting; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FixData; using Palaso.UI.WindowsForms.HotSpot; +using SIL.Utils; namespace FixFwData { diff --git a/Src/Utilities/FixFwDataDll/FixFwDataDllTests/FixFwDataDllTests.csproj b/Src/Utilities/FixFwDataDll/FixFwDataDllTests/FixFwDataDllTests.csproj index b5e12f7d23..c5c1bcfbbc 100644 --- a/Src/Utilities/FixFwDataDll/FixFwDataDllTests/FixFwDataDllTests.csproj +++ b/Src/Utilities/FixFwDataDll/FixFwDataDllTests/FixFwDataDllTests.csproj @@ -72,6 +72,10 @@ + + False + ..\..\..\..\Output\Debug\BasicUtils.dll + False ..\..\..\..\Output\Debug\BasicUtilsTests.dll diff --git a/Src/Utilities/FixFwDataDll/FwDataFixer.cs b/Src/Utilities/FixFwDataDll/FwDataFixer.cs index 58e26b1306..b9aa1fa1bb 100644 --- a/Src/Utilities/FixFwDataDll/FwDataFixer.cs +++ b/Src/Utilities/FixFwDataDll/FwDataFixer.cs @@ -18,6 +18,7 @@ using System.Xml; using System.IO; using SIL.FieldWorks.Common.FwUtils; +using SIL.Utils; namespace SIL.FieldWorks.FixData { diff --git a/Src/xWorks/xWorksTests/XWorksAppTestBase.cs b/Src/xWorks/xWorksTests/XWorksAppTestBase.cs index 0382d64199..2626796f14 100644 --- a/Src/xWorks/xWorksTests/XWorksAppTestBase.cs +++ b/Src/xWorks/xWorksTests/XWorksAppTestBase.cs @@ -29,6 +29,7 @@ using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.Common.Framework; using SIL.FieldWorks.FDO.DomainServices; +using SIL.Utils; using XCore; using SIL.FieldWorks.FDO.FDOTests; using SIL.FieldWorks.Common.FwUtils; From 6cb3651820992be525c314c34c36cde70ec6e74e Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Fri, 6 Dec 2013 15:38:19 +0700 Subject: [PATCH 025/143] Move some FwUtil code into BasicUtil Remove dependencies of FDO upon FwUtil. Move IThreadedProgress. Change-Id: I2831f3abe6867e7636e427712a6c6cbb32960382 --- Src/Common/FwUtils/FwUtils.csproj | 1 - Src/FDO/DomainServices/ClientServerServices.cs | 1 + .../DomainServices/DataMigration/FdoDataMigrationManager.cs | 1 + .../DomainServices/DataMigration/IDataMigrationManager.cs | 1 + Src/FDO/FDOTests/ClientServerServicesTests.cs | 1 + Src/FDO/FDOTests/PersistingBackendProviderTests.cs | 1 + Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs | 1 + Src/LexText/Interlinear/BIRDInterlinearImporter.cs | 1 + Src/LexText/Interlinear/LinguaLinksImport.cs | 1 + Src/LexText/Interlinear/WordsSfmImportWizard.cs | 1 + Src/LexText/LexTextControls/LexImport.cs | 1 + Src/TE/DiffView/DiffViewTests/BookMergerTestsBase.cs | 1 + Src/Utilities/BasicUtils/BasicUtils.csproj | 1 + .../FwUtils => Utilities/BasicUtils}/IThreadedProgress.cs | 5 ++--- 14 files changed, 14 insertions(+), 4 deletions(-) rename Src/{Common/FwUtils => Utilities/BasicUtils}/IThreadedProgress.cs (96%) diff --git a/Src/Common/FwUtils/FwUtils.csproj b/Src/Common/FwUtils/FwUtils.csproj index 683ef5a5ee..a738a3c99f 100644 --- a/Src/Common/FwUtils/FwUtils.csproj +++ b/Src/Common/FwUtils/FwUtils.csproj @@ -179,7 +179,6 @@ - diff --git a/Src/FDO/DomainServices/ClientServerServices.cs b/Src/FDO/DomainServices/ClientServerServices.cs index 77a4fbfef9..1f3655b668 100644 --- a/Src/FDO/DomainServices/ClientServerServices.cs +++ b/Src/FDO/DomainServices/ClientServerServices.cs @@ -25,6 +25,7 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.FDO.Infrastructure.Impl; +using SIL.Utils; namespace SIL.FieldWorks.FDO.DomainServices { diff --git a/Src/FDO/DomainServices/DataMigration/FdoDataMigrationManager.cs b/Src/FDO/DomainServices/DataMigration/FdoDataMigrationManager.cs index 98bb13986c..e63c02beda 100644 --- a/Src/FDO/DomainServices/DataMigration/FdoDataMigrationManager.cs +++ b/Src/FDO/DomainServices/DataMigration/FdoDataMigrationManager.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using SIL.FieldWorks.Common.FwUtils; +using SIL.Utils; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration { diff --git a/Src/FDO/DomainServices/DataMigration/IDataMigrationManager.cs b/Src/FDO/DomainServices/DataMigration/IDataMigrationManager.cs index a66258ea44..ae973dc13c 100644 --- a/Src/FDO/DomainServices/DataMigration/IDataMigrationManager.cs +++ b/Src/FDO/DomainServices/DataMigration/IDataMigrationManager.cs @@ -13,6 +13,7 @@ // --------------------------------------------------------------------------------------------- using System; using SIL.FieldWorks.Common.FwUtils; +using SIL.Utils; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration { diff --git a/Src/FDO/FDOTests/ClientServerServicesTests.cs b/Src/FDO/FDOTests/ClientServerServicesTests.cs index 961822d255..9ba804ba85 100644 --- a/Src/FDO/FDOTests/ClientServerServicesTests.cs +++ b/Src/FDO/FDOTests/ClientServerServicesTests.cs @@ -5,6 +5,7 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.Test.TestUtils; +using SIL.Utils; namespace SIL.FieldWorks.FDO.FDOTests { diff --git a/Src/FDO/FDOTests/PersistingBackendProviderTests.cs b/Src/FDO/FDOTests/PersistingBackendProviderTests.cs index 81723e0344..6b0fa54e5b 100644 --- a/Src/FDO/FDOTests/PersistingBackendProviderTests.cs +++ b/Src/FDO/FDOTests/PersistingBackendProviderTests.cs @@ -15,6 +15,7 @@ using SIL.FieldWorks.FDO.Infrastructure; using SIL.CoreImpl; using SIL.FieldWorks.FDO.Infrastructure.Impl; +using SIL.Utils; namespace SIL.FieldWorks.FDO.CoreTests.PersistingLayerTests { diff --git a/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs b/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs index 5a56f71135..8b54cba19c 100644 --- a/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs +++ b/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs @@ -10,6 +10,7 @@ using SIL.FieldWorks.FDO.FDOTests; using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.Test.TestUtils; +using SIL.Utils; namespace SIL.FieldWorks.FDO.CoreTests.PersistingLayerTests { diff --git a/Src/LexText/Interlinear/BIRDInterlinearImporter.cs b/Src/LexText/Interlinear/BIRDInterlinearImporter.cs index a9795295d3..004291f973 100644 --- a/Src/LexText/Interlinear/BIRDInterlinearImporter.cs +++ b/Src/LexText/Interlinear/BIRDInterlinearImporter.cs @@ -12,6 +12,7 @@ using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.IText.FlexInterlinModel; using SIL.FieldWorks.FDO.Application.ApplicationServices; +using SIL.Utils; namespace SIL.FieldWorks.IText { diff --git a/Src/LexText/Interlinear/LinguaLinksImport.cs b/Src/LexText/Interlinear/LinguaLinksImport.cs index b54f5ee346..92c497463f 100644 --- a/Src/LexText/Interlinear/LinguaLinksImport.cs +++ b/Src/LexText/Interlinear/LinguaLinksImport.cs @@ -30,6 +30,7 @@ using ECInterfaces; using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.IText.FlexInterlinModel; +using SIL.Utils; using SilEncConverters40; using SIL.FieldWorks.FDO.Application.ApplicationServices; using System.Xml.Serialization; diff --git a/Src/LexText/Interlinear/WordsSfmImportWizard.cs b/Src/LexText/Interlinear/WordsSfmImportWizard.cs index 141513687f..e78d78bba3 100644 --- a/Src/LexText/Interlinear/WordsSfmImportWizard.cs +++ b/Src/LexText/Interlinear/WordsSfmImportWizard.cs @@ -3,6 +3,7 @@ using System.IO; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.LexText.Controls; +using SIL.Utils; namespace SIL.FieldWorks.IText { diff --git a/Src/LexText/LexTextControls/LexImport.cs b/Src/LexText/LexTextControls/LexImport.cs index ee287573ae..7a79418280 100644 --- a/Src/LexText/LexTextControls/LexImport.cs +++ b/Src/LexText/LexTextControls/LexImport.cs @@ -24,6 +24,7 @@ using SIL.FieldWorks.FDO.Application.ApplicationServices; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Common.Controls; +using SIL.Utils; namespace SIL.FieldWorks.LexText.Controls { diff --git a/Src/TE/DiffView/DiffViewTests/BookMergerTestsBase.cs b/Src/TE/DiffView/DiffViewTests/BookMergerTestsBase.cs index ea0725ea0a..9067a1f580 100644 --- a/Src/TE/DiffView/DiffViewTests/BookMergerTestsBase.cs +++ b/Src/TE/DiffView/DiffViewTests/BookMergerTestsBase.cs @@ -24,6 +24,7 @@ using SIL.FieldWorks.Common.ScriptureUtils; using SIL.FieldWorks.Test.TestUtils; using SILUBS.SharedScrUtils; +using SIL.Utils; namespace SIL.FieldWorks.TE { diff --git a/Src/Utilities/BasicUtils/BasicUtils.csproj b/Src/Utilities/BasicUtils/BasicUtils.csproj index 4914bd1b98..911d5df3ae 100644 --- a/Src/Utilities/BasicUtils/BasicUtils.csproj +++ b/Src/Utilities/BasicUtils/BasicUtils.csproj @@ -81,6 +81,7 @@ Properties\CommonAssemblyInfo.cs + diff --git a/Src/Common/FwUtils/IThreadedProgress.cs b/Src/Utilities/BasicUtils/IThreadedProgress.cs similarity index 96% rename from Src/Common/FwUtils/IThreadedProgress.cs rename to Src/Utilities/BasicUtils/IThreadedProgress.cs index 910467625a..49c253542f 100644 --- a/Src/Common/FwUtils/IThreadedProgress.cs +++ b/Src/Utilities/BasicUtils/IThreadedProgress.cs @@ -1,4 +1,4 @@ -// --------------------------------------------------------------------------------------------- +// --------------------------------------------------------------------------------------------- #region // Copyright (c) 2011, SIL International. All Rights Reserved. // // Copyright (c) 2011, SIL International. All Rights Reserved. @@ -11,9 +11,8 @@ // File: IThreadedProgress.cs // --------------------------------------------------------------------------------------------- using System; -using SIL.Utils; -namespace SIL.FieldWorks.Common.FwUtils +namespace SIL.Utils { /// -------------------------------------------------------------------------------------------- /// From 5a4f365e1be50e7d9b223d258df101ed5402f62b Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Fri, 6 Dec 2013 16:30:54 +0700 Subject: [PATCH 026/143] Remove some dependencies of FDO upon FwUtil Move GenDate from FwUtil to CoreImpl. Change-Id: I64e4bd9f6a0c57f77d5e6a8c1b8779463a8789f2 --- .../DetailControls/GenDateChooserDlg.cs | 2 +- .../DetailControls/GenDateLauncher.cs | 2 +- Src/Common/CoreImpl/CoreImpl.csproj | 1 + .../CoreImpl/CoreImplStrings.Designer.cs | 53 +++++++++++++++++-- Src/Common/CoreImpl/CoreImplStrings.resx | 15 ++++++ Src/Common/{FwUtils => CoreImpl}/GenDate.cs | 49 +++++++++-------- Src/Common/Filters/DateTimeMatcher.cs | 2 +- Src/Common/FwUtils/FwUtils.csproj | 1 - .../ApplicationServices/XmlImportData.cs | 1 - .../ApplicationServices/XmlList.cs | 1 - .../DomainDataByFlidDecoratorBase.cs | 2 +- Src/FDO/Application/ISilDataAccessManaged.cs | 2 +- Src/FDO/DomainImpl/OverridesLing_Lex.cs | 1 - Src/FDO/DomainImpl/OverridesLing_MoClasses.cs | 2 - Src/FDO/DomainImpl/ReadWriteServices.cs | 1 - Src/FDO/DomainImpl/ScrBook.cs | 3 -- Src/FDO/DomainImpl/ScrScriptureNote.cs | 8 --- Src/FDO/DomainImpl/ScrSection.cs | 4 -- Src/FDO/DomainImpl/StFootnote.cs | 6 --- Src/FDO/DomainServices/ConstraintFailure.cs | 3 -- .../DataMigration/DataMigration7000040.cs | 9 ---- .../DataMigration/DataMigration7000041.cs | 7 --- .../DataMigration/DataMigration7000066.cs | 1 - .../DataMigration/FdoDataMigrationManager.cs | 1 - .../DataMigration/IDataMigrationManager.cs | 1 - .../DataStoreInitializationServices.cs | 1 - Src/FDO/DomainServices/ITextUtils.cs | 1 - Src/FDO/DomainServices/StTxtParaBldr.cs | 3 -- .../GeneratedPropertyAccessorTests.cs | 1 + Src/FDO/FdoInterfaceAdditions.cs | 1 - Src/FDO/FdoInterfaceDeclarations.cs | 1 - Src/FDO/FdoRepositoryInterfaceAdditions.cs | 1 - Src/FDO/FieldDescription.cs | 1 - .../Infrastructure/BackendStartupParameter.cs | 2 - .../IPersistenceStrategyInterfaces.cs | 1 - Src/FDO/Infrastructure/IUnitOfWorkService.cs | 2 +- .../Infrastructure/Impl/ChangeReconciler.cs | 1 - .../Impl/ClientServerBackendProvider.cs | 1 - .../Impl/FdoStateChangingClasses.cs | 1 - .../Impl/MemoryOnlyBackendProvider.cs | 5 +- .../Infrastructure/Impl/UnitOfWorkService.cs | 2 +- Src/FDOBrowser/FDOBrowserForm.cs | 1 + .../FixFwDataDll/FixFwDataDll.csproj | 6 +++ Src/Utilities/FixFwDataDll/FwDataFixer.cs | 1 + 44 files changed, 105 insertions(+), 106 deletions(-) rename Src/Common/{FwUtils => CoreImpl}/GenDate.cs (92%) diff --git a/Src/Common/Controls/DetailControls/GenDateChooserDlg.cs b/Src/Common/Controls/DetailControls/GenDateChooserDlg.cs index 93a977c99f..5291471bf5 100644 --- a/Src/Common/Controls/DetailControls/GenDateChooserDlg.cs +++ b/Src/Common/Controls/DetailControls/GenDateChooserDlg.cs @@ -3,7 +3,7 @@ using System.Linq; using System.Text; using System.Windows.Forms; - +using SIL.CoreImpl; using SIL.FieldWorks.FDO; using SIL.FieldWorks.Common.Framework.DetailControls.Resources; using SIL.FieldWorks.Common.FwUtils; diff --git a/Src/Common/Controls/DetailControls/GenDateLauncher.cs b/Src/Common/Controls/DetailControls/GenDateLauncher.cs index 63e2a0f3d0..c4b22734c1 100644 --- a/Src/Common/Controls/DetailControls/GenDateLauncher.cs +++ b/Src/Common/Controls/DetailControls/GenDateLauncher.cs @@ -3,7 +3,7 @@ using System.Linq; using System.Text; using System.Windows.Forms; - +using SIL.CoreImpl; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.Application; using SIL.FieldWorks.FDO.Infrastructure; diff --git a/Src/Common/CoreImpl/CoreImpl.csproj b/Src/Common/CoreImpl/CoreImpl.csproj index 674455805c..4ffa1edfa2 100644 --- a/Src/Common/CoreImpl/CoreImpl.csproj +++ b/Src/Common/CoreImpl/CoreImpl.csproj @@ -99,6 +99,7 @@ CommonAssemblyInfo.cs + diff --git a/Src/Common/CoreImpl/CoreImplStrings.Designer.cs b/Src/Common/CoreImpl/CoreImplStrings.Designer.cs index 13c195dfcc..37cec1c86e 100644 --- a/Src/Common/CoreImpl/CoreImplStrings.Designer.cs +++ b/Src/Common/CoreImpl/CoreImplStrings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.296 +// Runtime Version:4.0.30319.1008 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -69,6 +69,51 @@ internal static string ksCannotWriteWritingSystemInfo { } } + /// + /// Looks up a localized string similar to AD. + /// + internal static string ksGenDateAD { + get { + return ResourceManager.GetString("ksGenDateAD", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to After. + /// + internal static string ksGenDateAfter { + get { + return ResourceManager.GetString("ksGenDateAfter", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to About. + /// + internal static string ksGenDateApprox { + get { + return ResourceManager.GetString("ksGenDateApprox", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to BC. + /// + internal static string ksGenDateBC { + get { + return ResourceManager.GetString("ksGenDateBC", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Before. + /// + internal static string ksGenDateBefore { + get { + return ResourceManager.GetString("ksGenDateBefore", resourceCulture); + } + } + /// /// Looks up a localized string similar to Warning. /// @@ -96,8 +141,7 @@ internal static string ksWarning { ///AQ 2005-10-16 Antarctica ///AR 2005-10-16 Argentina ///AS 2005-10-16 American Samoa - ///AT 2005-10-16 Austria - ///AU 2005-10 [rest of string was truncated]";. + ///AT 2005-10-16 A [rest of string was truncated]";. /// internal static string regions { get { @@ -114,8 +158,7 @@ internal static string regions { ///1694acad 2007-03-20 Early Modern French fr ///1901 2005-10-16 Traditional German orthography de ///1959acad 2008-09-30 "Academic" ("governmental") variant of Belarusian as codified in 1959 be - ///1994 2007-07-28 Standardized Resian orthography sl-rozaj / sl-rozaj-biske / sl-rozaj-njiva / sl-rozaj-osojs / sl-rozaj-solba - ///1996 20 [rest of string was truncated]";. + ///1994 2007-07-28 Standardized Resian orthography sl-rozaj / sl-rozaj-biske / sl-rozaj-njiva / sl-rozaj-osojs / sl-rozaj-solba [rest of string was truncated]";. /// internal static string variants { get { diff --git a/Src/Common/CoreImpl/CoreImplStrings.resx b/Src/Common/CoreImpl/CoreImplStrings.resx index 026e43da47..911ca34a7f 100644 --- a/Src/Common/CoreImpl/CoreImplStrings.resx +++ b/Src/Common/CoreImpl/CoreImplStrings.resx @@ -120,6 +120,21 @@ FieldWorks is unable to save some writing system settings because access to {0} is not authorized. This may cause unexpected behavior, and may be indicative of a wider problem with access permissions that could cause program crashes. + + AD + + + After + + + About + + + BC + + + Before + Warning diff --git a/Src/Common/FwUtils/GenDate.cs b/Src/Common/CoreImpl/GenDate.cs similarity index 92% rename from Src/Common/FwUtils/GenDate.cs rename to Src/Common/CoreImpl/GenDate.cs index 1d5ac08d34..db34f706f6 100644 --- a/Src/Common/FwUtils/GenDate.cs +++ b/Src/Common/CoreImpl/GenDate.cs @@ -1,9 +1,8 @@ -using System; -using System.Text; -using System.Globalization; +using System; using System.Collections.Generic; +using System.Text; -namespace SIL.FieldWorks.Common.FwUtils +namespace SIL.CoreImpl { /// /// This class encapsulates the generic (vague) date type. This type can store dates @@ -215,15 +214,15 @@ public string ToLongString() switch (m_precision) { case PrecisionType.Approximate: - sb.Append(FwUtilsStrings.ksGenDateApprox); + sb.Append(CoreImplStrings.ksGenDateApprox); sb.Append(" "); break; case PrecisionType.After: - sb.Append(FwUtilsStrings.ksGenDateAfter); + sb.Append(CoreImplStrings.ksGenDateAfter); sb.Append(" "); break; case PrecisionType.Before: - sb.Append(FwUtilsStrings.ksGenDateBefore); + sb.Append(CoreImplStrings.ksGenDateBefore); sb.Append(" "); break; } @@ -247,7 +246,7 @@ public string ToLongString() } else if (m_year != UnknownYear && m_ad) { - sb.Append(FwUtilsStrings.ksGenDateAD); + sb.Append(CoreImplStrings.ksGenDateAD); sb.Append(" "); } @@ -257,7 +256,7 @@ public string ToLongString() if (!m_ad) { sb.Append(" "); - sb.Append(FwUtilsStrings.ksGenDateBC); + sb.Append(CoreImplStrings.ksGenDateBC); } } return sb.ToString(); @@ -279,15 +278,15 @@ public string ToXMLExportShortString() switch (m_precision) { case PrecisionType.Approximate: - sb.Append(FwUtilsStrings.ksGenDateApprox); + sb.Append(CoreImplStrings.ksGenDateApprox); sb.Append(" "); break; case PrecisionType.After: - sb.Append(FwUtilsStrings.ksGenDateAfter); + sb.Append(CoreImplStrings.ksGenDateAfter); sb.Append(" "); break; case PrecisionType.Before: - sb.Append(FwUtilsStrings.ksGenDateBefore); + sb.Append(CoreImplStrings.ksGenDateBefore); sb.Append(" "); break; } @@ -316,15 +315,15 @@ public string ToShortString() switch (m_precision) { case PrecisionType.Approximate: - sb.Append(FwUtilsStrings.ksGenDateApprox); + sb.Append(CoreImplStrings.ksGenDateApprox); sb.Append(" "); break; case PrecisionType.After: - sb.Append(FwUtilsStrings.ksGenDateAfter); + sb.Append(CoreImplStrings.ksGenDateAfter); sb.Append(" "); break; case PrecisionType.Before: - sb.Append(FwUtilsStrings.ksGenDateBefore); + sb.Append(CoreImplStrings.ksGenDateBefore); sb.Append(" "); break; } @@ -380,30 +379,30 @@ public static bool TryParse(string date, out GenDate gen) bool fAD = true; date = date.Trim(); - if (date.StartsWith(FwUtilsStrings.ksGenDateApprox)) + if (date.StartsWith(CoreImplStrings.ksGenDateApprox)) { precision = PrecisionType.Approximate; - date = date.Substring(FwUtilsStrings.ksGenDateApprox.Length + 1); + date = date.Substring(CoreImplStrings.ksGenDateApprox.Length + 1); } - else if (date.StartsWith(FwUtilsStrings.ksGenDateAfter)) + else if (date.StartsWith(CoreImplStrings.ksGenDateAfter)) { precision = PrecisionType.After; - date = date.Substring(FwUtilsStrings.ksGenDateAfter.Length + 1); + date = date.Substring(CoreImplStrings.ksGenDateAfter.Length + 1); } - else if (date.StartsWith(FwUtilsStrings.ksGenDateBefore)) + else if (date.StartsWith(CoreImplStrings.ksGenDateBefore)) { precision = PrecisionType.Before; - date = date.Substring(FwUtilsStrings.ksGenDateBefore.Length + 1); + date = date.Substring(CoreImplStrings.ksGenDateBefore.Length + 1); } - if (date.Contains(FwUtilsStrings.ksGenDateAD + " ")) + if (date.Contains(CoreImplStrings.ksGenDateAD + " ")) { fAD = true; - date = date.Replace(FwUtilsStrings.ksGenDateAD + " ", ""); + date = date.Replace(CoreImplStrings.ksGenDateAD + " ", ""); } - else if (date.EndsWith(FwUtilsStrings.ksGenDateBC)) + else if (date.EndsWith(CoreImplStrings.ksGenDateBC)) { fAD = false; - date = date.Substring(0, date.Length - (FwUtilsStrings.ksGenDateBC.Length + 1)); + date = date.Substring(0, date.Length - (CoreImplStrings.ksGenDateBC.Length + 1)); } int nDay = UnknownDay; int nMonth = UnknownMonth; diff --git a/Src/Common/Filters/DateTimeMatcher.cs b/Src/Common/Filters/DateTimeMatcher.cs index 0dc553ce5f..d9d2957b4f 100644 --- a/Src/Common/Filters/DateTimeMatcher.cs +++ b/Src/Common/Filters/DateTimeMatcher.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text; using System.Globalization; - +using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; using SIL.Utils; using SIL.FieldWorks.Common.FwUtils; diff --git a/Src/Common/FwUtils/FwUtils.csproj b/Src/Common/FwUtils/FwUtils.csproj index a738a3c99f..d71cb593b4 100644 --- a/Src/Common/FwUtils/FwUtils.csproj +++ b/Src/Common/FwUtils/FwUtils.csproj @@ -191,7 +191,6 @@ FwUtilsStrings.resx - diff --git a/Src/FDO/Application/ApplicationServices/XmlImportData.cs b/Src/FDO/Application/ApplicationServices/XmlImportData.cs index fc2e8f0c0e..01e50e9a8c 100644 --- a/Src/FDO/Application/ApplicationServices/XmlImportData.cs +++ b/Src/FDO/Application/ApplicationServices/XmlImportData.cs @@ -22,7 +22,6 @@ using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.Infrastructure; using SIL.Utils; diff --git a/Src/FDO/Application/ApplicationServices/XmlList.cs b/Src/FDO/Application/ApplicationServices/XmlList.cs index 4a91f8ea8c..3656ed9002 100644 --- a/Src/FDO/Application/ApplicationServices/XmlList.cs +++ b/Src/FDO/Application/ApplicationServices/XmlList.cs @@ -23,7 +23,6 @@ using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Infrastructure; using SIL.Utils; diff --git a/Src/FDO/Application/DomainDataByFlidDecoratorBase.cs b/Src/FDO/Application/DomainDataByFlidDecoratorBase.cs index 52ff181a8d..009c12ea2a 100644 --- a/Src/FDO/Application/DomainDataByFlidDecoratorBase.cs +++ b/Src/FDO/Application/DomainDataByFlidDecoratorBase.cs @@ -12,9 +12,9 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using System.Diagnostics; +using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.FDO.Infrastructure; -using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; namespace SIL.FieldWorks.FDO.Application diff --git a/Src/FDO/Application/ISilDataAccessManaged.cs b/Src/FDO/Application/ISilDataAccessManaged.cs index 4af751be9a..c3c47a4c7f 100644 --- a/Src/FDO/Application/ISilDataAccessManaged.cs +++ b/Src/FDO/Application/ISilDataAccessManaged.cs @@ -1,5 +1,5 @@ +using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using System; namespace SIL.FieldWorks.FDO.Application diff --git a/Src/FDO/DomainImpl/OverridesLing_Lex.cs b/Src/FDO/DomainImpl/OverridesLing_Lex.cs index ca401ea7c3..6d0be26b6b 100644 --- a/Src/FDO/DomainImpl/OverridesLing_Lex.cs +++ b/Src/FDO/DomainImpl/OverridesLing_Lex.cs @@ -27,7 +27,6 @@ using System.Drawing; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Application; using SIL.FieldWorks.FDO.Infrastructure.Impl; using SIL.Utils; diff --git a/Src/FDO/DomainImpl/OverridesLing_MoClasses.cs b/Src/FDO/DomainImpl/OverridesLing_MoClasses.cs index e4d28e2e9e..6804527098 100644 --- a/Src/FDO/DomainImpl/OverridesLing_MoClasses.cs +++ b/Src/FDO/DomainImpl/OverridesLing_MoClasses.cs @@ -20,11 +20,9 @@ using System.Linq; using System.Diagnostics; using System.Text; -using System.Collections; using System.Collections.Generic; using System.Xml; // XMLWriter using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.Infrastructure; using SIL.Utils; diff --git a/Src/FDO/DomainImpl/ReadWriteServices.cs b/Src/FDO/DomainImpl/ReadWriteServices.cs index 459289b820..e8fe6b6d6b 100644 --- a/Src/FDO/DomainImpl/ReadWriteServices.cs +++ b/Src/FDO/DomainImpl/ReadWriteServices.cs @@ -3,7 +3,6 @@ using System.Xml; using System.Xml.Linq; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Infrastructure; using SIL.CoreImpl; using System.Collections.Generic; diff --git a/Src/FDO/DomainImpl/ScrBook.cs b/Src/FDO/DomainImpl/ScrBook.cs index 86c8051c53..0b62f2f5df 100644 --- a/Src/FDO/DomainImpl/ScrBook.cs +++ b/Src/FDO/DomainImpl/ScrBook.cs @@ -15,10 +15,7 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics; -using System.Runtime.InteropServices; -using SIL.FieldWorks.FDO; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Common.ScriptureUtils; using SILUBS.SharedScrUtils; using SIL.Utils; diff --git a/Src/FDO/DomainImpl/ScrScriptureNote.cs b/Src/FDO/DomainImpl/ScrScriptureNote.cs index 7160a26a75..4902868909 100644 --- a/Src/FDO/DomainImpl/ScrScriptureNote.cs +++ b/Src/FDO/DomainImpl/ScrScriptureNote.cs @@ -16,17 +16,9 @@ // // -------------------------------------------------------------------------------------------- using System; -using System.Collections.Generic; using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Text; - -using SIL.FieldWorks.FDO; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.Utils; using SIL.FieldWorks.Common.ScriptureUtils; -using SIL.FieldWorks.Common.FwUtils; -using SIL.FieldWorks.Resources; using SILUBS.SharedScrUtils; using SIL.FieldWorks.FDO.DomainServices; using SIL.CoreImpl; diff --git a/Src/FDO/DomainImpl/ScrSection.cs b/Src/FDO/DomainImpl/ScrSection.cs index f76a871d53..9a22291c5b 100644 --- a/Src/FDO/DomainImpl/ScrSection.cs +++ b/Src/FDO/DomainImpl/ScrSection.cs @@ -16,16 +16,12 @@ // --------------------------------------------------------------------------------------------- using System; using System.Diagnostics; - -using SIL.FieldWorks.FDO; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Common.ScriptureUtils; using SILUBS.SharedScrUtils; using System.Collections.Generic; using SIL.FieldWorks.FDO.DomainServices; using SIL.CoreImpl; -using SIL.FieldWorks.FDO.Infrastructure; namespace SIL.FieldWorks.FDO.DomainImpl { diff --git a/Src/FDO/DomainImpl/StFootnote.cs b/Src/FDO/DomainImpl/StFootnote.cs index 050fb340cf..a0515b07e7 100644 --- a/Src/FDO/DomainImpl/StFootnote.cs +++ b/Src/FDO/DomainImpl/StFootnote.cs @@ -16,15 +16,9 @@ // --------------------------------------------------------------------------------------------- using System; using System.Diagnostics; -using System.Xml; using System.Text; -using System.Collections.Generic; - -using SIL.FieldWorks.FDO; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.FDO.Infrastructure; -using SIL.Utils; -using SIL.FieldWorks.Common.FwUtils; using SIL.CoreImpl; namespace SIL.FieldWorks.FDO.DomainImpl diff --git a/Src/FDO/DomainServices/ConstraintFailure.cs b/Src/FDO/DomainServices/ConstraintFailure.cs index d28a396ca2..ae59158a55 100644 --- a/Src/FDO/DomainServices/ConstraintFailure.cs +++ b/Src/FDO/DomainServices/ConstraintFailure.cs @@ -13,10 +13,7 @@ // // -------------------------------------------------------------------------------------------- -using System.Collections.Generic; using System.Linq; -using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.CoreImpl; namespace SIL.FieldWorks.FDO.DomainServices diff --git a/Src/FDO/DomainServices/DataMigration/DataMigration7000040.cs b/Src/FDO/DomainServices/DataMigration/DataMigration7000040.cs index 1f001b7e79..af19d77645 100644 --- a/Src/FDO/DomainServices/DataMigration/DataMigration7000040.cs +++ b/Src/FDO/DomainServices/DataMigration/DataMigration7000040.cs @@ -11,17 +11,8 @@ // File: DataMigration7000037.cs // Responsibility: mcconnel // --------------------------------------------------------------------------------------------- -using System; -using System.IO; using System.Linq; -using System.Text; -using System.Web; -using System.Xml; using System.Xml.Linq; -using System.Xml.XPath; - -using SIL.FieldWorks.Common.FwUtils; -using SIL.Utils; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration { diff --git a/Src/FDO/DomainServices/DataMigration/DataMigration7000041.cs b/Src/FDO/DomainServices/DataMigration/DataMigration7000041.cs index dfd0d46710..7a25606771 100644 --- a/Src/FDO/DomainServices/DataMigration/DataMigration7000041.cs +++ b/Src/FDO/DomainServices/DataMigration/DataMigration7000041.cs @@ -12,19 +12,12 @@ // Responsibility: lastufka // --------------------------------------------------------------------------------------------- using System; -using System.IO; using System.Linq; -using System.Text; -using System.Web; -using System.Xml; using System.Xml.Linq; using System.Xml.XPath; using System.Collections.Generic; using System.Diagnostics; -using SIL.FieldWorks.Common.FwUtils; -using SIL.Utils; - namespace SIL.FieldWorks.FDO.DomainServices.DataMigration { /// ---------------------------------------------------------------------------------------- diff --git a/Src/FDO/DomainServices/DataMigration/DataMigration7000066.cs b/Src/FDO/DomainServices/DataMigration/DataMigration7000066.cs index 0d0aa68ec1..f75dec2e8e 100644 --- a/Src/FDO/DomainServices/DataMigration/DataMigration7000066.cs +++ b/Src/FDO/DomainServices/DataMigration/DataMigration7000066.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Xml.Linq; using SIL.CoreImpl; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Infrastructure; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration diff --git a/Src/FDO/DomainServices/DataMigration/FdoDataMigrationManager.cs b/Src/FDO/DomainServices/DataMigration/FdoDataMigrationManager.cs index e63c02beda..cfaf727d6f 100644 --- a/Src/FDO/DomainServices/DataMigration/FdoDataMigrationManager.cs +++ b/Src/FDO/DomainServices/DataMigration/FdoDataMigrationManager.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration diff --git a/Src/FDO/DomainServices/DataMigration/IDataMigrationManager.cs b/Src/FDO/DomainServices/DataMigration/IDataMigrationManager.cs index ae973dc13c..dc5250af36 100644 --- a/Src/FDO/DomainServices/DataMigration/IDataMigrationManager.cs +++ b/Src/FDO/DomainServices/DataMigration/IDataMigrationManager.cs @@ -12,7 +12,6 @@ // Responsibility: FW team // --------------------------------------------------------------------------------------------- using System; -using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration diff --git a/Src/FDO/DomainServices/DataStoreInitializationServices.cs b/Src/FDO/DomainServices/DataStoreInitializationServices.cs index 20cb3d0c23..120813db7a 100644 --- a/Src/FDO/DomainServices/DataStoreInitializationServices.cs +++ b/Src/FDO/DomainServices/DataStoreInitializationServices.cs @@ -17,7 +17,6 @@ using System.Linq; using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainImpl; using SIL.Utils; using SILUBS.SharedScrUtils; diff --git a/Src/FDO/DomainServices/ITextUtils.cs b/Src/FDO/DomainServices/ITextUtils.cs index 8befb34839..df0537e82c 100644 --- a/Src/FDO/DomainServices/ITextUtils.cs +++ b/Src/FDO/DomainServices/ITextUtils.cs @@ -16,7 +16,6 @@ using System.Collections.Generic; using System.Linq; using System.Diagnostics; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.Common.ScriptureUtils; using SIL.FieldWorks.FDO.DomainImpl; diff --git a/Src/FDO/DomainServices/StTxtParaBldr.cs b/Src/FDO/DomainServices/StTxtParaBldr.cs index 9e6fec0f94..7b8e821af0 100644 --- a/Src/FDO/DomainServices/StTxtParaBldr.cs +++ b/Src/FDO/DomainServices/StTxtParaBldr.cs @@ -16,10 +16,7 @@ // // --------------------------------------------------------------------------------------------- using System; -using System.Runtime.InteropServices; // needed for Marshal using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; -using SIL.Utils; using SIL.CoreImpl; namespace SIL.FieldWorks.FDO.DomainServices diff --git a/Src/FDO/FDOTests/GeneratedPropertyAccessorTests.cs b/Src/FDO/FDOTests/GeneratedPropertyAccessorTests.cs index 7a8d2921f8..50cdbb5c1f 100644 --- a/Src/FDO/FDOTests/GeneratedPropertyAccessorTests.cs +++ b/Src/FDO/FDOTests/GeneratedPropertyAccessorTests.cs @@ -21,6 +21,7 @@ using System; using System.Linq; using NUnit.Framework; +using SIL.CoreImpl; using SIL.FieldWorks.FDO.FDOTests; using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.Common.FwUtils; diff --git a/Src/FDO/FdoInterfaceAdditions.cs b/Src/FDO/FdoInterfaceAdditions.cs index dd3eea3b3f..2d7f1222bc 100644 --- a/Src/FDO/FdoInterfaceAdditions.cs +++ b/Src/FDO/FdoInterfaceAdditions.cs @@ -23,7 +23,6 @@ using System.Collections.Specialized; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainImpl; using SIL.FieldWorks.FDO.DomainServices; using SIL.Utils; diff --git a/Src/FDO/FdoInterfaceDeclarations.cs b/Src/FDO/FdoInterfaceDeclarations.cs index ddee48c781..30626a7e0e 100644 --- a/Src/FDO/FdoInterfaceDeclarations.cs +++ b/Src/FDO/FdoInterfaceDeclarations.cs @@ -7,7 +7,6 @@ using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.Infrastructure; -using SIL.FieldWorks.Common.FwUtils; // Add additional methods/properties to domain object in FdoInterfaceAdditions.cs. // Add new interfaces to the FdoInterfaceDeclarations file. diff --git a/Src/FDO/FdoRepositoryInterfaceAdditions.cs b/Src/FDO/FdoRepositoryInterfaceAdditions.cs index 9aa98de26f..1a716a35e1 100644 --- a/Src/FDO/FdoRepositoryInterfaceAdditions.cs +++ b/Src/FDO/FdoRepositoryInterfaceAdditions.cs @@ -15,7 +15,6 @@ using System; using System.Collections.Generic; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.DomainServices.SemanticDomainSearch; using SIL.Utils; diff --git a/Src/FDO/FieldDescription.cs b/Src/FDO/FieldDescription.cs index 2fec587c44..68083f3d27 100644 --- a/Src/FDO/FieldDescription.cs +++ b/Src/FDO/FieldDescription.cs @@ -22,7 +22,6 @@ using System.Reflection; using System.Collections; using SIL.FieldWorks.FDO.DomainImpl; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Infrastructure.Impl; namespace SIL.FieldWorks.FDO diff --git a/Src/FDO/Infrastructure/BackendStartupParameter.cs b/Src/FDO/Infrastructure/BackendStartupParameter.cs index 481a175a9b..fe515de7c8 100644 --- a/Src/FDO/Infrastructure/BackendStartupParameter.cs +++ b/Src/FDO/Infrastructure/BackendStartupParameter.cs @@ -1,5 +1,3 @@ -using SIL.FieldWorks.Common.FwUtils; - namespace SIL.FieldWorks.FDO.Infrastructure { /// diff --git a/Src/FDO/Infrastructure/IPersistenceStrategyInterfaces.cs b/Src/FDO/Infrastructure/IPersistenceStrategyInterfaces.cs index 0d604ccfb2..6651885a82 100644 --- a/Src/FDO/Infrastructure/IPersistenceStrategyInterfaces.cs +++ b/Src/FDO/Infrastructure/IPersistenceStrategyInterfaces.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using SIL.Utils; -using SIL.FieldWorks.Common.FwUtils; namespace SIL.FieldWorks.FDO.Infrastructure { diff --git a/Src/FDO/Infrastructure/IUnitOfWorkService.cs b/Src/FDO/Infrastructure/IUnitOfWorkService.cs index 90ef6a7a10..4b977cb10a 100644 --- a/Src/FDO/Infrastructure/IUnitOfWorkService.cs +++ b/Src/FDO/Infrastructure/IUnitOfWorkService.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; +using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Infrastructure.Impl; namespace SIL.FieldWorks.FDO.Infrastructure diff --git a/Src/FDO/Infrastructure/Impl/ChangeReconciler.cs b/Src/FDO/Infrastructure/Impl/ChangeReconciler.cs index 181cfa8fd6..0317f5c41a 100644 --- a/Src/FDO/Infrastructure/Impl/ChangeReconciler.cs +++ b/Src/FDO/Infrastructure/Impl/ChangeReconciler.cs @@ -5,7 +5,6 @@ using System.Xml.Linq; using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainImpl; using SIL.Utils; diff --git a/Src/FDO/Infrastructure/Impl/ClientServerBackendProvider.cs b/Src/FDO/Infrastructure/Impl/ClientServerBackendProvider.cs index 0442eaba66..1267033fcc 100644 --- a/Src/FDO/Infrastructure/Impl/ClientServerBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/ClientServerBackendProvider.cs @@ -12,7 +12,6 @@ /* This class may well replace ClientServerBackend, which currently is used only by the MySQL classes */ using System.Collections.Generic; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.Infrastructure.Impl diff --git a/Src/FDO/Infrastructure/Impl/FdoStateChangingClasses.cs b/Src/FDO/Infrastructure/Impl/FdoStateChangingClasses.cs index 9673da5a4d..dd8bac2cd7 100644 --- a/Src/FDO/Infrastructure/Impl/FdoStateChangingClasses.cs +++ b/Src/FDO/Infrastructure/Impl/FdoStateChangingClasses.cs @@ -18,7 +18,6 @@ using System.Xml.Linq; using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Application; namespace SIL.FieldWorks.FDO.Infrastructure.Impl diff --git a/Src/FDO/Infrastructure/Impl/MemoryOnlyBackendProvider.cs b/Src/FDO/Infrastructure/Impl/MemoryOnlyBackendProvider.cs index 5f28588392..26170d6bee 100644 --- a/Src/FDO/Infrastructure/Impl/MemoryOnlyBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/MemoryOnlyBackendProvider.cs @@ -8,12 +8,9 @@ // Responsibility: Randy Regnier // Last reviewed: never // -------------------------------------------------------------------------------------------- -using System; + using System.Collections.Generic; -using System.IO; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; -using SIL.Utils; namespace SIL.FieldWorks.FDO.Infrastructure.Impl { diff --git a/Src/FDO/Infrastructure/Impl/UnitOfWorkService.cs b/Src/FDO/Infrastructure/Impl/UnitOfWorkService.cs index 1d64cad15f..7e0c9f21d9 100644 --- a/Src/FDO/Infrastructure/Impl/UnitOfWorkService.cs +++ b/Src/FDO/Infrastructure/Impl/UnitOfWorkService.cs @@ -13,9 +13,9 @@ using System.Runtime.InteropServices; using System.Threading; using System.Timers; +using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.FDO.Application; -using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; using Timer = System.Timers.Timer; diff --git a/Src/FDOBrowser/FDOBrowserForm.cs b/Src/FDOBrowser/FDOBrowserForm.cs index 887580b109..e0ecb6fd4f 100644 --- a/Src/FDOBrowser/FDOBrowserForm.cs +++ b/Src/FDOBrowser/FDOBrowserForm.cs @@ -8,6 +8,7 @@ using System.Reflection; using System.Resources; using System.Windows.Forms; +using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.Common.Controls; using SIL.FieldWorks.Common.Framework.DetailControls; diff --git a/Src/Utilities/FixFwDataDll/FixFwDataDll.csproj b/Src/Utilities/FixFwDataDll/FixFwDataDll.csproj index 4e6f0c9960..9324c296f8 100644 --- a/Src/Utilities/FixFwDataDll/FixFwDataDll.csproj +++ b/Src/Utilities/FixFwDataDll/FixFwDataDll.csproj @@ -144,6 +144,12 @@ true + + + {4C7D6B65-A331-4ED7-9B53-3301E714F8E7} + CoreImpl + + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - text/microsoft-resx + text/microsoft-resx - 2.0 + 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - You must have a region abbreviation if you specify a region name. + You must have a region abbreviation if you specify a region name. - You must have a unique variant abbreviation if you specify a variant name. Each variant name must be unique. To edit the variant abbreviation, first edit the variant name. + You must have a unique variant abbreviation if you specify a variant name. Each variant name must be unique. To edit the variant abbreviation, first edit the variant name. - Error - Caption for error messages in dialogs + Error + Caption for error messages in dialogs - The region abbreviation you entered is already in use. + The region abbreviation you entered is already in use. - The variant abbreviation you entered is already in use. + The variant abbreviation you entered is already in use. - None - Used in keyboard control (leading space causes it to be first in a sorted list) + None + Used in keyboard control (leading space causes it to be first in a sorted list) - More - Used for a overflow in a list + More + Used for a overflow in a list - Invalid keyboard + Invalid keyboard - -- Not Installed + -- Not Installed - Built In + Built In - Font Features... + Font Features... - The variant name "{0}" is already associated with "{1}", so it cannot be used here. - Used in RegionVariantControl + The variant name "{0}" is already associated with "{1}", so it cannot be used here. + Used in RegionVariantControl - The variant abbreviation "{0}" was associated with "{1}". Do you want to change "{0}" to refer to "{2}"? + The variant abbreviation "{0}" was associated with "{1}". Do you want to change "{0}" to refer to "{2}"? - The variant abbreviation "{0}" is reserved for "{1}", so it cannot be used here. + The variant abbreviation "{0}" is reserved for "{1}", so it cannot be used here. - Feature #{0} - Substring {0} MUST occur and will be replaced by integer feature number. + Feature #{0} + Substring {0} MUST occur and will be replaced by integer feature number. - Value #{0} + Value #{0} - "{0}" is not a valid measurement. + "{0}" is not a valid measurement. - The following system locales are invalid, so will be omitted from the list of System Languages for keyboard input: {0} - Used when filling a list of System keyboards + The following system locales are invalid, so will be omitted from the list of System Languages for keyboard input: {0} + Used when filling a list of System keyboards - FieldWorks is unable to recognize a language name. This item will be omitted from the list of System Languages for keyboard input. + FieldWorks is unable to recognize a language name. This item will be omitted from the list of System Languages for keyboard input. - <default settings> - Used in writing systems list box + <default settings> + Used in writing systems list box - (unspecified) - Used in Font combo box + (unspecified) + Used in Font combo box - Line spacing at least - Used in Description on the General tab of the Style dialog box + Line spacing at least + Used in Description on the General tab of the Style dialog box - Center - Used in Description on the General tab of the Style dialog box + Center + Used in Description on the General tab of the Style dialog box - Double Spacing - Used in Description on the General tab of the Style dialog box + Double Spacing + Used in Description on the General tab of the Style dialog box - Exact Spacing - Used in Description on the General tab of the Style dialog box + Exact Spacing + Used in Description on the General tab of the Style dialog box - First Line Hanging - Used in Description on the General tab of the Style dialog box + First Line Hanging + Used in Description on the General tab of the Style dialog box - First Line Indent - Used in Description on the General tab of the Style dialog box + First Line Indent + Used in Description on the General tab of the Style dialog box - Justify - Used in Description on the General tab of the Style dialog box + Justify + Used in Description on the General tab of the Style dialog box - Leading - Used in Description on the General tab of the Style dialog box + Leading + Used in Description on the General tab of the Style dialog box - Left - Used in Description on the General tab of the Style dialog box + Left + Used in Description on the General tab of the Style dialog box - Left-to-Right - Used in Description on the General tab of the Style dialog box + Left-to-Right + Used in Description on the General tab of the Style dialog box - None - Used in Description on the General tab of the Style dialog box + None + Used in Description on the General tab of the Style dialog box - Specifies the font to be used as a default in all “normal” styles when using this writing system. + Specifies the font to be used as a default in all “normal” styles when using this writing system. - 1.5 Line Spacing - Used in Description on the General tab of the Style dialog box + 1.5 Line Spacing + Used in Description on the General tab of the Style dialog box - Right - Used in Description on the General tab of the Style dialog box + Right + Used in Description on the General tab of the Style dialog box - Right-to-Left - Used in Description on the General tab of the Style dialog box + Right-to-Left + Used in Description on the General tab of the Style dialog box - Single Spacing - Used in Description on the General tab of the Style dialog box + Single Spacing + Used in Description on the General tab of the Style dialog box - Spacing After - Used in Description on the General tab of the Style dialog box + Spacing After + Used in Description on the General tab of the Style dialog box - Spacing Before - Used in Description on the General tab of the Style dialog box + Spacing Before + Used in Description on the General tab of the Style dialog box - Special Indent - Used in Description on the General tab of the Style dialog box + Special Indent + Used in Description on the General tab of the Style dialog box - Trailing - Used in Description on the General tab of the Style dialog box + Trailing + Used in Description on the General tab of the Style dialog box - Bulleted - Used in Description on the General tab of the Style dialog box + Bulleted + Used in Description on the General tab of the Style dialog box - Numbered - Used in Description on the General tab of the Style dialog box + Numbered + Used in Description on the General tab of the Style dialog box - All - Used in Description on the General tab of the Style dialog box + All + Used in Description on the General tab of the Style dialog box - Border ({0}) - Used in Description on the General tab of the Style dialog box + Border ({0}) + Used in Description on the General tab of the Style dialog box - {0}, {1} pt - Used in Description on the General tab of the Style dialog box for formatting the Color and point size of the border + {0}, {1} pt + Used in Description on the General tab of the Style dialog box for formatting the Color and point size of the border - {0} pt - Used in Description on the General tab of the Style dialog box for formatting the point size of the border + {0} pt + Used in Description on the General tab of the Style dialog box for formatting the point size of the border - Bottom - Used in Description on the General tab of the Style dialog box + Bottom + Used in Description on the General tab of the Style dialog box - , - Used in Description on the General tab of the Style dialog box to separate detail items + , + Used in Description on the General tab of the Style dialog box to separate detail items - : - Used in Description on the General tab of the Style dialog box to separate an item label from its value + : + Used in Description on the General tab of the Style dialog box to separate an item label from its value - No border - Used in Description on the General tab of the Style dialog box + No border + Used in Description on the General tab of the Style dialog box - No bullets or numbering - Used in Description on the General tab of the Style dialog box + No bullets or numbering + Used in Description on the General tab of the Style dialog box - Top - Used in Description on the General tab of the Style dialog box + Top + Used in Description on the General tab of the Style dialog box - Keyman initialization failed - Error message to display if Keyman initialization fails (application may append a colon and specific error details) + Keyman initialization failed + Error message to display if Keyman initialization fails (application may append a colon and specific error details) - L&eading - Used in the Border tab to show leading instead of a simple left or right + L&eading + Used in the Border tab to show leading instead of a simple left or right - L&eft - Used in the Border tab to show left instead of leading or trailing + L&eft + Used in the Border tab to show left instead of leading or trailing - &Right - Used in the Border tab to show right instead of leading or trailing + &Right + Used in the Border tab to show right instead of leading or trailing - T&railing - Used in the Border tab to show trailing instead of a simple left or right + T&railing + Used in the Border tab to show trailing instead of a simple left or right - Character + Character - Paragraph + Paragraph - Schema - Used for bullets/numbers in Description on the General tab of the Style dialog box + Schema + Used for bullets/numbers in Description on the General tab of the Style dialog box - Start at - Used for bullets/numbers in Description on the General tab of the + Start at + Used for bullets/numbers in Description on the General tab of the - Text after - Used for bullets/numbers in Description on the General tab of the + Text after + Used for bullets/numbers in Description on the General tab of the - Text before - Used for bullets/numbers in Description on the General tab of the + Text before + Used for bullets/numbers in Description on the General tab of the - <Missing: {0}> + <Missing: {0}> - The Script Abbreviation must be exactly 4 characters long. + The Script Abbreviation must be exactly 4 characters long. - The Region Abbreviation must be exactly 2 or 3 characters long. + The Region Abbreviation must be exactly 2 or 3 characters long. - Undo Marking Style {0} as Used + Undo Marking Style {0} as Used - Redo Marking Style {0} as Used + Redo Marking Style {0} as Used - The script abbreviation you entered is already in use. + The script abbreviation you entered is already in use. - You must have a script abbreviation if you specify a script name. + You must have a script abbreviation if you specify a script name. - The region abbreviation is invalid. It must be 2 alphabetic characters or 3 numeric characters. + The region abbreviation is invalid. It must be 2 alphabetic characters or 3 numeric characters. - The script abbreviation is invalid. It must be 4 alphabetic characters. + The script abbreviation is invalid. It must be 4 alphabetic characters. - The variant abbreviation is invalid. It must consist of alphanumeric characters, possibly with hyphens separating subsections. + The variant abbreviation is invalid. It must consist of alphanumeric characters, possibly with hyphens separating subsections. - Keyboard - Label of combo box in Linux to select a keyboard to use to type a language. + Keyboard + Label of combo box in Linux to select a keyboard to use to type a language. - The writing sytem codes you entered include the code {0} twice. This is not allowed. + The writing sytem codes you entered include the code {0} twice. This is not allowed. + + + Background is {0} + text background color + + + Bold + + + {0} Strikethrough + + + {0} Underline + + + Dashed {0} Underline + + + Dashed Underline + + + Dotted {0} Underline + + + Dotted Underline + + + Double {0} Underline + + + Double Underline + + + Italic + + + , + separate items in a list (comma space) + + + Lowered by {0} pt + Font lowered by X points + + + No ({0}) Underline + nonsense, but a possibility + + + No Super/Subscript + + + Not Bold + + + Not Italic + + + Not Raised/Lowered + + + No Underline + + + Raised by {0} pt + Font raised by X points + + + Single {0} Underline + insert explicit color + + + Single Underline + + + Strikethrough + + + Subscript + + + Superscript + + + Text is {0} + text foreground color + + + Text is {0} on {1} + text foreground and background colors + + + {0} pt + size in "points" \ No newline at end of file diff --git a/Src/FwCoreDlgs/FwCoreDlgControls/FwCoreDlgControlsTests/StylesComboTests.cs b/Src/FwCoreDlgs/FwCoreDlgControls/FwCoreDlgControlsTests/StylesComboTests.cs index 39d74df129..c9489ab069 100644 --- a/Src/FwCoreDlgs/FwCoreDlgControls/FwCoreDlgControlsTests/StylesComboTests.cs +++ b/Src/FwCoreDlgs/FwCoreDlgControls/FwCoreDlgControlsTests/StylesComboTests.cs @@ -72,7 +72,7 @@ protected override void CreateTestData() m_lp.StylesOC); m_styleSheet = new FwStyleSheet(); m_styleSheet.Init(Cache, m_lp.Hvo, - LangProjectTags.kflidStyles); + LangProjectTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); Debug.Assert(m_stylesComboBox == null, "m_stylesComboBox is not null."); //if (m_stylesComboBox != null) diff --git a/Src/FwCoreDlgs/FwCoreDlgControls/StyleInfo.cs b/Src/FwCoreDlgs/FwCoreDlgControls/StyleInfo.cs index 875aa69ce1..0aaebe6d9e 100644 --- a/Src/FwCoreDlgs/FwCoreDlgControls/StyleInfo.cs +++ b/Src/FwCoreDlgs/FwCoreDlgControls/StyleInfo.cs @@ -309,7 +309,7 @@ private void AddBulletInfo(StringBuilder text) AppendItem(tmp, FwCoreDlgControls.kstidSchema, scheme.ToString()); } if (m_bulletInfo.Value.FontInfo.IsAnyExplicit) - AppendItem(tmp, m_bulletInfo.Value.FontInfo.ToString()); + AppendItem(tmp, m_bulletInfo.Value.FontInfo.ToString(false)); } else { @@ -327,7 +327,7 @@ private void AddBulletInfo(StringBuilder text) GetNumberSchemeNameForType(m_bulletInfo.Value.m_numberScheme)); } if (m_bulletInfo.Value.FontInfo.IsAnyExplicit) - AppendItem(tmp, m_bulletInfo.Value.FontInfo.ToString()); + AppendItem(tmp, m_bulletInfo.Value.FontInfo.ToString(false)); } if (tmp.Length > 0) @@ -380,7 +380,7 @@ private void AddWsSpecificFontInfo(StringBuilder text) var ws = m_style.Cache.ServiceLocator.WritingSystemManager.Get(wsInfo.Key); text.Append(ws.DisplayLabel); text.Append(": "); - text.Append(wsInfo.Value.ToString()); + text.Append(wsInfo.Value.ToString(false)); text.AppendLine(); } } diff --git a/Src/FwCoreDlgs/FwFontDialog.cs b/Src/FwCoreDlgs/FwFontDialog.cs index 17bc829d46..d92d1c30a4 100644 --- a/Src/FwCoreDlgs/FwFontDialog.cs +++ b/Src/FwCoreDlgs/FwFontDialog.cs @@ -16,6 +16,7 @@ // --------------------------------------------------------------------------------------------- using System; using System.Drawing; +using System.Globalization; using System.Linq; using System.Windows.Forms; using SIL.FieldWorks.Common.COMInterfaces; @@ -97,9 +98,9 @@ void IFontDialog.Initialize(FontInfo fontInfo, bool fAllowSubscript, int ws, m_preview.WritingSystemCode = ws; m_preview.StyleSheet = styleSheet; - m_tbFontName.Text = fontInfo.UIFontName; + m_tbFontName.Text = fontInfo.UIFontName(); FontSize = fontInfo.m_fontSize.Value / 1000; - m_tbFontSize.Text = FontSize.ToString(); + m_tbFontSize.Text = FontSize.ToString(CultureInfo.InvariantCulture); m_FontAttributes.UpdateForStyle(fontInfo); m_FontAttributes.AllowSuperSubScript = fAllowSubscript; @@ -129,7 +130,7 @@ DialogResult IFontDialog.ShowDialog(IWin32Window parent) void IFontDialog.SaveFontInfo(FontInfo fontInfo) { // Font name - string newValue = FontInfo.GetInternalFontName(m_tbFontName.Text); + string newValue = GetInternalFontName(m_tbFontName.Text); fontInfo.IsDirty |= fontInfo.m_fontName.Save(false, newValue); // font size @@ -435,5 +436,18 @@ private void btnHelp_Click(object sender, EventArgs e) ShowHelp.ShowHelpTopic(m_helpTopicProvider, "kstidBulletsAndNumberingSelectFont"); } + /// ------------------------------------------------------------------------------------ + /// + /// Gets the internal font name for the given UI font. + /// + /// UI name of the font. + /// Internal font name + /// ------------------------------------------------------------------------------------ + private static string GetInternalFontName(string fontNameUI) + { + if (fontNameUI == ResourceHelper.GetResourceString("kstidDefaultFont")) + return StyleServices.DefaultFont; + return fontNameUI; + } } } diff --git a/Src/FwResources/FwStrings.Designer.cs b/Src/FwResources/FwStrings.Designer.cs index 1008cd15f1..21202c9265 100644 --- a/Src/FwResources/FwStrings.Designer.cs +++ b/Src/FwResources/FwStrings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.1008 +// Runtime Version:4.0.30319.18052 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -60,19 +60,6 @@ internal FwStrings() { } } - /// - /// Looks up a localized string similar to Backup file contains a version of the project which was created using a newer version of FieldWorks: - ///{0} - /// - ///To restore from this backup, install version {1} of FieldWorks. - ///. - /// - internal static string ksBackupFileCreatedByNewerFwVersion { - get { - return ResourceManager.GetString("ksBackupFileCreatedByNewerFwVersion", resourceCulture); - } - } - /// /// Looks up a localized string similar to .... /// @@ -82,15 +69,6 @@ internal static string ksEllipsis { } } - /// - /// Looks up a localized string similar to File is not a valid FieldWorks backup:. - /// - internal static string ksInvalidFwBackupFile { - get { - return ResourceManager.GetString("ksInvalidFwBackupFile", resourceCulture); - } - } - /// /// Looks up a localized string similar to FieldWorks has encountered a problem setting up the writing systems. It may be that you need to first log out and then back in. If that doesn't fix it, you can also try asking an administrator to add you to the fieldworks group by using the command: $ sudo adduser 'yourusername' fieldworks. /// @@ -244,15 +222,6 @@ internal static string kstidAllVideo { } } - /// - /// Looks up a localized string similar to analysis. - /// - internal static string kstidAnalysis { - get { - return ResourceManager.GetString("kstidAnalysis", resourceCulture); - } - } - /// /// Looks up a localized string similar to Anthropology Codes. /// @@ -1678,15 +1647,6 @@ internal static string kstidImportMapping { } } - /// - /// Looks up a localized string similar to Style {0} could not be added because an incompatible style with the same name already exists.. - /// - internal static string kstidIncompatibleStyleExists { - get { - return ResourceManager.GetString("kstidIncompatibleStyleExists", resourceCulture); - } - } - /// /// Looks up a localized string similar to Initializing Window.... /// @@ -1885,15 +1845,6 @@ internal static string kstidNotBaseCharErrorMsg { } } - /// - /// Looks up a localized string similar to FieldWorks project has no current {0} writing systems.. - /// - internal static string kstidNoWritingSystems { - get { - return ResourceManager.GetString("kstidNoWritingSystems", resourceCulture); - } - } - /// /// Looks up a localized string similar to Outdated Version of FieldWorks. /// @@ -2330,15 +2281,6 @@ internal static string kstidSavingChanges { } } - /// - /// Looks up a localized string similar to Footnote. - /// - internal static string kstidScriptureFootnote { - get { - return ResourceManager.GetString("kstidScriptureFootnote", resourceCulture); - } - } - /// /// Looks up a localized string similar to Introduction. /// @@ -2348,15 +2290,6 @@ internal static string kstidScriptureIntro { } } - /// - /// Looks up a localized string similar to Introduction({0}). - /// - internal static string kstidScriptureSectionIntroduction { - get { - return ResourceManager.GetString("kstidScriptureSectionIntroduction", resourceCulture); - } - } - /// /// Looks up a localized string similar to Title. /// @@ -2826,15 +2759,6 @@ internal static string kstidUserStyleSuffix { } } - /// - /// Looks up a localized string similar to vernacular. - /// - internal static string kstidVernacular { - get { - return ResourceManager.GetString("kstidVernacular", resourceCulture); - } - } - /// /// Looks up a localized string similar to Version History. /// diff --git a/Src/FwResources/FwStrings.resx b/Src/FwResources/FwStrings.resx index 55b84165ee..c06d97388e 100644 --- a/Src/FwResources/FwStrings.resx +++ b/Src/FwResources/FwStrings.resx @@ -901,10 +901,6 @@ only in multiple-paragraph fields like 'Description' Updating: '{0}' ... This is the status message for the progress dialog used when creating factory (default) styles. (Creating styles requires up to four passes. The message is for the second pass.) - - FieldWorks project has no current {0} writing systems. - Message box displayed if count of current vernacular/analysis writing systems is 0. (parameter is either verncaular or analysis) - Warning Title for warning message box @@ -928,9 +924,6 @@ only in multiple-paragraph fields like 'Description' All Vernacular and Analysis - - analysis - Best Analysis @@ -952,9 +945,6 @@ only in multiple-paragraph fields like 'Description' Default Vernacular - - vernacular - No Filter The name for the no filters menu item @@ -967,18 +957,9 @@ only in multiple-paragraph fields like 'Description' ... ellipsis - mark showing missing words, "more to come", or more info than is displayed. - - Footnote - - - Introduction({0}) - Introduction - - Title - A4 for list of paper sizes in Page Setup dialog @@ -1011,10 +992,6 @@ only in multiple-paragraph fields like 'Description' The gutter is too big for the publication page to fit on the selected paper size. error message from Page Setup dialog - - Style {0} could not be added because an incompatible style with the same name already exists. - Error message when someone adds a style that has been added on another machine that is incompatible (e.g. because of different context, structure, etc). - Paratext Language Files Used in the Browse for Language File filter accessed from the Valid Characters dialog box @@ -1361,16 +1338,6 @@ FieldWorks ReadMe for help in this area. FieldWorks Project Files Used in the list of file types in file open dialogs - - File is not a valid FieldWorks backup: - - - Backup file contains a version of the project which was created using a newer version of FieldWorks: -{0} - -To restore from this backup, install version {1} of FieldWorks. - - Unable to restore. @@ -1449,4 +1416,7 @@ To restore from this backup, install version {1} of FieldWorks. FieldWorks has encountered a problem setting up the writing systems. It may be that you need to first log out and then back in. If that doesn't fix it, you can also try asking an administrator to add you to the fieldworks group by using the command: $ sudo adduser 'yourusername' fieldworks Used in Linux version if the user forgets to logout and back in after New Install. + + Title + \ No newline at end of file diff --git a/Src/LexText/Interlinear/InterlinearTextsRecordClerk.cs b/Src/LexText/Interlinear/InterlinearTextsRecordClerk.cs index 4be9c48b35..530db001ed 100644 --- a/Src/LexText/Interlinear/InterlinearTextsRecordClerk.cs +++ b/Src/LexText/Interlinear/InterlinearTextsRecordClerk.cs @@ -12,6 +12,7 @@ using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.Infrastructure; +using SIL.FieldWorks.Resources; using SIL.FieldWorks.XWorks; using SIL.Utils; using XCore; @@ -429,7 +430,7 @@ public IScrBook Import(int bookNum, Form owningForm, bool importBt) IScripture scr = Cache.LangProject.TranslatedScriptureOA; bool haveSomethingToImport = NonUndoableUnitOfWorkHelper.Do(Cache.ActionHandlerAccessor, () => { - IScrImportSet importSettings = scr.FindOrCreateDefaultImportSettings(TypeOfImport.Paratext6); + IScrImportSet importSettings = scr.FindOrCreateDefaultImportSettings(TypeOfImport.Paratext6, ResourceHelper.DefaultParaCharsStyleName); ScrText paratextProj = ParatextHelper.GetAssociatedProject(Cache.ProjectId); importSettings.ParatextScrProj = paratextProj.Name; importSettings.IncludeBooks(bookNum, bookNum, paratextProj.Versification); @@ -475,7 +476,7 @@ private FwStyleSheet ScriptureStylesheet if (m_stylesheet == null) { m_stylesheet = new FwStyleSheet(); - m_stylesheet.Init(Cache, Cache.LangProject.TranslatedScriptureOA.Hvo, ScriptureTags.kflidStyles); + m_stylesheet.Init(Cache, Cache.LangProject.TranslatedScriptureOA.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); } return m_stylesheet; } diff --git a/Src/LexText/Interlinear/RawTextPane.cs b/Src/LexText/Interlinear/RawTextPane.cs index 02e1070e56..85cbd29678 100644 --- a/Src/LexText/Interlinear/RawTextPane.cs +++ b/Src/LexText/Interlinear/RawTextPane.cs @@ -12,6 +12,7 @@ using SIL.FieldWorks.FDO.Application; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FdoUi; +using SIL.FieldWorks.Resources; using SIL.FieldWorks.XWorks; using XCore; using SIL.FieldWorks.FDO.Infrastructure; @@ -143,7 +144,7 @@ private void SetStyleSheet(int hvo) { m_flexStylesheet = m_styleSheet; // remember the default. var stylesheet = new FwStyleSheet(); - stylesheet.Init(Cache, Cache.LangProject.TranslatedScriptureOA.Hvo, ScriptureTags.kflidStyles); + stylesheet.Init(Cache, Cache.LangProject.TranslatedScriptureOA.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); m_teStylesheet = stylesheet; } wantedStylesheet = m_teStylesheet; diff --git a/Src/LexText/LexTextControls/ConfigureHomographDlg.cs b/Src/LexText/LexTextControls/ConfigureHomographDlg.cs index ea32a19869..5a60b2249b 100644 --- a/Src/LexText/LexTextControls/ConfigureHomographDlg.cs +++ b/Src/LexText/LexTextControls/ConfigureHomographDlg.cs @@ -7,6 +7,7 @@ using SIL.FieldWorks.FDO.DomainImpl; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FwCoreDlgs; +using SIL.FieldWorks.Resources; using XCore; namespace SIL.FieldWorks.LexText.Controls @@ -157,7 +158,7 @@ private void RunStyleDialog(string styleName) { m_app.Synchronize(SyncMsg.ksyncStyle); FwStyleSheet stylesheet = new FwStyleSheet(); - stylesheet.Init(m_cache, m_cache.LangProject.Hvo, LangProjectTags.kflidStyles); + stylesheet.Init(m_cache, m_cache.LangProject.Hvo, LangProjectTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); m_stylesheet = stylesheet; } } diff --git a/Src/LexText/LexTextControls/DataNotebook/ImportCharMappingDlg.cs b/Src/LexText/LexTextControls/DataNotebook/ImportCharMappingDlg.cs index 627089ba8d..8efcac81b7 100644 --- a/Src/LexText/LexTextControls/DataNotebook/ImportCharMappingDlg.cs +++ b/Src/LexText/LexTextControls/DataNotebook/ImportCharMappingDlg.cs @@ -24,6 +24,7 @@ using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices; +using SIL.FieldWorks.Resources; using XCore; using SIL.FieldWorks.FwCoreDlgs; @@ -147,7 +148,7 @@ private void m_btnStyles_Click(object sender, EventArgs e) { m_app.Synchronize(SyncMsg.ksyncStyle); FwStyleSheet stylesheet = new FwStyleSheet(); - stylesheet.Init(m_cache, m_cache.LangProject.Hvo, LangProjectTags.kflidStyles); + stylesheet.Init(m_cache, m_cache.LangProject.Hvo, LangProjectTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); m_stylesheet = stylesheet; } string stySel = null; diff --git a/Src/LexText/LexTextControls/DataNotebook/NotebookImportWiz.cs b/Src/LexText/LexTextControls/DataNotebook/NotebookImportWiz.cs index a553b34504..318effc7a9 100644 --- a/Src/LexText/LexTextControls/DataNotebook/NotebookImportWiz.cs +++ b/Src/LexText/LexTextControls/DataNotebook/NotebookImportWiz.cs @@ -771,7 +771,7 @@ public void Init(FdoCache cache, Mediator mediator) if (m_stylesheet == null) { FwStyleSheet styles = new FwStyleSheet(); - styles.Init(m_cache, m_cache.LangProject.Hvo, LangProjectTags.kflidStyles); + styles.Init(m_cache, m_cache.LangProject.Hvo, LangProjectTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); m_stylesheet = styles; } ShowSaveButtonOrNot(); diff --git a/Src/TE/DiffView/DiffViewTests/DiffDialogTests.cs b/Src/TE/DiffView/DiffViewTests/DiffDialogTests.cs index 6a3a207ef4..6669fd1e85 100644 --- a/Src/TE/DiffView/DiffViewTests/DiffDialogTests.cs +++ b/Src/TE/DiffView/DiffViewTests/DiffDialogTests.cs @@ -18,6 +18,7 @@ using SIL.FieldWorks.Common.RootSites; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.FDOTests; +using SIL.FieldWorks.Resources; using SIL.FieldWorks.Test.TestUtils; using SIL.Utils; using SIL.FieldWorks.Common.ScriptureUtils; @@ -608,7 +609,7 @@ private void CompleteInitialize(bool fMakePhilemonChanges, IScrBook bookRev) } m_styleSheet = new FwStyleSheet(); - m_styleSheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles); + m_styleSheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); Debug.Assert(m_dlg == null, "m_dlg is not null."); //if (m_dlg != null) @@ -1605,7 +1606,7 @@ public override void TestSetup() m_bookMerger = new DummyBookMerger(Cache, null, m_philemonRev); m_styleSheet = new FwStyleSheet(); - m_styleSheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles); + m_styleSheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); Debug.Assert(m_dlg == null, "m_dlg is not null."); //if (m_dlg != null) diff --git a/Src/TE/DiffView/DiffViewTests/DiffViewTests.csproj b/Src/TE/DiffView/DiffViewTests/DiffViewTests.csproj index d180a33141..abeb98ff5c 100644 --- a/Src/TE/DiffView/DiffViewTests/DiffViewTests.csproj +++ b/Src/TE/DiffView/DiffViewTests/DiffViewTests.csproj @@ -137,6 +137,10 @@ FwControls ..\..\..\..\Output\Debug\FwControls.dll + + False + ..\..\..\..\Output\Debug\FwResources.dll + FwUtils ..\..\..\..\Output\Debug\FwUtils.dll diff --git a/Src/TE/TeDialogs/TeDialogsTests/BookPropertiesTests.cs b/Src/TE/TeDialogs/TeDialogsTests/BookPropertiesTests.cs index 49d4ab19d0..fa2383361f 100644 --- a/Src/TE/TeDialogs/TeDialogsTests/BookPropertiesTests.cs +++ b/Src/TE/TeDialogs/TeDialogsTests/BookPropertiesTests.cs @@ -25,6 +25,7 @@ using SIL.FieldWorks.FDO.FDOTests; using SIL.FieldWorks.Common.RootSites; using SIL.FieldWorks.FDO.DomainServices; +using SIL.FieldWorks.Resources; namespace SIL.FieldWorks.TE { @@ -105,7 +106,7 @@ protected override void CreateTestData() AddSectionHeadParaToSection(section, "Section Heading", ScrStyleNames.SectionHead); m_stylesheet = new FwStyleSheet(); - m_stylesheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles); + m_stylesheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); } #endregion diff --git a/Src/TE/TeDialogs/TeDialogsTests/ScripturePropertiesTests.cs b/Src/TE/TeDialogs/TeDialogsTests/ScripturePropertiesTests.cs index a8fbcae890..a4d2c9c8b9 100644 --- a/Src/TE/TeDialogs/TeDialogsTests/ScripturePropertiesTests.cs +++ b/Src/TE/TeDialogs/TeDialogsTests/ScripturePropertiesTests.cs @@ -19,6 +19,7 @@ using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.Common.ScriptureUtils; using SIL.FieldWorks.FDO.FDOTests; +using SIL.FieldWorks.Resources; using SIL.Utils; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.Test.TestUtils; @@ -49,7 +50,7 @@ public class ScripturePropertiesTests : ScrInMemoryFdoTestBase protected override void CreateTestData() { m_stylesheet = new FwStyleSheet(); - m_stylesheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles); + m_stylesheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); m_exodus = AddBookToMockedScripture(2, "Exodus"); AddTitleToMockedBook(m_exodus, "Exodus"); diff --git a/Src/TE/TeDialogs/TeDialogsTests/TeDialogsTests.csproj b/Src/TE/TeDialogs/TeDialogsTests/TeDialogsTests.csproj index 002b4d1e2f..059fe8fee0 100644 --- a/Src/TE/TeDialogs/TeDialogsTests/TeDialogsTests.csproj +++ b/Src/TE/TeDialogs/TeDialogsTests/TeDialogsTests.csproj @@ -120,6 +120,10 @@ False ..\..\..\..\Output\Debug\DiffView.dll + + False + ..\..\..\..\Output\Debug\FwResources.dll + False ..\..\..\..\Output\Debug\FwUtils.dll diff --git a/Src/TE/TeEditing/TeEditingTests/TeEditingHelper_NavigationTests.cs b/Src/TE/TeEditing/TeEditingTests/TeEditingHelper_NavigationTests.cs index 22db2b81b2..31044f565c 100644 --- a/Src/TE/TeEditing/TeEditingTests/TeEditingHelper_NavigationTests.cs +++ b/Src/TE/TeEditing/TeEditingTests/TeEditingHelper_NavigationTests.cs @@ -20,6 +20,7 @@ using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.FDOTests; using SIL.FieldWorks.FDO.DomainServices; +using SIL.FieldWorks.Resources; using SILUBS.SharedScrUtils; namespace SIL.FieldWorks.TE.TeEditingHelpers @@ -140,7 +141,7 @@ public override void TestSetup() base.TestSetup(); FwStyleSheet styleSheet = new FwStyleSheet(); - styleSheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles); + styleSheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); Debug.Assert(m_draftView == null); m_draftView = new TeDummyBasicView(); diff --git a/Src/TE/TeEditing/TeEditingTests/TeEditingTests.csproj b/Src/TE/TeEditing/TeEditingTests/TeEditingTests.csproj index d78ecb8c4f..53f64d7d42 100644 --- a/Src/TE/TeEditing/TeEditingTests/TeEditingTests.csproj +++ b/Src/TE/TeEditing/TeEditingTests/TeEditingTests.csproj @@ -128,6 +128,10 @@ Framework ..\..\..\..\Output\Debug\Framework.dll + + False + ..\..\..\..\Output\Debug\FwResources.dll + FwUtils ..\..\..\..\Output\Debug\FwUtils.dll @@ -252,4 +256,4 @@ - + \ No newline at end of file diff --git a/Src/TE/TeImportExport/ImportWizard.cs b/Src/TE/TeImportExport/ImportWizard.cs index 38580903c4..2cf82eabd8 100644 --- a/Src/TE/TeImportExport/ImportWizard.cs +++ b/Src/TE/TeImportExport/ImportWizard.cs @@ -107,7 +107,7 @@ private enum WizSteps /// protected IScripture m_scr; - /// Either or + /// Either or protected FwListView m_lvCurrentMappingList; /// Either m_btnAddScrMapping or m_btnAddAnnotMapping protected Button m_btnCurrentAddButton; @@ -262,7 +262,7 @@ public ImportWizard(string langProjName, IScripture scr, FwStyleSheet styleSheet m_cache = scr.Cache; // Attempt to get the default import settings. - m_settings = m_scr.FindOrCreateDefaultImportSettings(TypeOfImport.Unknown); + m_settings = m_scr.FindOrCreateDefaultImportSettings(TypeOfImport.Unknown, ResourceHelper.DefaultParaCharsStyleName); if (m_settings.ImportTypeEnum == TypeOfImport.Unknown) m_settings.ImportTypeEnum = TypeOfImport.Paratext6; @@ -1957,7 +1957,7 @@ private void panStep3_VisibleChanged(object sender, EventArgs e) /// Handles the Click event of the m_btnNext control. /// /// The source of the event. - /// The instance containing the event + /// The instance containing the event /// data. /// ------------------------------------------------------------------------------------ protected void m_btnNext_Click(object sender, EventArgs e) @@ -1999,7 +1999,7 @@ protected void m_btnNext_Click(object sender, EventArgs e) /// Handles the Click event of the m_btnBack control. /// /// The source of the event. - /// The instance containing the event + /// The instance containing the event /// data. /// ------------------------------------------------------------------------------------ protected void m_btnBack_Click(object sender, EventArgs e) @@ -2119,7 +2119,7 @@ private void lvMappings_DrawSubItem(object sender, DrawListViewSubItemEventArgs /// Handles the CheckedChanged event of the rbParatext6 control (Paratext 6 radio button). /// /// The source of the event. - /// The instance containing the event + /// The instance containing the event /// data. /// ------------------------------------------------------------------------------------ private void rbParatext6_CheckedChanged(object sender, EventArgs e) @@ -2133,7 +2133,7 @@ private void rbParatext6_CheckedChanged(object sender, EventArgs e) /// Handles the CheckedChanged event of the rbParatext5 control (Paratext 5 radio button). /// /// The source of the event. - /// The instance containing the event + /// The instance containing the event /// data. /// ------------------------------------------------------------------------------------ private void rbParatext5_CheckedChanged(object sender, EventArgs e) @@ -2147,7 +2147,7 @@ private void rbParatext5_CheckedChanged(object sender, EventArgs e) /// Handles the CheckedChanged event of the rbOther control (Other USFM radio button). /// /// The source of the event. - /// The instance containing the event + /// The instance containing the event /// data. /// ------------------------------------------------------------------------------------ private void rbOther_CheckedChanged(object sender, EventArgs e) @@ -2167,7 +2167,7 @@ private void DefineImportSettings(TypeOfImport importType) { NonUndoableUnitOfWorkHelper.DoUsingNewOrCurrentUOW(m_cache.ActionHandlerAccessor, () => { - m_settings = m_scr.FindOrCreateDefaultImportSettings(importType); + m_settings = m_scr.FindOrCreateDefaultImportSettings(importType, ResourceHelper.DefaultParaCharsStyleName); }); InitializeScrImportSettings(); } diff --git a/Src/TE/TeImportExport/ScrNoteImportManager.cs b/Src/TE/TeImportExport/ScrNoteImportManager.cs index 6053176543..df9c2102f8 100644 --- a/Src/TE/TeImportExport/ScrNoteImportManager.cs +++ b/Src/TE/TeImportExport/ScrNoteImportManager.cs @@ -19,6 +19,7 @@ using SIL.CoreImpl; using SIL.FieldWorks.FDO; +using SIL.FieldWorks.Resources; using SILUBS.SharedScrUtils; using SIL.FieldWorks.TE.TeEditorialChecks; using System.Diagnostics; @@ -143,7 +144,7 @@ private static void CacheCheckIds() // This creates the annotation types for installed checks. SortedList chks = - InstalledScriptureChecks.GetChecks(new ScrChecksDataSource(s_scr.Cache)); + InstalledScriptureChecks.GetChecks(new ScrChecksDataSource(s_scr.Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"))); if (chks != null) { diff --git a/Src/TE/TeImportExport/TeImportExportTests/ExportTests/ExportRtfTests.cs b/Src/TE/TeImportExport/TeImportExportTests/ExportTests/ExportRtfTests.cs index e3173e3d02..a0f307289d 100644 --- a/Src/TE/TeImportExport/TeImportExportTests/ExportTests/ExportRtfTests.cs +++ b/Src/TE/TeImportExport/TeImportExportTests/ExportTests/ExportRtfTests.cs @@ -18,6 +18,7 @@ using SIL.FieldWorks.FDO; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.FDO.FDOTests; +using SIL.FieldWorks.Resources; using SIL.FieldWorks.Test.TestUtils; using SIL.Utils; using SIL.FieldWorks.FDO.DomainServices; @@ -577,7 +578,7 @@ public override void TestSetup() m_fileName = FileUtils.GetTempFile("tmp"); m_styleSheet = new FwStyleSheet(); m_styleSheet.Init(Cache, Cache.LangProject.TranslatedScriptureOA.Hvo, - ScriptureTags.kflidStyles); + ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); } /// ------------------------------------------------------------------------------------ diff --git a/Src/TE/TeImportExport/TeImportExportTests/ExportTests/ExportXhtmlTests.cs b/Src/TE/TeImportExport/TeImportExportTests/ExportTests/ExportXhtmlTests.cs index 7e5e994cb9..0881477032 100644 --- a/Src/TE/TeImportExport/TeImportExportTests/ExportTests/ExportXhtmlTests.cs +++ b/Src/TE/TeImportExport/TeImportExportTests/ExportTests/ExportXhtmlTests.cs @@ -14,6 +14,7 @@ using NUnit.Framework; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.FDOTests; +using SIL.FieldWorks.Resources; using SIL.Utils; using SIL.FieldWorks.FDO.DomainServices; using SIL.CoreImpl; @@ -47,7 +48,7 @@ public override void TestSetup() m_fileName = FileUtils.GetTempFile("tmp"); FileUtils.Delete(m_fileName); // exporter pops up dialog if file exists! m_stylesheet = new FwStyleSheet(); - m_stylesheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles); + m_stylesheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); m_book = AddBookToMockedScripture(1, "Genesis"); AddTitleToMockedBook(m_book, "Genesis"); diff --git a/Src/TE/TeImportExport/TeImportExportTests/ExportTests/ExportXmlTests.cs b/Src/TE/TeImportExport/TeImportExportTests/ExportTests/ExportXmlTests.cs index 38ab848622..c4fb415820 100644 --- a/Src/TE/TeImportExport/TeImportExportTests/ExportTests/ExportXmlTests.cs +++ b/Src/TE/TeImportExport/TeImportExportTests/ExportTests/ExportXmlTests.cs @@ -20,6 +20,7 @@ using SIL.FieldWorks.FDO.FDOTests; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.Common.ScriptureUtils; +using SIL.FieldWorks.Resources; using SIL.Utils; using SILUBS.SharedScrUtils; using SIL.FieldWorks.Test.TestUtils; @@ -195,7 +196,7 @@ public override void TestSetup() m_fileName = FileUtils.GetTempFile("tmp"); FileUtils.Delete(m_fileName); // exporter pops up dialog if file exists! m_stylesheet = new FwStyleSheet(); - m_stylesheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles); + m_stylesheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); m_book = AddBookToMockedScripture(1, "Genesis"); AddTitleToMockedBook(m_book, "Genesis"); diff --git a/Src/TE/TeImportExport/TeImportExportTests/ImportComponentsTests/CharacterMappingSettingsTests.cs b/Src/TE/TeImportExport/TeImportExportTests/ImportComponentsTests/CharacterMappingSettingsTests.cs index 8201afffbb..43440c1158 100644 --- a/Src/TE/TeImportExport/TeImportExportTests/ImportComponentsTests/CharacterMappingSettingsTests.cs +++ b/Src/TE/TeImportExport/TeImportExportTests/ImportComponentsTests/CharacterMappingSettingsTests.cs @@ -22,6 +22,7 @@ using SIL.FieldWorks.FDO.FDOTests; using SIL.FieldWorks.FwCoreDlgControls; using SIL.FieldWorks.FDO.DomainServices; +using SIL.FieldWorks.Resources; namespace SIL.FieldWorks.TE.ImportComponentsTests { @@ -158,7 +159,7 @@ public override void TestSetup() m_Scripture = Cache.LangProject.TranslatedScriptureOA; m_styleSheet = new FwStyleSheet(); - m_styleSheet.Init(Cache, m_Scripture.Hvo, ScriptureTags.kflidStyles); + m_styleSheet.Init(Cache, m_Scripture.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); m_mapping = new ImportMappingInfo("emph{", "}", "Emphasis"); Options.ShowTheseStylesSetting = Options.ShowTheseStyles.All; diff --git a/Src/TE/TeImportExport/TeImportExportTests/ImportComponentsTests/ImportWizardTests.cs b/Src/TE/TeImportExport/TeImportExportTests/ImportComponentsTests/ImportWizardTests.cs index d9e31dbf9a..8b9c07f314 100644 --- a/Src/TE/TeImportExport/TeImportExportTests/ImportComponentsTests/ImportWizardTests.cs +++ b/Src/TE/TeImportExport/TeImportExportTests/ImportComponentsTests/ImportWizardTests.cs @@ -23,6 +23,7 @@ using SIL.FieldWorks.Common.ScriptureUtils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.FDOTests; +using SIL.FieldWorks.Resources; using SIL.Utils; using SIL.FieldWorks.Test.ProjectUnpacker; using SIL.FieldWorks.FDO.DomainServices; @@ -479,10 +480,10 @@ public override void FixtureTeardown() /// ------------------------------------------------------------------------------------ protected override void CreateTestData() { - m_scr.FindOrCreateDefaultImportSettings(TypeOfImport.Other); + m_scr.FindOrCreateDefaultImportSettings(TypeOfImport.Other, ResourceHelper.DefaultParaCharsStyleName); m_styleSheet = new FwStyleSheet(); - m_styleSheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles); + m_styleSheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); } /// --------------------------------------------------------------------------------- diff --git a/Src/TE/TeImportExport/TeImportExportTests/ImportTests/ImportDialogTests.cs b/Src/TE/TeImportExport/TeImportExportTests/ImportTests/ImportDialogTests.cs index 4f3404c2d5..d860a74fb2 100644 --- a/Src/TE/TeImportExport/TeImportExportTests/ImportTests/ImportDialogTests.cs +++ b/Src/TE/TeImportExport/TeImportExportTests/ImportTests/ImportDialogTests.cs @@ -13,6 +13,7 @@ using NUnit.Framework; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.FDOTests; +using SIL.FieldWorks.Resources; using SIL.Utils; using SILUBS.SharedScrControls; using SILUBS.SharedScrUtils; @@ -100,7 +101,7 @@ public override void TestSetup() FileUtils.Manager.SetFileAdapter(m_mockFileOs); string fileGen = m_mockFileOs.MakeSfFile("GEN", @"\c 1"); string fileRev = m_mockFileOs.MakeSfFile("REV", @"\c 1"); - m_settings = m_scr.FindOrCreateDefaultImportSettings(TypeOfImport.Other); + m_settings = m_scr.FindOrCreateDefaultImportSettings(TypeOfImport.Other, ResourceHelper.DefaultParaCharsStyleName); m_settings.AddFile(fileGen, ImportDomain.Main, null, null); m_settings.AddFile(fileRev, ImportDomain.Main, null, null); m_dlg = new DummyImportDialog(null, Cache, m_settings); diff --git a/Src/TE/TeImportExport/TeImportExportTests/ImportTests/ImportStyleProxyTests.cs b/Src/TE/TeImportExport/TeImportExportTests/ImportTests/ImportStyleProxyTests.cs index ff78541da0..7e703158e8 100644 --- a/Src/TE/TeImportExport/TeImportExportTests/ImportTests/ImportStyleProxyTests.cs +++ b/Src/TE/TeImportExport/TeImportExportTests/ImportTests/ImportStyleProxyTests.cs @@ -25,6 +25,7 @@ using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.Common.Framework; using SIL.FieldWorks.Common.RootSites; +using SIL.FieldWorks.Resources; using SIL.FieldWorks.Test.TestUtils; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.Common.ScriptureUtils; @@ -58,7 +59,7 @@ public override void TestSetup() // Force load of styles IScripture scr = Cache.LangProject.TranslatedScriptureOA; Assert.IsTrue(scr.StylesOC.Count > 0); - m_styleSheet.Init(Cache, scr.Hvo, ScriptureTags.kflidStyles); + m_styleSheet.Init(Cache, scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); } /// ------------------------------------------------------------------------------------ diff --git a/Src/TE/TeImportExport/TeImportExportTests/ImportTests/TeAnnotationXmlImportTests.cs b/Src/TE/TeImportExport/TeImportExportTests/ImportTests/TeAnnotationXmlImportTests.cs index 1397dd445f..2c557f9d5c 100644 --- a/Src/TE/TeImportExport/TeImportExportTests/ImportTests/TeAnnotationXmlImportTests.cs +++ b/Src/TE/TeImportExport/TeImportExportTests/ImportTests/TeAnnotationXmlImportTests.cs @@ -30,6 +30,7 @@ using SIL.Utils; using SIL.CoreImpl; using SIL.FieldWorks.TE.TeEditorialChecks; +using SIL.FieldWorks.Resources; namespace SIL.FieldWorks.TE.ImportTests { @@ -81,7 +82,7 @@ public override void FixtureSetup() // part of the normal undoable work. NonUndoableUnitOfWorkHelper.Do(m_actionHandler, () => { - InstalledScriptureChecks.GetChecks(new ScrChecksDataSource(m_scr.Cache)); + InstalledScriptureChecks.GetChecks(new ScrChecksDataSource(m_scr.Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"))); }); } @@ -95,7 +96,7 @@ public override void TestSetup() base.TestSetup(); m_stylesheet = new FwStyleSheet(); - m_stylesheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles); + m_stylesheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); StyleProxyListManager.Initialize(m_stylesheet); } diff --git a/Src/TE/TeImportExport/TeImportExportTests/ImportTests/TeImportManagerTests.cs b/Src/TE/TeImportExport/TeImportExportTests/ImportTests/TeImportManagerTests.cs index 81a2adc920..952893c6e1 100644 --- a/Src/TE/TeImportExport/TeImportExportTests/ImportTests/TeImportManagerTests.cs +++ b/Src/TE/TeImportExport/TeImportExportTests/ImportTests/TeImportManagerTests.cs @@ -18,6 +18,7 @@ using SIL.FieldWorks.FDO; using SIL.FieldWorks.Common.Controls; using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.Resources; using SIL.Utils; using SIL.FieldWorks.Common.ScriptureUtils; using SIL.FieldWorks.FDO.FDOTests; @@ -43,7 +44,7 @@ internal class SegmentInfo /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The segment marker. /// The segment text. @@ -57,7 +58,7 @@ internal SegmentInfo(string sMarker, string sText, ImportDomain domain, /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The segment marker. /// The segment text. @@ -97,7 +98,7 @@ internal class MockScrObjWrapper : ScrObjWrapper /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The importer. /// The segment list. @@ -223,7 +224,7 @@ internal class MockTeImporter : TeSfmImporter /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Import settings object (filled in by wizard) /// The cache used to import to and get misc. info. from. @@ -395,7 +396,7 @@ public class DummyTeImportManager : TeImportManager #region Constructor /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The cache. /// The style sheet. @@ -545,7 +546,7 @@ internal class DummyTeImportManagerWithMockImporter : DummyTeImportManager #region Constructor /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The cache. /// The style sheet. @@ -621,7 +622,7 @@ public override void FixtureSetup() base.FixtureSetup(); m_styleSheet = new FwStyleSheet(); - m_styleSheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles); + m_styleSheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); // By default, use auto-generated footnote markers for import tests. m_scr.FootnoteMarkerType = FootnoteMarkerTypes.AutoFootnoteMarker; @@ -630,7 +631,7 @@ public override void FixtureSetup() NonUndoableUnitOfWorkHelper.Do(m_actionHandler, () => { - m_settings = m_scr.FindOrCreateDefaultImportSettings(TypeOfImport.Unknown); + m_settings = m_scr.FindOrCreateDefaultImportSettings(TypeOfImport.Unknown, ResourceHelper.DefaultParaCharsStyleName); DummyTeImporter.MakeSFImportTestSettings(m_settings); }); } diff --git a/Src/TE/TeImportExport/TeImportExportTests/ImportTests/TeImportTestsBase.cs b/Src/TE/TeImportExport/TeImportExportTests/ImportTests/TeImportTestsBase.cs index c63f7e85cd..24be36045c 100644 --- a/Src/TE/TeImportExport/TeImportExportTests/ImportTests/TeImportTestsBase.cs +++ b/Src/TE/TeImportExport/TeImportExportTests/ImportTests/TeImportTestsBase.cs @@ -21,6 +21,7 @@ using SIL.FieldWorks.FDO; using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.Resources; using SIL.Utils; using SIL.FieldWorks.Common.ScriptureUtils; using SIL.FieldWorks.Test.TestUtils; @@ -89,14 +90,14 @@ public override void TestSetup() base.TestSetup(); m_styleSheet = new FwStyleSheet(); - m_styleSheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles); + m_styleSheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); InitWsInfo(); DummyTeImporter.s_translatorNoteDefn = Cache.ServiceLocator.GetInstance().TranslatorAnnotationDefn; DummyTeImporter.s_consultantNoteDefn = Cache.ServiceLocator.GetInstance().ConsultantAnnotationDefn; m_titus = new BCVRef(56001001); - m_settings = m_scr.FindOrCreateDefaultImportSettings(TypeOfImport.Other); + m_settings = m_scr.FindOrCreateDefaultImportSettings(TypeOfImport.Other, ResourceHelper.DefaultParaCharsStyleName); m_settings.StartRef = m_titus; m_settings.EndRef = m_titus; m_settings.ImportTranslation = true; diff --git a/Src/TE/TeImportExport/TeImportExportTests/ImportTests/TeXmlImportTests.cs b/Src/TE/TeImportExport/TeImportExportTests/ImportTests/TeXmlImportTests.cs index 0b743072c5..b8233782fe 100644 --- a/Src/TE/TeImportExport/TeImportExportTests/ImportTests/TeXmlImportTests.cs +++ b/Src/TE/TeImportExport/TeImportExportTests/ImportTests/TeXmlImportTests.cs @@ -32,6 +32,7 @@ using SIL.CoreImpl; using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.TE.TeEditorialChecks; +using SIL.FieldWorks.Resources; namespace SIL.FieldWorks.TE.ImportTests { @@ -100,7 +101,7 @@ public override void FixtureSetup() // part of the normal undoable work. NonUndoableUnitOfWorkHelper.Do(m_actionHandler, () => { - InstalledScriptureChecks.GetChecks(new ScrChecksDataSource(m_scr.Cache)); + InstalledScriptureChecks.GetChecks(new ScrChecksDataSource(m_scr.Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"))); }); } @@ -121,7 +122,7 @@ public override void TestSetup() base.TestSetup(); m_styleSheet = new FwStyleSheet(); - m_styleSheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles); + m_styleSheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); InitWsInfo(); m_actionHandler.EndUndoTask(); // Import expects to handle undo diff --git a/Src/TE/TeImportExport/TeImportExportTests/SCTextEnumTests.cs b/Src/TE/TeImportExport/TeImportExportTests/SCTextEnumTests.cs index ed4e0a51d8..3467b021e3 100644 --- a/Src/TE/TeImportExport/TeImportExportTests/SCTextEnumTests.cs +++ b/Src/TE/TeImportExport/TeImportExportTests/SCTextEnumTests.cs @@ -30,6 +30,7 @@ using SILUBS.SharedScrUtils; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.Test.TestUtils; +using SIL.FieldWorks.Resources; namespace SIL.FieldWorks.TE { @@ -298,7 +299,7 @@ public override void TestTearDown() /// ------------------------------------------------------------------------------------ protected override void CreateTestData() { - m_settings = Cache.ServiceLocator.GetInstance().Create(); + m_settings = Cache.ServiceLocator.GetInstance().Create(ResourceHelper.DefaultParaCharsStyleName); Cache.LangProject.TranslatedScriptureOA.ImportSettingsOC.Add(m_settings); m_settings.ImportTypeEnum = TypeOfImport.Other; m_converters = null; diff --git a/Src/TE/TeImportExport/TeImportExportTests/SFFileListBuilderTests.cs b/Src/TE/TeImportExport/TeImportExportTests/SFFileListBuilderTests.cs index a5e7df145b..222f71f2ad 100644 --- a/Src/TE/TeImportExport/TeImportExportTests/SFFileListBuilderTests.cs +++ b/Src/TE/TeImportExport/TeImportExportTests/SFFileListBuilderTests.cs @@ -23,6 +23,7 @@ using NUnit.Framework; using SIL.CoreImpl; using SIL.FieldWorks.Common.Controls; +using SIL.FieldWorks.Resources; using SIL.FieldWorks.Test.TestUtils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.FDOTests; @@ -327,7 +328,7 @@ public override void FixtureSetup() Cache.ServiceLocator.WritingSystems.AnalysisWritingSystems.Add(wsGerman); Cache.ServiceLocator.WritingSystems.CurrentAnalysisWritingSystems.Add(wsGerman); }); - m_mappingList = new ScrMappingList(MappingSet.Main, null); + m_mappingList = new ScrMappingList(MappingSet.Main, null, ResourceHelper.DefaultParaCharsStyleName); } /// ------------------------------------------------------------------------------------ @@ -337,7 +338,7 @@ public override void FixtureSetup() /// ------------------------------------------------------------------------------------ protected override void CreateTestData() { - m_settings = m_scr.FindOrCreateDefaultImportSettings(TypeOfImport.Other); + m_settings = m_scr.FindOrCreateDefaultImportSettings(TypeOfImport.Other, ResourceHelper.DefaultParaCharsStyleName); m_builder = new DummySFFileListBuilder(); m_builder.ImportSettings = m_settings; DummyScrImportFileInfo.s_alwaysPretendFileDoesNotExist = false; diff --git a/Src/TE/TeImportExport/TeImportManager.cs b/Src/TE/TeImportExport/TeImportManager.cs index 75a9bb995a..f7fb0a96e2 100644 --- a/Src/TE/TeImportExport/TeImportManager.cs +++ b/Src/TE/TeImportExport/TeImportManager.cs @@ -26,6 +26,7 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Common.RootSites; using SIL.FieldWorks.Common.ScriptureUtils; +using SIL.FieldWorks.Resources; using SIL.Utils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices; @@ -285,7 +286,7 @@ protected IScrImportSet GetImportSettings() NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, () => { importSettings = - scr.FindOrCreateDefaultImportSettings(TypeOfImport.Unknown); + scr.FindOrCreateDefaultImportSettings(TypeOfImport.Unknown, ResourceHelper.DefaultParaCharsStyleName); }); importSettings.StyleSheet = m_styleSheet; diff --git a/Src/TE/TePrintLayout/TePrintLayoutTests/TeHeaderFooterVcTests.cs b/Src/TE/TePrintLayout/TePrintLayoutTests/TeHeaderFooterVcTests.cs index 0d2f281520..006f5b8c83 100644 --- a/Src/TE/TePrintLayout/TePrintLayoutTests/TeHeaderFooterVcTests.cs +++ b/Src/TE/TePrintLayout/TePrintLayoutTests/TeHeaderFooterVcTests.cs @@ -19,6 +19,7 @@ using NUnit.Framework; using SIL.FieldWorks.FDO; using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.Resources; using SIL.Utils; using SIL.FieldWorks.Common.RootSites; using SIL.FieldWorks.Common.PrintLayout; @@ -164,7 +165,7 @@ protected void ConfigurePublication() FwStyleSheet styleSheet = new FwStyleSheet(); styleSheet.Init(Cache, Cache.LangProject.TranslatedScriptureOA.Hvo, - ScriptureTags.kflidStyles); + ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); m_pubCtrl = new DummyScripturePublicationNoDb(pub, styleSheet, m_division, DateTime.Now, m_filterInstance); m_pubCtrl.Configure(); diff --git a/Src/TE/TePrintLayout/TePrintLayoutTests/TePrintLayoutTests.cs b/Src/TE/TePrintLayout/TePrintLayoutTests/TePrintLayoutTests.cs index ad88e2ec18..a479d81bab 100644 --- a/Src/TE/TePrintLayout/TePrintLayoutTests/TePrintLayoutTests.cs +++ b/Src/TE/TePrintLayout/TePrintLayoutTests/TePrintLayoutTests.cs @@ -27,6 +27,7 @@ using SIL.FieldWorks.Common.RootSites; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.Common.ScriptureUtils; +using SIL.FieldWorks.Resources; namespace SIL.FieldWorks.TE { @@ -706,7 +707,7 @@ private void ConfigurePublication(bool fAddSubStream, bool fAddContent) FwStyleSheet styleSheet = new FwStyleSheet(); styleSheet.Init(Cache, Cache.LangProject.TranslatedScriptureOA.Hvo, - ScriptureTags.kflidStyles); + ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); FootnoteVc footnoteVc = new FootnoteVc(TeStVc.LayoutViewTarget.targetPrint, -1); footnoteVc.Cache = Cache; diff --git a/Src/TE/TePrintLayout/TePrintLayoutTests/TePrintLayoutTests.csproj b/Src/TE/TePrintLayout/TePrintLayoutTests/TePrintLayoutTests.csproj index f805b7ad64..798e34574d 100644 --- a/Src/TE/TePrintLayout/TePrintLayoutTests/TePrintLayoutTests.csproj +++ b/Src/TE/TePrintLayout/TePrintLayoutTests/TePrintLayoutTests.csproj @@ -137,6 +137,10 @@ FwPrintLayoutComponentsTests ..\..\..\..\Output\Debug\FwPrintLayoutComponentsTests.dll + + False + ..\..\..\..\Output\Debug\FwResources.dll + False ..\..\..\..\Output\Debug\FwUtils.dll @@ -219,7 +223,9 @@ UserControl - + + UserControl + diff --git a/Src/TE/TePrintLayout/TePrintLayoutTests/TextScalingTests.cs b/Src/TE/TePrintLayout/TePrintLayoutTests/TextScalingTests.cs index 4ec46f7a29..4bd9e496c1 100644 --- a/Src/TE/TePrintLayout/TePrintLayoutTests/TextScalingTests.cs +++ b/Src/TE/TePrintLayout/TePrintLayoutTests/TextScalingTests.cs @@ -25,6 +25,7 @@ using SIL.FieldWorks.Common.PrintLayout; using SIL.FieldWorks.Common.ScriptureUtils; using SIL.FieldWorks.FDO.DomainServices; +using SIL.FieldWorks.Resources; namespace SIL.FieldWorks.TE.TePrintLayoutComponents { @@ -136,7 +137,7 @@ protected override void CreateTestData() m_pub = m_scr.PublicationsOC.ToArray()[0]; Assert.IsNotNull(m_pub); m_realStylesheet = new FwStyleSheet(); - m_realStylesheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles); + m_realStylesheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); SetFontSizeLineHeightAndSpaceBeforeAfter(m_realStylesheet, ScrStyleNames.Normal, null, 10000, -12000, -1, -1); SetFontSizeLineHeightAndSpaceBeforeAfter(m_realStylesheet, ScrStyleNames.NormalParagraph, diff --git a/Src/TE/TeScrInitializer/TeScrInitializerTests/TeScrInitializerTests.cs b/Src/TE/TeScrInitializer/TeScrInitializerTests/TeScrInitializerTests.cs index 0c91d8df92..04c69cf5bd 100644 --- a/Src/TE/TeScrInitializer/TeScrInitializerTests/TeScrInitializerTests.cs +++ b/Src/TE/TeScrInitializer/TeScrInitializerTests/TeScrInitializerTests.cs @@ -23,6 +23,7 @@ using SIL.FieldWorks.Common.ScriptureUtils; using SIL.FieldWorks.FDO.FDOTests; using SILUBS.SharedScrUtils; +using SIL.FieldWorks.Resources; namespace SIL.FieldWorks.TE { @@ -521,7 +522,7 @@ private void VerifyResourceForFixedOrphans() /// ------------------------------------------------------------------------------------ private void VerifyNoOrphanedFootnotes() { - ScrChecksDataSource scrData = new ScrChecksDataSource(Cache); + ScrChecksDataSource scrData = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); foreach (IScrBook book in m_scr.ScriptureBooksOS) { using (IEnumerator footnotes = book.FootnotesOS.GetEnumerator()) diff --git a/Src/TE/TeScrInitializer/TeScrInitializerTests/TeScrInitializerTests.csproj b/Src/TE/TeScrInitializer/TeScrInitializerTests/TeScrInitializerTests.csproj index b5c0f172ee..0b840d30d5 100644 --- a/Src/TE/TeScrInitializer/TeScrInitializerTests/TeScrInitializerTests.csproj +++ b/Src/TE/TeScrInitializer/TeScrInitializerTests/TeScrInitializerTests.csproj @@ -133,6 +133,10 @@ False ..\..\..\..\Output\Debug\FwPrintLayoutComponents.dll + + False + ..\..\..\..\Output\Debug\FwResources.dll + FwUtils ..\..\..\..\Output\Debug\FwUtils.dll @@ -173,6 +177,7 @@ System + System.XML diff --git a/Src/TeDll/TeDll.csproj b/Src/TeDll/TeDll.csproj index 0cd402a918..4e59ca1e91 100644 --- a/Src/TeDll/TeDll.csproj +++ b/Src/TeDll/TeDll.csproj @@ -317,7 +317,9 @@ Code - + + Component + UserControl @@ -325,11 +327,21 @@ DockableUsfmBrowser.cs - - - - - + + UserControl + + + UserControl + + + UserControl + + + Component + + + UserControl + Form @@ -344,12 +356,16 @@ ScrTextListSelectionForm.cs - + + Component + Code - + + Form + Code @@ -360,8 +376,12 @@ TrainingAvailable.cs - - + + Component + + + UserControl + Designer BtDraftSplitWrapper.cs diff --git a/Src/TeDll/TeDllTests/DummyDraftViewForm.cs b/Src/TeDll/TeDllTests/DummyDraftViewForm.cs index 1aaa3dc554..756bcc2784 100644 --- a/Src/TeDll/TeDllTests/DummyDraftViewForm.cs +++ b/Src/TeDll/TeDllTests/DummyDraftViewForm.cs @@ -22,6 +22,7 @@ using SIL.FieldWorks.Common.Controls; using SIL.FieldWorks.Common.RootSites; using SIL.FieldWorks.FDO.Infrastructure.Impl; +using SIL.FieldWorks.Resources; using SIL.Utils; using SIL.FieldWorks.FDO.DomainServices; @@ -286,7 +287,7 @@ public FwStyleSheet StyleSheet ILangProject lgproj = Cache.LangProject; IScripture scripture = lgproj.TranslatedScriptureOA; - m_styleSheet.Init(Cache, scripture.Hvo, ScriptureTags.kflidStyles); + m_styleSheet.Init(Cache, scripture.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); } return m_styleSheet; } diff --git a/Src/TeDll/TeDllTests/DummyFootnoteViewForm.cs b/Src/TeDll/TeDllTests/DummyFootnoteViewForm.cs index 2472300522..05888a6b9b 100644 --- a/Src/TeDll/TeDllTests/DummyFootnoteViewForm.cs +++ b/Src/TeDll/TeDllTests/DummyFootnoteViewForm.cs @@ -19,6 +19,7 @@ using SIL.FieldWorks.FDO; using SIL.FieldWorks.Common.Controls; using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.Resources; using SIL.Utils; using SIL.FieldWorks.Common.RootSites; using SIL.FieldWorks.FDO.DomainServices; @@ -436,7 +437,7 @@ public void CreateFootnoteView(FdoCache cache) ILangProject lgproj = Cache.LangProject; IScripture scripture = lgproj.TranslatedScriptureOA; - styleSheet.Init(Cache, scripture.Hvo, ScriptureTags.kflidStyles); + styleSheet.Init(Cache, scripture.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); m_footnoteView = new DummyFootnoteView(Cache); m_footnoteView.Anchor = AnchorStyles.Top | AnchorStyles.Left | diff --git a/Src/TeDll/TeDllTests/ScrObjWrapperTests.cs b/Src/TeDll/TeDllTests/ScrObjWrapperTests.cs index 526fd7d455..3b50df31af 100644 --- a/Src/TeDll/TeDllTests/ScrObjWrapperTests.cs +++ b/Src/TeDll/TeDllTests/ScrObjWrapperTests.cs @@ -17,6 +17,7 @@ using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.FDOTests; +using SIL.FieldWorks.Resources; using SIL.FieldWorks.Test.TestUtils; using SIL.FieldWorks.Common.ScriptureUtils; using SIL.FieldWorks.Test.ProjectUnpacker; @@ -42,7 +43,7 @@ public void LoadParatext5Project() { using (ScrObjWrapper wrapper = new ScrObjWrapper()) { - IScrImportSet settings = m_scr.FindOrCreateDefaultImportSettings(TypeOfImport.Paratext5); + IScrImportSet settings = m_scr.FindOrCreateDefaultImportSettings(TypeOfImport.Paratext5, ResourceHelper.DefaultParaCharsStyleName); settings.StartRef = new BCVRef(1, 1, 1); settings.EndRef = new BCVRef(66, 22, 21); TempSFFileMaker fileMaker = new TempSFFileMaker(); @@ -80,7 +81,7 @@ public void LoadP6ProjectForAnnotationOnlyImportWithOnlyScriptureProjectSet() { using (ScrObjWrapper wrapper = new ScrObjWrapper()) { - IScrImportSet settings = m_scr.FindOrCreateDefaultImportSettings(TypeOfImport.Paratext6); + IScrImportSet settings = m_scr.FindOrCreateDefaultImportSettings(TypeOfImport.Paratext6, ResourceHelper.DefaultParaCharsStyleName); Unpacker.UnPackParatextTestProjects(); settings.ParatextScrProj = "KAM"; @@ -109,7 +110,7 @@ public void LoadP6ProjectForAnnotationOnlyImportWithOnlyBTProjectSet() { using (ScrObjWrapper wrapper = new ScrObjWrapper()) { - IScrImportSet settings = m_scr.FindOrCreateDefaultImportSettings(TypeOfImport.Paratext6); + IScrImportSet settings = m_scr.FindOrCreateDefaultImportSettings(TypeOfImport.Paratext6, ResourceHelper.DefaultParaCharsStyleName); Unpacker.UnPackParatextTestProjects(); settings.ParatextBTProj = "KAM"; diff --git a/Src/TeDll/TeDllTests/SyncedDraftViewTests.cs b/Src/TeDll/TeDllTests/SyncedDraftViewTests.cs index 6215f484dd..15ab6423f0 100644 --- a/Src/TeDll/TeDllTests/SyncedDraftViewTests.cs +++ b/Src/TeDll/TeDllTests/SyncedDraftViewTests.cs @@ -16,6 +16,7 @@ using SIL.FieldWorks.Common.RootSites; using SIL.FieldWorks.Common.ScriptureUtils; using SIL.FieldWorks.FDO; +using SIL.FieldWorks.Resources; namespace SIL.FieldWorks.TE.DraftViews { @@ -69,7 +70,7 @@ public void WithBorderOnBottomOfTitle() (int)FwTextPropVar.ktpvMilliPoint, 20); titleMain.Rules = propBldr.GetTextProps(); m_draftForm.StyleSheet.Init(Cache, m_scr.Hvo, - ScriptureTags.kflidStyles); + ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); m_group.RefreshDisplay(); m_draftView.PerformLayout(); diff --git a/Src/TeDll/TeDllTests/TeMainWndTests.cs b/Src/TeDll/TeDllTests/TeMainWndTests.cs index f835e1471e..c5d8caa40c 100644 --- a/Src/TeDll/TeDllTests/TeMainWndTests.cs +++ b/Src/TeDll/TeDllTests/TeMainWndTests.cs @@ -25,6 +25,7 @@ using SIL.FieldWorks.Common.RootSites; using SIL.FieldWorks.Common.ScriptureUtils; using SIL.FieldWorks.FDO.DomainServices; +using SIL.FieldWorks.Resources; using SIL.Utils; using SILUBS.SharedScrUtils; @@ -88,7 +89,7 @@ public override bool BookFilterInEffect { ILangProject lgproj = Cache.LangProject; IScripture scripture = lgproj.TranslatedScriptureOA; - m_StyleSheet.Init(Cache, scripture.Hvo, ScriptureTags.kflidStyles); + m_StyleSheet.Init(Cache, scripture.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); } return m_StyleSheet; } diff --git a/Src/xWorks/FwXWindow.cs b/Src/xWorks/FwXWindow.cs index 051c911316..2eeefb8def 100644 --- a/Src/xWorks/FwXWindow.cs +++ b/Src/xWorks/FwXWindow.cs @@ -2245,7 +2245,7 @@ private void ResyncRootboxStyles() if (fss != fssPrev) { Debug.Assert(fss.RootObjectHvo != 0); - fss.Init(Cache, fss.RootObjectHvo, fss.StyleListTag); + fss.Init(Cache, fss.RootObjectHvo, fss.StyleListTag, ResourceHelper.DefaultParaCharsStyleName); } rootb.OnStylesheetChange(); fssPrev = fss; @@ -2423,7 +2423,7 @@ private void ResyncStylesheet() { if (m_StyleSheet == null) m_StyleSheet = new FwStyleSheet(); - m_StyleSheet.Init(Cache, Cache.LanguageProject.Hvo, LangProjectTags.kflidStyles); + m_StyleSheet.Init(Cache, Cache.LanguageProject.Hvo, LangProjectTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); if (m_rebarAdapter is IUIAdapterForceRegenerate) ((IUIAdapterForceRegenerate)m_rebarAdapter).ForceFullRegenerate(); } From fca70d4c07258168dd99ba90bef3a6a9784f9da2 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Mon, 9 Dec 2013 10:46:02 +0700 Subject: [PATCH 029/143] Move toward removing FwUtils reference from FDO Prepare for refactoring of DirectoryFinder. One step closer to removal of duplicate code in FwFileExtensions. Change-Id: I20e881ea670ed50df9e5a5e3002838960afe6211 --- Src/Common/FieldWorks/FieldWorks.cs | 10 +- Src/Common/FieldWorks/ProjectId.cs | 10 +- .../ScrUtilsInterfaces.csproj | 330 +++++++++--------- .../ScriptureUtilsException.cs | 2 - .../BackupRestore/BackupFileRepository.cs | 4 +- .../BackupRestore/BackupFileSettings.cs | 4 +- .../BackupRestore/BackupProjectSettings.cs | 2 +- .../BackupRestore/ProjectRestoreService.cs | 4 +- .../DomainServices/ClientServerServices.cs | 6 +- .../DataMigration/ImportFrom6_0.cs | 2 +- Src/FDO/DomainServices/FwProjectFinder.cs | 2 +- Src/FDO/FDO.csproj | 2 +- .../BackupFileRepositoryTests.cs | 2 +- .../BackupRestoreSettingsTests.cs | 6 +- .../ProjectRestoreServiceTests.cs | 2 +- Src/FDO/FDOTests/ClientServerServicesTests.cs | 2 +- Src/FDO/FDOTests/Db4oServerInfoTests.cs | 2 +- ...{FdoFileExtensions.cs => FdoFileHelper.cs} | 22 +- Src/FDO/Infrastructure/Impl/Db4oServerInfo.cs | 4 +- .../Infrastructure/Impl/XMLBackendProvider.cs | 2 +- Src/FDOBrowser/FDOBrowserForm.cs | 4 +- Src/FwCoreDlgs/ChooseLangProjectDialog.cs | 4 +- .../RestoreProjectPresenterTests.cs | 3 +- Src/FwCoreDlgs/FwDeleteProjectDlg.cs | 12 +- Src/FwResources/FwFileExtensions.cs | 12 +- Src/LexText/Lexicon/FLExBridgeListener.cs | 12 +- Src/Utilities/FixFwDataDll/ErrorFixer.cs | 6 +- Src/Utilities/FixFwDataDll/FixErrorsDlg.cs | 3 +- .../FixFwDataDll/FixFwDataDll.csproj | 4 + Src/Utilities/FixFwDataDll/FwDataFixer.cs | 4 +- Src/xWorks/Archiving/ReapRamp.cs | 2 +- 31 files changed, 244 insertions(+), 242 deletions(-) rename Src/FDO/{FdoFileExtensions.cs => FdoFileHelper.cs} (73%) diff --git a/Src/Common/FieldWorks/FieldWorks.cs b/Src/Common/FieldWorks/FieldWorks.cs index 88e6d2cc04..2f629b5197 100644 --- a/Src/Common/FieldWorks/FieldWorks.cs +++ b/Src/Common/FieldWorks/FieldWorks.cs @@ -1304,10 +1304,10 @@ private static ProjectId GetBestGuessProjectId(string latestProject, string late if (!File.Exists(projId.Path)) { string altProject; - if (Path.GetExtension(latestProject) == FwFileExtensions.ksFwDataXmlFileExtension) - altProject = Path.ChangeExtension(latestProject, FwFileExtensions.ksFwDataDb4oFileExtension); + if (Path.GetExtension(latestProject) == FdoFileHelper.ksFwDataXmlFileExtension) + altProject = Path.ChangeExtension(latestProject, FdoFileHelper.ksFwDataDb4oFileExtension); else - altProject = Path.ChangeExtension(latestProject, FwFileExtensions.ksFwDataXmlFileExtension); + altProject = Path.ChangeExtension(latestProject, FdoFileHelper.ksFwDataXmlFileExtension); projId = new ProjectId(altProject, latestServer); } } @@ -2310,12 +2310,12 @@ private static bool IsFieldWorksProjectFolder(string projectFolder) { var projectName = Path.GetFileName(projectFolder); // If it contains a matching fwdata file it is a project folder. - var projectFileName = Path.ChangeExtension(Path.Combine(projectFolder, projectName), FwFileExtensions.ksFwDataXmlFileExtension); + var projectFileName = Path.ChangeExtension(Path.Combine(projectFolder, projectName), FdoFileHelper.ksFwDataXmlFileExtension); if(File.Exists(projectFileName)) return true; // Just in case some project didn't get converted back to fwdata before we ask this question, // allow folders containing fwdb files, too. - projectFileName = Path.ChangeExtension(projectFileName, FwFileExtensions.ksFwDataDb4oFileExtension); + projectFileName = Path.ChangeExtension(projectFileName, FdoFileHelper.ksFwDataDb4oFileExtension); if (File.Exists(projectFileName)) return true; return false; diff --git a/Src/Common/FieldWorks/ProjectId.cs b/Src/Common/FieldWorks/ProjectId.cs index eeb02a9760..04a1e8e37f 100644 --- a/Src/Common/FieldWorks/ProjectId.cs +++ b/Src/Common/FieldWorks/ProjectId.cs @@ -321,7 +321,7 @@ public string UiName } return string.Format(Properties.Resources.ksProjectNameAndServerFmt, Name, hostName); case FDOBackendProviderType.kXML: - return (SysPath.GetExtension(Path) != FwFileExtensions.ksFwDataXmlFileExtension) ? + return (SysPath.GetExtension(Path) != FdoFileHelper.ksFwDataXmlFileExtension) ? SysPath.GetFileName(Path) : Name; case FDOBackendProviderType.kInvalid: return string.Empty; @@ -530,12 +530,12 @@ private static string CleanUpNameForType(FDOBackendProviderType type, string nam switch (type) { case FDOBackendProviderType.kXML: - ext = FwFileExtensions.ksFwDataXmlFileExtension; + ext = FdoFileHelper.ksFwDataXmlFileExtension; break; case FDOBackendProviderType.kDb4oClientServer: if (!IsServerLocal(server)) return name; - ext = FwFileExtensions.ksFwDataDb4oFileExtension; + ext = FdoFileHelper.ksFwDataDb4oFileExtension; break; default: return name; @@ -584,9 +584,9 @@ private static FDOBackendProviderType GetType(string type, string pathname, stri switch (ext) // Includes period. { case ".db4o": // for historical purposes - case FwFileExtensions.ksFwDataDb4oFileExtension: + case FdoFileHelper.ksFwDataDb4oFileExtension: return FDOBackendProviderType.kDb4oClientServer; - case FwFileExtensions.ksFwDataXmlFileExtension: + case FdoFileHelper.ksFwDataXmlFileExtension: return FDOBackendProviderType.kXML; } } diff --git a/Src/Common/ScrUtilsInterfaces/ScrUtilsInterfaces.csproj b/Src/Common/ScrUtilsInterfaces/ScrUtilsInterfaces.csproj index 998ce9007c..428996b88e 100644 --- a/Src/Common/ScrUtilsInterfaces/ScrUtilsInterfaces.csproj +++ b/Src/Common/ScrUtilsInterfaces/ScrUtilsInterfaces.csproj @@ -1,185 +1,183 @@ - + - Local - 9.0.30729 - 2.0 - {9CA14238-3229-4FB3-A42A-A173D25F4A6B} - - - - Debug - AnyCPU - - - - - ScrUtilsInterfaces - - - JScript - Grid - IE50 - false - Library - SIL.FieldWorks.Common.ScriptureUtils - OnBuildSuccess - - - - - - - - - 3.5 - false - v4.0 - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - true - + Local + 9.0.30729 + 2.0 + {9CA14238-3229-4FB3-A42A-A173D25F4A6B} + + + + + + + Debug + AnyCPU + + + + + ScrUtilsInterfaces + + + JScript + Grid + IE50 + false + Library + SIL.FieldWorks.Common.ScriptureUtils + OnBuildSuccess + + + + + + + + + 3.5 + false + v4.0 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + - ..\..\..\Output\Debug\ - false - 285212672 - false - - - DEBUG;TRACE - ..\..\..\Output\Debug\ScrUtilsInterfaces.xml - true - 4096 - false - 168,169,219,414,649,1635,1702,1701 - false - false - false - true - 4 - full - prompt - AllRules.ruleset - x86 + ..\..\..\Output\Debug\ + false + 285212672 + false + + + DEBUG;TRACE + ..\..\..\Output\Debug\ScrUtilsInterfaces.xml + true + 4096 + false + 168,169,219,414,649,1635,1702,1701 + false + false + false + true + 4 + full + prompt + AllRules.ruleset + x86 - ..\..\..\Output\Release\ - false - 285212672 - false - - - TRACE - - - false - 4096 - false - 168,169,219,414,649,1635,1702,1701 - true - false - false - false - 4 - none - prompt - AllRules.ruleset - x86 + ..\..\..\Output\Release\ + false + 285212672 + false + + + TRACE + + + false + 4096 + false + 168,169,219,414,649,1635,1702,1701 + true + false + false + false + 4 + none + prompt + AllRules.ruleset + x86 - - False - ..\..\..\Output\Debug\COMInterfaces.dll - - - False - ..\..\..\Output\Debug\FwResources.dll - - - False - ..\..\..\Output\Debug\SharedScrUtils.dll - - - System - - - - System.Data - - - - System.XML - + + False + ..\..\..\Output\Debug\COMInterfaces.dll + + + False + ..\..\..\Output\Debug\SharedScrUtils.dll + + + System + + + + System.Data + + + System.XML + - - CommonAssemblyInfo.cs - - - Code - - - Code - - - Code - - - Code - - - - + + CommonAssemblyInfo.cs + + + Code + + + Code + + + Code + + + Code + + + + - - Designer - + + Designer + - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 2.0 %28x86%29 - true - - - False - .NET Framework 3.0 %28x86%29 - false - - - False - .NET Framework 3.5 - false - - - False - .NET Framework 3.5 SP1 - false - + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + true + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + False + .NET Framework 3.5 SP1 + false + - - - - + + + + \ No newline at end of file diff --git a/Src/Common/ScrUtilsInterfaces/ScriptureUtilsException.cs b/Src/Common/ScrUtilsInterfaces/ScriptureUtilsException.cs index 9b90e27ebd..d4023bc62e 100644 --- a/Src/Common/ScrUtilsInterfaces/ScriptureUtilsException.cs +++ b/Src/Common/ScrUtilsInterfaces/ScriptureUtilsException.cs @@ -15,11 +15,9 @@ // // --------------------------------------------------------------------------------------------- using System; -using System.Runtime; using System.Reflection; using System.Resources; using SILUBS.SharedScrUtils; -using SIL.FieldWorks.Resources; namespace SIL.FieldWorks.Common.ScriptureUtils { diff --git a/Src/FDO/DomainServices/BackupRestore/BackupFileRepository.cs b/Src/FDO/DomainServices/BackupRestore/BackupFileRepository.cs index d80408172e..9618c564ec 100644 --- a/Src/FDO/DomainServices/BackupRestore/BackupFileRepository.cs +++ b/Src/FDO/DomainServices/BackupRestore/BackupFileRepository.cs @@ -57,7 +57,7 @@ public BackupFileRepository() foreach (string backup in backups) { string ext = Path.GetExtension(backup); - if (ext != FdoFileExtensions.ksFwBackupFileExtension && ext != FdoFileExtensions.ksFw60BackupFileExtension) + if (ext != FdoFileHelper.ksFwBackupFileExtension && ext != FdoFileHelper.ksFw60BackupFileExtension) continue; string filename = Path.GetFileNameWithoutExtension(backup); MatchCollection matches = regex.Matches(filename); @@ -79,7 +79,7 @@ public BackupFileRepository() { SortedDictionary versions = GetOrCreateProjectVersions(projectName); string comment; - if (ext == FdoFileExtensions.ksFw60BackupFileExtension) + if (ext == FdoFileHelper.ksFw60BackupFileExtension) comment = Properties.Resources.kstidFw60OrEarlierBackupComment; else { diff --git a/Src/FDO/DomainServices/BackupRestore/BackupFileSettings.cs b/Src/FDO/DomainServices/BackupRestore/BackupFileSettings.cs index c5f961cd5e..049f71b4ff 100644 --- a/Src/FDO/DomainServices/BackupRestore/BackupFileSettings.cs +++ b/Src/FDO/DomainServices/BackupRestore/BackupFileSettings.cs @@ -396,7 +396,7 @@ private void PopulateSettingsFromZipFileIfNeeded() return; string extension = Path.GetExtension(m_sZipFileName).ToLowerInvariant(); - if (extension == FdoFileExtensions.ksFw60BackupFileExtension) + if (extension == FdoFileHelper.ksFw60BackupFileExtension) { ProcessOldZipFile(); return; @@ -430,7 +430,7 @@ private void PopulateSettingsFromZipFileIfNeeded() foundBackupSettingsFile = true; InitializeFromStream(zipIn); } - else if (Path.GetExtension(fileName) == FdoFileExtensions.ksFwDataXmlFileExtension) + else if (Path.GetExtension(fileName) == FdoFileHelper.ksFwDataXmlFileExtension) { if (dataFileName != null) throw new InvalidOperationException("Zip file " + m_sZipFileName + diff --git a/Src/FDO/DomainServices/BackupRestore/BackupProjectSettings.cs b/Src/FDO/DomainServices/BackupRestore/BackupProjectSettings.cs index d59480315e..4762a3ac17 100644 --- a/Src/FDO/DomainServices/BackupRestore/BackupProjectSettings.cs +++ b/Src/FDO/DomainServices/BackupRestore/BackupProjectSettings.cs @@ -153,7 +153,7 @@ public string AdjustedComment private string MakeBackupFileName(string comment) { return ProjectName + " " + BackupTime.ToString(ksBackupDateFormat) + - comment + FdoFileExtensions.ksFwBackupFileExtension; + comment + FdoFileHelper.ksFwBackupFileExtension; } /// ------------------------------------------------------------------------------------ diff --git a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs index 7cae893341..63e3a02037 100644 --- a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs +++ b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs @@ -100,7 +100,7 @@ public void RestoreProject(IThreadedProgress progressDlg) { //Import from FW version 6.0 based on the file extension. var extension = Path.GetExtension(fileSettings.File).ToLowerInvariant(); - if (extension == FdoFileExtensions.ksFw60BackupFileExtension || extension == ".xml") + if (extension == FdoFileHelper.ksFw60BackupFileExtension || extension == ".xml") ImportFrom6_0Backup(fileSettings, progressDlg); else //Restore from FW version 7.0 and newer backup. RestoreFrom7_0AndNewerBackup(fileSettings); @@ -292,7 +292,7 @@ private void UncompressDataFiles() m_restoreSettings.ProjectPath, entry.DateTime); } string bakFile = Path.Combine(m_restoreSettings.ProjectPath, m_restoreSettings.ProjectName) - + FdoFileExtensions.ksFwDataFallbackFileExtension; + + FdoFileHelper.ksFwDataFallbackFileExtension; if (FileUtils.TrySimilarFileExists(bakFile, out bakFile)) { FileUtils.Delete(bakFile); // TODO: do something about the .Lock file....... diff --git a/Src/FDO/DomainServices/ClientServerServices.cs b/Src/FDO/DomainServices/ClientServerServices.cs index 1f3655b668..99ec1d3208 100644 --- a/Src/FDO/DomainServices/ClientServerServices.cs +++ b/Src/FDO/DomainServices/ClientServerServices.cs @@ -78,8 +78,8 @@ public static string GetExtension(this FDOBackendProviderType type) { switch (type) { - case FDOBackendProviderType.kDb4oClientServer: return FdoFileExtensions.ksFwDataDb4oFileExtension; - case FDOBackendProviderType.kXML: return FdoFileExtensions.ksFwDataXmlFileExtension; + case FDOBackendProviderType.kDb4oClientServer: return FdoFileHelper.ksFwDataDb4oFileExtension; + case FDOBackendProviderType.kXML: return FdoFileHelper.ksFwDataXmlFileExtension; default: throw new InvalidEnumArgumentException("type", (int)type, typeof(FDOBackendProviderType)); } } @@ -864,7 +864,7 @@ public string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string { if (!ShareMyProjects) return xmlFilename; // no conversion needed. - string desiredPath = Path.ChangeExtension(xmlFilename, FdoFileExtensions.ksFwDataDb4oFileExtension); + string desiredPath = Path.ChangeExtension(xmlFilename, FdoFileHelper.ksFwDataDb4oFileExtension); if (!EnsureNoClientsAreConnected(Path.GetFileNameWithoutExtension(desiredPath), ui)) return null; // fail diff --git a/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs b/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs index 39d10bcfc3..2abdea2ebc 100644 --- a/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs +++ b/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs @@ -75,7 +75,7 @@ public bool Import(string pathname, string projectName, out string projectFile) { var destFolder = DirectoryFinder.ProjectsDirectory; var folderName = Path.Combine(destFolder, projectName); - projectFile = Path.Combine(folderName, projectName + FdoFileExtensions.ksFwDataXmlFileExtension); + projectFile = Path.Combine(folderName, projectName + FdoFileHelper.ksFwDataXmlFileExtension); string extension = Path.GetExtension(pathname); if (extension != null) extension = extension.ToLowerInvariant(); diff --git a/Src/FDO/DomainServices/FwProjectFinder.cs b/Src/FDO/DomainServices/FwProjectFinder.cs index 7a9068c35e..935b87bf6e 100644 --- a/Src/FDO/DomainServices/FwProjectFinder.cs +++ b/Src/FDO/DomainServices/FwProjectFinder.cs @@ -93,7 +93,7 @@ private void FindProjects() if (!FileUtils.SimilarFileExists(db4oFile)) { // See if there is a .bak file - string backupFile = Path.ChangeExtension(file, FdoFileExtensions.ksFwDataFallbackFileExtension); + string backupFile = Path.ChangeExtension(file, FdoFileHelper.ksFwDataFallbackFileExtension); //NOTE: RickM I think this probably should be changed to TrySimilarFileExists but don't want to try this //on a release build. if (FileUtils.SimilarFileExists(backupFile)) diff --git a/Src/FDO/FDO.csproj b/Src/FDO/FDO.csproj index 9c804a72a9..4df5508718 100644 --- a/Src/FDO/FDO.csproj +++ b/Src/FDO/FDO.csproj @@ -366,7 +366,7 @@ - + diff --git a/Src/FDO/FDOTests/BackupRestore/BackupFileRepositoryTests.cs b/Src/FDO/FDOTests/BackupRestore/BackupFileRepositoryTests.cs index e0d8f6380a..649c37e2df 100644 --- a/Src/FDO/FDOTests/BackupRestore/BackupFileRepositoryTests.cs +++ b/Src/FDO/FDOTests/BackupRestore/BackupFileRepositoryTests.cs @@ -189,7 +189,7 @@ public void BackupHasOldStyleDatetimeFormat() DummyBackupProjectSettings backupSettings = new DummyBackupProjectSettings("monkey", "Floozy", null, FDOBackendProviderType.kXML); string backupFileName1 = Path.Combine(DirectoryFinder.DefaultBackupDirectory, - Path.ChangeExtension("Floozy 2010-8-21-0506", FdoFileExtensions.ksFwBackupFileExtension)); + Path.ChangeExtension("Floozy 2010-8-21-0506", FdoFileHelper.ksFwBackupFileExtension)); m_fileOs.AddExistingFile(backupFileName1); BackupFileRepository repo = new BackupFileRepository(); diff --git a/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs b/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs index 74c397c11e..ceb5bdf38e 100644 --- a/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs +++ b/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs @@ -82,7 +82,7 @@ public void RestoreProjectSettings_VerifyExistenceOfProject() RestoreProjectSettings restoreSettings = new RestoreProjectSettings() { Backup = new BackupFileSettings(Path.Combine(restoreTestsZipFileDir, - Path.ChangeExtension("TestRestoreFWProject", FdoFileExtensions.ksFwBackupFileExtension))), + Path.ChangeExtension("TestRestoreFWProject", FdoFileHelper.ksFwBackupFileExtension))), IncludeConfigurationSettings = false, IncludeLinkedFiles = false, IncludeSupportingFiles = true, @@ -122,7 +122,7 @@ public void RestoreProjectSettings_VerifyExistenceOfHgRepo() RestoreProjectSettings restoreSettings = new RestoreProjectSettings() { Backup = new BackupFileSettings(Path.Combine(restoreTestsZipFileDir, - Path.ChangeExtension("TestRestoreFWProject", FdoFileExtensions.ksFwBackupFileExtension))), + Path.ChangeExtension("TestRestoreFWProject", FdoFileHelper.ksFwBackupFileExtension))), IncludeConfigurationSettings = false, IncludeLinkedFiles = false, IncludeSupportingFiles = true, @@ -220,7 +220,7 @@ public void RestoreProjectSettings_CreateFromCommandLineOptions() public void BackupFileSettings_InitializeFromZipfileMetadata() { string zipFilePath = Path.Combine(Path.Combine(DirectoryFinder.FwSourceDirectory, "FDO/FDOTests/BackupRestore/RestoreProjectPresenterTests"), - Path.ChangeExtension("RestoreProjectPresenterTests", FdoFileExtensions.ksFwBackupFileExtension)); + Path.ChangeExtension("RestoreProjectPresenterTests", FdoFileHelper.ksFwBackupFileExtension)); BackupFileSettings backupSettings = new BackupFileSettings(zipFilePath); Assert.AreEqual("BackupOnlyCoreFiles", backupSettings.Comment); diff --git a/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs b/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs index 5348750517..d5faafa312 100644 --- a/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs +++ b/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs @@ -69,7 +69,7 @@ public void Initialize() m_restoreSettings = new RestoreProjectSettings() { Backup = new BackupFileSettings(Path.Combine(restoreTestsZipFileDir, - Path.ChangeExtension("TestRestoreFWProject", FdoFileExtensions.ksFwBackupFileExtension))), + Path.ChangeExtension("TestRestoreFWProject", FdoFileHelper.ksFwBackupFileExtension))), IncludeConfigurationSettings = false, IncludeLinkedFiles = false, IncludeSupportingFiles = false, diff --git a/Src/FDO/FDOTests/ClientServerServicesTests.cs b/Src/FDO/FDOTests/ClientServerServicesTests.cs index 9ba804ba85..998cfcc00d 100644 --- a/Src/FDO/FDOTests/ClientServerServicesTests.cs +++ b/Src/FDO/FDOTests/ClientServerServicesTests.cs @@ -133,7 +133,7 @@ public void IdForLocalProject_SimpleNameProjectsAreNotShared_ReturnedFilenameHas string filename = ClientServerServices.Current.Local.IdForLocalProject("tom"); // Assert ends with .fwdata - Assert.AreEqual(FdoFileExtensions.ksFwDataXmlFileExtension, Path.GetExtension(filename)); + Assert.AreEqual(FdoFileHelper.ksFwDataXmlFileExtension, Path.GetExtension(filename)); // Check file is in ProjectDirectory. Assert.That(filename, Is.SubPath(DirectoryFinder.ProjectsDirectory)); diff --git a/Src/FDO/FDOTests/Db4oServerInfoTests.cs b/Src/FDO/FDOTests/Db4oServerInfoTests.cs index 45cc819110..c98ff66d59 100644 --- a/Src/FDO/FDOTests/Db4oServerInfoTests.cs +++ b/Src/FDO/FDOTests/Db4oServerInfoTests.cs @@ -202,7 +202,7 @@ public void StopFwRemoteDatabaseConnector() [Test] public void ListServers_UnknownNumberOfServers_ReturnsAllServersInProjectsDirectory() { - int projectsCount = Directory.GetFiles(DirectoryFinder.ProjectsDirectory, "*" + FdoFileExtensions.ksFwDataDb4oFileExtension, + int projectsCount = Directory.GetFiles(DirectoryFinder.ProjectsDirectory, "*" + FdoFileHelper.ksFwDataDb4oFileExtension, SearchOption.AllDirectories).Count(); m_db4OServerInfo.RefreshServerList(); diff --git a/Src/FDO/FdoFileExtensions.cs b/Src/FDO/FdoFileHelper.cs similarity index 73% rename from Src/FDO/FdoFileExtensions.cs rename to Src/FDO/FdoFileHelper.cs index d5deb1e016..d0941860e4 100644 --- a/Src/FDO/FdoFileExtensions.cs +++ b/Src/FDO/FdoFileHelper.cs @@ -8,7 +8,7 @@ // #endregion // -// File: FdoFileExtensions.cs +// File: FdoFileHelper.cs // -------------------------------------------------------------------------------------------- namespace SIL.FieldWorks.FDO @@ -18,25 +18,27 @@ namespace SIL.FieldWorks.FDO /// Static class to hold a few constant FDO file extensions. /// /// ---------------------------------------------------------------------------------------- - internal static class FdoFileExtensions + public static class FdoFileHelper { /* - * The following extensions are also defined in FwFileExtensions + * The following 4 extensions are also defined in FwFileExtensions * as a temporary stopgap. - * The idea is that eventually, those will be removed - * and all references will use FdoFileExtensions. + * The idea is that once FwUtils references FDO, those will be removed + * and all references will use FdoFileHelper. * * If a change is made here, it should be made in FwFileExtensions as well. */ /// Default extension for FieldWorks XML data files (with the period) - internal const string ksFwDataXmlFileExtension = ".fwdata"; + public const string ksFwDataXmlFileExtension = ".fwdata"; /// Default extension for FieldWorks DB4o data files (with the period) - internal const string ksFwDataDb4oFileExtension = ".fwdb"; + public const string ksFwDataDb4oFileExtension = ".fwdb"; /// Default extension for FieldWorks backup files (with the period). - internal const string ksFwBackupFileExtension = ".fwbackup"; + public const string ksFwBackupFileExtension = ".fwbackup"; /// Default extension for FieldWorks 6.0 and earlier backup files (with the period). - internal const string ksFw60BackupFileExtension = ".zip"; + public const string ksFw60BackupFileExtension = ".zip"; + + /// Default extension for FieldWorks TEMPORARY fallback data files (with the period). - internal const string ksFwDataFallbackFileExtension = ".bak"; + public const string ksFwDataFallbackFileExtension = ".bak"; } } diff --git a/Src/FDO/Infrastructure/Impl/Db4oServerInfo.cs b/Src/FDO/Infrastructure/Impl/Db4oServerInfo.cs index bf732fe5ed..6a114ed7c4 100644 --- a/Src/FDO/Infrastructure/Impl/Db4oServerInfo.cs +++ b/Src/FDO/Infrastructure/Impl/Db4oServerInfo.cs @@ -96,14 +96,14 @@ internal void PopulateServerList() if (!Directory.Exists(DirectoryFinder.ProjectsDirectory)) throw new DirectoryNotFoundException(String.Format(Strings.ksWarningProjectFolderNotFoundOnServer, DirectoryFinder.ProjectsDirectory)); - string[] files = Directory.GetFiles(DirectoryFinder.ProjectsDirectory, "*" + FdoFileExtensions.ksFwDataDb4oFileExtension); + string[] files = Directory.GetFiles(DirectoryFinder.ProjectsDirectory, "*" + FdoFileHelper.ksFwDataDb4oFileExtension); m_allServers.AddRange(files); // search sub dirs string[] dirs = Directory.GetDirectories(DirectoryFinder.ProjectsDirectory); foreach (var dir in dirs) { - files = Directory.GetFiles(dir, "*" + FdoFileExtensions.ksFwDataDb4oFileExtension); + files = Directory.GetFiles(dir, "*" + FdoFileHelper.ksFwDataDb4oFileExtension); m_allServers.AddRange(files); } } diff --git a/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs b/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs index abf2eba539..2aa971b72b 100644 --- a/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs @@ -413,7 +413,7 @@ internal void UnlockProject() //protected override void RestoreWithoutMigration(string xmlBepPathname) //{ // // Copy original file to backup. - // var bakPathname = m_databasePath + FdoFileExtensions.ksFwDataFallbackFileExtension; + // var bakPathname = m_databasePath + FdoFileHelper.ksFwDataFallbackFileExtension; // if (File.Exists(bakPathname)) // File.Delete(bakPathname); // File.Copy(m_databasePath, bakPathname); diff --git a/Src/FDOBrowser/FDOBrowserForm.cs b/Src/FDOBrowser/FDOBrowserForm.cs index e0ecb6fd4f..deeb2e9e2e 100644 --- a/Src/FDOBrowser/FDOBrowserForm.cs +++ b/Src/FDOBrowser/FDOBrowserForm.cs @@ -506,9 +506,9 @@ private static FDOBackendProviderType GetBEPTypeFromFileExtension(string pathnam { default: return FDOBackendProviderType.kMemoryOnly; - case FwFileExtensions.ksFwDataXmlFileExtension: + case FdoFileHelper.ksFwDataXmlFileExtension: return FDOBackendProviderType.kXML; - case FwFileExtensions.ksFwDataDb4oFileExtension: + case FdoFileHelper.ksFwDataDb4oFileExtension: return FDOBackendProviderType.kDb4oClientServer; } diff --git a/Src/FwCoreDlgs/ChooseLangProjectDialog.cs b/Src/FwCoreDlgs/ChooseLangProjectDialog.cs index 0e69f64de1..e36541f0a4 100644 --- a/Src/FwCoreDlgs/ChooseLangProjectDialog.cs +++ b/Src/FwCoreDlgs/ChooseLangProjectDialog.cs @@ -506,12 +506,12 @@ private void OkButtonClick(object sender, EventArgs e) if (m_hostsTreeView.SelectedNode == m_localhostNode) { Project = ((LanguageProjectInfo)m_lstLanguageProjects.SelectedItem).FullName; - if (Project.EndsWith(FwFileExtensions.ksFwDataFallbackFileExtension)) + if (Project.EndsWith(FdoFileHelper.ksFwDataFallbackFileExtension)) { // The user chose a .bak file, only possible when the fwdata file is missing. // Rename it and open it. string bakFileName = Project; - Project = Path.ChangeExtension(bakFileName, FwFileExtensions.ksFwDataXmlFileExtension); + Project = Path.ChangeExtension(bakFileName, FdoFileHelper.ksFwDataXmlFileExtension); try { File.Move(bakFileName, Project); diff --git a/Src/FwCoreDlgs/FwCoreDlgsTests/RestoreProjectPresenterTests.cs b/Src/FwCoreDlgs/FwCoreDlgsTests/RestoreProjectPresenterTests.cs index 3fd7524bea..9e821f3e7b 100644 --- a/Src/FwCoreDlgs/FwCoreDlgsTests/RestoreProjectPresenterTests.cs +++ b/Src/FwCoreDlgs/FwCoreDlgsTests/RestoreProjectPresenterTests.cs @@ -12,6 +12,7 @@ using System.IO; using NUnit.Framework; using SIL.FieldWorks.Common.FwUtils; +using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices.BackupRestore; using SIL.FieldWorks.FDO.FDOTests; using SIL.FieldWorks.FwCoreDlgs.BackupRestore; @@ -56,7 +57,7 @@ public void VerifyStringForBackupPropertiesLabel() { var restoreProjectPresenter = new RestoreProjectPresenter(null, string.Empty); BackupFileSettings backupSettings = new BackupFileSettings( - Path.ChangeExtension("dummy", FwFileExtensions.ksFwBackupFileExtension), false); + Path.ChangeExtension("dummy", FdoFileHelper.ksFwBackupFileExtension), false); // This is needed to thwart BackupFileSettings's normal logic to populate the flags // from the backup zip file ReflectionHelper.SetField(backupSettings, "m_projectName", "dummy"); diff --git a/Src/FwCoreDlgs/FwDeleteProjectDlg.cs b/Src/FwCoreDlgs/FwDeleteProjectDlg.cs index ffc7cbdc24..6095b1197b 100644 --- a/Src/FwCoreDlgs/FwDeleteProjectDlg.cs +++ b/Src/FwCoreDlgs/FwDeleteProjectDlg.cs @@ -299,13 +299,13 @@ private void m_btnDelete_Click(object sender, System.EventArgs e) } else { - string path = Path.Combine(folder, info.DatabaseName + FwFileExtensions.ksFwDataXmlFileExtension); + string path = Path.Combine(folder, info.DatabaseName + FdoFileHelper.ksFwDataXmlFileExtension); if (File.Exists(path)) File.Delete(path); - path = Path.ChangeExtension(path, FwFileExtensions.ksFwDataDb4oFileExtension); + path = Path.ChangeExtension(path, FdoFileHelper.ksFwDataDb4oFileExtension); if (File.Exists(path)) File.Delete(path); - path = Path.ChangeExtension(path, FwFileExtensions.ksFwDataFallbackFileExtension); + path = Path.ChangeExtension(path, FdoFileHelper.ksFwDataFallbackFileExtension); if (File.Exists(path)) File.Delete(path); path = Path.Combine(folder, DirectoryFinder.ksWritingSystemsDir); @@ -361,9 +361,9 @@ private static bool CheckForExtraData(ProjectInfo info, string folder) foreach (string filepath in files) { string file = Path.GetFileName(filepath); - if (file != info.DatabaseName + FwFileExtensions.ksFwDataXmlFileExtension && - file != info.DatabaseName + FwFileExtensions.ksFwDataDb4oFileExtension && - file != info.DatabaseName + FwFileExtensions.ksFwDataFallbackFileExtension) + if (file != info.DatabaseName + FdoFileHelper.ksFwDataXmlFileExtension && + file != info.DatabaseName + FdoFileHelper.ksFwDataDb4oFileExtension && + file != info.DatabaseName + FdoFileHelper.ksFwDataFallbackFileExtension) { return true; } diff --git a/Src/FwResources/FwFileExtensions.cs b/Src/FwResources/FwFileExtensions.cs index 77196a9cd0..543c22b428 100644 --- a/Src/FwResources/FwFileExtensions.cs +++ b/Src/FwResources/FwFileExtensions.cs @@ -33,12 +33,12 @@ public static class FwFileExtensions /* - * The following extensions are also defined in FdoFileExtensions. + * The following 4 extensions are also defined in FdoFileHelper. * They are defined here as a temporary stopgap. - * The idea is that eventually, these will be removed - * from here and all references will use FdoFileExtensions. + * The idea is that once FwUtils references FDO, these will be removed + * from here and all references will use FdoFileHelper. * - * If a change is made here, it should be made in FdoFileExtensions as well. + * If a change is made here, it should be made in FdoFileHelper as well. */ /// Default extension for FieldWorks XML data files (with the period) public const string ksFwDataXmlFileExtension = ".fwdata"; @@ -47,8 +47,6 @@ public static class FwFileExtensions /// Default extension for FieldWorks backup files (with the period). public const string ksFwBackupFileExtension = ".fwbackup"; /// Default extension for FieldWorks 6.0 and earlier backup files (with the period). - public const string ksFw60BackupFileExtension = ".zip"; - /// Default extension for FieldWorks TEMPORARY fallback data files (with the period). - public const string ksFwDataFallbackFileExtension = ".bak"; + internal const string ksFw60BackupFileExtension = ".zip"; } } diff --git a/Src/LexText/Lexicon/FLExBridgeListener.cs b/Src/LexText/Lexicon/FLExBridgeListener.cs index 168574b93e..c06b47c067 100644 --- a/Src/LexText/Lexicon/FLExBridgeListener.cs +++ b/Src/LexText/Lexicon/FLExBridgeListener.cs @@ -322,7 +322,7 @@ public bool OnFLExBridge(object commandObject) var projectFolder = Cache.ProjectId.ProjectFolder; var savedState = PrepareToDetectMainConflicts(projectFolder); string dummy; - var fullProjectFileName = Path.Combine(projectFolder, Cache.ProjectId.Name + FwFileExtensions.ksFwDataXmlFileExtension); + var fullProjectFileName = Path.Combine(projectFolder, Cache.ProjectId.Name + FdoFileHelper.ksFwDataXmlFileExtension); bool dataChanged; var success = FLExBridgeHelper.LaunchFieldworksBridge(fullProjectFileName, SendReceiveUser, FLExBridgeHelper.SendReceive, @@ -497,8 +497,8 @@ public bool OnLiftBridge(object argument) private string GetFullProjectFileName() { var currentExtension = IsDb4oProject - ? FwFileExtensions.ksFwDataDb4oFileExtension - : FwFileExtensions.ksFwDataXmlFileExtension; + ? FdoFileHelper.ksFwDataDb4oFileExtension + : FdoFileHelper.ksFwDataXmlFileExtension; return Path.Combine(Cache.ProjectId.ProjectFolder, Cache.ProjectId.Name + currentExtension); } @@ -633,7 +633,7 @@ public bool OnViewMessages(object commandObject) bool dummy1; string dummy2; FLExBridgeHelper.FLExJumpUrlChanged += JumpToFlexObject; - var success = FLExBridgeHelper.LaunchFieldworksBridge(Path.Combine(Cache.ProjectId.ProjectFolder, Cache.ProjectId.Name + FwFileExtensions.ksFwDataXmlFileExtension), + var success = FLExBridgeHelper.LaunchFieldworksBridge(Path.Combine(Cache.ProjectId.ProjectFolder, Cache.ProjectId.Name + FdoFileHelper.ksFwDataXmlFileExtension), SendReceiveUser, FLExBridgeHelper.ConflictViewer, null, FDOBackendProvider.ModelVersion, "0.13", null, @@ -1400,7 +1400,7 @@ private bool ChangeProjectNameIfNeeded() { // Continuing straight on from here renames the db on disk, but not in the cache, apparently // Try a more indirect approach... - var fullProjectFileName = Path.Combine(projectFolder, revisedProjName + FwFileExtensions.ksFwDataXmlFileExtension); + var fullProjectFileName = Path.Combine(projectFolder, revisedProjName + FdoFileHelper.ksFwDataXmlFileExtension); var tempWindow = RefreshCacheWindowAndAll(app, fullProjectFileName); tempWindow.Mediator.SendMessageDefered("FLExBridge", null); // to hopefully come back here after resetting things @@ -1483,7 +1483,7 @@ private void DisplayAllNonAsciiComplaint() private static bool CheckForExistingFileName(string projectFolder, string revisedFileName) { - if (File.Exists(Path.Combine(projectFolder, revisedFileName + FwFileExtensions.ksFwDataXmlFileExtension))) + if (File.Exists(Path.Combine(projectFolder, revisedFileName + FdoFileHelper.ksFwDataXmlFileExtension))) { MessageBox.Show( LexEdStrings.ksExistingProjectName, LexEdStrings.ksWarning, MessageBoxButtons.OK, MessageBoxIcon.Information); diff --git a/Src/Utilities/FixFwDataDll/ErrorFixer.cs b/Src/Utilities/FixFwDataDll/ErrorFixer.cs index e0c22ebf8c..18b9919251 100644 --- a/Src/Utilities/FixFwDataDll/ErrorFixer.cs +++ b/Src/Utilities/FixFwDataDll/ErrorFixer.cs @@ -13,7 +13,7 @@ // --------------------------------------------------------------------------------------------- using System.Collections.Generic; using System.Diagnostics; - +using SIL.FieldWorks.FDO; using SIL.FieldWorks.FwCoreDlgs; using System.Windows.Forms; using System.IO; @@ -105,7 +105,7 @@ public void Process() { string pathname = Path.Combine( Path.Combine(DirectoryFinder.ProjectsDirectory, dlg.SelectedProject), - dlg.SelectedProject + Resources.FwFileExtensions.ksFwDataXmlFileExtension); + dlg.SelectedProject + FdoFileHelper.ksFwDataXmlFileExtension); if (File.Exists(pathname)) { using (new WaitCursor(m_dlg)) @@ -116,7 +116,7 @@ public void Process() if (fixes.Length > 0) { MessageBox.Show(fixes, Strings.ksErrorsFoundOrFixed); - File.WriteAllText(pathname.Replace(Resources.FwFileExtensions.ksFwDataXmlFileExtension, "fixes"), fixes); + File.WriteAllText(pathname.Replace(FdoFileHelper.ksFwDataXmlFileExtension, "fixes"), fixes); } } } diff --git a/Src/Utilities/FixFwDataDll/FixErrorsDlg.cs b/Src/Utilities/FixFwDataDll/FixErrorsDlg.cs index 1eaaa1d81e..e6ab85aa3d 100644 --- a/Src/Utilities/FixFwDataDll/FixErrorsDlg.cs +++ b/Src/Utilities/FixFwDataDll/FixErrorsDlg.cs @@ -21,6 +21,7 @@ using SIL.FieldWorks.Common.FwUtils; using System.IO; using System.Collections; +using SIL.FieldWorks.FDO; namespace SIL.FieldWorks.FixData { @@ -40,7 +41,7 @@ public FixErrorsDlg() { InitializeComponent(); m_btnFixLinks.Enabled = false; - string ext = Resources.FwFileExtensions.ksFwDataXmlFileExtension; + string ext = FdoFileHelper.ksFwDataXmlFileExtension; string lockext = ext + ".lock"; foreach (var dir in Directory.GetDirectories(DirectoryFinder.ProjectsDirectory)) { diff --git a/Src/Utilities/FixFwDataDll/FixFwDataDll.csproj b/Src/Utilities/FixFwDataDll/FixFwDataDll.csproj index 9324c296f8..d00b7b2147 100644 --- a/Src/Utilities/FixFwDataDll/FixFwDataDll.csproj +++ b/Src/Utilities/FixFwDataDll/FixFwDataDll.csproj @@ -59,6 +59,10 @@ False + + False + ..\..\..\Output\Debug\FDO.dll + False ..\..\..\Output\Debug\FwControls.dll diff --git a/Src/Utilities/FixFwDataDll/FwDataFixer.cs b/Src/Utilities/FixFwDataDll/FwDataFixer.cs index 09d48deec7..f547e8e515 100644 --- a/Src/Utilities/FixFwDataDll/FwDataFixer.cs +++ b/Src/Utilities/FixFwDataDll/FwDataFixer.cs @@ -19,6 +19,7 @@ using System.IO; using SIL.CoreImpl; using SIL.FieldWorks.Common.FwUtils; +using SIL.FieldWorks.FDO; using SIL.Utils; namespace SIL.FieldWorks.FixData @@ -181,8 +182,7 @@ public void FixErrorsAndSave() xw.Close(); } - var bakfile = Path.ChangeExtension(m_filename, - Resources.FwFileExtensions.ksFwDataFallbackFileExtension); + var bakfile = Path.ChangeExtension(m_filename, FdoFileHelper.ksFwDataFallbackFileExtension); if (File.Exists(bakfile)) File.Delete(bakfile); File.Move(m_filename, bakfile); diff --git a/Src/xWorks/Archiving/ReapRamp.cs b/Src/xWorks/Archiving/ReapRamp.cs index 23e55f02d3..825eab8eda 100644 --- a/Src/xWorks/Archiving/ReapRamp.cs +++ b/Src/xWorks/Archiving/ReapRamp.cs @@ -128,7 +128,7 @@ private string GetFileDescription(string key, string file) { // TODO: Extend to supply "relationship" also (source, presentation or supporting) - if (Path.GetExtension(file) == FwFileExtensions.ksFwBackupFileExtension) + if (Path.GetExtension(file) == FdoFileHelper.ksFwBackupFileExtension) return "FieldWorks backup"; if (Path.GetExtension(file) == FwFileExtensions.ksLexiconInterchangeFormat) return "Lexical Interchange Format Standard file"; From d72510456e5be503e43fdc88b1cf5a1982abc6c8 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Mon, 9 Dec 2013 13:16:41 +0700 Subject: [PATCH 030/143] Move FDO code out of DirectoryFinder into FdoFileHelper Remove more dependencies upon FwUtils. Change-Id: I116fc844f4ecedae43dc4828ee26e8aa81168be1 --- .../Widgets/LabeledMultiStringView.cs | 4 +- Src/Common/FieldWorks/FieldWorks.cs | 10 +- .../FieldWorksTests/ProjectIDTests.cs | 32 +- Src/Common/FwUtils/DirectoryFinder.cs | 476 +----------------- .../FwUtilsTests/DirectoryFinderTests.cs | 25 +- .../FwUtils/FwUtilsTests/FwUtilsTests.csproj | 4 + Src/FDO/DomainImpl/OverridesCellar.cs | 4 +- Src/FDO/DomainImpl/OverridesLangProj.cs | 6 +- .../BackupRestore/BackupFileSettings.cs | 12 +- .../BackupRestore/BackupProjectSettings.cs | 2 +- .../BackupRestore/BackupSettings.cs | 16 +- .../BackupRestore/ProjectBackupService.cs | 2 +- .../BackupRestore/ProjectRestoreService.cs | 22 +- .../DomainServices/ClientServerServices.cs | 8 +- .../DataMigration/DataMigration7000019.cs | 2 +- .../DataMigration/DataMigration7000029.cs | 6 +- .../DataMigration/DataMigration7000030.cs | 6 +- .../DataMigration/DataMigration7000044.cs | 4 +- .../DataMigration/DataMigration7000060.cs | 2 +- Src/FDO/DomainServices/FwProjectFinder.cs | 4 +- Src/FDO/DomainServices/StringServices.cs | 2 +- Src/FDO/FDO.csproj | 1 + .../ProjectRestoreServiceTests.cs | 10 +- .../DataMigration7000019Tests.cs | 2 +- .../DataMigration7000044Tests.cs | 4 +- .../DataMigration7000060Tests.cs | 2 +- Src/FDO/FDOTests/FdoCacheTests.cs | 4 +- .../PersistingBackendProviderTests.cs | 8 +- .../PersistingLayerTests.BEPPortTests.cs | 4 +- Src/FDO/FdoFileHelper.cs | 188 +++++++ Src/FDO/FdoFileHelperRelativePaths.cs | 299 +++++++++++ .../Impl/Db4oClientServerBackendProvider.cs | 4 +- Src/FDO/Infrastructure/Impl/Db4oServerInfo.cs | 2 +- .../Infrastructure/Impl/FDOBackendProvider.cs | 2 +- Src/FDO/fdoCache.cs | 24 +- .../BackupRestore/BackupProjectPresenter.cs | 6 +- .../FwCoreDlgsTests/FwNewLangProjectTests.cs | 4 +- Src/FwCoreDlgs/FwDeleteProjectDlg.cs | 16 +- Src/FwCoreDlgs/FwProjPropertiesDlg.cs | 4 +- Src/FwCoreDlgs/MoveOrCopyFilesDlg.cs | 4 +- Src/FwCoreDlgs/ProjectLocationSharingDlg.cs | 2 +- .../LexTextControlsTests/LiftExportTests.cs | 8 +- .../LexTextControlsTests/LiftMergerTests.cs | 20 +- Src/LexText/LexTextControls/LiftExporter.cs | 14 +- Src/LexText/LexTextControls/LiftMerger.cs | 4 +- .../LiftMergerSupportCodeAndClasses.cs | 6 +- Src/LexText/Lexicon/FLExBridgeListener.cs | 4 +- Src/XCore/Inventory.cs | 4 +- Src/XCore/xCore.csproj | 4 + Src/xWorks/FwXWindow.cs | 4 +- Src/xWorks/RecordView.cs | 2 +- Src/xWorks/XmlDocConfigureDlg.cs | 4 +- 52 files changed, 672 insertions(+), 641 deletions(-) create mode 100644 Src/FDO/FdoFileHelperRelativePaths.cs diff --git a/Src/Common/Controls/Widgets/LabeledMultiStringView.cs b/Src/Common/Controls/Widgets/LabeledMultiStringView.cs index d143838ea8..17c7543ec3 100644 --- a/Src/Common/Controls/Widgets/LabeledMultiStringView.cs +++ b/Src/Common/Controls/Widgets/LabeledMultiStringView.cs @@ -329,7 +329,7 @@ private void SetupSoundControls() } else { - var mediaDir = DirectoryFinder.GetMediaDir(m_innerView.Cache.LangProject.LinkedFilesRootDir); + var mediaDir = FdoFileHelper.GetMediaDir(m_innerView.Cache.LangProject.LinkedFilesRootDir); Directory.CreateDirectory(mediaDir); // Palaso media library does not cope if it does not exist. path = Path.Combine(mediaDir, filename.Normalize(NormalizationForm.FormC)); @@ -381,7 +381,7 @@ void soundFieldControl_BeforeStartingToRecord(object sender, EventArgs e) private string CreateNewSoundFilename(out string path) { var obj = m_innerView.Cache.ServiceLocator.GetObject(m_innerView.HvoObj); - var mediaDir = DirectoryFinder.GetMediaDir(m_innerView.Cache.LangProject.LinkedFilesRootDir); + var mediaDir = FdoFileHelper.GetMediaDir(m_innerView.Cache.LangProject.LinkedFilesRootDir); Directory.CreateDirectory(mediaDir); // Palaso media library does not cope if it does not exist. // Make up a unique file name for the new recording. It starts with the shortname of the object // so as to somewhat link them together, then adds a unique timestamp, then if by any chance diff --git a/Src/Common/FieldWorks/FieldWorks.cs b/Src/Common/FieldWorks/FieldWorks.cs index 2f629b5197..6c9d7243e5 100644 --- a/Src/Common/FieldWorks/FieldWorks.cs +++ b/Src/Common/FieldWorks/FieldWorks.cs @@ -829,7 +829,7 @@ private static void EnsureValidLinkedFilesFolder(FdoCache cache) return; var linkedFilesFolder = cache.LangProject.LinkedFilesRootDir; - var defaultFolder = DirectoryFinder.GetDefaultLinkedFilesDir(cache.ProjectId.ProjectFolder); + var defaultFolder = FdoFileHelper.GetDefaultLinkedFilesDir(cache.ProjectId.ProjectFolder); EnsureValidLinkedFilesFolderCore(linkedFilesFolder, defaultFolder); if (!Directory.Exists(linkedFilesFolder)) @@ -2323,7 +2323,7 @@ private static bool IsFieldWorksProjectFolder(string projectFolder) private static bool IsFieldWorksSettingsFolder(string projectFolder) { - var settingsDir = Path.Combine(projectFolder, DirectoryFinder.ksConfigurationSettingsDir); + var settingsDir = Path.Combine(projectFolder, FdoFileHelper.ksConfigurationSettingsDir); if (Directory.Exists(settingsDir)) return true; return false; @@ -2795,7 +2795,7 @@ private static void MoveExternalLinkDirectoryAndFiles(FwApp app) var sLinkedFilesRootDir = app.Cache.LangProject.LinkedFilesRootDir; NonUndoableUnitOfWorkHelper.Do(app.Cache.ActionHandlerAccessor, () => { - app.Cache.LangProject.LinkedFilesRootDir = DirectoryFinder.GetDefaultLinkedFilesDir( + app.Cache.LangProject.LinkedFilesRootDir = FdoFileHelper.GetDefaultLinkedFilesDir( app.Cache.ProjectId.ProjectFolder); }); app.UpdateExternalLinks(sLinkedFilesRootDir); @@ -3272,7 +3272,7 @@ private static string GetDefaultApp(FwAppArgs args) if (!Directory.Exists(projectFolder)) return FwUtils.ksFlexAbbrev; // got to do something - var settingsFolder = Path.Combine(projectFolder, DirectoryFinder.ksConfigurationSettingsDir); + var settingsFolder = Path.Combine(projectFolder, FdoFileHelper.ksConfigurationSettingsDir); if (!Directory.Exists(settingsFolder)) return FwUtils.ksFlexAbbrev; // no settings at all, take the default. @@ -3296,7 +3296,7 @@ private static void RecordLastAppForProject() if (s_flexApp != null && s_teApp != null) return; // this isn't the last one to shut down, not time to record. - var settingsFolder = Path.Combine(Cache.ProjectId.ProjectFolder, DirectoryFinder.ksConfigurationSettingsDir); + var settingsFolder = Path.Combine(Cache.ProjectId.ProjectFolder, FdoFileHelper.ksConfigurationSettingsDir); var teMarkerPath = Path.Combine(settingsFolder, ksTeOpenMarkerFileName); try { diff --git a/Src/Common/FieldWorks/FieldWorksTests/ProjectIDTests.cs b/Src/Common/FieldWorks/FieldWorksTests/ProjectIDTests.cs index 4ffd763cc8..651f90042a 100644 --- a/Src/Common/FieldWorks/FieldWorksTests/ProjectIDTests.cs +++ b/Src/Common/FieldWorks/FieldWorksTests/ProjectIDTests.cs @@ -126,7 +126,7 @@ public void IsValid_BogusType() public void IsValid_NullType() { const string sProjectName = "monkey"; - string sFile = DirectoryFinder.GetXmlDataFileName(sProjectName); + string sFile = FdoFileHelper.GetXmlDataFileName(sProjectName); m_mockFileOs.AddExistingFile(GetXmlProjectFilename(sProjectName)); ProjectId proj = new ProjectId(null, sFile, null); Assert.AreEqual(FDOBackendProviderType.kXML, proj.Type); @@ -154,7 +154,7 @@ public void IsValid_XML_False() public void IsValid_XML_True() { const string sProjectName = "monkey"; - string sFile = DirectoryFinder.GetXmlDataFileName(sProjectName); + string sFile = FdoFileHelper.GetXmlDataFileName(sProjectName); m_mockFileOs.AddExistingFile(GetXmlProjectFilename(sProjectName)); ProjectId proj = new ProjectId("xml", sFile, null); Assert.IsTrue(proj.IsValid); @@ -201,7 +201,7 @@ public void CleanUpNameForType_Default_onlyName() { m_defaultBepType = FDOBackendProviderType.kDb4oClientServer; string expectedPath = Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, "ape"), - DirectoryFinder.GetDb4oDataFileName("ape")); + FdoFileHelper.GetDb4oDataFileName("ape")); m_localCsSvcs.Stub(cs => cs.IdForLocalProject("ape")).Return(expectedPath); m_mockFileOs.AddExistingFile(expectedPath); @@ -242,7 +242,7 @@ public void CleanUpNameForType_Default_NameWithPeriod_Exists() public void CleanUpNameForType_XML_NameWithPeriod_FilesWithAndWithoutExtensionExist() { string myMonkeyProjectFolder = Path.Combine(DirectoryFinder.ProjectsDirectory, "my.monkey"); - string expectedPath = Path.Combine(myMonkeyProjectFolder, DirectoryFinder.GetXmlDataFileName("my.monkey")); + string expectedPath = Path.Combine(myMonkeyProjectFolder, FdoFileHelper.GetXmlDataFileName("my.monkey")); m_mockFileOs.AddExistingFile(expectedPath); m_mockFileOs.AddExistingFile(Path.Combine(myMonkeyProjectFolder, "my.monkey")); @@ -266,7 +266,7 @@ public void CleanUpNameForType_XML_NameWithPeriod_WithXmlExtension() string expectedPath = GetXmlProjectFilename(projectName); m_mockFileOs.AddExistingFile(expectedPath); - var proj = new ProjectId(DirectoryFinder.GetXmlDataFileName(projectName), null); + var proj = new ProjectId(FdoFileHelper.GetXmlDataFileName(projectName), null); Assert.AreEqual(expectedPath, proj.Path); Assert.AreEqual(FDOBackendProviderType.kXML, proj.Type); Assert.IsTrue(proj.IsValid); @@ -302,7 +302,7 @@ public void CleanUpNameForType_XML_onlyNameWithExtension() string expectedPath = GetXmlProjectFilename("monkey"); m_mockFileOs.AddExistingFile(expectedPath); - var proj = new ProjectId(DirectoryFinder.GetXmlDataFileName("monkey"), null); + var proj = new ProjectId(FdoFileHelper.GetXmlDataFileName("monkey"), null); Assert.AreEqual(expectedPath, proj.Path); Assert.AreEqual(FDOBackendProviderType.kXML, proj.Type); Assert.IsTrue(proj.IsValid); @@ -317,7 +317,7 @@ public void CleanUpNameForType_XML_onlyNameWithExtension() [Test] public void CleanUpNameForType_XML_FullPath() { - string expectedPath = Path.Combine(DirectoryFinder.ProjectsDirectory, DirectoryFinder.GetXmlDataFileName("monkey")); + string expectedPath = Path.Combine(DirectoryFinder.ProjectsDirectory, FdoFileHelper.GetXmlDataFileName("monkey")); m_mockFileOs.AddExistingFile(expectedPath); var proj = new ProjectId(expectedPath, null); @@ -336,7 +336,7 @@ public void CleanUpNameForType_XML_FullPath() [Ignore("Not sure what this would be useful for or if this would be the desired behavior.")] public void CleanUpNameForType_XML_RelativePath() { - string relativePath = Path.Combine("primate", DirectoryFinder.GetXmlDataFileName("monkey")); + string relativePath = Path.Combine("primate", FdoFileHelper.GetXmlDataFileName("monkey")); string expectedPath = Path.Combine(DirectoryFinder.ProjectsDirectory, relativePath); m_mockFileOs.AddExistingFile(expectedPath); @@ -359,7 +359,7 @@ public void AssertValid_Valid() string projFile = GetXmlProjectFilename("monkey"); m_mockFileOs.AddExistingFile(projFile); - var proj = new ProjectId(DirectoryFinder.GetXmlDataFileName("monkey"), null); + var proj = new ProjectId(FdoFileHelper.GetXmlDataFileName("monkey"), null); proj.AssertValid(); // no exception should be thrown here for a valid project. } @@ -393,7 +393,7 @@ public void AssertValid_Invalid_NoName() [Test] public void AssertValid_Invalid_FileNotFound() { - var proj = new ProjectId(DirectoryFinder.GetXmlDataFileName("notfound"), null); + var proj = new ProjectId(FdoFileHelper.GetXmlDataFileName("notfound"), null); try { proj.AssertValid(); @@ -414,7 +414,7 @@ public void AssertValid_Invalid_FileNotFound() [Test] public void AssertValid_InvalidProjectType() { - var proj = new ProjectId(FDOBackendProviderType.kInvalid, DirectoryFinder.GetXmlDataFileName("invalid"), null); + var proj = new ProjectId(FDOBackendProviderType.kInvalid, FdoFileHelper.GetXmlDataFileName("invalid"), null); try { proj.AssertValid(); @@ -435,7 +435,7 @@ public void AssertValid_InvalidProjectType() [Test] public void AssertValid_Invalid_SharedFolderNotFound() { - var proj = new ProjectId(DirectoryFinder.GetDb4oDataFileName("monkey"), FwLinkArgs.kLocalHost); + var proj = new ProjectId(FdoFileHelper.GetDb4oDataFileName("monkey"), FwLinkArgs.kLocalHost); try { proj.AssertValid(); @@ -463,7 +463,7 @@ public void CheckProperties() const string type = "db4ocs"; const string host = "127.0.0.1"; - string filename = DirectoryFinder.GetDb4oDataFileName("SomeTest"); + string filename = FdoFileHelper.GetDb4oDataFileName("SomeTest"); var proj = new ProjectId(type, filename, host); proj.AssertValid(); @@ -484,11 +484,11 @@ public void NameAndPath() { string myProjectFolder = Path.Combine(DirectoryFinder.ProjectsDirectory, "My.Project"); ProjectId projId = new ProjectId(FDOBackendProviderType.kXML, "My.Project", null); - Assert.AreEqual(Path.Combine(myProjectFolder, DirectoryFinder.GetXmlDataFileName("My.Project")), projId.Path); + Assert.AreEqual(Path.Combine(myProjectFolder, FdoFileHelper.GetXmlDataFileName("My.Project")), projId.Path); Assert.AreEqual("My.Project", projId.Name); projId = new ProjectId(FDOBackendProviderType.kDb4oClientServer, "My.Project", null); - Assert.AreEqual(Path.Combine(myProjectFolder, DirectoryFinder.GetDb4oDataFileName("My.Project")), projId.Path); + Assert.AreEqual(Path.Combine(myProjectFolder, FdoFileHelper.GetDb4oDataFileName("My.Project")), projId.Path); Assert.AreEqual("My.Project", projId.Name); } @@ -505,7 +505,7 @@ public void NameAndPath() public static string GetXmlProjectFilename(string projectName) { return Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, projectName), - DirectoryFinder.GetXmlDataFileName(projectName)); + FdoFileHelper.GetXmlDataFileName(projectName)); } #endregion } diff --git a/Src/Common/FwUtils/DirectoryFinder.cs b/Src/Common/FwUtils/DirectoryFinder.cs index c000d6f611..3ce57e49b9 100644 --- a/Src/Common/FwUtils/DirectoryFinder.cs +++ b/Src/Common/FwUtils/DirectoryFinder.cs @@ -52,29 +52,16 @@ public static class DirectoryFinder /// public const string ksFlexFolderName = FwUtils.ksFlexAppName; - /// The name of the folder containing FLEx configuration settings - public const string ksConfigurationSettingsDir = "ConfigurationSettings"; - /// The name of the folder containing FLEx backup settings - public const string ksBackupSettingsDir = "BackupSettings"; - /// The name of the folder where the user can copy files for backup such as fonts and keyboards - public const string ksSupportingFilesDir = "SupportingFiles"; - /// The default name of the folder containing LinkedFiles (media, pictures, etc) for a project - public const string ksLinkedFilesDir = "LinkedFiles"; - /// The name of the subfolder containing media for a project - public const string ksMediaDir = "AudioVisual"; - /// The name of the subfolder containing pictures for a project - public const string ksPicturesDir = "Pictures"; - /// The name of the subfolder containing other LinkedFiles for a project - public const string ksOtherLinkedFilesDir = "Others"; - /// The name of the folder containing writing systems for a project - public const string ksWritingSystemsDir = "WritingSystemStore"; - /// The name of the folder containing temporary persisted sort sequence info for a project - public const string ksSortSequenceTempDir = "Temp"; /// The Scripture-specific stylesheet (ideally, this would be in a TE-specific place, but FDO needs it) public const string kTeStylesFilename = "TeStyles.xml"; /// The filename of the backup settings file public const string kBackupSettingsFilename = "BackupSettings.xml"; + /// The name of the folder containing global writing systems. + /// Also see SIL.FieldWorks.FDO.FdoFileHelper.ksWritingSystemsDir + /// for the project-level directory. + private const string ksWritingSystemsDir = "WritingSystemStore"; + private const string ksBiblicaltermsLocFilePrefix = "BiblicalTerms-"; private const string ksBiblicaltermsLocFileExtension = ".xml"; private const string ksProjectsDir = "ProjectsDir"; @@ -410,50 +397,6 @@ public static string GetFWCodeFile(string filename) return Path.Combine(FWCodeDirectory, filename); } - /// ------------------------------------------------------------------------------------ - /// - /// Gets the path to the configuration settings for the specified project. - /// - /// The path to the project folder. - /// ------------------------------------------------------------------------------------ - public static string GetConfigSettingsDir(string projectFolder) - { - return Path.Combine(projectFolder, ksConfigurationSettingsDir); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets the path to the backup settings for the specified project - /// - /// The path to the project folder. - /// ------------------------------------------------------------------------------------ - public static string GetBackupSettingsDir(string projectFolder) - { - return Path.Combine(projectFolder, ksBackupSettingsDir); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets the path to the fonts for the specified project. - /// - /// The path to the project folder. - /// ------------------------------------------------------------------------------------ - public static string GetSupportingFilesDir(string projectFolder) - { - return Path.Combine(projectFolder, ksSupportingFilesDir); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets the path to the writing systems for the specified project. - /// - /// The path to the project folder. - /// ------------------------------------------------------------------------------------ - public static string GetWritingSystemDir(string projectFolder) - { - return Path.Combine(projectFolder, ksWritingSystemsDir); - } - /// ------------------------------------------------------------------------------------ /// /// Gets the path without the root directory (i.e. make it un-rooted). @@ -482,38 +425,6 @@ public static string GetZipfileFormattedPath(string path) return strBldr.ToString(); } - /// ------------------------------------------------------------------------------------ - /// - /// Gets the name of the XML data file, given a project name (basically just adds the - /// FW data XML file extension). - /// - /// Name of the project (not a filename). - /// ------------------------------------------------------------------------------------ - public static string GetXmlDataFileName(string projectName) - { - Debug.Assert(Path.GetExtension(projectName) != FwFileExtensions.ksFwDataXmlFileExtension, - String.Format("There is a faint chance the user might have specified a real project name ending in {0} (in which case, sorry, but we're going to trim it off), but probably this is a programming error", FwFileExtensions.ksFwDataXmlFileExtension)); - // Do not use Path.ChangeExtension because it will strip off anything following a period in the project name! - return projectName.EndsWith(FwFileExtensions.ksFwDataXmlFileExtension) ? projectName : - projectName + FwFileExtensions.ksFwDataXmlFileExtension; - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets the name of the DB4O data file, given a project name (basically just adds the - /// FW db4o file extension). - /// - /// Name of the project (not a filename). - /// ------------------------------------------------------------------------------------ - public static string GetDb4oDataFileName(string projectName) - { - Debug.Assert(Path.GetExtension(projectName) != FwFileExtensions.ksFwDataDb4oFileExtension, - String.Format("There is a faint chance the user might have specified a real project name ending in {0} (in which case, sorry, but we're going to trim it off), but probably this is a programming error", FwFileExtensions.ksFwDataDb4oFileExtension)); - // Do not use Path.ChangeExtension because it will strip off anything following a period in the project name! - return projectName.EndsWith(FwFileExtensions.ksFwDataDb4oFileExtension) ? projectName : - projectName + FwFileExtensions.ksFwDataDb4oFileExtension; - } - /// ------------------------------------------------------------------------------------ /// /// Gets a subdirectory of FieldWorks either by reading the @@ -921,382 +832,5 @@ static public string GetLocaleFromKeyTermsLocFile(string locFilename) return Path.GetFileName(locFilename).Replace(ksBiblicaltermsLocFilePrefix, String.Empty).Replace(ksBiblicaltermsLocFileExtension, String.Empty); } - - #region ExternalLinks folders - //This region has all methods which return the values for the ExternalLinks files associated with a project. - //This includes .../ProjectName/LinkedFiles and all subfolders. i.e. Pictures, AudioVisual and Others. - - - /// - /// Gets the path to the standard eternal linked files directory for the specified project. - /// - /// The path to the project. - /// - public static string GetDefaultLinkedFilesDir(string projectPath) - { - return Path.Combine(projectPath, ksLinkedFilesDir); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets the path to the standard media files directory for the specified project. Note - /// that if this project keepes its externally linked files in a separate folder from - /// the rest of the project files (such as a shared folder common to multiple projects - /// on a server), the directory returned by this method will not actually contain any - /// files. - /// - /// The path to the project. - /// ------------------------------------------------------------------------------------ - public static string GetDefaultMediaDir(string projectPath) - { - return Path.Combine(projectPath, Path.Combine(ksLinkedFilesDir, ksMediaDir)); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets the path to the standard pictures directory for the specified project. Note - /// that if this project keepes its externally linked files in a separate folder from - /// the rest of the project files (such as a shared folder common to multiple projects - /// on a server), the directory returned by this method will not actually contain any - /// files. - /// - /// The path to the project. - /// ------------------------------------------------------------------------------------ - public static string GetDefaultPicturesDir(string projectPath) - { - return Path.Combine(projectPath, Path.Combine(ksLinkedFilesDir, ksPicturesDir)); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets the path to the standard directory for other externally linked project files. - /// Note that if this project keepes its externally linked files in a separate folder - /// from the rest of the project files (such as a shared folder common to multiple - /// projects on a server), the directory returned by this method will not actually - /// contain any files. - /// - /// The path to the project. - /// ------------------------------------------------------------------------------------ - public static string GetDefaultOtherExternalFilesDir(string projectPath) - { - return Path.Combine(projectPath, Path.Combine(ksLinkedFilesDir, ksOtherLinkedFilesDir)); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets the path to the media files directory for the project. - /// - /// The project's LinkedFiles path. (eg. m_cache.LangProject.LinkedFilesRootDir) - /// ------------------------------------------------------------------------------------ - public static string GetMediaDir(string projectLinkedFilesPath) - { - return Path.Combine(projectLinkedFilesPath, ksMediaDir); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets the path to the pictures directory for the project. - /// - /// The project's LinkedFiles path. (eg. m_cache.LangProject.LinkedFilesRootDir) - /// ------------------------------------------------------------------------------------ - public static string GetPicturesDir(string projectLinkedFilesPath) - { - return Path.Combine(projectLinkedFilesPath, ksPicturesDir); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets the path to the directory for other externally linked project files. - /// - /// The project's LinkedFiles path. (eg. m_cache.LangProject.LinkedFilesRootDir) - /// ------------------------------------------------------------------------------------ - public static string GetOtherExternalFilesDir(string projectLinkedFilesPath) - { - return Path.Combine(projectLinkedFilesPath, ksOtherLinkedFilesDir); - } - - #endregion - } - - /// - /// This class is designed for converting between relative paths and full paths for the LinkedFiles of a FW project - /// - public class DirectoryFinderRelativePaths - { - /// Substitution string for a path that is under the LinkedFiles directory. - public const string ksLFrelPath = "%lf%"; - /// Substitution string for a path that is under the project's directory. - public const string ksProjectRelPath = "%proj%"; - /// Substitution string for a path that is under the default directory for projects. - public const string ksProjectsRelPath = "%Projects%"; - /// Substitution string for a path that is under the My Documents directory. - public const string ksMyDocsRelPath = "%MyDocuments%"; - /// Substitution string for a path that is under the Shared Application Data directory. - public const string ksCommonAppDataRelPath = "%CommonApplicationData%"; - - #region Methods to covert between RelativePaths and FullPaths - - /// - /// If a filePath is stored in the format %lf%\path\filename then this method returns the full path. - /// Otherwise return null - /// - /// - /// - /// - public static String GetFullFilePathFromRelativeLFPath(string relativePath, string projectLinkedFilesPath) - { - String fullfilePath = null; - fullfilePath = GetFullPathForRelativePath(relativePath, ksLFrelPath, projectLinkedFilesPath); - - if (String.IsNullOrEmpty(fullfilePath)) - return null; - return FixPathSlashesIfNeeded(fullfilePath); - } - - /// - /// If a file path is non rooted then return combination of the linkedFiledRootDir and the relative - /// path. Otherwise just return the full path passed in as an arguement. - /// - /// - /// - /// - public static String GetFullPathFromRelativeLFPath(string relativeLFPath, string linkedFilesRootDir) - { - // We could just catch the exception that IsPathRooted throws if there are invalid characters, - // or use Path.GetInvalidPathChars(). But that would pass things on Linux that will fail on Windows, - // which both makes unit testing difficult, and also may hide from Linux users the fact that their - // paths will cause problems on Windows. - var invalidChars = MiscUtils.GetInvalidProjectNameChars(MiscUtils.FilenameFilterStrength.kFilterProjName); - // relativeLFPath is allowed to include directories. And it MAY be rooted, meaning on Windows it could start X: - invalidChars = invalidChars.Replace(@"\", "").Replace("/", "").Replace(":", ""); - // colon is allowed only as second character--such a path is probably no good on Linux, but will just be not found, not cause a crash - int indexOfColon = relativeLFPath.IndexOf(':'); - if (relativeLFPath.IndexOfAny(invalidChars.ToCharArray()) != -1 - || (indexOfColon != -1 && indexOfColon != 1)) - { - // This is a fairly clumsy solution, designed as a last-resort way to avoid crashing the program. - // Hopefully most paths for entering path names into the relevant fields do something nicer to - // avoid getting illegal characters there. - return FixPathSlashesIfNeeded(Path.Combine(linkedFilesRootDir, "__ILLEGALCHARS__")); - } - if (Path.IsPathRooted(relativeLFPath)) - return FixPathSlashesIfNeeded(relativeLFPath); - else - return FixPathSlashesIfNeeded(Path.Combine(linkedFilesRootDir, relativeLFPath)); - } - - /// - /// If a path gets stored with embedded \, fix it to work away from Windows. (FWNX-882) - /// - public static string FixPathSlashesIfNeeded(string path) - { - if (string.IsNullOrEmpty(path)) - return string.Empty; - if (MiscUtils.IsUnix || MiscUtils.IsMac) - { - if (path.Contains("\\")) - return path.Replace('\\', '/'); - } - return path; - } - - /// - /// If the path is relative to the project's linkedFiles path then substitute %lf% - /// and return it. Otherwise return an empty string - /// - /// - /// - /// - public static string GetRelativeLFPathFromFullFilePath(string filePath, - string projectLinkedFilesPath) - { - if (string.IsNullOrEmpty(projectLinkedFilesPath)) - return string.Empty; - - var linkedFilesPathLowercaseRoot = GetPathWithLowercaseRoot(filePath); - - var relativePath = GetRelativePathIfExists(ksLFrelPath, linkedFilesPathLowercaseRoot, - projectLinkedFilesPath); - if (!string.IsNullOrEmpty(relativePath)) - return FixPathSlashesIfNeeded(relativePath); - //Just return an empty path if we cannot find a relative path. - return string.Empty; - } - - /// - /// If the specified path starts with the LinkedFiles root directory then return - /// the part after the linkedFilesRootDir; - /// otherwise if it is a file path at all convert it to the current platform and return it; - /// otherwise (it's a URL, determined by containing a colon after more than one initial character) - /// return null to indicate no change made. - /// - /// - /// - /// - public static string GetRelativeLinkedFilesPath(string filePath, - string linkedFilesRootDir) - { - if (filePath.IndexOf(':') > 1) - { - // It's a URL, not a path at all; don't mess with it. - return null; - } - string directory = FileUtils.ChangePathToPlatform(linkedFilesRootDir); - string relativePath = FileUtils.ChangePathToPlatform(filePath); - - // Does the specified path start with the LinkedFiles root directory? - if (relativePath.StartsWith(directory, true, System.Globalization.CultureInfo.InvariantCulture) && - relativePath.Length > directory.Length + 1) - { - // Keep the portion of the specified path that is a subfolder of - // the LinkedFiles folder and make sure to strip off an initial - // path separator if there is one. - relativePath = relativePath.Substring(directory.Length); - if (relativePath[0] == Path.DirectorySeparatorChar) - relativePath = relativePath.Substring(1); - } - return FixPathSlashesIfNeeded(relativePath); - } - - - /// - /// Return the fullPath for a project's LinkedFiles based on the relative path that was persisted. - /// If no match on a relativePath match is made then return the relativePath passed in assuming it - /// is actually a full path. - /// - /// - /// - /// - public static String GetLinkedFilesFullPathFromRelativePath(string relativePath, String projectPath) - { - String fullPath = null; - fullPath = GetFullPathForRelativePath(relativePath, ksProjectRelPath, projectPath); - - if (String.IsNullOrEmpty(fullPath)) - fullPath = GetFullPathForRelativePath(relativePath, ksProjectsRelPath, - DirectoryFinder.ProjectsDirectory); - if (String.IsNullOrEmpty(fullPath)) - fullPath = GetFullPathForRelativePath(relativePath, ksCommonAppDataRelPath, - DirectoryFinder.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)); - if (String.IsNullOrEmpty(fullPath)) - fullPath = GetFullPathForRelativePath(relativePath, ksMyDocsRelPath, - DirectoryFinder.GetFolderPath(Environment.SpecialFolder.MyDocuments)); - if (String.IsNullOrEmpty(fullPath)) - return FixPathSlashesIfNeeded(relativePath); - return FixPathSlashesIfNeeded(fullPath); - } - - private static String GetFullPathForRelativePath(String relativePath, String relativePart, String fullPathReplacement) - { - if (relativePath.StartsWith(relativePart)) - { - var length = relativePart.Length; - var restOfPath = relativePath.Substring(length, relativePath.Length - length); - return fullPathReplacement + restOfPath; - } - else - { - return string.Empty; - } - } - - /// - /// Get a relative path for the LinkedFilesPath which we will persist to be used when - /// restoring a project. - /// - /// - /// - /// - /// - public static string GetLinkedFilesRelativePathFromFullPath(string linkedFilesFullPath, - string projectPath, string projectName) - { - var linkedFilesPathLowercaseRoot = GetPathWithLowercaseRoot(linkedFilesFullPath); - // Case where the ExternalLinks folder is located somewhere under the project folder. - // This is the default location. - var relativePath = GetRelativePathIfExists(ksProjectRelPath, linkedFilesPathLowercaseRoot, - projectPath); - if (!string.IsNullOrEmpty(relativePath)) - return FixPathSlashesIfNeeded(relativePath); - // GetRelativePathIfExists may miss a case where, say, projectPath is - // \\ls-thomson-0910.dallas.sil.org\Projects\MyProj, and linkedFilesFullPath is - // C:\Documents and settings\All Users\SIL\FieldWorks\Projects\MyProj\LinkedFiles - // Even though the MyProj directory in both paths is the same directory. - // It's important to catch this case and return a relative path. - var projectFolderName = Path.GetFileName(projectPath); - var projectsPath = Path.GetDirectoryName(projectPath); - var allProjectsName = Path.GetFileName(projectsPath); - var match = Path.Combine(allProjectsName, projectFolderName); - int index = linkedFilesFullPath.IndexOf(match, StringComparison.InvariantCultureIgnoreCase); - if (index >= 0) - { - // There's a very good chance these are the same folders! - var alternateProjectPath = linkedFilesFullPath.Substring(0, index + match.Length); - if (Directory.Exists(alternateProjectPath) && - Directory.GetLastWriteTime(alternateProjectPath) == Directory.GetLastWriteTime(projectPath)) - { - // They ARE the same directory! (I suppose we could miss if someone wrote to it at the - // exact wrong moment, but we shouldn't be changing this setting while shared, anyway.) - return FixPathSlashesIfNeeded(ksProjectRelPath + linkedFilesFullPath.Substring(index + match.Length)); - } - } - - //See if linkedFilesPath begins with one of the other standard paths. - - // Case where user is presumably having a LinkedFiles folder shared among a number - // of projects under the Projects folder. That would be a good reason to put it in - // the projects folder common to all projects. - relativePath = GetRelativePathIfExists(ksProjectsRelPath, linkedFilesPathLowercaseRoot, - DirectoryFinder.ProjectsDirectory); - if (!String.IsNullOrEmpty(relativePath)) - return FixPathSlashesIfNeeded(relativePath); - - // Case where the user has the LinkedFiles folder in a shared folder. - relativePath = GetRelativePathIfExists(ksCommonAppDataRelPath, - linkedFilesPathLowercaseRoot, DirectoryFinder.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)); - if (!string.IsNullOrEmpty(relativePath)) - return FixPathSlashesIfNeeded(relativePath); - - // Case where the user has the LinkedFiles folder in their MyDocuments folder - relativePath = GetRelativePathIfExists(ksMyDocsRelPath, - linkedFilesPathLowercaseRoot, - DirectoryFinder.GetFolderPath(Environment.SpecialFolder.MyDocuments)); - if (!string.IsNullOrEmpty(relativePath)) - return FixPathSlashesIfNeeded(relativePath); - - //Just return the complete path if we cannot find a relative path. - return FixPathSlashesIfNeeded(linkedFilesFullPath); - } - - private static string GetRelativePathIfExists(string relativePart, string fullPath, - string parentPath) - { - var parentPathLowerCaseRoot = GetPathWithLowercaseRoot(parentPath); - if (!string.IsNullOrEmpty(parentPathLowerCaseRoot) && - fullPath.StartsWith(parentPathLowerCaseRoot)) - { - var length = parentPath.Length; - var restOfPath = fullPath.Substring(length, fullPath.Length - length); - return relativePart + restOfPath; - } - return string.Empty; - } - - private static string GetPathWithLowercaseRoot(string path) - { - try - { - var rootOfPath = Path.GetPathRoot(path); - return rootOfPath.ToLowerInvariant() + - path.Substring(rootOfPath.Length, path.Length - rootOfPath.Length); - } - catch (ArgumentException e) - { - return path.ToLowerInvariant(); - } - } - - - #endregion } } diff --git a/Src/Common/FwUtils/FwUtilsTests/DirectoryFinderTests.cs b/Src/Common/FwUtils/FwUtilsTests/DirectoryFinderTests.cs index 3d8fd9ac66..8c467d6815 100644 --- a/Src/Common/FwUtils/FwUtilsTests/DirectoryFinderTests.cs +++ b/Src/Common/FwUtils/FwUtilsTests/DirectoryFinderTests.cs @@ -17,6 +17,7 @@ using System; using System.IO; using NUnit.Framework; +using SIL.FieldWorks.FDO; using SIL.FieldWorks.Test.TestUtils; using SIL.Utils; @@ -234,7 +235,7 @@ public void GetFWDataSubDirectory_InvalidDir() public void GetLinkedFilesRelativePathFromFullPath() { Assert.AreEqual(String.Format("%proj%{0}LinkedFiles", Path.DirectorySeparatorChar), - DirectoryFinderRelativePaths.GetLinkedFilesRelativePathFromFullPath(String.Format("%proj%{0}LinkedFiles", Path.DirectorySeparatorChar), + FdoFileHelperRelativePaths.GetLinkedFilesRelativePathFromFullPath(String.Format("%proj%{0}LinkedFiles", Path.DirectorySeparatorChar), Path.Combine(DirectoryFinder.FwSourceDirectory, "FDO/FDOTests/BackupRestore/Project"), "Project")); } @@ -250,7 +251,7 @@ public void GetLinkedFilesFullPathFromRelativePath() var projectPath = Path.Combine(DirectoryFinder.ProjectsDirectory, "TestProject"); var linkedFilesRootDir = Path.Combine(projectPath, "LinkedFiles"); var linkedFilesPath = - DirectoryFinderRelativePaths.GetLinkedFilesFullPathFromRelativePath(String.Format("%proj%{0}LinkedFiles", Path.DirectorySeparatorChar), projectPath); + FdoFileHelperRelativePaths.GetLinkedFilesFullPathFromRelativePath(String.Format("%proj%{0}LinkedFiles", Path.DirectorySeparatorChar), projectPath); Assert.AreEqual(linkedFilesRootDir, linkedFilesPath); } @@ -264,13 +265,13 @@ public void GetLinkedFilesFullPathFromRelativePath() public void GetFullFilePathFromRelativeLFPath() { var linkedFilesRootDir = Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, "TestProject"), "LinkedFiles"); - var fullLFPath = DirectoryFinderRelativePaths.GetFullFilePathFromRelativeLFPath(String.Format("%lf%{0}AudioVisual{0}StarWars.mvi", Path.DirectorySeparatorChar), linkedFilesRootDir); + var fullLFPath = FdoFileHelperRelativePaths.GetFullFilePathFromRelativeLFPath(String.Format("%lf%{0}AudioVisual{0}StarWars.mvi", Path.DirectorySeparatorChar), linkedFilesRootDir); var audioVisualFile = Path.Combine(Path.Combine(linkedFilesRootDir, "AudioVisual"), "StarWars.mvi"); Assert.AreEqual(audioVisualFile, fullLFPath); //if a fully rooted path is passed in the return value should be null. var projectRootDir = DirectoryFinder.FWDataDirectory; - fullLFPath = DirectoryFinderRelativePaths.GetFullFilePathFromRelativeLFPath(projectRootDir, linkedFilesRootDir); + fullLFPath = FdoFileHelperRelativePaths.GetFullFilePathFromRelativeLFPath(projectRootDir, linkedFilesRootDir); Assert.True(string.IsNullOrEmpty(fullLFPath)); } @@ -285,12 +286,12 @@ public void GetRelativeLFPathFromFullFilePath() { var linkedFilesRootDir = Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, "TestProject"), "LinkedFiles"); var audioVisualFile = Path.Combine(Path.Combine(linkedFilesRootDir, "AudioVisual"), "StarWars.mvi"); - var relativeLFPath = DirectoryFinderRelativePaths.GetRelativeLFPathFromFullFilePath(audioVisualFile, linkedFilesRootDir); + var relativeLFPath = FdoFileHelperRelativePaths.GetRelativeLFPathFromFullFilePath(audioVisualFile, linkedFilesRootDir); Assert.AreEqual(String.Format("%lf%{0}AudioVisual{0}StarWars.mvi", Path.DirectorySeparatorChar), relativeLFPath); //Ensure empty string is returned when the path is not relative to the LinkedFiles directory. var pathNotUnderLinkedFiles = Path.Combine(DirectoryFinder.FWDataDirectory, "LordOfTheRings.mvi"); - relativeLFPath = DirectoryFinderRelativePaths.GetRelativeLFPathFromFullFilePath(pathNotUnderLinkedFiles, linkedFilesRootDir); + relativeLFPath = FdoFileHelperRelativePaths.GetRelativeLFPathFromFullFilePath(pathNotUnderLinkedFiles, linkedFilesRootDir); Assert.True(string.IsNullOrEmpty(relativeLFPath)); } @@ -304,14 +305,14 @@ public void GetRelativeLinkedFilesPath() { var linkedFilesRootDir = Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, "TestProject"), "LinkedFiles"); var audioVisualFile = Path.Combine(Path.Combine(linkedFilesRootDir, "AudioVisual"), "StarWars.mvi"); - var relativeLFPath = DirectoryFinderRelativePaths.GetRelativeLinkedFilesPath(audioVisualFile, linkedFilesRootDir); + var relativeLFPath = FdoFileHelperRelativePaths.GetRelativeLinkedFilesPath(audioVisualFile, linkedFilesRootDir); Assert.True(String.Equals(String.Format("AudioVisual{0}StarWars.mvi", Path.DirectorySeparatorChar), relativeLFPath)); //Ensure ORIGINAL path is returned when the path is not relative to the LinkedFiles directory. var pathNotUnderLinkedFiles = Path.Combine(DirectoryFinder.FWDataDirectory, "LordOfTheRings.mvi"); - relativeLFPath = DirectoryFinderRelativePaths.GetRelativeLinkedFilesPath(pathNotUnderLinkedFiles, linkedFilesRootDir); + relativeLFPath = FdoFileHelperRelativePaths.GetRelativeLinkedFilesPath(pathNotUnderLinkedFiles, linkedFilesRootDir); Assert.True(String.Equals(pathNotUnderLinkedFiles,relativeLFPath)); - Assert.That(DirectoryFinderRelativePaths.GetRelativeLinkedFilesPath( + Assert.That(FdoFileHelperRelativePaths.GetRelativeLinkedFilesPath( "silfw:\\localhost\\link?app%3dflex%26database%3dc%3a%5cTestLangProj%5cTestLangProj.fwdata%26server%3d%26tool%3dnaturalClassedit%26guid%3d43c9ba97-2883-4f95-aa5d-ef9309e85025%26tag%3d", relativeLFPath), Is.Null, "hyperlinks should be left well alone!!"); } @@ -325,13 +326,13 @@ public void GetRelativeLinkedFilesPath() public void GetFullPathFromRelativeLFPath() { var linkedFilesRootDir = Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, "TestProject"), "LinkedFiles"); - var fullLFPath = DirectoryFinderRelativePaths.GetFullPathFromRelativeLFPath(String.Format("AudioVisual{0}StarWars.mvi", Path.DirectorySeparatorChar), linkedFilesRootDir); + var fullLFPath = FdoFileHelperRelativePaths.GetFullPathFromRelativeLFPath(String.Format("AudioVisual{0}StarWars.mvi", Path.DirectorySeparatorChar), linkedFilesRootDir); var audioVisualFile = Path.Combine(Path.Combine(linkedFilesRootDir, "AudioVisual"), "StarWars.mvi"); Assert.AreEqual(audioVisualFile, fullLFPath); //if a fully rooted path is passed in the return value should be the path that was passed in. var fileUnderProjectRootDir = String.Format("{1}{0}AudioVisual{0}StarWars.mvi", Path.DirectorySeparatorChar, DirectoryFinder.FWDataDirectory); - fullLFPath = DirectoryFinderRelativePaths.GetFullPathFromRelativeLFPath(fileUnderProjectRootDir, linkedFilesRootDir); + fullLFPath = FdoFileHelperRelativePaths.GetFullPathFromRelativeLFPath(fileUnderProjectRootDir, linkedFilesRootDir); Assert.AreEqual(fullLFPath, fileUnderProjectRootDir); } @@ -344,7 +345,7 @@ public void GetFullPathFromRelativeLFPath() public void GetFullPathFromRelativeLFPath_WithIllegalCharacters_ReturnsSpecialPath() { var linkedFilesRootDir = Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, "TestProject"), "LinkedFiles"); - var fullLFPath = DirectoryFinderRelativePaths.GetFullPathFromRelativeLFPath("1\";1\"", linkedFilesRootDir); + var fullLFPath = FdoFileHelperRelativePaths.GetFullPathFromRelativeLFPath("1\";1\"", linkedFilesRootDir); Assert.That(fullLFPath, Is.EqualTo(Path.Combine(linkedFilesRootDir,"__ILLEGALCHARS__"))); } diff --git a/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj b/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj index fefe6781c3..d66bf0c1f2 100644 --- a/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj +++ b/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj @@ -114,6 +114,10 @@ False ..\..\..\..\Output\Debug\CoreImpl.dll + + False + ..\..\..\..\Output\Debug\FDO.dll + False ..\..\..\..\Output\Debug\FwUtils.dll diff --git a/Src/FDO/DomainImpl/OverridesCellar.cs b/Src/FDO/DomainImpl/OverridesCellar.cs index 5ac948fa1f..3b12aacec4 100644 --- a/Src/FDO/DomainImpl/OverridesCellar.cs +++ b/Src/FDO/DomainImpl/OverridesCellar.cs @@ -1979,7 +1979,7 @@ public string InternalPath if (value == null) throw new ArgumentNullException("value"); - string srcFilename = DirectoryFinderRelativePaths.GetRelativeLinkedFilesPath(value, m_cache.LangProject.LinkedFilesRootDir); + string srcFilename = FdoFileHelperRelativePaths.GetRelativeLinkedFilesPath(value, m_cache.LangProject.LinkedFilesRootDir); InternalPath_Generated = srcFilename; } @@ -2010,7 +2010,7 @@ public string AbsoluteInternalPath string internalPath = InternalPath; if (String.IsNullOrEmpty(internalPath)) internalPath = DomainObjectServices.EmptyFileName; - return DirectoryFinderRelativePaths.GetFullPathFromRelativeLFPath(internalPath, m_cache.LangProject.LinkedFilesRootDir); + return FdoFileHelperRelativePaths.GetFullPathFromRelativeLFPath(internalPath, m_cache.LangProject.LinkedFilesRootDir); } } diff --git a/Src/FDO/DomainImpl/OverridesLangProj.cs b/Src/FDO/DomainImpl/OverridesLangProj.cs index 055cdafb5c..0f31cf3ff7 100644 --- a/Src/FDO/DomainImpl/OverridesLangProj.cs +++ b/Src/FDO/DomainImpl/OverridesLangProj.cs @@ -93,13 +93,13 @@ public string LinkedFilesRootDir get { return String.IsNullOrEmpty(LinkedFilesRootDir_Generated) - ? Path.Combine(m_cache.ProjectId.SharedProjectFolder, DirectoryFinder.ksLinkedFilesDir) - : DirectoryFinderRelativePaths.GetLinkedFilesFullPathFromRelativePath(LinkedFilesRootDir_Generated, + ? Path.Combine(m_cache.ProjectId.SharedProjectFolder, FdoFileHelper.ksLinkedFilesDir) + : FdoFileHelperRelativePaths.GetLinkedFilesFullPathFromRelativePath(LinkedFilesRootDir_Generated, m_cache.ProjectId.SharedProjectFolder); } set { - string relativePath = DirectoryFinderRelativePaths.GetLinkedFilesRelativePathFromFullPath(value, + string relativePath = FdoFileHelperRelativePaths.GetLinkedFilesRelativePathFromFullPath(value, m_cache.ProjectId.SharedProjectFolder, ShortName); LinkedFilesRootDir_Generated = relativePath; diff --git a/Src/FDO/DomainServices/BackupRestore/BackupFileSettings.cs b/Src/FDO/DomainServices/BackupRestore/BackupFileSettings.cs index 049f71b4ff..a13518f827 100644 --- a/Src/FDO/DomainServices/BackupRestore/BackupFileSettings.cs +++ b/Src/FDO/DomainServices/BackupRestore/BackupFileSettings.cs @@ -128,7 +128,7 @@ private BackupFileSettings(BackupProjectSettings settings) m_spellCheckAdditions = settings.IncludeSpellCheckAdditions; m_dbVersion = settings.DbVersion; m_fwVersion = settings.FwVersion; - m_linkedFilesPathRelative = DirectoryFinderRelativePaths.GetLinkedFilesRelativePathFromFullPath(settings.LinkedFilesPath, settings.ProjectPath, settings.ProjectName); + m_linkedFilesPathRelative = FdoFileHelperRelativePaths.GetLinkedFilesRelativePathFromFullPath(settings.LinkedFilesPath, settings.ProjectPath, settings.ProjectName); m_linkedFilesPathActual = settings.LinkedFilesPath; m_appAbbrev = settings.AppAbbrev; } @@ -437,7 +437,7 @@ private void PopulateSettingsFromZipFileIfNeeded() " contained multiple project data files."); dataFileName = fileName; } - else if (!entry.Name.EndsWith("/") && entry.Name.Contains(DirectoryFinder.ksWritingSystemsDir + "/")) + else if (!entry.Name.EndsWith("/") && entry.Name.Contains(FdoFileHelper.ksWritingSystemsDir + "/")) foundWritingSystemFiles = true; } @@ -447,7 +447,7 @@ private void PopulateSettingsFromZipFileIfNeeded() if (m_projectName == null) throw new InvalidOperationException(DirectoryFinder.kBackupSettingsFilename + " in " + m_sZipFileName + " did not contain a project name."); - string expectedProjectFile = DirectoryFinder.GetXmlDataFileName(m_projectName); + string expectedProjectFile = FdoFileHelper.GetXmlDataFileName(m_projectName); if (dataFileName == null || dataFileName != expectedProjectFile) throw new InvalidOperationException("Zip file " + m_sZipFileName + " did not contain the " + expectedProjectFile + " file."); @@ -544,9 +544,9 @@ private void InitializeFromStream(Stream persistenceStream) m_backupTime = settings.BackupTime; m_comment = settings.Comment; m_projectName = settings.ProjectName; - m_linkedFilesPathRelative = DirectoryFinderRelativePaths.FixPathSlashesIfNeeded(settings.LinkedFilesPathRelativePersisted); - m_linkedFilesPathActual = DirectoryFinderRelativePaths.FixPathSlashesIfNeeded(settings.LinkedFilesPathActualPersisted); - m_projectPathPersisted = DirectoryFinderRelativePaths.FixPathSlashesIfNeeded(settings.ProjectPathPersisted); + m_linkedFilesPathRelative = FdoFileHelperRelativePaths.FixPathSlashesIfNeeded(settings.LinkedFilesPathRelativePersisted); + m_linkedFilesPathActual = FdoFileHelperRelativePaths.FixPathSlashesIfNeeded(settings.LinkedFilesPathActualPersisted); + m_projectPathPersisted = FdoFileHelperRelativePaths.FixPathSlashesIfNeeded(settings.ProjectPathPersisted); m_configurationSettings = settings.IncludeConfigurationSettings; m_linkedFiles = settings.IncludeLinkedFiles; m_supportingFiles = settings.IncludeSupportingFiles; diff --git a/Src/FDO/DomainServices/BackupRestore/BackupProjectSettings.cs b/Src/FDO/DomainServices/BackupRestore/BackupProjectSettings.cs index 4762a3ac17..10e8deaae4 100644 --- a/Src/FDO/DomainServices/BackupRestore/BackupProjectSettings.cs +++ b/Src/FDO/DomainServices/BackupRestore/BackupProjectSettings.cs @@ -165,7 +165,7 @@ public string BackupSettingsFile { get { - return Path.Combine(DirectoryFinder.GetBackupSettingsDir(ProjectPath), + return Path.Combine(FdoFileHelper.GetBackupSettingsDir(ProjectPath), DirectoryFinder.kBackupSettingsFilename); } } diff --git a/Src/FDO/DomainServices/BackupRestore/BackupSettings.cs b/Src/FDO/DomainServices/BackupRestore/BackupSettings.cs index b639027d13..d9f28f8599 100644 --- a/Src/FDO/DomainServices/BackupRestore/BackupSettings.cs +++ b/Src/FDO/DomainServices/BackupRestore/BackupSettings.cs @@ -88,7 +88,7 @@ protected BackupSettings(string projectsRootFolder, string linkedFilesPath, /// ------------------------------------------------------------------------------------ public string DbFilename { - get { return DirectoryFinder.GetXmlDataFileName(ProjectName); } + get { return FdoFileHelper.GetXmlDataFileName(ProjectName); } } #region IBackupSettings implementation @@ -181,7 +181,7 @@ public string QuestionNotesFilename /// public string FlexConfigurationSettingsPath { - get { return DirectoryFinder.GetConfigSettingsDir(ProjectPath); } + get { return FdoFileHelper.GetConfigSettingsDir(ProjectPath); } } /// @@ -194,7 +194,7 @@ public string LinkedFilesPath if (String.IsNullOrEmpty(m_linkedFilesPath)) { return Path.Combine(!string.IsNullOrEmpty(m_sharedProjectFolder) ? - m_sharedProjectFolder : ProjectPath, DirectoryFinder.ksLinkedFilesDir); + m_sharedProjectFolder : ProjectPath, FdoFileHelper.ksLinkedFilesDir); } return m_linkedFilesPath; } @@ -209,7 +209,7 @@ public string LinkedFilesPath /// public string PicturesPath { - get { return DirectoryFinder.GetPicturesDir(LinkedFilesPath); } + get { return FdoFileHelper.GetPicturesDir(LinkedFilesPath); } } /// @@ -217,7 +217,7 @@ public string PicturesPath /// public string MediaPath { - get { return DirectoryFinder.GetMediaDir(LinkedFilesPath); } + get { return FdoFileHelper.GetMediaDir(LinkedFilesPath); } } /// @@ -225,7 +225,7 @@ public string MediaPath /// public string OtherExternalFilesPath { - get { return DirectoryFinder.GetOtherExternalFilesDir(LinkedFilesPath); } + get { return FdoFileHelper.GetOtherExternalFilesDir(LinkedFilesPath); } } /// @@ -235,7 +235,7 @@ public string WritingSystemStorePath { get { - return DirectoryFinder.GetWritingSystemDir( + return FdoFileHelper.GetWritingSystemDir( string.IsNullOrEmpty(m_sharedProjectFolder) ? ProjectPath : m_sharedProjectFolder); } } @@ -254,7 +254,7 @@ public string SpellingDictionariesPath /// public string ProjectSupportingFilesPath { - get { return DirectoryFinder.GetSupportingFilesDir(ProjectPath); } + get { return FdoFileHelper.GetSupportingFilesDir(ProjectPath); } } #endregion } diff --git a/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs b/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs index 3f26b4f4b7..352f7f7c3c 100644 --- a/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs +++ b/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs @@ -98,7 +98,7 @@ public bool BackupProject(IThreadedProgress progressDlg, out string backupFile) /// ------------------------------------------------------------------------------------ private void PersistBackupFileSettings() { - string backupSettingsFile = Path.Combine(DirectoryFinder.GetBackupSettingsDir( + string backupSettingsFile = Path.Combine(FdoFileHelper.GetBackupSettingsDir( m_settings.ProjectPath), DirectoryFinder.kBackupSettingsFilename); string settingsDir = Path.GetDirectoryName(backupSettingsFile); diff --git a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs index 63e3a02037..aae2161679 100644 --- a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs +++ b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs @@ -159,7 +159,7 @@ private void RestoreFrom7_0AndNewerBackup(BackupFileSettings fileSettings) { // Get rid of any saved settings, since they may not be consistent with something about the data // or settings we are restoring. (This extension is also known to RecordView.GetClerkPersistPathname()). - var tempDirectory = Path.Combine(m_restoreSettings.ProjectPath, DirectoryFinder.ksSortSequenceTempDir); + var tempDirectory = Path.Combine(m_restoreSettings.ProjectPath, FdoFileHelper.ksSortSequenceTempDir); if (Directory.Exists(tempDirectory)) { foreach (var sortSeqFile in Directory.GetFiles(tempDirectory, "*.fwss")) @@ -169,19 +169,19 @@ private void RestoreFrom7_0AndNewerBackup(BackupFileSettings fileSettings) UncompressDataFiles(); // We can't use Path.Combine here, because the zip files stores all file paths with '/'s - UncompressFilesMatchingPath(DirectoryFinder.ksWritingSystemsDir + "/", m_restoreSettings.WritingSystemStorePath); + UncompressFilesMatchingPath(FdoFileHelper.ksWritingSystemsDir + "/", m_restoreSettings.WritingSystemStorePath); if (m_restoreSettings.IncludeSupportingFiles) { Debug.Assert(fileSettings.IncludeSupportingFiles, "The option to include supporting files should not be allowed if they aren't available in the backup settings"); - var zipEntryStartsWith = DirectoryFinder.ksSupportingFilesDir; + var zipEntryStartsWith = FdoFileHelper.ksSupportingFilesDir; UncompressFilesContainedInFolderandSubFolders(DirectoryFinder.GetZipfileFormattedPath(zipEntryStartsWith), m_restoreSettings.ProjectSupportingFilesPath); } if (m_restoreSettings.IncludeConfigurationSettings) - UncompressFilesMatchingPath(DirectoryFinder.ksConfigurationSettingsDir + "/", m_restoreSettings.FlexConfigurationSettingsPath); + UncompressFilesMatchingPath(FdoFileHelper.ksConfigurationSettingsDir + "/", m_restoreSettings.FlexConfigurationSettingsPath); if (m_restoreSettings.IncludeLinkedFiles) RestoreLinkedFiles(fileSettings); @@ -284,7 +284,7 @@ private void UncompressDataFiles() while ((entry = zipIn.GetNextEntry()) != null) { var fileName = Path.GetFileName(entry.Name); - if (fileName == DirectoryFinder.GetXmlDataFileName(m_restoreSettings.Backup.ProjectName)) + if (fileName == FdoFileHelper.GetXmlDataFileName(m_restoreSettings.Backup.ProjectName)) UnzipFileToRestoreFolder(zipIn, m_restoreSettings.DbFilename, entry.Size, m_restoreSettings.ProjectPath, entry.DateTime); if (fileName == m_restoreSettings.QuestionNotesFilename) @@ -306,22 +306,22 @@ private void RestoreLinkedFiles(BackupFileSettings fileSettings) "The option to include linked files should not be allowed if they aren't available in the backup settings"); var proposedDestinationLinkedFilesPath = - DirectoryFinderRelativePaths.GetLinkedFilesFullPathFromRelativePath( + FdoFileHelperRelativePaths.GetLinkedFilesFullPathFromRelativePath( fileSettings.LinkedFilesPathRelativePersisted, m_restoreSettings.ProjectPath); var linkedFilesPathInZip = fileSettings.LinkedFilesPathActualPersisted; - if (fileSettings.LinkedFilesPathRelativePersisted.StartsWith(DirectoryFinderRelativePaths.ksProjectRelPath)) + if (fileSettings.LinkedFilesPathRelativePersisted.StartsWith(FdoFileHelperRelativePaths.ksProjectRelPath)) { // We store any files inside the project folder as a relative path from the project's directory. // Make sure we don't attempt to search for the whole directory structure in the zip file. (FWR-2909) linkedFilesPathInZip = fileSettings.LinkedFilesPathRelativePersisted.Substring( - DirectoryFinderRelativePaths.ksProjectRelPath.Length + 1); + FdoFileHelperRelativePaths.ksProjectRelPath.Length + 1); } var filesContainedInLinkdFilesFolder = GetAllFilesUnderFolderInZipFileAndDateTimes(linkedFilesPathInZip); //If the proposed location is not in the default location under the project, then ask the user if they want //to restore the files to the default location instead. Otherwise just go ahead and restore the files. - var defaultLinkedFilesPath = DirectoryFinder.GetDefaultLinkedFilesDir(m_restoreSettings.ProjectPath); + var defaultLinkedFilesPath = FdoFileHelper.GetDefaultLinkedFilesDir(m_restoreSettings.ProjectPath); if (proposedDestinationLinkedFilesPath.Equals(defaultLinkedFilesPath)) { if (!Directory.Exists(defaultLinkedFilesPath)) @@ -360,7 +360,7 @@ protected void RestoreLinkedFiles(bool fPutFilesInProject, Dictionary ProcessExternalLinksRelativePaths(IDomainObjectDTORepositor var filePath = FileUtils.ChangeWindowsPathIfLinux(externalLinkAttributeForThisRun.Value); //Check the path and if it is a rooted path which is relative to the LinkedFilesRootDir //then we will have to confirm that is was changed to a relative path after the migration. - var fileAsRelativePath = DirectoryFinderRelativePaths.GetRelativeLinkedFilesPath(filePath, + var fileAsRelativePath = FdoFileHelperRelativePaths.GetRelativeLinkedFilesPath(filePath, linkedFilesRootDir); //Save the file paths so they can be turned into CmFiles filePathsInTsStrings.Add(fileAsRelativePath); diff --git a/Src/FDO/DomainServices/DataMigration/DataMigration7000044.cs b/Src/FDO/DomainServices/DataMigration/DataMigration7000044.cs index d9ca8ad820..e7abfc4a2d 100644 --- a/Src/FDO/DomainServices/DataMigration/DataMigration7000044.cs +++ b/Src/FDO/DomainServices/DataMigration/DataMigration7000044.cs @@ -61,7 +61,7 @@ public void PerformMigration(IDomainObjectDTORepository repoDto) globalMigrator.Migrate(); } - var ldmlFolder = Path.Combine(repoDto.ProjectFolder, DirectoryFinder.ksWritingSystemsDir); + var ldmlFolder = Path.Combine(repoDto.ProjectFolder, FdoFileHelper.ksWritingSystemsDir); var migrator = new LdmlInFolderWritingSystemRepositoryMigrator(ldmlFolder, NoteMigration); migrator.Migrate(); UpdateTags(repoDto); @@ -162,7 +162,7 @@ private void UpdateTags(IDomainObjectDTORepository repoDto) lpChanged |= UpdateAttr(langProj, "VernWss"); if (lpChanged) DataMigrationServices.UpdateDTO(repoDto, langProjDto, langProj.ToString()); - var settingsFolder = Path.Combine(repoDto.ProjectFolder, DirectoryFinder.ksConfigurationSettingsDir); + var settingsFolder = Path.Combine(repoDto.ProjectFolder, FdoFileHelper.ksConfigurationSettingsDir); if (Directory.Exists(settingsFolder)) { m_tagMap["$wsname"] = "$wsname"; // should never be changed. diff --git a/Src/FDO/DomainServices/DataMigration/DataMigration7000060.cs b/Src/FDO/DomainServices/DataMigration/DataMigration7000060.cs index ba6ee5e948..321d9f647d 100644 --- a/Src/FDO/DomainServices/DataMigration/DataMigration7000060.cs +++ b/Src/FDO/DomainServices/DataMigration/DataMigration7000060.cs @@ -51,7 +51,7 @@ public void PerformMigration(IDomainObjectDTORepository repoDto) { DataMigrationServices.CheckVersionNumber(repoDto, 7000059); - var configFolder = Path.Combine(repoDto.ProjectFolder, DirectoryFinder.ksConfigurationSettingsDir); + var configFolder = Path.Combine(repoDto.ProjectFolder, FdoFileHelper.ksConfigurationSettingsDir); if (Directory.Exists(configFolder)) // Some of Randy's test data doesn't have the config folder, so it crashes here. { const string layoutSuffix = "_Layouts.xml"; diff --git a/Src/FDO/DomainServices/FwProjectFinder.cs b/Src/FDO/DomainServices/FwProjectFinder.cs index 935b87bf6e..932f04e8b1 100644 --- a/Src/FDO/DomainServices/FwProjectFinder.cs +++ b/Src/FDO/DomainServices/FwProjectFinder.cs @@ -82,12 +82,12 @@ private void FindProjects() string[] dirs = Directory.GetDirectories(DirectoryFinder.ProjectsDirectory); foreach (string dir in dirs) { - string file = Path.Combine(dir, DirectoryFinder.GetXmlDataFileName(Path.GetFileName(dir))); + string file = Path.Combine(dir, FdoFileHelper.GetXmlDataFileName(Path.GetFileName(dir))); if (FileUtils.SimilarFileExists(file)) m_projectFoundCallback(file); else { - string db4oFile = Path.Combine(dir, DirectoryFinder.GetDb4oDataFileName(Path.GetFileName(dir))); + string db4oFile = Path.Combine(dir, FdoFileHelper.GetDb4oDataFileName(Path.GetFileName(dir))); //If the db4o file exists it will be added to the list later and therefore we do not want to //show the .bak file to the user in the open project dialog if (!FileUtils.SimilarFileExists(db4oFile)) diff --git a/Src/FDO/DomainServices/StringServices.cs b/Src/FDO/DomainServices/StringServices.cs index afd3b4b5db..83d7032920 100644 --- a/Src/FDO/DomainServices/StringServices.cs +++ b/Src/FDO/DomainServices/StringServices.cs @@ -77,7 +77,7 @@ public static void MarkTextInBldrAsHyperlink(ITsStrBldr strBldr, int ichStart, public static string MarkTextInBldrAsHyperlink(ITsStrBldr strBldr, int ichStart, int ichLim, string url, IStStyle linkStyle, string linkedFilesRootDir) { - var relativeUrl = DirectoryFinderRelativePaths.GetRelativeLinkedFilesPath(url, linkedFilesRootDir); + var relativeUrl = FdoFileHelperRelativePaths.GetRelativeLinkedFilesPath(url, linkedFilesRootDir); if (string.IsNullOrEmpty(relativeUrl)) { MarkTextInBldrAsHyperlink(strBldr, ichStart, ichLim, url, linkStyle); diff --git a/Src/FDO/FDO.csproj b/Src/FDO/FDO.csproj index 4df5508718..0e49285bd7 100644 --- a/Src/FDO/FDO.csproj +++ b/Src/FDO/FDO.csproj @@ -189,6 +189,7 @@ + diff --git a/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs b/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs index d5faafa312..77069d085a 100644 --- a/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs +++ b/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs @@ -240,8 +240,8 @@ public void RestoreProject_OverwriteOnlyDataRestored() m_restoreProjectService.RestoreProject(progressDlg); string restoreProjectDirectory = m_restoreSettings.ProjectPath; - VerifyFileExists(restoreProjectDirectory, DirectoryFinder.GetXmlDataFileName("TestRestoreFWProject")); - var dateTimeTicksOfFirstFile = GetLastWriteTimeOfRestoredFile(restoreProjectDirectory, DirectoryFinder.GetXmlDataFileName("TestRestoreFWProject")); + VerifyFileExists(restoreProjectDirectory, FdoFileHelper.GetXmlDataFileName("TestRestoreFWProject")); + var dateTimeTicksOfFirstFile = GetLastWriteTimeOfRestoredFile(restoreProjectDirectory, FdoFileHelper.GetXmlDataFileName("TestRestoreFWProject")); // Linux filesystem modification time precision can be to the second, so wait a moment. if (MiscUtils.IsUnix) @@ -255,7 +255,7 @@ public void RestoreProject_OverwriteOnlyDataRestored() //Now do another restore then verify that the two files are not the same by comparing the LastWriteTime values. m_restoreProjectService.RestoreProject(progressDlg); - var dateTimeTicksOfSecondFile = GetLastWriteTimeOfRestoredFile(restoreProjectDirectory, DirectoryFinder.GetXmlDataFileName("TestRestoreFWProject")); + var dateTimeTicksOfSecondFile = GetLastWriteTimeOfRestoredFile(restoreProjectDirectory, FdoFileHelper.GetXmlDataFileName("TestRestoreFWProject")); Assert.True(dateTimeTicksOfSecondFile.Equals(dateTimeTicksOfFirstFile), "The dates and times of the files should be the same since they are set to the timestamp of the file in the zip file."); VerifyManditoryFilesUnzippedAndDeleteThem(); @@ -290,7 +290,7 @@ private static void RemoveAllFilesFromFolderAndSubfolders(string restoreDirector internal static void RemoveAnyFilesAndFoldersCreatedByTests(RestoreProjectSettings settings) { - RemoveAllFilesFromFolderAndSubfolders(DirectoryFinder.GetBackupSettingsDir(settings.ProjectPath)); + RemoveAllFilesFromFolderAndSubfolders(FdoFileHelper.GetBackupSettingsDir(settings.ProjectPath)); RemoveAllFilesFromFolderAndSubfolders(settings.ProjectSupportingFilesPath); RemoveAllFilesFromFolderAndSubfolders(settings.FlexConfigurationSettingsPath); RemoveAllFilesFromFolderAndSubfolders(settings.PicturesPath); @@ -298,7 +298,7 @@ internal static void RemoveAnyFilesAndFoldersCreatedByTests(RestoreProjectSettin RemoveAllFilesFromFolderAndSubfolders(settings.OtherExternalFilesPath); RemoveAllFilesFromFolderAndSubfolders(settings.LinkedFilesPath); RemoveAllFilesFromFolderAndSubfolders(settings.WritingSystemStorePath); - RemoveAllFilesFromFolderAndSubfolders(Path.Combine(settings.ProjectPath, DirectoryFinder.ksSortSequenceTempDir)); + RemoveAllFilesFromFolderAndSubfolders(Path.Combine(settings.ProjectPath, FdoFileHelper.ksSortSequenceTempDir)); //Remove this one last of all because the other folders need to be removed first. RemoveAllFilesFromFolderAndSubfolders(settings.ProjectPath); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000019Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000019Tests.cs index dcf25f9f3c..e887677cd0 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000019Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000019Tests.cs @@ -38,7 +38,7 @@ private static void PrepareStore(string path) [Test] public void DataMigration7000019Test() { - string storePath = Path.Combine(Path.GetTempPath(), DirectoryFinder.ksWritingSystemsDir); + string storePath = Path.Combine(Path.GetTempPath(), FdoFileHelper.ksWritingSystemsDir); PrepareStore(storePath); string globalStorePath = DirectoryFinder.GlobalWritingSystemStoreDirectory; PrepareStore(globalStorePath); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000044Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000044Tests.cs index 490a7de1ff..4e58ccc65e 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000044Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000044Tests.cs @@ -73,7 +73,7 @@ public DataMigration7000044Tests() public void DataMigration7000044Test() { var projectFolder = Path.GetTempPath(); - var storePath = Path.Combine(projectFolder, DirectoryFinder.ksWritingSystemsDir); + var storePath = Path.Combine(projectFolder, FdoFileHelper.ksWritingSystemsDir); PrepareStore(storePath); var testDataPath = Path.Combine(DirectoryFinder.FwSourceDirectory, "FDO/FDOTests/TestData"); var testEnglishPath = Path.Combine(storePath, "en.ldml"); @@ -100,7 +100,7 @@ public void DataMigration7000044Test() mockMDC.AddClass(8, "CmPossibilityList", "CmObject", new List()); mockMDC.AddClass(9, "CmBaseAnnotation", "CmObject", new List()); - var settingsFolder = Path.Combine(projectFolder, DirectoryFinder.ksConfigurationSettingsDir); + var settingsFolder = Path.Combine(projectFolder, FdoFileHelper.ksConfigurationSettingsDir); Directory.CreateDirectory(settingsFolder); var sampleLayout = Path.Combine(settingsFolder, "Test_Layouts.xml"); File.WriteAllText(sampleLayout, sampleLayoutData, Encoding.UTF8); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000060Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000060Tests.cs index c47551a888..313d268b02 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000060Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000060Tests.cs @@ -26,7 +26,7 @@ public void DataMigration7000060Test() { var projectFolder = Path.GetTempPath(); - var settingsFolder = Path.Combine(projectFolder, DirectoryFinder.ksConfigurationSettingsDir); + var settingsFolder = Path.Combine(projectFolder, FdoFileHelper.ksConfigurationSettingsDir); var sampleLayout = Path.Combine(settingsFolder, "Test_Layouts.xml"); var otherFile = Path.Combine(settingsFolder, "other.xml"); var newLayoutPath = Path.Combine(settingsFolder, "Test.fwlayout"); diff --git a/Src/FDO/FDOTests/FdoCacheTests.cs b/Src/FDO/FDOTests/FdoCacheTests.cs index c7a974bf06..15ff7d0b2e 100644 --- a/Src/FDO/FDOTests/FdoCacheTests.cs +++ b/Src/FDO/FDOTests/FdoCacheTests.cs @@ -84,7 +84,7 @@ public void CreateNewLangProject_DbFilesExist() try { // Setup: Create "pre-existing" DB filenames - using (new DummyFileMaker(Path.Combine(DirectoryFinder.ProjectsDirectory, "Gumby", DirectoryFinder.GetXmlDataFileName("Gumby")))) + using (new DummyFileMaker(Path.Combine(DirectoryFinder.ProjectsDirectory, "Gumby", FdoFileHelper.GetXmlDataFileName("Gumby")))) { using (var threadHelper = new ThreadHelper()) FdoCache.CreateNewLangProj(new DummyProgressDlg(), "Gumby", threadHelper, new DummyFdoUI()); @@ -110,7 +110,7 @@ public void CreateNewLangProject_NameWithSingleQuote() SureRemoveDb(dbName); var expectedDirs = new List(Directory.GetDirectories(DirectoryFinder.ProjectsDirectory)) { dbDir }; - var writingSystemsCommonDir = Path.Combine(DirectoryFinder.ProjectsDirectory, DirectoryFinder.ksWritingSystemsDir); + var writingSystemsCommonDir = Path.Combine(DirectoryFinder.ProjectsDirectory, FdoFileHelper.ksWritingSystemsDir); List currentDirs = null; try diff --git a/Src/FDO/FDOTests/PersistingBackendProviderTests.cs b/Src/FDO/FDOTests/PersistingBackendProviderTests.cs index 6b0fa54e5b..3ebffaf775 100644 --- a/Src/FDO/FDOTests/PersistingBackendProviderTests.cs +++ b/Src/FDO/FDOTests/PersistingBackendProviderTests.cs @@ -564,7 +564,7 @@ public override void FixtureTeardown() protected override void CheckAdditionalStuffAfterFirstRename() { Assert.AreEqual(Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, NewProjectName), - DirectoryFinder.GetDb4oDataFileName(NewProjectName)), Cache.ProjectId.Path); + FdoFileHelper.GetDb4oDataFileName(NewProjectName)), Cache.ProjectId.Path); } } @@ -586,7 +586,7 @@ protected override FdoCache CreateCache() { const string projName = "TestLangProj-test"; string filename = Path.Combine(DirectoryFinder.ProjectsDirectory, - Path.Combine(projName, DirectoryFinder.GetXmlDataFileName(projName))); + Path.Combine(projName, FdoFileHelper.GetXmlDataFileName(projName))); if (!m_internalRestart) { if (File.Exists(filename)) @@ -606,7 +606,7 @@ protected override FdoCache CreateCache() [Ignore("There is a timing problem with this test - project file may not exist becuase background thread is doing commit.")] public void OnlyOneCacheAllowed() { - string filename = DirectoryFinder.GetXmlDataFileName("TestLangProj"); + string filename = FdoFileHelper.GetXmlDataFileName("TestLangProj"); Assert.True(File.Exists(filename), "Test XML file not found"); using (FdoCache cache = OpenExistingFile(filename)) Assert.Fail("Able to open XML file that is already open"); @@ -626,7 +626,7 @@ private FdoCache OpenExistingFile(string filename) protected override void CheckAdditionalStuffAfterFirstRename() { Assert.AreEqual(Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, NewProjectName), - DirectoryFinder.GetXmlDataFileName(NewProjectName)), Cache.ProjectId.Path); + FdoFileHelper.GetXmlDataFileName(NewProjectName)), Cache.ProjectId.Path); } /// diff --git a/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs b/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs index 8b54cba19c..14357a3b85 100644 --- a/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs +++ b/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs @@ -81,7 +81,7 @@ public BEPPortTests() m_sourceInfo = new List { new BackendStartupParameter(true, BackendBulkLoadDomain.All, - new TestProjectId(FDOBackendProviderType.kXML, DirectoryFinder.GetXmlDataFileName("TLP" + randomFileExtension))), + new TestProjectId(FDOBackendProviderType.kXML, FdoFileHelper.GetXmlDataFileName("TLP" + randomFileExtension))), new BackendStartupParameter(true, BackendBulkLoadDomain.All, new TestProjectId(FDOBackendProviderType.kMemoryOnly, null)), new BackendStartupParameter(true, BackendBulkLoadDomain.All, @@ -90,7 +90,7 @@ public BEPPortTests() m_targetInfo = new List { new BackendStartupParameter(true, BackendBulkLoadDomain.All, - new TestProjectId(FDOBackendProviderType.kXML, DirectoryFinder.GetXmlDataFileName("TLP_New" + randomFileExtension))), + new TestProjectId(FDOBackendProviderType.kXML, FdoFileHelper.GetXmlDataFileName("TLP_New" + randomFileExtension))), new BackendStartupParameter(true, BackendBulkLoadDomain.All, new TestProjectId(FDOBackendProviderType.kMemoryOnly, null)), new BackendStartupParameter(true, BackendBulkLoadDomain.All, diff --git a/Src/FDO/FdoFileHelper.cs b/Src/FDO/FdoFileHelper.cs index d0941860e4..b74cbbe91b 100644 --- a/Src/FDO/FdoFileHelper.cs +++ b/Src/FDO/FdoFileHelper.cs @@ -11,6 +11,10 @@ // File: FdoFileHelper.cs // -------------------------------------------------------------------------------------------- +using System; +using System.Diagnostics; +using System.IO; + namespace SIL.FieldWorks.FDO { /// ---------------------------------------------------------------------------------------- @@ -40,5 +44,189 @@ public static class FdoFileHelper /// Default extension for FieldWorks TEMPORARY fallback data files (with the period). public const string ksFwDataFallbackFileExtension = ".bak"; + + + /// The name of the folder containing FLEx configuration settings + public const string ksConfigurationSettingsDir = "ConfigurationSettings"; + /// The name of the folder containing FLEx backup settings + public const string ksBackupSettingsDir = "BackupSettings"; + /// The name of the folder where the user can copy files for backup such as fonts and keyboards + public const string ksSupportingFilesDir = "SupportingFiles"; + /// The default name of the folder containing LinkedFiles (media, pictures, etc) for a project + public const string ksLinkedFilesDir = "LinkedFiles"; + /// The name of the subfolder containing media for a project + public const string ksMediaDir = "AudioVisual"; + /// The name of the subfolder containing pictures for a project + public const string ksPicturesDir = "Pictures"; + /// The name of the subfolder containing other LinkedFiles for a project + public const string ksOtherLinkedFilesDir = "Others"; + /// The name of the folder containing writing systems for a project + public const string ksWritingSystemsDir = "WritingSystemStore"; + /// The name of the folder containing temporary persisted sort sequence info for a project + public const string ksSortSequenceTempDir = "Temp"; + + /// ------------------------------------------------------------------------------------ + /// + /// Gets the path to the configuration settings for the specified project. + /// + /// The path to the project folder. + /// ------------------------------------------------------------------------------------ + public static string GetConfigSettingsDir(string projectFolder) + { + return Path.Combine(projectFolder, ksConfigurationSettingsDir); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Gets the path to the backup settings for the specified project + /// + /// The path to the project folder. + /// ------------------------------------------------------------------------------------ + public static string GetBackupSettingsDir(string projectFolder) + { + return Path.Combine(projectFolder, ksBackupSettingsDir); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Gets the path to the fonts for the specified project. + /// + /// The path to the project folder. + /// ------------------------------------------------------------------------------------ + public static string GetSupportingFilesDir(string projectFolder) + { + return Path.Combine(projectFolder, ksSupportingFilesDir); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Gets the path to the writing systems for the specified project. + /// + /// The path to the project folder. + /// ------------------------------------------------------------------------------------ + public static string GetWritingSystemDir(string projectFolder) + { + return Path.Combine(projectFolder, ksWritingSystemsDir); + } + + /// + /// Gets the path to the standard eternal linked files directory for the specified project. + /// + /// The path to the project. + /// + public static string GetDefaultLinkedFilesDir(string projectPath) + { + return Path.Combine(projectPath, ksLinkedFilesDir); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Gets the path to the standard media files directory for the specified project. Note + /// that if this project keepes its externally linked files in a separate folder from + /// the rest of the project files (such as a shared folder common to multiple projects + /// on a server), the directory returned by this method will not actually contain any + /// files. + /// + /// The path to the project. + /// ------------------------------------------------------------------------------------ + public static string GetDefaultMediaDir(string projectPath) + { + return Path.Combine(projectPath, Path.Combine(ksLinkedFilesDir, ksMediaDir)); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Gets the path to the standard pictures directory for the specified project. Note + /// that if this project keepes its externally linked files in a separate folder from + /// the rest of the project files (such as a shared folder common to multiple projects + /// on a server), the directory returned by this method will not actually contain any + /// files. + /// + /// The path to the project. + /// ------------------------------------------------------------------------------------ + public static string GetDefaultPicturesDir(string projectPath) + { + return Path.Combine(projectPath, Path.Combine(ksLinkedFilesDir, ksPicturesDir)); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Gets the path to the standard directory for other externally linked project files. + /// Note that if this project keepes its externally linked files in a separate folder + /// from the rest of the project files (such as a shared folder common to multiple + /// projects on a server), the directory returned by this method will not actually + /// contain any files. + /// + /// The path to the project. + /// ------------------------------------------------------------------------------------ + public static string GetDefaultOtherExternalFilesDir(string projectPath) + { + return Path.Combine(projectPath, Path.Combine(ksLinkedFilesDir, ksOtherLinkedFilesDir)); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Gets the path to the media files directory for the project. + /// + /// The project's LinkedFiles path. (eg. m_cache.LangProject.LinkedFilesRootDir) + /// ------------------------------------------------------------------------------------ + public static string GetMediaDir(string projectLinkedFilesPath) + { + return Path.Combine(projectLinkedFilesPath, ksMediaDir); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Gets the path to the pictures directory for the project. + /// + /// The project's LinkedFiles path. (eg. m_cache.LangProject.LinkedFilesRootDir) + /// ------------------------------------------------------------------------------------ + public static string GetPicturesDir(string projectLinkedFilesPath) + { + return Path.Combine(projectLinkedFilesPath, ksPicturesDir); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Gets the path to the directory for other externally linked project files. + /// + /// The project's LinkedFiles path. (eg. m_cache.LangProject.LinkedFilesRootDir) + /// ------------------------------------------------------------------------------------ + public static string GetOtherExternalFilesDir(string projectLinkedFilesPath) + { + return Path.Combine(projectLinkedFilesPath, ksOtherLinkedFilesDir); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Gets the name of the XML data file, given a project name (basically just adds the + /// FW data XML file extension). + /// + /// Name of the project (not a filename). + /// ------------------------------------------------------------------------------------ + public static string GetXmlDataFileName(string projectName) + { + Debug.Assert(Path.GetExtension(projectName) != ksFwDataXmlFileExtension, + String.Format("There is a faint chance the user might have specified a real project name ending in {0} (in which case, sorry, but we're going to trim it off), but probably this is a programming error", ksFwDataXmlFileExtension)); + // Do not use Path.ChangeExtension because it will strip off anything following a period in the project name! + return projectName.EndsWith(ksFwDataXmlFileExtension) ? projectName : + projectName + ksFwDataXmlFileExtension; + } + + /// ------------------------------------------------------------------------------------ + /// + /// Gets the name of the DB4O data file, given a project name (basically just adds the + /// FW db4o file extension). + /// + /// Name of the project (not a filename). + /// ------------------------------------------------------------------------------------ + public static string GetDb4oDataFileName(string projectName) + { + Debug.Assert(Path.GetExtension(projectName) != ksFwDataDb4oFileExtension, + String.Format("There is a faint chance the user might have specified a real project name ending in {0} (in which case, sorry, but we're going to trim it off), but probably this is a programming error", ksFwDataDb4oFileExtension)); + // Do not use Path.ChangeExtension because it will strip off anything following a period in the project name! + return projectName.EndsWith(ksFwDataDb4oFileExtension) ? projectName : + projectName + ksFwDataDb4oFileExtension; + } } } diff --git a/Src/FDO/FdoFileHelperRelativePaths.cs b/Src/FDO/FdoFileHelperRelativePaths.cs new file mode 100644 index 0000000000..c164b8f88f --- /dev/null +++ b/Src/FDO/FdoFileHelperRelativePaths.cs @@ -0,0 +1,299 @@ +// -------------------------------------------------------------------------------------------- +#region // Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Distributable under the terms of either the Common Public License or the +// GNU Lesser General Public License, as specified in the LICENSING.txt file. +// +#endregion +// -------------------------------------------------------------------------------------------- +using System; +using System.IO; +using SIL.FieldWorks.Common.FwUtils; +using SIL.Utils; + +namespace SIL.FieldWorks.FDO +{ + /// + /// This class is designed for converting between relative paths and full paths for the LinkedFiles of a FW project + /// + public class FdoFileHelperRelativePaths + { + /// Substitution string for a path that is under the LinkedFiles directory. + public const string ksLFrelPath = "%lf%"; + /// Substitution string for a path that is under the project's directory. + public const string ksProjectRelPath = "%proj%"; + /// Substitution string for a path that is under the default directory for projects. + public const string ksProjectsRelPath = "%Projects%"; + /// Substitution string for a path that is under the My Documents directory. + public const string ksMyDocsRelPath = "%MyDocuments%"; + /// Substitution string for a path that is under the Shared Application Data directory. + public const string ksCommonAppDataRelPath = "%CommonApplicationData%"; + + #region Methods to covert between RelativePaths and FullPaths + + /// + /// If a filePath is stored in the format %lf%\path\filename then this method returns the full path. + /// Otherwise return null + /// + /// + /// + /// + public static String GetFullFilePathFromRelativeLFPath(string relativePath, string projectLinkedFilesPath) + { + String fullfilePath = null; + fullfilePath = GetFullPathForRelativePath(relativePath, ksLFrelPath, projectLinkedFilesPath); + + if (String.IsNullOrEmpty(fullfilePath)) + return null; + return FixPathSlashesIfNeeded(fullfilePath); + } + + /// + /// If a file path is non rooted then return combination of the linkedFiledRootDir and the relative + /// path. Otherwise just return the full path passed in as an arguement. + /// + /// + /// + /// + public static String GetFullPathFromRelativeLFPath(string relativeLFPath, string linkedFilesRootDir) + { + // We could just catch the exception that IsPathRooted throws if there are invalid characters, + // or use Path.GetInvalidPathChars(). But that would pass things on Linux that will fail on Windows, + // which both makes unit testing difficult, and also may hide from Linux users the fact that their + // paths will cause problems on Windows. + var invalidChars = MiscUtils.GetInvalidProjectNameChars(MiscUtils.FilenameFilterStrength.kFilterProjName); + // relativeLFPath is allowed to include directories. And it MAY be rooted, meaning on Windows it could start X: + invalidChars = invalidChars.Replace(@"\", "").Replace("/", "").Replace(":", ""); + // colon is allowed only as second character--such a path is probably no good on Linux, but will just be not found, not cause a crash + int indexOfColon = relativeLFPath.IndexOf(':'); + if (relativeLFPath.IndexOfAny(invalidChars.ToCharArray()) != -1 + || (indexOfColon != -1 && indexOfColon != 1)) + { + // This is a fairly clumsy solution, designed as a last-resort way to avoid crashing the program. + // Hopefully most paths for entering path names into the relevant fields do something nicer to + // avoid getting illegal characters there. + return FixPathSlashesIfNeeded(Path.Combine(linkedFilesRootDir, "__ILLEGALCHARS__")); + } + if (Path.IsPathRooted(relativeLFPath)) + return FixPathSlashesIfNeeded(relativeLFPath); + else + return FixPathSlashesIfNeeded(Path.Combine(linkedFilesRootDir, relativeLFPath)); + } + + /// + /// If a path gets stored with embedded \, fix it to work away from Windows. (FWNX-882) + /// + public static string FixPathSlashesIfNeeded(string path) + { + if (string.IsNullOrEmpty(path)) + return string.Empty; + if (MiscUtils.IsUnix || MiscUtils.IsMac) + { + if (path.Contains("\\")) + return path.Replace('\\', '/'); + } + return path; + } + + /// + /// If the path is relative to the project's linkedFiles path then substitute %lf% + /// and return it. Otherwise return an empty string + /// + /// + /// + /// + public static string GetRelativeLFPathFromFullFilePath(string filePath, + string projectLinkedFilesPath) + { + if (string.IsNullOrEmpty(projectLinkedFilesPath)) + return string.Empty; + + var linkedFilesPathLowercaseRoot = GetPathWithLowercaseRoot(filePath); + + var relativePath = GetRelativePathIfExists(ksLFrelPath, linkedFilesPathLowercaseRoot, + projectLinkedFilesPath); + if (!string.IsNullOrEmpty(relativePath)) + return FixPathSlashesIfNeeded(relativePath); + //Just return an empty path if we cannot find a relative path. + return string.Empty; + } + + /// + /// If the specified path starts with the LinkedFiles root directory then return + /// the part after the linkedFilesRootDir; + /// otherwise if it is a file path at all convert it to the current platform and return it; + /// otherwise (it's a URL, determined by containing a colon after more than one initial character) + /// return null to indicate no change made. + /// + /// + /// + /// + public static string GetRelativeLinkedFilesPath(string filePath, + string linkedFilesRootDir) + { + if (filePath.IndexOf(':') > 1) + { + // It's a URL, not a path at all; don't mess with it. + return null; + } + string directory = FileUtils.ChangePathToPlatform(linkedFilesRootDir); + string relativePath = FileUtils.ChangePathToPlatform(filePath); + + // Does the specified path start with the LinkedFiles root directory? + if (relativePath.StartsWith(directory, true, System.Globalization.CultureInfo.InvariantCulture) && + relativePath.Length > directory.Length + 1) + { + // Keep the portion of the specified path that is a subfolder of + // the LinkedFiles folder and make sure to strip off an initial + // path separator if there is one. + relativePath = relativePath.Substring(directory.Length); + if (relativePath[0] == Path.DirectorySeparatorChar) + relativePath = relativePath.Substring(1); + } + return FixPathSlashesIfNeeded(relativePath); + } + + + /// + /// Return the fullPath for a project's LinkedFiles based on the relative path that was persisted. + /// If no match on a relativePath match is made then return the relativePath passed in assuming it + /// is actually a full path. + /// + /// + /// + /// + public static String GetLinkedFilesFullPathFromRelativePath(string relativePath, String projectPath) + { + String fullPath = null; + fullPath = GetFullPathForRelativePath(relativePath, ksProjectRelPath, projectPath); + + if (String.IsNullOrEmpty(fullPath)) + fullPath = GetFullPathForRelativePath(relativePath, ksProjectsRelPath, + DirectoryFinder.ProjectsDirectory); + if (String.IsNullOrEmpty(fullPath)) + fullPath = GetFullPathForRelativePath(relativePath, ksCommonAppDataRelPath, + DirectoryFinder.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)); + if (String.IsNullOrEmpty(fullPath)) + fullPath = GetFullPathForRelativePath(relativePath, ksMyDocsRelPath, + DirectoryFinder.GetFolderPath(Environment.SpecialFolder.MyDocuments)); + if (String.IsNullOrEmpty(fullPath)) + return FixPathSlashesIfNeeded(relativePath); + return FixPathSlashesIfNeeded(fullPath); + } + + private static String GetFullPathForRelativePath(String relativePath, String relativePart, String fullPathReplacement) + { + if (relativePath.StartsWith(relativePart)) + { + var length = relativePart.Length; + var restOfPath = relativePath.Substring(length, relativePath.Length - length); + return fullPathReplacement + restOfPath; + } + else + { + return string.Empty; + } + } + + /// + /// Get a relative path for the LinkedFilesPath which we will persist to be used when + /// restoring a project. + /// + /// + /// + /// + /// + public static string GetLinkedFilesRelativePathFromFullPath(string linkedFilesFullPath, + string projectPath, string projectName) + { + var linkedFilesPathLowercaseRoot = GetPathWithLowercaseRoot(linkedFilesFullPath); + // Case where the ExternalLinks folder is located somewhere under the project folder. + // This is the default location. + var relativePath = GetRelativePathIfExists(ksProjectRelPath, linkedFilesPathLowercaseRoot, + projectPath); + if (!string.IsNullOrEmpty(relativePath)) + return FixPathSlashesIfNeeded(relativePath); + // GetRelativePathIfExists may miss a case where, say, projectPath is + // \\ls-thomson-0910.dallas.sil.org\Projects\MyProj, and linkedFilesFullPath is + // C:\Documents and settings\All Users\SIL\FieldWorks\Projects\MyProj\LinkedFiles + // Even though the MyProj directory in both paths is the same directory. + // It's important to catch this case and return a relative path. + var projectFolderName = Path.GetFileName(projectPath); + var projectsPath = Path.GetDirectoryName(projectPath); + var allProjectsName = Path.GetFileName(projectsPath); + var match = Path.Combine(allProjectsName, projectFolderName); + int index = linkedFilesFullPath.IndexOf(match, StringComparison.InvariantCultureIgnoreCase); + if (index >= 0) + { + // There's a very good chance these are the same folders! + var alternateProjectPath = linkedFilesFullPath.Substring(0, index + match.Length); + if (Directory.Exists(alternateProjectPath) && + Directory.GetLastWriteTime(alternateProjectPath) == Directory.GetLastWriteTime(projectPath)) + { + // They ARE the same directory! (I suppose we could miss if someone wrote to it at the + // exact wrong moment, but we shouldn't be changing this setting while shared, anyway.) + return FixPathSlashesIfNeeded(ksProjectRelPath + linkedFilesFullPath.Substring(index + match.Length)); + } + } + + //See if linkedFilesPath begins with one of the other standard paths. + + // Case where user is presumably having a LinkedFiles folder shared among a number + // of projects under the Projects folder. That would be a good reason to put it in + // the projects folder common to all projects. + relativePath = GetRelativePathIfExists(ksProjectsRelPath, linkedFilesPathLowercaseRoot, + DirectoryFinder.ProjectsDirectory); + if (!String.IsNullOrEmpty(relativePath)) + return FixPathSlashesIfNeeded(relativePath); + + // Case where the user has the LinkedFiles folder in a shared folder. + relativePath = GetRelativePathIfExists(ksCommonAppDataRelPath, + linkedFilesPathLowercaseRoot, DirectoryFinder.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)); + if (!string.IsNullOrEmpty(relativePath)) + return FixPathSlashesIfNeeded(relativePath); + + // Case where the user has the LinkedFiles folder in their MyDocuments folder + relativePath = GetRelativePathIfExists(ksMyDocsRelPath, + linkedFilesPathLowercaseRoot, + DirectoryFinder.GetFolderPath(Environment.SpecialFolder.MyDocuments)); + if (!string.IsNullOrEmpty(relativePath)) + return FixPathSlashesIfNeeded(relativePath); + + //Just return the complete path if we cannot find a relative path. + return FixPathSlashesIfNeeded(linkedFilesFullPath); + } + + private static string GetRelativePathIfExists(string relativePart, string fullPath, + string parentPath) + { + var parentPathLowerCaseRoot = GetPathWithLowercaseRoot(parentPath); + if (!string.IsNullOrEmpty(parentPathLowerCaseRoot) && + fullPath.StartsWith(parentPathLowerCaseRoot)) + { + var length = parentPath.Length; + var restOfPath = fullPath.Substring(length, fullPath.Length - length); + return relativePart + restOfPath; + } + return string.Empty; + } + + private static string GetPathWithLowercaseRoot(string path) + { + try + { + var rootOfPath = Path.GetPathRoot(path); + return rootOfPath.ToLowerInvariant() + + path.Substring(rootOfPath.Length, path.Length - rootOfPath.Length); + } + catch (ArgumentException e) + { + return path.ToLowerInvariant(); + } + } + + + #endregion + } +} \ No newline at end of file diff --git a/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs b/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs index 1a2b8d5af3..0317b1365d 100644 --- a/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs @@ -604,8 +604,8 @@ public override bool RenameDatabase(string sNewProjectName) } string oldProjectFolder = Path.Combine(DirectoryFinder.ProjectsDirectory, ProjectId.Name); - string oldFile = Path.Combine(sNewProjectFolder, DirectoryFinder.GetDb4oDataFileName(ProjectId.Name)); - string newFile = Path.Combine(sNewProjectFolder, DirectoryFinder.GetDb4oDataFileName(sNewProjectName)); + string oldFile = Path.Combine(sNewProjectFolder, FdoFileHelper.GetDb4oDataFileName(ProjectId.Name)); + string newFile = Path.Combine(sNewProjectFolder, FdoFileHelper.GetDb4oDataFileName(sNewProjectName)); try { diff --git a/Src/FDO/Infrastructure/Impl/Db4oServerInfo.cs b/Src/FDO/Infrastructure/Impl/Db4oServerInfo.cs index 6a114ed7c4..c396a7acf0 100644 --- a/Src/FDO/Infrastructure/Impl/Db4oServerInfo.cs +++ b/Src/FDO/Infrastructure/Impl/Db4oServerInfo.cs @@ -202,7 +202,7 @@ public string[] ListRunningServers() public void CreateServerFile(string projectName) { string projectDir = Path.Combine(DirectoryFinder.ProjectsDirectory, projectName); - string newFilename = Path.Combine(projectDir, DirectoryFinder.GetDb4oDataFileName(projectName)); + string newFilename = Path.Combine(projectDir, FdoFileHelper.GetDb4oDataFileName(projectName)); // Ensure directory exists. Directory.CreateDirectory(projectDir); diff --git a/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs b/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs index badd7ca750..2945a5c2ad 100644 --- a/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs @@ -550,7 +550,7 @@ private void InitializeWritingSystemManager() return; var globalStore = new GlobalFileWritingSystemStore(DirectoryFinder.GlobalWritingSystemStoreDirectory); - string storePath = Path.Combine(ProjectId.SharedProjectFolder, DirectoryFinder.ksWritingSystemsDir); + string storePath = Path.Combine(ProjectId.SharedProjectFolder, FdoFileHelper.ksWritingSystemsDir); var wsManager = (PalasoWritingSystemManager)m_cache.ServiceLocator.WritingSystemManager; wsManager.GlobalWritingSystemStore = globalStore; wsManager.LocalWritingSystemStore = new LocalFileWritingSystemStore(storePath, globalStore); diff --git a/Src/FDO/fdoCache.cs b/Src/FDO/fdoCache.cs index e1f265195a..8b0274a4aa 100644 --- a/Src/FDO/fdoCache.cs +++ b/Src/FDO/fdoCache.cs @@ -470,7 +470,7 @@ public static string CreateNewLangProj(IThreadedProgress progressDlg, params obj // Make sure that the new project has all the writing systems actually used by the // default data. See FWR-1774. - AddMissingWritingSystems(Path.Combine(DirectoryFinder.TemplateDirectory, DirectoryFinder.GetXmlDataFileName("NewLangProj")), + AddMissingWritingSystems(Path.Combine(DirectoryFinder.TemplateDirectory, FdoFileHelper.GetXmlDataFileName("NewLangProj")), cache.ServiceLocator.WritingSystemManager); AddMissingWritingSystems(Path.Combine(DirectoryFinder.TemplateDirectory, "POS.xml"), cache.ServiceLocator.WritingSystemManager); @@ -487,7 +487,7 @@ public static string CreateNewLangProj(IThreadedProgress progressDlg, params obj { //Make sure the new project has the default location set up for the External files. cache.LanguageProject.LinkedFilesRootDir = Path.Combine(cache.ProjectId.ProjectFolder, - DirectoryFinder.ksLinkedFilesDir); + FdoFileHelper.ksLinkedFilesDir); // Set the Date Created and Date Modified values. (See FWR-3189.) cache.LangProject.DateCreated = DateTime.Now; @@ -682,14 +682,14 @@ private static string CreateNewDbFile(ref string projectName) if (ProjectInfo.GetProjectInfoByName(projectName) != null) throw new ArgumentException("The specified project already exists.", "projectName"); string dbDirName = Path.Combine(DirectoryFinder.ProjectsDirectory, projectName); - string dbFileName = Path.Combine(dbDirName, DirectoryFinder.GetXmlDataFileName(projectName)); + string dbFileName = Path.Combine(dbDirName, FdoFileHelper.GetXmlDataFileName(projectName)); try { Directory.CreateDirectory(dbDirName); CreateProjectSubfolders(dbDirName); // Make a copy of the template database that will become the new database File.Copy(Path.Combine(DirectoryFinder.TemplateDirectory, - DirectoryFinder.GetXmlDataFileName("NewLangProj")), dbFileName, false); + FdoFileHelper.GetXmlDataFileName("NewLangProj")), dbFileName, false); File.SetAttributes(dbFileName, FileAttributes.Normal); // Change the LangProject Guid to a new one to make it unique between projects, so Lift Bridge won't get cross with FLEx. @@ -725,14 +725,14 @@ internal static void CreateProjectSubfolders(string dbDirName) { try { - Directory.CreateDirectory(DirectoryFinder.GetBackupSettingsDir(dbDirName)); - Directory.CreateDirectory(DirectoryFinder.GetConfigSettingsDir(dbDirName)); - Directory.CreateDirectory(DirectoryFinder.GetSupportingFilesDir(dbDirName)); - Directory.CreateDirectory(DirectoryFinder.GetDefaultMediaDir(dbDirName)); - Directory.CreateDirectory(DirectoryFinder.GetDefaultPicturesDir(dbDirName)); - Directory.CreateDirectory(DirectoryFinder.GetDefaultOtherExternalFilesDir(dbDirName)); - Directory.CreateDirectory(Path.Combine(dbDirName, DirectoryFinder.ksSortSequenceTempDir)); - Directory.CreateDirectory(DirectoryFinder.GetWritingSystemDir(dbDirName)); + Directory.CreateDirectory(FdoFileHelper.GetBackupSettingsDir(dbDirName)); + Directory.CreateDirectory(FdoFileHelper.GetConfigSettingsDir(dbDirName)); + Directory.CreateDirectory(FdoFileHelper.GetSupportingFilesDir(dbDirName)); + Directory.CreateDirectory(FdoFileHelper.GetDefaultMediaDir(dbDirName)); + Directory.CreateDirectory(FdoFileHelper.GetDefaultPicturesDir(dbDirName)); + Directory.CreateDirectory(FdoFileHelper.GetDefaultOtherExternalFilesDir(dbDirName)); + Directory.CreateDirectory(Path.Combine(dbDirName, FdoFileHelper.ksSortSequenceTempDir)); + Directory.CreateDirectory(FdoFileHelper.GetWritingSystemDir(dbDirName)); } catch (Exception e) { diff --git a/Src/FwCoreDlgs/BackupRestore/BackupProjectPresenter.cs b/Src/FwCoreDlgs/BackupRestore/BackupProjectPresenter.cs index 61dce80548..119b2ea89e 100644 --- a/Src/FwCoreDlgs/BackupRestore/BackupProjectPresenter.cs +++ b/Src/FwCoreDlgs/BackupRestore/BackupProjectPresenter.cs @@ -43,7 +43,7 @@ internal BackupProjectPresenter(IBackupProjectView backupProjectView, string app m_backupProjectView = backupProjectView; //Older projects might not have this folder so when launching the backup dialog we want to create it. - Directory.CreateDirectory(DirectoryFinder.GetSupportingFilesDir(m_cache.ProjectId.ProjectFolder)); + Directory.CreateDirectory(FdoFileHelper.GetSupportingFilesDir(m_cache.ProjectId.ProjectFolder)); } /// @@ -53,7 +53,7 @@ internal String PersistanceFilePath { get { - return Path.Combine(DirectoryFinder.GetBackupSettingsDir(m_cache.ProjectId.ProjectFolder), + return Path.Combine(FdoFileHelper.GetBackupSettingsDir(m_cache.ProjectId.ProjectFolder), DirectoryFinder.kBackupSettingsFilename); } } @@ -65,7 +65,7 @@ internal bool SupportingFilesFolderContainsFiles { get { - var supportingFilesFolder = DirectoryFinder.GetSupportingFilesDir(m_cache.ProjectId.ProjectFolder); + var supportingFilesFolder = FdoFileHelper.GetSupportingFilesDir(m_cache.ProjectId.ProjectFolder); var files = ProjectBackupService.GenerateFileListFolderAndSubfolders(supportingFilesFolder); if (files.Count > 0) return true; diff --git a/Src/FwCoreDlgs/FwCoreDlgsTests/FwNewLangProjectTests.cs b/Src/FwCoreDlgs/FwCoreDlgsTests/FwNewLangProjectTests.cs index 837cc1f6ce..89f880a0de 100644 --- a/Src/FwCoreDlgs/FwCoreDlgsTests/FwNewLangProjectTests.cs +++ b/Src/FwCoreDlgs/FwCoreDlgsTests/FwNewLangProjectTests.cs @@ -122,7 +122,7 @@ public class FwNewLangProjectTests: BaseTest public void CreateNewLangProject() { const string dbName = "Maileingwij2025"; - string storePath = DirectoryFinder.GetWritingSystemDir(Path.Combine(DirectoryFinder.ProjectsDirectory, dbName)); + string storePath = FdoFileHelper.GetWritingSystemDir(Path.Combine(DirectoryFinder.ProjectsDirectory, dbName)); string sharedStorePath = DirectoryFinder.GlobalWritingSystemStoreDirectory; using (var dlg = new DummyFwNewLangProject()) @@ -371,7 +371,7 @@ private static string DbDirectory(string dbName) private static string DbFilename(string dbName) { - return Path.Combine(DbDirectory(dbName), DirectoryFinder.GetXmlDataFileName(dbName)); + return Path.Combine(DbDirectory(dbName), FdoFileHelper.GetXmlDataFileName(dbName)); } /// ------------------------------------------------------------------------------------ diff --git a/Src/FwCoreDlgs/FwDeleteProjectDlg.cs b/Src/FwCoreDlgs/FwDeleteProjectDlg.cs index 6095b1197b..6685accd83 100644 --- a/Src/FwCoreDlgs/FwDeleteProjectDlg.cs +++ b/Src/FwCoreDlgs/FwDeleteProjectDlg.cs @@ -308,16 +308,16 @@ private void m_btnDelete_Click(object sender, System.EventArgs e) path = Path.ChangeExtension(path, FdoFileHelper.ksFwDataFallbackFileExtension); if (File.Exists(path)) File.Delete(path); - path = Path.Combine(folder, DirectoryFinder.ksWritingSystemsDir); + path = Path.Combine(folder, FdoFileHelper.ksWritingSystemsDir); if (Directory.Exists(path)) Directory.Delete(path, true); - path = Path.Combine(folder, DirectoryFinder.ksBackupSettingsDir); + path = Path.Combine(folder, FdoFileHelper.ksBackupSettingsDir); if (Directory.Exists(path)) Directory.Delete(path, true); - path = Path.Combine(folder, DirectoryFinder.ksConfigurationSettingsDir); + path = Path.Combine(folder, FdoFileHelper.ksConfigurationSettingsDir); if (Directory.Exists(path)) Directory.Delete(path, true); - path = Path.Combine(folder, DirectoryFinder.ksSortSequenceTempDir); + path = Path.Combine(folder, FdoFileHelper.ksSortSequenceTempDir); if (Directory.Exists(path)) Directory.Delete(path, true); string[] folders = Directory.GetDirectories(folder); @@ -345,10 +345,10 @@ private static bool CheckForExtraData(ProjectInfo info, string folder) foreach (string dir in folders) { string name = Path.GetFileName(dir); - if (name == DirectoryFinder.ksWritingSystemsDir || - name == DirectoryFinder.ksBackupSettingsDir || - name == DirectoryFinder.ksConfigurationSettingsDir || - name == DirectoryFinder.ksSortSequenceTempDir) + if (name == FdoFileHelper.ksWritingSystemsDir || + name == FdoFileHelper.ksBackupSettingsDir || + name == FdoFileHelper.ksConfigurationSettingsDir || + name == FdoFileHelper.ksSortSequenceTempDir) { continue; } diff --git a/Src/FwCoreDlgs/FwProjPropertiesDlg.cs b/Src/FwCoreDlgs/FwProjPropertiesDlg.cs index fc1404a22b..280902d08c 100644 --- a/Src/FwCoreDlgs/FwProjPropertiesDlg.cs +++ b/Src/FwCoreDlgs/FwProjPropertiesDlg.cs @@ -186,7 +186,7 @@ public FwProjPropertiesDlg(FdoCache cache, IApp app, IHelpTopicProvider helpTopi txtExtLnkEdit.Enabled = false; } - m_defaultLinkedFilesFolder = DirectoryFinder.GetDefaultLinkedFilesDir(m_cache.ServiceLocator.DataSetup.ProjectId.ProjectFolder); + m_defaultLinkedFilesFolder = FdoFileHelper.GetDefaultLinkedFilesDir(m_cache.ServiceLocator.DataSetup.ProjectId.ProjectFolder); } /// ------------------------------------------------------------------------------------ @@ -1452,7 +1452,7 @@ private void WarnOnNonDefaultLinkedFilesChange() private string HandleLinkedFilesPathDoesNotExist(string linkedFilesPath) { - var defaultLinkedFilesPath = DirectoryFinder.GetDefaultLinkedFilesDir(m_cache.ProjectId.ProjectFolder); + var defaultLinkedFilesPath = FdoFileHelper.GetDefaultLinkedFilesDir(m_cache.ProjectId.ProjectFolder); if (!Directory.Exists(linkedFilesPath) && linkedFilesPath.Equals(defaultLinkedFilesPath)) { //if the path points to the default location but does not exist then create it. diff --git a/Src/FwCoreDlgs/MoveOrCopyFilesDlg.cs b/Src/FwCoreDlgs/MoveOrCopyFilesDlg.cs index 618d9eeff8..4064e454a3 100644 --- a/Src/FwCoreDlgs/MoveOrCopyFilesDlg.cs +++ b/Src/FwCoreDlgs/MoveOrCopyFilesDlg.cs @@ -314,7 +314,7 @@ public static string MoveCopyOrLeaveMediaFile(string sFile, string sRootDirLinke IHelpTopicProvider helpTopicProvider, bool isLocal) { return MoveCopyOrLeaveFile(sFile, - Path.Combine(sRootDirLinkedFiles, DirectoryFinder.ksMediaDir), + Path.Combine(sRootDirLinkedFiles, FdoFileHelper.ksMediaDir), sRootDirLinkedFiles, helpTopicProvider, isLocal); } @@ -339,7 +339,7 @@ public static string MoveCopyOrLeaveExternalFile(string sFile, string sRootDirLi IHelpTopicProvider helpTopicProvider, bool isLocal) { return MoveCopyOrLeaveFile(sFile, - Path.Combine(sRootDirLinkedFiles, DirectoryFinder.ksOtherLinkedFilesDir), + Path.Combine(sRootDirLinkedFiles, FdoFileHelper.ksOtherLinkedFilesDir), sRootDirLinkedFiles, helpTopicProvider, isLocal); } diff --git a/Src/FwCoreDlgs/ProjectLocationSharingDlg.cs b/Src/FwCoreDlgs/ProjectLocationSharingDlg.cs index 90ab0a570b..236a7db04e 100644 --- a/Src/FwCoreDlgs/ProjectLocationSharingDlg.cs +++ b/Src/FwCoreDlgs/ProjectLocationSharingDlg.cs @@ -97,7 +97,7 @@ private void m_tbProjectsFolder_TextChanged(object sender, EventArgs e) { string path = m_tbProjectsFolder.Text; // If it contains a settings directory, assume it's a project settings folder...possibly settings for a remote project. - if (Directory.Exists(Path.Combine(path, DirectoryFinder.ksConfigurationSettingsDir))) + if (Directory.Exists(Path.Combine(path, FdoFileHelper.ksConfigurationSettingsDir))) { m_btnOK.Enabled = false; return; diff --git a/Src/LexText/LexTextControls/LexTextControlsTests/LiftExportTests.cs b/Src/LexText/LexTextControls/LexTextControlsTests/LiftExportTests.cs index e362ee2c0f..6955233333 100644 --- a/Src/LexText/LexTextControls/LexTextControlsTests/LiftExportTests.cs +++ b/Src/LexText/LexTextControls/LexTextControlsTests/LiftExportTests.cs @@ -491,7 +491,7 @@ public void CreateMockCache() var mockProjectPath = Path.Combine(MockProjectFolder, mockProjectName + ".fwdata"); m_cache = FdoCache.CreateCacheWithNewBlankLangProj( new TestProjectId(FDOBackendProviderType.kMemoryOnly, mockProjectPath), "en", "fr", "en", new DummyFdoUI()); - MockLinkedFilesFolder = Path.Combine(MockProjectFolder, DirectoryFinder.ksLinkedFilesDir); + MockLinkedFilesFolder = Path.Combine(MockProjectFolder, FdoFileHelper.ksLinkedFilesDir); Directory.CreateDirectory(MockLinkedFilesFolder); //m_cache.LangProject.LinkedFilesRootDir = MockLinkedFilesFolder; this is already the default. @@ -600,7 +600,7 @@ private void AddLexEntries() var tssDefn = m_cache.TsStrFactory.MakeString("Definition for sense.\x2028Another para of defn", m_cache.DefaultAnalWs); var bldr = tssDefn.GetBldr(); int len = bldr.Length; - var otherFileFolder = Path.Combine(MockLinkedFilesFolder, DirectoryFinder.ksOtherLinkedFilesDir); + var otherFileFolder = Path.Combine(MockLinkedFilesFolder, FdoFileHelper.ksOtherLinkedFilesDir); var otherFilePath = Path.Combine(otherFileFolder, kotherLinkedFileName); CreateDummyFile(otherFilePath); var mockStyle = new MockStyle() { Name = "hyperlink" }; @@ -657,7 +657,7 @@ private void AddLexEntries() MakePicture(picFolder, m_tempPictureFilePath); // See if we can export audio writing system stuff. - var audioFolderPath = Path.Combine(MockLinkedFilesFolder, DirectoryFinder.ksMediaDir); + var audioFolderPath = Path.Combine(MockLinkedFilesFolder, FdoFileHelper.ksMediaDir); CreateDummyFile(Path.Combine(audioFolderPath, kaudioFileName)); m_entryTest.SensesOS[0].Definition.set_String(m_audioWsCode, kaudioFileName); @@ -680,7 +680,7 @@ private void AddLexEntries() var pronunFile = m_cache.ServiceLocator.GetInstance().Create(); picFolder.FilesOC.Add(pronunFile); // maybe not quite appropriate, but has to be owned somewhere. media.MediaFileRA = pronunFile; - pronunFile.InternalPath = Path.Combine(DirectoryFinder.ksMediaDir, kpronunciationFileName); + pronunFile.InternalPath = Path.Combine(FdoFileHelper.ksMediaDir, kpronunciationFileName); // We should be able to export LexEntryRefs. BaseForm is a special case. var entryUn = entryFact.Create("un", "not", new SandboxGenericMSA() { MsaType = MsaType.kDeriv }); diff --git a/Src/LexText/LexTextControls/LexTextControlsTests/LiftMergerTests.cs b/Src/LexText/LexTextControls/LexTextControlsTests/LiftMergerTests.cs index cbf8c9741a..b29f905f84 100644 --- a/Src/LexText/LexTextControls/LexTextControlsTests/LiftMergerTests.cs +++ b/Src/LexText/LexTextControls/LexTextControlsTests/LiftMergerTests.cs @@ -66,7 +66,7 @@ public override void TestSetup() var mockProjectName = "xxyyzProjectFolderForLIFTImport"; MockProjectFolder = Path.Combine(Path.GetTempPath(), mockProjectName); var mockProjectPath = Path.Combine(MockProjectFolder, mockProjectName + ".fwdata"); - MockLinkedFilesFolder = Path.Combine(MockProjectFolder, DirectoryFinder.ksLinkedFilesDir); + MockLinkedFilesFolder = Path.Combine(MockProjectFolder, FdoFileHelper.ksLinkedFilesDir); if (Directory.Exists(MockLinkedFilesFolder)) Directory.Delete(MockLinkedFilesFolder, true); Directory.CreateDirectory(MockLinkedFilesFolder); @@ -346,18 +346,18 @@ public void TestLiftImport1() } Assert.That(sense0.PicturesOS.Count, Is.EqualTo(2)); - Assert.That(sense0.PicturesOS[0].PictureFileRA.InternalPath, Is.EqualTo(Path.Combine(DirectoryFinder.ksPicturesDir, "Desert.jpg"))); - Assert.That(sense0.PicturesOS[1].PictureFileRA.InternalPath, Is.EqualTo(Path.Combine(DirectoryFinder.ksPicturesDir, myPicRelativePath))); - VerifyLinkedFileExists(DirectoryFinder.ksPicturesDir, "Desert.jpg"); - VerifyLinkedFileExists(DirectoryFinder.ksPicturesDir, myPicRelativePath); + Assert.That(sense0.PicturesOS[0].PictureFileRA.InternalPath, Is.EqualTo(Path.Combine(FdoFileHelper.ksPicturesDir, "Desert.jpg"))); + Assert.That(sense0.PicturesOS[1].PictureFileRA.InternalPath, Is.EqualTo(Path.Combine(FdoFileHelper.ksPicturesDir, myPicRelativePath))); + VerifyLinkedFileExists(FdoFileHelper.ksPicturesDir, "Desert.jpg"); + VerifyLinkedFileExists(FdoFileHelper.ksPicturesDir, myPicRelativePath); Assert.That(entry.PronunciationsOS.Count, Is.EqualTo(1)); Assert.That(entry.PronunciationsOS[0].MediaFilesOS[0].MediaFileRA.InternalPath, - Is.EqualTo(Path.Combine(DirectoryFinder.ksMediaDir, "Sleep Away.mp3"))); - VerifyLinkedFileExists(DirectoryFinder.ksMediaDir, "Sleep Away.mp3"); - VerifyLinkedFileExists(DirectoryFinder.ksMediaDir, "hombre634407358826681759.wav"); - VerifyLinkedFileExists(DirectoryFinder.ksMediaDir, "male adult634407358826681760.wav"); - VerifyLinkedFileExists(DirectoryFinder.ksOtherLinkedFilesDir, "SomeFile.txt"); + Is.EqualTo(Path.Combine(FdoFileHelper.ksMediaDir, "Sleep Away.mp3"))); + VerifyLinkedFileExists(FdoFileHelper.ksMediaDir, "Sleep Away.mp3"); + VerifyLinkedFileExists(FdoFileHelper.ksMediaDir, "hombre634407358826681759.wav"); + VerifyLinkedFileExists(FdoFileHelper.ksMediaDir, "male adult634407358826681760.wav"); + VerifyLinkedFileExists(FdoFileHelper.ksOtherLinkedFilesDir, "SomeFile.txt"); Assert.IsTrue(repoEntry.TryGetObject(new Guid("766aaee2-34b6-4e28-a883-5c2186125a2f"), out entry)); Assert.AreEqual(1, entry.SensesOS.Count); diff --git a/Src/LexText/LexTextControls/LiftExporter.cs b/Src/LexText/LexTextControls/LiftExporter.cs index 0d95fdd456..8da96a44a5 100644 --- a/Src/LexText/LexTextControls/LiftExporter.cs +++ b/Src/LexText/LexTextControls/LiftExporter.cs @@ -313,7 +313,7 @@ private void WriteCustomFields(TextWriter w, ICmObject obj) var internalPath = tssString.Text; // usually this will be unchanged, but it is pathologically possible that the file name conflicts. var exportedForm = ExportFile(internalPath, - Path.Combine(DirectoryFinder.GetMediaDir(m_cache.LangProject.LinkedFilesRootDir), internalPath), + Path.Combine(FdoFileHelper.GetMediaDir(m_cache.LangProject.LinkedFilesRootDir), internalPath), "audio"); if (internalPath != exportedForm) tssString = m_cache.TsStrFactory.MakeString(exportedForm, ws); @@ -542,7 +542,7 @@ private void WriteMediaFile(TextWriter w, ICmMedia file) return; w.Write(""); @@ -818,7 +818,7 @@ private void WriteCmPicture(TextWriter w, ICmPicture picture) if (picture.PictureFileRA != null) { ExportFile(w, picture.PictureFileRA.InternalPath, picture.PictureFileRA.AbsoluteInternalPath, - "pictures", DirectoryFinder.ksPicturesDir); + "pictures", FdoFileHelper.ksPicturesDir); } w.WriteLine("\">"); WriteAllForms(w, "label", null, "form", picture.Caption); @@ -1355,7 +1355,7 @@ private void WriteAllForms(TextWriter w, string wrappingElementName, string attr var internalPath = sForm; // usually this will be unchanged, but it is pathologically possible that the file name conflicts. sForm = ExportFile(internalPath, - Path.Combine(DirectoryFinder.GetMediaDir(m_cache.LangProject.LinkedFilesRootDir), internalPath), + Path.Combine(FdoFileHelper.GetMediaDir(m_cache.LangProject.LinkedFilesRootDir), internalPath), "audio"); } w.WriteLine("<{0} lang=\"{1}\">{2}", elementName, @@ -1406,7 +1406,7 @@ private string GetFormWithMarkers(IMoForm alt, int ws) var internalPath = alt.Form.get_String(ws).Text; // usually this will be unchanged, but it is pathologically possible that the file name conflicts. var writePath = ExportFile(internalPath, - Path.Combine(DirectoryFinder.GetMediaDir(m_cache.LangProject.LinkedFilesRootDir), internalPath), + Path.Combine(FdoFileHelper.GetMediaDir(m_cache.LangProject.LinkedFilesRootDir), internalPath), "audio"); return writePath; } @@ -1473,7 +1473,7 @@ private string ConvertTsStringToLiftXml(ITsString tssVal, int wsString) var internalPath = tssVal.Text == null ? "" : tssVal.Text; // usually this will be unchanged, but it is pathologically possible that the file name conflicts. var writePath = ExportFile(internalPath, - Path.Combine(DirectoryFinder.GetMediaDir(m_cache.LangProject.LinkedFilesRootDir), internalPath), + Path.Combine(FdoFileHelper.GetMediaDir(m_cache.LangProject.LinkedFilesRootDir), internalPath), "audio"); return XmlUtils.MakeSafeXml(writePath); } @@ -1544,7 +1544,7 @@ private void AddObjPropData(StringBuilder bldr, string sProp) var absPath = destination; if (!Path.IsPathRooted(destination)) absPath = Path.Combine(m_cache.LangProject.LinkedFilesRootDir, destination); - var writePath = ExportFile(destination, absPath, "others", DirectoryFinder.ksOtherLinkedFilesDir); + var writePath = ExportFile(destination, absPath, "others", FdoFileHelper.ksOtherLinkedFilesDir); // We force the file to be in the "others" directory, but in this case we include "others" in the URL, // so it will actually work as a URL relative to the LIFT file. bldr.AppendFormat(" href=\"file://others/{0}\"", XmlUtils.MakeSafeXmlAttribute(writePath.Replace('\\', '/'))); diff --git a/Src/LexText/LexTextControls/LiftMerger.cs b/Src/LexText/LexTextControls/LiftMerger.cs index 695abb02a5..d39eb7fbca 100644 --- a/Src/LexText/LexTextControls/LiftMerger.cs +++ b/Src/LexText/LexTextControls/LiftMerger.cs @@ -3383,7 +3383,7 @@ private string CopyPronunciationFile(string sFile) // give up and store relative path Pictures/filename (even though it doesn't exist) string sPath = Path.Combine(Path.GetDirectoryName(m_sLiftFile), String.Format("audio{0}{1}", Path.DirectorySeparatorChar, sFile)); - sPath = CopyFileToLinkedFiles(sFile, sPath, DirectoryFinder.ksMediaDir); + sPath = CopyFileToLinkedFiles(sFile, sPath, FdoFileHelper.ksMediaDir); if (!File.Exists(sPath) && !String.IsNullOrEmpty(m_cache.LangProject.LinkedFilesRootDir)) { sPath = Path.Combine(m_cache.LangProject.LinkedFilesRootDir, sFile); @@ -5610,7 +5610,7 @@ private string CopyPicture(string sFile) } string sPath = Path.Combine(Path.GetDirectoryName(m_sLiftFile), String.Format("pictures{0}{1}", Path.DirectorySeparatorChar, ssFile)); - sPath = CopyFileToLinkedFiles(ssFile, sPath, DirectoryFinder.ksPicturesDir); + sPath = CopyFileToLinkedFiles(ssFile, sPath, FdoFileHelper.ksPicturesDir); if (!File.Exists(sPath) && !String.IsNullOrEmpty(m_cache.LangProject.LinkedFilesRootDir)) { sPath = Path.Combine(m_cache.LangProject.LinkedFilesRootDir, sFile); diff --git a/Src/LexText/LexTextControls/LiftMergerSupportCodeAndClasses.cs b/Src/LexText/LexTextControls/LiftMergerSupportCodeAndClasses.cs index 3e1c50adea..7a93299e41 100644 --- a/Src/LexText/LexTextControls/LiftMergerSupportCodeAndClasses.cs +++ b/Src/LexText/LexTextControls/LiftMergerSupportCodeAndClasses.cs @@ -245,7 +245,7 @@ private void MergeInAllomorphForms(LiftMultiText forms, ITsMultiString tsm, { string sPath = Path.Combine(Path.GetDirectoryName(m_sLiftFile), String.Format("audio{0}{1}", Path.DirectorySeparatorChar, form)); - CopyFileToLinkedFiles(form, sPath, DirectoryFinder.ksMediaDir); + CopyFileToLinkedFiles(form, sPath, FdoFileHelper.ksMediaDir); } else { @@ -329,7 +329,7 @@ private void MergeInMultiString(ITsMultiString tsm, int flid, LiftMultiText form { string sPath = Path.Combine(Path.GetDirectoryName(m_sLiftFile), String.Format("audio{0}{1}", Path.DirectorySeparatorChar, tss.Text)); - CopyFileToLinkedFiles(tss.Text, sPath, DirectoryFinder.ksMediaDir); + CopyFileToLinkedFiles(tss.Text, sPath, FdoFileHelper.ksMediaDir); } } } @@ -373,7 +373,7 @@ private ITsString CreateTsStringFromLiftString(LiftString liftstr, int wsHvo) || linkPath.StartsWith("others" + Path.DirectorySeparatorChar)) { linkPath = CopyFileToLinkedFiles(linkPath.Substring("others/".Length), sPath, - DirectoryFinder.ksOtherLinkedFilesDir); + FdoFileHelper.ksOtherLinkedFilesDir); } char chOdt = Convert.ToChar((int)FwObjDataTypes.kodtExternalPathName); string sRef = chOdt.ToString() + linkPath; diff --git a/Src/LexText/Lexicon/FLExBridgeListener.cs b/Src/LexText/Lexicon/FLExBridgeListener.cs index c06b47c067..f08a9a7efb 100644 --- a/Src/LexText/Lexicon/FLExBridgeListener.cs +++ b/Src/LexText/Lexicon/FLExBridgeListener.cs @@ -294,7 +294,7 @@ public bool OnFLExBridge(object commandObject) var sLinkedFilesRootDir = app.Cache.LangProject.LinkedFilesRootDir; NonUndoableUnitOfWorkHelper.Do(app.Cache.ActionHandlerAccessor, () => { - app.Cache.LangProject.LinkedFilesRootDir = DirectoryFinder.GetDefaultLinkedFilesDir( + app.Cache.LangProject.LinkedFilesRootDir = FdoFileHelper.GetDefaultLinkedFilesDir( app.Cache.ProjectId.ProjectFolder); }); app.UpdateExternalLinks(sLinkedFilesRootDir); @@ -356,7 +356,7 @@ public bool OnFLExBridge(object commandObject) private bool LinkedFilesLocationIsDefault() { - var defaultLinkedFilesFolder = DirectoryFinder.GetDefaultLinkedFilesDir(Cache.ServiceLocator.DataSetup.ProjectId.ProjectFolder); + var defaultLinkedFilesFolder = FdoFileHelper.GetDefaultLinkedFilesDir(Cache.ServiceLocator.DataSetup.ProjectId.ProjectFolder); if (!defaultLinkedFilesFolder.Equals(Cache.LanguageProject.LinkedFilesRootDir)) return false; else diff --git a/Src/XCore/Inventory.cs b/Src/XCore/Inventory.cs index 7f09adc15c..ba59570ea1 100644 --- a/Src/XCore/Inventory.cs +++ b/Src/XCore/Inventory.cs @@ -23,7 +23,7 @@ using System.IO; using System.Collections.Generic; using System.Linq; - +using SIL.FieldWorks.FDO; using SIL.Utils; using SIL.FieldWorks.Common.FwUtils; @@ -520,7 +520,7 @@ private string[] GetParentElementNames() private string UserOverrideConfigurationSettingsPath { - get { return DirectoryFinder.GetConfigSettingsDir(m_projectPath); } + get { return FdoFileHelper.GetConfigSettingsDir(m_projectPath); } } /// diff --git a/Src/XCore/xCore.csproj b/Src/XCore/xCore.csproj index 8d92c59680..9cf3a6f26a 100644 --- a/Src/XCore/xCore.csproj +++ b/Src/XCore/xCore.csproj @@ -98,6 +98,10 @@ False ..\..\Output\Debug\BasicUtils.dll + + False + ..\..\Output\Debug\FDO.dll + False ..\..\Output\Debug\FwUtils.dll diff --git a/Src/xWorks/FwXWindow.cs b/Src/xWorks/FwXWindow.cs index 2eeefb8def..3f8ee95dcc 100644 --- a/Src/xWorks/FwXWindow.cs +++ b/Src/xWorks/FwXWindow.cs @@ -324,7 +324,7 @@ private void BasicInit(FwApp app) string path = null; if (app != null) // if configFile in FwXApp == null { - path = DirectoryFinder.GetConfigSettingsDir(app.Cache.ProjectId.ProjectFolder); + path = FdoFileHelper.GetConfigSettingsDir(app.Cache.ProjectId.ProjectFolder); Directory.CreateDirectory(path); } m_mediator.PropertyTable.UserSettingDirectory = path; @@ -419,7 +419,7 @@ protected override void RestoreProperties() /// protected override void DiscardProperties() { - var tempDirectory = Path.Combine(Cache.ProjectId.ProjectFolder, DirectoryFinder.ksSortSequenceTempDir); + var tempDirectory = Path.Combine(Cache.ProjectId.ProjectFolder, FdoFileHelper.ksSortSequenceTempDir); foreach (var pathname in Directory.GetFiles(tempDirectory, "*.fwss")) { File.Delete(pathname); diff --git a/Src/xWorks/RecordView.cs b/Src/xWorks/RecordView.cs index a32ae0dc30..938ae5933f 100644 --- a/Src/xWorks/RecordView.cs +++ b/Src/xWorks/RecordView.cs @@ -274,7 +274,7 @@ internal static string GetSortFilePersistPathname(FdoCache cache, string clerkId //(This extension is also known to ProjectRestoreService.RestoreFrom7_0AndNewerBackup.) // Also to FwXWindow.DiscardProperties(). var filenameWithExt = Path.ChangeExtension(filename, "fwss"); - var tempDirectory = Path.Combine(cache.ProjectId.ProjectFolder, DirectoryFinder.ksSortSequenceTempDir); + var tempDirectory = Path.Combine(cache.ProjectId.ProjectFolder, FdoFileHelper.ksSortSequenceTempDir); if (!Directory.Exists(tempDirectory)) Directory.CreateDirectory(tempDirectory); return Path.Combine(tempDirectory, filenameWithExt); diff --git a/Src/xWorks/XmlDocConfigureDlg.cs b/Src/xWorks/XmlDocConfigureDlg.cs index 4fd25a6d42..4666b65853 100644 --- a/Src/xWorks/XmlDocConfigureDlg.cs +++ b/Src/xWorks/XmlDocConfigureDlg.cs @@ -5096,7 +5096,7 @@ private static void UpdateLayoutName(XmlNode node, string attrName, string code) private void DeleteUnwantedConfigurations(IEnumerable viewsToDelete) { - var configDir = DirectoryFinder.GetConfigSettingsDir(m_cache.ProjectId.ProjectFolder); + var configDir = FdoFileHelper.GetConfigSettingsDir(m_cache.ProjectId.ProjectFolder); // Load in existing combobox LayoutTypeComboItems var layoutMap = LoadLayoutMapFromComboBox(); @@ -5147,7 +5147,7 @@ private void RewriteComboBoxItemsAfterDelete(Dictionary> viewsToRename) { - var configDir = DirectoryFinder.GetConfigSettingsDir(m_cache.ProjectId.ProjectFolder); + var configDir = FdoFileHelper.GetConfigSettingsDir(m_cache.ProjectId.ProjectFolder); // Load in existing combobox LayoutTypeComboItems var layoutMap = LoadLayoutMapFromComboBox(); From 93ee1d09e863188067206db713731d4471a86023 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Mon, 9 Dec 2013 14:19:56 +0700 Subject: [PATCH 031/143] Remove more FDO references to FwUtils Change-Id: I7fd14e8b13ae896fe476712c00ed120734bb6070 --- Src/Common/FwUtils/DirectoryFinder.cs | 28 ----------------- Src/FDO/DomainImpl/OverridesCellar.cs | 1 - .../BackupRestore/BackupFileSettings.cs | 2 +- .../BackupRestore/BackupSettings.cs | 1 - .../BackupRestore/ProjectRestoreService.cs | 8 ++--- .../DataMigration/DataMigration7000029.cs | 1 - .../DataMigration/DataMigration7000030.cs | 1 - .../DataMigration/DataMigration7000060.cs | 10 ------- Src/FDO/DomainServices/StringServices.cs | 1 - Src/FDO/FDOGenerate/main.vm.cs | 1 - .../ProjectBackupServiceTests.cs | 2 +- Src/FDO/FdoFileHelper.cs | 30 +++++++++++++++++++ 12 files changed, 36 insertions(+), 50 deletions(-) diff --git a/Src/Common/FwUtils/DirectoryFinder.cs b/Src/Common/FwUtils/DirectoryFinder.cs index 3ce57e49b9..f7f295910a 100644 --- a/Src/Common/FwUtils/DirectoryFinder.cs +++ b/Src/Common/FwUtils/DirectoryFinder.cs @@ -397,34 +397,6 @@ public static string GetFWCodeFile(string filename) return Path.Combine(FWCodeDirectory, filename); } - /// ------------------------------------------------------------------------------------ - /// - /// Gets the path without the root directory (i.e. make it un-rooted). - /// - /// ------------------------------------------------------------------------------------ - public static string GetPathWithoutRoot(string pathWithRoot) - { - string pathRoot = Path.GetPathRoot(pathWithRoot); - return pathWithRoot.Substring(pathRoot.Length); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Takes a windows path and returns it in the format which our backup zip files - /// stores them in. - /// - /// ------------------------------------------------------------------------------------ - public static string GetZipfileFormattedPath(string path) - { - StringBuilder strBldr = new StringBuilder(path); - string pathRoot = Path.GetPathRoot(path); - strBldr.Remove(0, pathRoot.Length); - // replace back slashes with forward slashes (for Windows) - if (!MiscUtils.IsUnix && !MiscUtils.IsMac) - strBldr.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); - return strBldr.ToString(); - } - /// ------------------------------------------------------------------------------------ /// /// Gets a subdirectory of FieldWorks either by reading the diff --git a/Src/FDO/DomainImpl/OverridesCellar.cs b/Src/FDO/DomainImpl/OverridesCellar.cs index 3b12aacec4..b702e61eed 100644 --- a/Src/FDO/DomainImpl/OverridesCellar.cs +++ b/Src/FDO/DomainImpl/OverridesCellar.cs @@ -20,7 +20,6 @@ using System.Diagnostics; using System.IO; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.Infrastructure; diff --git a/Src/FDO/DomainServices/BackupRestore/BackupFileSettings.cs b/Src/FDO/DomainServices/BackupRestore/BackupFileSettings.cs index a13518f827..2cc0fa0bdc 100644 --- a/Src/FDO/DomainServices/BackupRestore/BackupFileSettings.cs +++ b/Src/FDO/DomainServices/BackupRestore/BackupFileSettings.cs @@ -124,7 +124,7 @@ private BackupFileSettings(BackupProjectSettings settings) m_supportingFiles = settings.IncludeSupportingFiles; m_linkedFiles = settings.IncludeLinkedFiles; m_projectName = settings.ProjectName; - m_projectPathPersisted = DirectoryFinder.GetPathWithoutRoot(settings.ProjectPath); + m_projectPathPersisted = FdoFileHelper.GetPathWithoutRoot(settings.ProjectPath); m_spellCheckAdditions = settings.IncludeSpellCheckAdditions; m_dbVersion = settings.DbVersion; m_fwVersion = settings.FwVersion; diff --git a/Src/FDO/DomainServices/BackupRestore/BackupSettings.cs b/Src/FDO/DomainServices/BackupRestore/BackupSettings.cs index d9f28f8599..8c78bdec4f 100644 --- a/Src/FDO/DomainServices/BackupRestore/BackupSettings.cs +++ b/Src/FDO/DomainServices/BackupRestore/BackupSettings.cs @@ -14,7 +14,6 @@ using System; using System.IO; using SIL.Utils; -using SIL.FieldWorks.Common.FwUtils; namespace SIL.FieldWorks.FDO.DomainServices.BackupRestore { diff --git a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs index aae2161679..3725d6764d 100644 --- a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs +++ b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs @@ -176,7 +176,7 @@ private void RestoreFrom7_0AndNewerBackup(BackupFileSettings fileSettings) Debug.Assert(fileSettings.IncludeSupportingFiles, "The option to include supporting files should not be allowed if they aren't available in the backup settings"); var zipEntryStartsWith = FdoFileHelper.ksSupportingFilesDir; - UncompressFilesContainedInFolderandSubFolders(DirectoryFinder.GetZipfileFormattedPath(zipEntryStartsWith), + UncompressFilesContainedInFolderandSubFolders(FdoFileHelper.GetZipfileFormattedPath(zipEntryStartsWith), m_restoreSettings.ProjectSupportingFilesPath); } @@ -450,7 +450,7 @@ protected virtual void CouldNotRestoreLinkedFilesToOriginalLocation(string linke private Dictionary GetAllFilesUnderFolderInZipFileAndDateTimes(string dir) { var filesAndDateTime = new Dictionary(); - var dirZipFileFormat = DirectoryFinder.GetZipfileFormattedPath(dir); + var dirZipFileFormat = FdoFileHelper.GetZipfileFormattedPath(dir); using (var zipIn = OpenFWBackupZipfile()) { ZipEntry entry; @@ -546,14 +546,14 @@ private void UncompressLinkedFiles(Dictionary fileList, String Debug.Assert(!String.IsNullOrEmpty(fileName)); //Contruct the path where the file will be unzipped too. - var zipFileLinkFilesPath = DirectoryFinder.GetZipfileFormattedPath(linkedFilesPathPersisted); + var zipFileLinkFilesPath = FdoFileHelper.GetZipfileFormattedPath(linkedFilesPathPersisted); var filenameWithSubFolders = entry.Name.Substring(zipFileLinkFilesPath.Length); String pathForFileSubFolders = ""; if (!fileName.Equals(filenameWithSubFolders)) //if they are equal the file is in the root of LinkedFiles { pathForFileSubFolders = GetPathForSubFolders(filenameWithSubFolders, fileName.Length); } - var destFolderZipFileFormat = DirectoryFinder.GetZipfileFormattedPath(destinationLinkedFilesPath); + var destFolderZipFileFormat = FdoFileHelper.GetZipfileFormattedPath(destinationLinkedFilesPath); var pathRoot = Path.GetPathRoot(destinationLinkedFilesPath); Debug.Assert(!String.IsNullOrEmpty(pathRoot)); var pathforfileunzip = Path.Combine(pathRoot, destFolderZipFileFormat, pathForFileSubFolders); diff --git a/Src/FDO/DomainServices/DataMigration/DataMigration7000029.cs b/Src/FDO/DomainServices/DataMigration/DataMigration7000029.cs index 2bf6319eeb..e205301234 100644 --- a/Src/FDO/DomainServices/DataMigration/DataMigration7000029.cs +++ b/Src/FDO/DomainServices/DataMigration/DataMigration7000029.cs @@ -19,7 +19,6 @@ using System.Xml.Linq; using System.Linq; using System.Xml.XPath; -using SIL.FieldWorks.Common.FwUtils; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration { diff --git a/Src/FDO/DomainServices/DataMigration/DataMigration7000030.cs b/Src/FDO/DomainServices/DataMigration/DataMigration7000030.cs index 089e188cbb..a783acdd50 100644 --- a/Src/FDO/DomainServices/DataMigration/DataMigration7000030.cs +++ b/Src/FDO/DomainServices/DataMigration/DataMigration7000030.cs @@ -21,7 +21,6 @@ using System.Text; using System.Xml.Linq; using System.Xml.XPath; -using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration diff --git a/Src/FDO/DomainServices/DataMigration/DataMigration7000060.cs b/Src/FDO/DomainServices/DataMigration/DataMigration7000060.cs index 321d9f647d..dfdec90d53 100644 --- a/Src/FDO/DomainServices/DataMigration/DataMigration7000060.cs +++ b/Src/FDO/DomainServices/DataMigration/DataMigration7000060.cs @@ -13,16 +13,6 @@ // --------------------------------------------------------------------------------------------- using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Xml; -using System.Xml.Linq; -using System.Xml.XPath; -using Palaso.WritingSystems.Migration; -using Palaso.WritingSystems.Migration.WritingSystemsLdmlV0To1Migration; -using SIL.FieldWorks.Common.FwUtils; -using System; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration { diff --git a/Src/FDO/DomainServices/StringServices.cs b/Src/FDO/DomainServices/StringServices.cs index 83d7032920..06834d0efc 100644 --- a/Src/FDO/DomainServices/StringServices.cs +++ b/Src/FDO/DomainServices/StringServices.cs @@ -14,7 +14,6 @@ using System.Xml; using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Application; using SIL.FieldWorks.FDO.DomainImpl; using SIL.FieldWorks.FDO.Infrastructure; diff --git a/Src/FDO/FDOGenerate/main.vm.cs b/Src/FDO/FDOGenerate/main.vm.cs index f676d8deb5..291fe2e29d 100644 --- a/Src/FDO/FDOGenerate/main.vm.cs +++ b/Src/FDO/FDOGenerate/main.vm.cs @@ -17,7 +17,6 @@ using System.Xml.Linq; using System.Linq; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.CoreImpl; using SIL.Utils; using SIL.FieldWorks.FDO.Infrastructure; diff --git a/Src/FDO/FDOTests/BackupRestore/ProjectBackupServiceTests.cs b/Src/FDO/FDOTests/BackupRestore/ProjectBackupServiceTests.cs index 5e104ab6fe..e949e3b226 100644 --- a/Src/FDO/FDOTests/BackupRestore/ProjectBackupServiceTests.cs +++ b/Src/FDO/FDOTests/BackupRestore/ProjectBackupServiceTests.cs @@ -326,7 +326,7 @@ private static bool DateTimesAreWithinACoupleSecondsOfEachOther(DateTime dateTim /// ------------------------------------------------------------------------------------ private static void VerifyFileExistsInZipFile(ZipFile zip, String fileNameAndPath) { - string str = DirectoryFinder.GetZipfileFormattedPath(fileNameAndPath); + string str = FdoFileHelper.GetZipfileFormattedPath(fileNameAndPath); //ensure the entry is the correct one. ZipEntry entry = zip.GetEntry(str); Assert.True(entry.Name.Equals(str), String.Format("File {0} should exist in zipFile", str)); diff --git a/Src/FDO/FdoFileHelper.cs b/Src/FDO/FdoFileHelper.cs index b74cbbe91b..a0f0debd0e 100644 --- a/Src/FDO/FdoFileHelper.cs +++ b/Src/FDO/FdoFileHelper.cs @@ -14,6 +14,8 @@ using System; using System.Diagnostics; using System.IO; +using System.Text; +using SIL.Utils; namespace SIL.FieldWorks.FDO { @@ -228,5 +230,33 @@ public static string GetDb4oDataFileName(string projectName) return projectName.EndsWith(ksFwDataDb4oFileExtension) ? projectName : projectName + ksFwDataDb4oFileExtension; } + + /// ------------------------------------------------------------------------------------ + /// + /// Gets the path without the root directory (i.e. make it un-rooted). + /// + /// ------------------------------------------------------------------------------------ + public static string GetPathWithoutRoot(string pathWithRoot) + { + string pathRoot = Path.GetPathRoot(pathWithRoot); + return pathWithRoot.Substring(pathRoot.Length); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Takes a windows path and returns it in the format which our backup zip files + /// stores them in. + /// + /// ------------------------------------------------------------------------------------ + public static string GetZipfileFormattedPath(string path) + { + StringBuilder strBldr = new StringBuilder(path); + string pathRoot = Path.GetPathRoot(path); + strBldr.Remove(0, pathRoot.Length); + // replace back slashes with forward slashes (for Windows) + if (!MiscUtils.IsUnix && !MiscUtils.IsMac) + strBldr.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + return strBldr.ToString(); + } } } From 6768298db13c515404d4b8b4b808ec373eb27ff9 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Mon, 9 Dec 2013 15:20:29 +0700 Subject: [PATCH 032/143] Move some classes from FwUtils to BasicUtils and CoreImpl Change-Id: Iee42145223938692606f64c1946ec7884c249367 --- Src/Common/Controls/DetailControls/BasicTypeSlices.cs | 4 ++-- Src/Common/Controls/XMLViews/XmlVc.cs | 2 +- Src/Common/Controls/XMLViews/XmlViewsUtils.cs | 2 +- Src/Common/{FwUtils => CoreImpl}/CaseFunctions.cs | 2 +- Src/Common/CoreImpl/CoreImpl.csproj | 5 +++++ Src/Common/CoreImpl/CoreImplTests/CoreImplTests.csproj | 6 +++--- .../CoreImplTests}/SpellingHelperTests.cs | 3 +-- Src/Common/{FwUtils => CoreImpl}/ISpellEngine.cs | 4 ++-- Src/Common/{FwUtils => CoreImpl}/SilTime.cs | 6 ++---- Src/Common/{FwUtils => CoreImpl}/SpellEngine.cs | 4 ++-- Src/Common/{FwUtils => CoreImpl}/SpellingHelper.cs | 6 ++---- Src/Common/FwUtils/FwUtils.csproj | 7 ------- Src/Common/FwUtils/FwUtilsTests/CaseFunctionsTest.cs | 3 +-- Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj | 1 - .../DomainServices/BackupRestore/ProjectRestoreService.cs | 1 + .../DomainServices/DataMigration/DataMigration7000042.cs | 1 + Src/FDO/IOC/FdoServiceLocatorFactory.cs | 1 + Src/Utilities/BasicUtils/BasicUtils.csproj | 3 +++ .../BasicUtils}/IServiceLocatorBootstrapper.cs | 4 ++-- .../BasicUtils}/StringIgnoreCaseComparer.cs | 2 +- 20 files changed, 32 insertions(+), 35 deletions(-) rename Src/Common/{FwUtils => CoreImpl}/CaseFunctions.cs (99%) rename Src/Common/{FwUtils/FwUtilsTests => CoreImpl/CoreImplTests}/SpellingHelperTests.cs (99%) rename Src/Common/{FwUtils => CoreImpl}/ISpellEngine.cs (92%) rename Src/Common/{FwUtils => CoreImpl}/SilTime.cs (96%) rename Src/Common/{FwUtils => CoreImpl}/SpellEngine.cs (99%) rename Src/Common/{FwUtils => CoreImpl}/SpellingHelper.cs (99%) rename Src/{Common/FwUtils => Utilities/BasicUtils}/IServiceLocatorBootstrapper.cs (89%) rename Src/{Common/FwUtils => Utilities/BasicUtils}/StringIgnoreCaseComparer.cs (97%) diff --git a/Src/Common/Controls/DetailControls/BasicTypeSlices.cs b/Src/Common/Controls/DetailControls/BasicTypeSlices.cs index 9232a49e27..05c4ffd5d0 100644 --- a/Src/Common/Controls/DetailControls/BasicTypeSlices.cs +++ b/Src/Common/Controls/DetailControls/BasicTypeSlices.cs @@ -18,6 +18,7 @@ using System; using System.Windows.Forms; using System.Xml; +using SIL.CoreImpl; using SIL.FieldWorks.Common.Controls; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.Application; @@ -76,7 +77,6 @@ private void SetToggleValue(XmlNode node) /// "reused" (e.g. refresh or new target object) /// /// - /// public override void Install(DataTree parent) { CheckDisposed(); @@ -384,7 +384,7 @@ protected override void Dispose(bool disposing) protected override void UpdateDisplayFromDatabase() { RichTextBox rtb = ((RichTextBox)this.Control); - DateTime dt = FwUtils.SilTime.GetTimeProperty(m_cache.DomainDataByFlid, Object.Hvo, m_flid); + DateTime dt = SilTime.GetTimeProperty(m_cache.DomainDataByFlid, Object.Hvo, m_flid); if (dt == DateTime.MinValue) { rtb.Text = "Date/Time not set"; diff --git a/Src/Common/Controls/XMLViews/XmlVc.cs b/Src/Common/Controls/XMLViews/XmlVc.cs index 47e8b3c3a6..d56a276628 100644 --- a/Src/Common/Controls/XMLViews/XmlVc.cs +++ b/Src/Common/Controls/XMLViews/XmlVc.cs @@ -1534,7 +1534,7 @@ public virtual void ProcessFrag(XmlNode frag, IVwEnv vwenv, int hvo, bool fEdita CellarPropertyType itype = (CellarPropertyType)m_sda.MetaDataCache.GetFieldType(flid); if (itype == CellarPropertyType.Time) { - DateTime dt = FwUtils.SilTime.GetTimeProperty(m_sda, hvo, flid); + DateTime dt = SilTime.GetTimeProperty(m_sda, hvo, flid); XmlNode dtNode = XmlViewsUtils.CopyWithParamDefaults(frag); string format; if (vwenv is SortCollectorEnv) diff --git a/Src/Common/Controls/XMLViews/XmlViewsUtils.cs b/Src/Common/Controls/XMLViews/XmlViewsUtils.cs index 30da878cb4..5b0768c576 100644 --- a/Src/Common/Controls/XMLViews/XmlViewsUtils.cs +++ b/Src/Common/Controls/XMLViews/XmlViewsUtils.cs @@ -959,7 +959,7 @@ static public string[] StringsFor(FdoCache fdoCache, ISilDataAccess sda, XmlNode CellarPropertyType itype = (CellarPropertyType)sda.MetaDataCache.GetFieldType(flid); if (itype == CellarPropertyType.Time) { - DateTime dt = FwUtils.SilTime.GetTimeProperty(sda, hvo, flid); + DateTime dt = SilTime.GetTimeProperty(sda, hvo, flid); return new[] {DateTimeCompString(dt)}; } else diff --git a/Src/Common/FwUtils/CaseFunctions.cs b/Src/Common/CoreImpl/CaseFunctions.cs similarity index 99% rename from Src/Common/FwUtils/CaseFunctions.cs rename to Src/Common/CoreImpl/CaseFunctions.cs index 46dde357ec..1c61f2772d 100644 --- a/Src/Common/FwUtils/CaseFunctions.cs +++ b/Src/Common/CoreImpl/CaseFunctions.cs @@ -13,7 +13,7 @@ // --------------------------------------------------------------------------------------------- using SIL.FieldWorks.Common.COMInterfaces; -namespace SIL.FieldWorks.Common.FwUtils +namespace SIL.CoreImpl { /// /// CaseFunctions provides a set of case conversion functions derived from the ICU diff --git a/Src/Common/CoreImpl/CoreImpl.csproj b/Src/Common/CoreImpl/CoreImpl.csproj index 4ffa1edfa2..15308adf26 100644 --- a/Src/Common/CoreImpl/CoreImpl.csproj +++ b/Src/Common/CoreImpl/CoreImpl.csproj @@ -99,8 +99,10 @@ CommonAssemblyInfo.cs + + @@ -133,6 +135,9 @@ + + + diff --git a/Src/Common/CoreImpl/CoreImplTests/CoreImplTests.csproj b/Src/Common/CoreImpl/CoreImplTests/CoreImplTests.csproj index 4fdd3f52b9..064b81cf59 100644 --- a/Src/Common/CoreImpl/CoreImplTests/CoreImplTests.csproj +++ b/Src/Common/CoreImpl/CoreImplTests/CoreImplTests.csproj @@ -1,4 +1,4 @@ - + Debug @@ -116,6 +116,7 @@ + @@ -143,8 +144,7 @@ - ../../../../DistFiles - + \ No newline at end of file diff --git a/Src/Common/FwUtils/FwUtilsTests/SpellingHelperTests.cs b/Src/Common/CoreImpl/CoreImplTests/SpellingHelperTests.cs similarity index 99% rename from Src/Common/FwUtils/FwUtilsTests/SpellingHelperTests.cs rename to Src/Common/CoreImpl/CoreImplTests/SpellingHelperTests.cs index c9228a4c9e..79673ea8b2 100644 --- a/Src/Common/FwUtils/FwUtilsTests/SpellingHelperTests.cs +++ b/Src/Common/CoreImpl/CoreImplTests/SpellingHelperTests.cs @@ -1,12 +1,11 @@ using System; -using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using NUnit.Framework; using SIL.Utils; -namespace SIL.FieldWorks.Common.FwUtils +namespace SIL.CoreImpl { /// /// Tests (for now pretty incomplete) of the SpellingHelper class. diff --git a/Src/Common/FwUtils/ISpellEngine.cs b/Src/Common/CoreImpl/ISpellEngine.cs similarity index 92% rename from Src/Common/FwUtils/ISpellEngine.cs rename to Src/Common/CoreImpl/ISpellEngine.cs index 8e868a0b24..690b8f6c9f 100644 --- a/Src/Common/FwUtils/ISpellEngine.cs +++ b/Src/Common/CoreImpl/ISpellEngine.cs @@ -1,7 +1,7 @@ -using System.Collections.Generic; +using System.Collections.Generic; using SIL.FieldWorks.Common.COMInterfaces; -namespace SIL.FieldWorks.Common.FwUtils +namespace SIL.CoreImpl { /// /// This is our wrapper for Hunspell, currently. It hides everything we don't use in case we want to change again! diff --git a/Src/Common/FwUtils/SilTime.cs b/Src/Common/CoreImpl/SilTime.cs similarity index 96% rename from Src/Common/FwUtils/SilTime.cs rename to Src/Common/CoreImpl/SilTime.cs index e6601c7205..128bf5a3d0 100644 --- a/Src/Common/FwUtils/SilTime.cs +++ b/Src/Common/CoreImpl/SilTime.cs @@ -14,13 +14,11 @@ // // // --------------------------------------------------------------------------------------------- -using System; -using System.Collections.Generic; -using System.Text; +using System; using SIL.FieldWorks.Common.COMInterfaces; -namespace SIL.FieldWorks.Common.FwUtils +namespace SIL.CoreImpl { /// ---------------------------------------------------------------------------------------- /// diff --git a/Src/Common/FwUtils/SpellEngine.cs b/Src/Common/CoreImpl/SpellEngine.cs similarity index 99% rename from Src/Common/FwUtils/SpellEngine.cs rename to Src/Common/CoreImpl/SpellEngine.cs index aa4dac108c..82399e007c 100644 --- a/Src/Common/FwUtils/SpellEngine.cs +++ b/Src/Common/CoreImpl/SpellEngine.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -6,7 +6,7 @@ using System.Text; using SIL.FieldWorks.Common.COMInterfaces; -namespace SIL.FieldWorks.Common.FwUtils +namespace SIL.CoreImpl { internal class SpellEngine : ISpellEngine, IDisposable { diff --git a/Src/Common/FwUtils/SpellingHelper.cs b/Src/Common/CoreImpl/SpellingHelper.cs similarity index 99% rename from Src/Common/FwUtils/SpellingHelper.cs rename to Src/Common/CoreImpl/SpellingHelper.cs index 427a90e51c..3789998f0f 100644 --- a/Src/Common/FwUtils/SpellingHelper.cs +++ b/Src/Common/CoreImpl/SpellingHelper.cs @@ -1,15 +1,13 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Text; -using System.Windows.Forms; using SIL.FieldWorks.Common.COMInterfaces; using SIL.Utils; -using XCore; -namespace SIL.FieldWorks.Common.FwUtils +namespace SIL.CoreImpl { /// /// This class manages a dictionary of (currently) Hunspell objects so that we can do spell checking. diff --git a/Src/Common/FwUtils/FwUtils.csproj b/Src/Common/FwUtils/FwUtils.csproj index d71cb593b4..966bd24f37 100644 --- a/Src/Common/FwUtils/FwUtils.csproj +++ b/Src/Common/FwUtils/FwUtils.csproj @@ -174,11 +174,9 @@ CommonAssemblyInfo.cs - - @@ -193,7 +191,6 @@ - @@ -208,10 +205,6 @@ Code - - - - diff --git a/Src/Common/FwUtils/FwUtilsTests/CaseFunctionsTest.cs b/Src/Common/FwUtils/FwUtilsTests/CaseFunctionsTest.cs index 42673a1a2a..0c4ebb6952 100644 --- a/Src/Common/FwUtils/FwUtilsTests/CaseFunctionsTest.cs +++ b/Src/Common/FwUtils/FwUtilsTests/CaseFunctionsTest.cs @@ -11,9 +11,8 @@ // File: CaseFunctionsTest.cs // Responsibility: // --------------------------------------------------------------------------------------------- -using System; using NUnit.Framework; -using SIL.FieldWorks.Common.COMInterfaces; +using SIL.CoreImpl; using SIL.FieldWorks.Test.TestUtils; using SIL.Utils; diff --git a/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj b/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj index d66bf0c1f2..fd071f2d9a 100644 --- a/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj +++ b/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj @@ -169,7 +169,6 @@ - diff --git a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs index 3725d6764d..3b0897401a 100644 --- a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs +++ b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs @@ -18,6 +18,7 @@ using System.IO; using System.Text; using ICSharpCode.SharpZipLib.Zip; +using SIL.CoreImpl; using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; diff --git a/Src/FDO/DomainServices/DataMigration/DataMigration7000042.cs b/Src/FDO/DomainServices/DataMigration/DataMigration7000042.cs index 6ecf95bdf8..2620e727f1 100644 --- a/Src/FDO/DomainServices/DataMigration/DataMigration7000042.cs +++ b/Src/FDO/DomainServices/DataMigration/DataMigration7000042.cs @@ -18,6 +18,7 @@ using System.Xml.XPath; using SIL.FieldWorks.Common.FwUtils; using System; +using SIL.Utils; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration { diff --git a/Src/FDO/IOC/FdoServiceLocatorFactory.cs b/Src/FDO/IOC/FdoServiceLocatorFactory.cs index 99dc9de820..895b089139 100644 --- a/Src/FDO/IOC/FdoServiceLocatorFactory.cs +++ b/Src/FDO/IOC/FdoServiceLocatorFactory.cs @@ -24,6 +24,7 @@ using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.FDO.Infrastructure.Impl; using SIL.FieldWorks.FDO.DomainServices.DataMigration; +using SIL.Utils; using StructureMap; using StructureMap.Configuration.DSL; using StructureMap.Pipeline; diff --git a/Src/Utilities/BasicUtils/BasicUtils.csproj b/Src/Utilities/BasicUtils/BasicUtils.csproj index 911d5df3ae..64489b182a 100644 --- a/Src/Utilities/BasicUtils/BasicUtils.csproj +++ b/Src/Utilities/BasicUtils/BasicUtils.csproj @@ -62,6 +62,7 @@ + False ..\..\..\Output\Debug\SilUtils.dll @@ -81,6 +82,7 @@ Properties\CommonAssemblyInfo.cs + @@ -105,6 +107,7 @@ + diff --git a/Src/Common/FwUtils/IServiceLocatorBootstrapper.cs b/Src/Utilities/BasicUtils/IServiceLocatorBootstrapper.cs similarity index 89% rename from Src/Common/FwUtils/IServiceLocatorBootstrapper.cs rename to Src/Utilities/BasicUtils/IServiceLocatorBootstrapper.cs index afd926e2aa..bb348460b8 100644 --- a/Src/Common/FwUtils/IServiceLocatorBootstrapper.cs +++ b/Src/Utilities/BasicUtils/IServiceLocatorBootstrapper.cs @@ -1,6 +1,6 @@ -using Microsoft.Practices.ServiceLocation; +using Microsoft.Practices.ServiceLocation; -namespace SIL.FieldWorks.Common.FwUtils +namespace SIL.Utils { /// /// Create an IServiceLocator. diff --git a/Src/Common/FwUtils/StringIgnoreCaseComparer.cs b/Src/Utilities/BasicUtils/StringIgnoreCaseComparer.cs similarity index 97% rename from Src/Common/FwUtils/StringIgnoreCaseComparer.cs rename to Src/Utilities/BasicUtils/StringIgnoreCaseComparer.cs index e9abef4316..a26af8379c 100644 --- a/Src/Common/FwUtils/StringIgnoreCaseComparer.cs +++ b/Src/Utilities/BasicUtils/StringIgnoreCaseComparer.cs @@ -14,7 +14,7 @@ using System; using System.Collections.Generic; -namespace SIL.FieldWorks.Common.FwUtils +namespace SIL.Utils { /// ---------------------------------------------------------------------------------------- /// From 9e237da4ca7f1399dd295318fcdd28032b6691fa Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Mon, 9 Dec 2013 15:47:35 +0700 Subject: [PATCH 033/143] Move some classes from FwUtils to BasicUtils and CoreImpl Fix previous commit by fixing the reference to Microsoft.Practices.ServiceLocation. Change-Id: I65eb5de9d39c581d5276f2c9f3bdfaae97b3184d --- Src/Common/FwUtils/FwUtils.csproj | 4 ---- Src/Utilities/BasicUtils/BasicUtils.csproj | 5 ++++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Src/Common/FwUtils/FwUtils.csproj b/Src/Common/FwUtils/FwUtils.csproj index 966bd24f37..2e95db141b 100644 --- a/Src/Common/FwUtils/FwUtils.csproj +++ b/Src/Common/FwUtils/FwUtils.csproj @@ -122,10 +122,6 @@ False ..\..\..\Downloads\IPCFramework.dll - - False - ..\..\..\DistFiles\Microsoft.Practices.ServiceLocation.dll - False ..\..\..\Downloads\Palaso.dll diff --git a/Src/Utilities/BasicUtils/BasicUtils.csproj b/Src/Utilities/BasicUtils/BasicUtils.csproj index 64489b182a..01571e48ac 100644 --- a/Src/Utilities/BasicUtils/BasicUtils.csproj +++ b/Src/Utilities/BasicUtils/BasicUtils.csproj @@ -62,7 +62,10 @@ - + + False + ..\..\..\DistFiles\Microsoft.Practices.ServiceLocation.dll + False ..\..\..\Output\Debug\SilUtils.dll From e3b1c1eac33494cd70cc189a36d6f34619993ba8 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Mon, 9 Dec 2013 17:36:21 +0700 Subject: [PATCH 034/143] Remove more FwUtils dependencies from FDO Change-Id: If105bae1bb699e4b3273b028d36da6c3cb957675 --- Src/Common/CoreImpl/CoreImpl.csproj | 1 + .../StartupException.cs} | 43 +++++++------------ Src/Common/FieldWorks/FieldWorks.cs | 24 +++++------ .../FieldWorksTests/FieldWorksTests.csproj | 4 ++ .../FieldWorksTests/ProjectIDTests.cs | 9 ++-- Src/Common/FieldWorks/ProjectId.cs | 15 ++++--- .../FieldWorks/WelcomeToFieldWorksDlg.cs | 3 +- Src/Common/FwUtils/FLExBridgeHelper.cs | 8 +--- Src/Common/FwUtils/FwUtils.csproj | 1 - Src/FDO/DomainImpl/OverridesLangProj.cs | 2 +- .../BackupRestore/RestoreProjectSettings.cs | 2 +- .../DomainServices/ClientServerServices.cs | 3 +- .../DataMigration/DataMigration7000037.cs | 14 +++--- Src/FDO/FDO.csproj | 1 + .../BackupRestoreSettingsTests.cs | 2 +- .../PersistingBackendProviderTests.cs | 4 +- Src/FDO/FdoFileHelper.cs | 14 ++++++ Src/FDO/FdoNewerVersionException.cs | 27 ++++++++++++ .../Impl/Db4oClientServerBackendProvider.cs | 11 ++--- .../Infrastructure/Impl/FDOBackendProvider.cs | 2 +- .../Infrastructure/Impl/XMLBackendProvider.cs | 5 ++- Src/FDO/fdoCache.cs | 4 +- Src/FwCoreDlgs/FwNewLangProject.cs | 2 +- Src/LexText/Lexicon/FLExBridgeListener.cs | 10 ++--- Src/TeDll/TeApp.cs | 4 +- 25 files changed, 127 insertions(+), 88 deletions(-) rename Src/Common/{FwUtils/FwStartupException.cs => CoreImpl/StartupException.cs} (72%) create mode 100644 Src/FDO/FdoNewerVersionException.cs diff --git a/Src/Common/CoreImpl/CoreImpl.csproj b/Src/Common/CoreImpl/CoreImpl.csproj index 15308adf26..45155a9f03 100644 --- a/Src/Common/CoreImpl/CoreImpl.csproj +++ b/Src/Common/CoreImpl/CoreImpl.csproj @@ -100,6 +100,7 @@ CommonAssemblyInfo.cs + diff --git a/Src/Common/FwUtils/FwStartupException.cs b/Src/Common/CoreImpl/StartupException.cs similarity index 72% rename from Src/Common/FwUtils/FwStartupException.cs rename to Src/Common/CoreImpl/StartupException.cs index e03007907e..716b7a22a9 100644 --- a/Src/Common/FwUtils/FwStartupException.cs +++ b/Src/Common/CoreImpl/StartupException.cs @@ -8,7 +8,7 @@ // #endregion // -// File: FwStartupException.cs +// File: StartupException.cs // Responsibility: TE Team // // @@ -16,83 +16,83 @@ // --------------------------------------------------------------------------------------------- using System; -namespace SIL.FieldWorks.Common.FwUtils +namespace SIL.CoreImpl { /// ---------------------------------------------------------------------------------------- /// /// Exception thrown during FieldWorks startup if something goes wrong /// /// ---------------------------------------------------------------------------------------- - public class FwStartupException : Exception + public class StartupException : Exception { /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The message. /// ------------------------------------------------------------------------------------ - public FwStartupException(string message) : this(message, null) + public StartupException(string message) : this(message, null) { } /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The message. /// The inner exception. /// ------------------------------------------------------------------------------------ - public FwStartupException(string message, Exception innerException) : + public StartupException(string message, Exception innerException) : this(message, innerException, true) { } /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The message. /// True to report this error to the user, false otherwise /// /// ------------------------------------------------------------------------------------ - public FwStartupException(string message, bool fReportToUser) : + public StartupException(string message, bool fReportToUser) : this(message, null, fReportToUser) { } /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The inner exception. /// ------------------------------------------------------------------------------------ - public FwStartupException(Exception innerException) : this(innerException, true) + public StartupException(Exception innerException) : this(innerException, true) { } /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The inner exception. /// True to report this error to the user, false otherwise /// /// ------------------------------------------------------------------------------------ - public FwStartupException(Exception innerException, bool fReportToUser) : + public StartupException(Exception innerException, bool fReportToUser) : this(null, innerException, fReportToUser) { } /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The message. /// The inner exception. /// True to report this error to the user, false otherwise /// /// ------------------------------------------------------------------------------------ - public FwStartupException(string message, Exception innerException, bool fReportToUser) : + public StartupException(string message, Exception innerException, bool fReportToUser) : base(message, innerException) { ReportToUser = fReportToUser; @@ -109,17 +109,4 @@ public bool ReportToUser private set; } } - - /// - /// Exception thrown when we try to open a project that belongs to a newer version of FieldWorks than this. - /// - public class FwNewerVersionException : FwStartupException - { - /// - /// Make one. - /// - public FwNewerVersionException(string message) : base(message) - { - } - } } diff --git a/Src/Common/FieldWorks/FieldWorks.cs b/Src/Common/FieldWorks/FieldWorks.cs index 6c9d7243e5..c2dfcb6b60 100644 --- a/Src/Common/FieldWorks/FieldWorks.cs +++ b/Src/Common/FieldWorks/FieldWorks.cs @@ -1247,7 +1247,7 @@ private static ProjectId DetermineProject(FwAppArgs args) // If we try to use command-line arguments and it fails, we will use the Welcome dialog // to help the user figure out what to do next. var projId = new ProjectId(args.DatabaseType, args.Database, args.Server); - FwStartupException projectOpenError; + StartupException projectOpenError; if (TryCommandLineOption(projId, out projectOpenError)) return projId; @@ -1270,7 +1270,7 @@ private static ProjectId DetermineProject(FwAppArgs args) else if (previousStartupStatus == StartupStatus.Failed && !string.IsNullOrEmpty(latestProject)) { // The previous project failed to open, so notify the user. - projectOpenError = new FwStartupException(String.Format( + projectOpenError = new StartupException(String.Format( Properties.Resources.kstidUnableToOpenLastProject, app.ApplicationName, latestProject)); } @@ -1322,15 +1322,15 @@ private static ProjectId GetBestGuessProjectId(string latestProject, string late /// /// /// - private static bool TryCommandLineOption(ProjectId projId, out FwStartupException exception) + private static bool TryCommandLineOption(ProjectId projId, out StartupException exception) { exception = null; if (string.IsNullOrEmpty(projId.Name)) return false; var ex = projId.GetExceptionIfInvalid(); - if (ex is FwStartupException) + if (ex is StartupException) { - exception = (FwStartupException) ex; + exception = (StartupException) ex; return false; // Invalid command-line arguments supplied. } if (ex == null) @@ -1381,7 +1381,7 @@ private static bool LaunchProject(FwAppArgs args, ref ProjectId projectId) { return InitializeFirstApp(app, projectId); } - catch (FwStartupException e) + catch (StartupException e) { if (s_cache != null) { @@ -1585,7 +1585,7 @@ private static void ProjectNameChanged(FdoCache sender) /// ------------------------------------------------------------------------------------ [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", Justification="startingApp is a reference")] - private static ProjectId ShowWelcomeDialog(FwAppArgs args, FwApp startingApp, ProjectId lastProjectId, FwStartupException exception) + private static ProjectId ShowWelcomeDialog(FwAppArgs args, FwApp startingApp, ProjectId lastProjectId, StartupException exception) { CloseSplashScreen(); @@ -1674,7 +1674,7 @@ private static ProjectId ShowWelcomeDialog(FwAppArgs args, FwApp startingApp, Pr if (projectToTry != null) projectToTry.AssertValid(); } - catch (FwStartupException e) + catch (StartupException e) { exception = e; } @@ -2868,7 +2868,7 @@ internal static bool CreateAndInitNewMainWindow(FwApp app, bool fNewCache, Form // so just record it now as the active one. s_activeMainWnd = (IFwMainWnd)fwMainWindow; } - catch (FwStartupException ex) + catch (StartupException ex) { // REVIEW: Can this actually happen when just creating a new main window? CloseSplashScreen(); @@ -3153,13 +3153,13 @@ private static bool InitializeApp(FwApp app, IProgress progressDlg) try { if (!app.InitCacheForApp(progressDlg)) - throw new FwStartupException(Properties.Resources.kstidCacheInitFailure); + throw new StartupException(Properties.Resources.kstidCacheInitFailure); } catch (Exception e) { - if (e is FwStartupException) + if (e is StartupException) throw; - throw new FwStartupException(Properties.Resources.kstidCacheInitFailure, e, true); + throw new StartupException(Properties.Resources.kstidCacheInitFailure, e, true); } undoHelper.RollBack = false; } diff --git a/Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.csproj b/Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.csproj index 881ee50095..7eecfeafb7 100644 --- a/Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.csproj +++ b/Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.csproj @@ -72,6 +72,10 @@ False ..\..\..\..\Output\Debug\COMInterfacesTests.dll + + False + ..\..\..\..\Output\Debug\CoreImpl.dll + False ..\..\..\..\Output\Debug\FDO.dll diff --git a/Src/Common/FieldWorks/FieldWorksTests/ProjectIDTests.cs b/Src/Common/FieldWorks/FieldWorksTests/ProjectIDTests.cs index 651f90042a..8dad54a244 100644 --- a/Src/Common/FieldWorks/FieldWorksTests/ProjectIDTests.cs +++ b/Src/Common/FieldWorks/FieldWorksTests/ProjectIDTests.cs @@ -15,6 +15,7 @@ using System.IO; using NUnit.Framework; using Rhino.Mocks; +using SIL.CoreImpl; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices; @@ -378,7 +379,7 @@ public void AssertValid_Invalid_NoName() proj.AssertValid(); Assert.Fail("FwStartupException expected"); } - catch (FwStartupException exception) + catch (StartupException exception) { Assert.IsFalse(exception.ReportToUser); } @@ -399,7 +400,7 @@ public void AssertValid_Invalid_FileNotFound() proj.AssertValid(); Assert.Fail("FwStartupException expected"); } - catch (FwStartupException exception) + catch (StartupException exception) { Assert.IsTrue(exception.ReportToUser); } @@ -420,7 +421,7 @@ public void AssertValid_InvalidProjectType() proj.AssertValid(); Assert.Fail("FwStartupException expected"); } - catch (FwStartupException exception) + catch (StartupException exception) { Assert.IsTrue(exception.ReportToUser); } @@ -441,7 +442,7 @@ public void AssertValid_Invalid_SharedFolderNotFound() proj.AssertValid(); Assert.Fail("FwStartupException expected"); } - catch (FwStartupException exception) + catch (StartupException exception) { Assert.IsTrue(exception.ReportToUser); } diff --git a/Src/Common/FieldWorks/ProjectId.cs b/Src/Common/FieldWorks/ProjectId.cs index 04a1e8e37f..11e375dc20 100644 --- a/Src/Common/FieldWorks/ProjectId.cs +++ b/Src/Common/FieldWorks/ProjectId.cs @@ -14,6 +14,7 @@ using System; using System.Diagnostics; using System.Net; +using SIL.CoreImpl; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.Infrastructure; @@ -345,7 +346,7 @@ public bool IsValid var ex = GetExceptionIfInvalid(); if (ex == null) return true; - if (ex is FwStartupException) + if (ex is StartupException) return false; // something totally unexpected that we don't know how to handle happened. // Don't suppress it. @@ -381,7 +382,7 @@ public string TypeString /// /// here. /// - /// If invalid (e.g., project Name is not set, the + /// If invalid (e.g., project Name is not set, the /// XML file can not be found, etc.) /// ------------------------------------------------------------------------------------ public void AssertValid() @@ -402,7 +403,7 @@ public void AssertValid() internal Exception GetExceptionIfInvalid() { if (string.IsNullOrEmpty(Name)) - return new FwStartupException(Properties.Resources.kstidNoProjectName, false); + return new StartupException(Properties.Resources.kstidNoProjectName, false); switch (Type) { @@ -413,7 +414,7 @@ internal Exception GetExceptionIfInvalid() } catch (SocketException e) { - return new FwStartupException(String.Format(Properties.Resources.kstidInvalidServer, ServerName, e.Message), e); + return new StartupException(String.Format(Properties.Resources.kstidInvalidServer, ServerName, e.Message), e); } catch (Exception ex) { @@ -422,10 +423,10 @@ internal Exception GetExceptionIfInvalid() break; case FDOBackendProviderType.kXML: if (!FileUtils.SimilarFileExists(Path)) - return new FwStartupException(string.Format(Properties.Resources.kstidFileNotFound, Path)); + return new StartupException(string.Format(Properties.Resources.kstidFileNotFound, Path)); break; case FDOBackendProviderType.kInvalid: - return new FwStartupException(Properties.Resources.kstidInvalidFwProjType); + return new StartupException(Properties.Resources.kstidInvalidFwProjType); default: return new NotImplementedException("Unknown type of project."); } @@ -433,7 +434,7 @@ internal Exception GetExceptionIfInvalid() // Check this after checking for other valid information (e.g. if the server is // not available, we want to show that error, not this error). if (!FileUtils.DirectoryExists(SharedProjectFolder)) - return new FwStartupException(String.Format(Properties.Resources.kstidCannotAccessProjectPath, SharedProjectFolder)); + return new StartupException(String.Format(Properties.Resources.kstidCannotAccessProjectPath, SharedProjectFolder)); return null; // valid } diff --git a/Src/Common/FieldWorks/WelcomeToFieldWorksDlg.cs b/Src/Common/FieldWorks/WelcomeToFieldWorksDlg.cs index 7eb6f7272b..a952728914 100644 --- a/Src/Common/FieldWorks/WelcomeToFieldWorksDlg.cs +++ b/Src/Common/FieldWorks/WelcomeToFieldWorksDlg.cs @@ -14,6 +14,7 @@ using System.ComponentModel; using System.Diagnostics; using System.Windows.Forms; +using SIL.CoreImpl; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices; @@ -76,7 +77,7 @@ public enum ButtonPress /// True (usually only on the first run) when we want to show the first-time warning about /// sending google analytics information /// ------------------------------------------------------------------------------------ - public WelcomeToFieldWorksDlg(IHelpTopicProvider helpTopicProvider, string appAbbrev, FwStartupException exception, bool showReportingRow) + public WelcomeToFieldWorksDlg(IHelpTopicProvider helpTopicProvider, string appAbbrev, StartupException exception, bool showReportingRow) { m_appAbbrev = appAbbrev; InitializeComponent(); diff --git a/Src/Common/FwUtils/FLExBridgeHelper.cs b/Src/Common/FwUtils/FLExBridgeHelper.cs index ef12312bfc..b63bc0326c 100644 --- a/Src/Common/FwUtils/FLExBridgeHelper.cs +++ b/Src/Common/FwUtils/FLExBridgeHelper.cs @@ -120,13 +120,9 @@ public class FLExBridgeHelper #endregion End of available '-v' parameter options: - // The two paths of a path that locate the Lift repository within a FLEx project. /// - /// constant for locating the nested lift repository (part 1 of 2) - /// - public const string OtherRepositories = @"OtherRepositories"; - /// - /// constant for locating the nested lift repository (part 2 of 2) + /// constant for locating the nested lift repository (within the "OtherRepositories" path of a project). + /// See also SIL.FieldWorks.FDO.FdoFileHelper.OtherRepositories /// public const string LIFT = @"LIFT"; diff --git a/Src/Common/FwUtils/FwUtils.csproj b/Src/Common/FwUtils/FwUtils.csproj index 2e95db141b..8dd787356a 100644 --- a/Src/Common/FwUtils/FwUtils.csproj +++ b/Src/Common/FwUtils/FwUtils.csproj @@ -176,7 +176,6 @@ - diff --git a/Src/FDO/DomainImpl/OverridesLangProj.cs b/Src/FDO/DomainImpl/OverridesLangProj.cs index 0f31cf3ff7..2d6287f5ca 100644 --- a/Src/FDO/DomainImpl/OverridesLangProj.cs +++ b/Src/FDO/DomainImpl/OverridesLangProj.cs @@ -146,7 +146,7 @@ public IList InterlinearTexts // Get regular texts. - if (FwUtils.IsOkToDisplayScriptureIfPresent && TranslatedScriptureOA != null) + if (TranslatedScriptureOA != null) { // TE installed, so also get them from Sripture. foreach (var book in TranslatedScriptureOA.ScriptureBooksOS) diff --git a/Src/FDO/DomainServices/BackupRestore/RestoreProjectSettings.cs b/Src/FDO/DomainServices/BackupRestore/RestoreProjectSettings.cs index e82b95cd70..c82f4067fa 100644 --- a/Src/FDO/DomainServices/BackupRestore/RestoreProjectSettings.cs +++ b/Src/FDO/DomainServices/BackupRestore/RestoreProjectSettings.cs @@ -155,7 +155,7 @@ public bool UsingSendReceive { get { - var otherRepoPath = Path.Combine(ProjectPath, FLExBridgeHelper.OtherRepositories); + var otherRepoPath = Path.Combine(ProjectPath, FdoFileHelper.OtherRepositories); return Directory.Exists(Path.Combine(ProjectPath, ".hg")) || (Directory.Exists(otherRepoPath) && Directory.EnumerateDirectories(otherRepoPath).Any(dir => Directory.Exists(Path.Combine(dir, ".hg")))); diff --git a/Src/FDO/DomainServices/ClientServerServices.cs b/Src/FDO/DomainServices/ClientServerServices.cs index 0145d1d0f9..e6893be354 100644 --- a/Src/FDO/DomainServices/ClientServerServices.cs +++ b/Src/FDO/DomainServices/ClientServerServices.cs @@ -22,6 +22,7 @@ using System.Net.Sockets; using System.Text; using FwRemoteDatabaseConnector; +using SIL.CoreImpl; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.FDO.Infrastructure.Impl; @@ -834,7 +835,7 @@ private object ConvertAllProjectsToDb4o(IThreadedProgress progress, object[] arg private static void ReportConversionError(IFdoUI ui, string projectPath, Exception e) { string message; - if (e is FwNewerVersionException) + if (e is FdoNewerVersionException) { message = string.Format(Strings.ksConvertFailedNewerVersion, Path.GetFileName(projectPath), Path.GetDirectoryName(projectPath)); diff --git a/Src/FDO/DomainServices/DataMigration/DataMigration7000037.cs b/Src/FDO/DomainServices/DataMigration/DataMigration7000037.cs index 9879d5e30b..ec19117d00 100644 --- a/Src/FDO/DomainServices/DataMigration/DataMigration7000037.cs +++ b/Src/FDO/DomainServices/DataMigration/DataMigration7000037.cs @@ -36,6 +36,10 @@ internal class DataMigration7000037 : IDataMigration { private static readonly byte[] s_externalLinkTag = Encoding.UTF8.GetBytes("externalLink"); + // Moved here from FWLinkArgs. We don't want it to change here if it is changed there since + // the data migration will expect it to be what it was at that time, not the new value. + private const string kFwUrlPrefix = "silfw://localhost/link?"; + #region IDataMigration Members public void PerformMigration(IDomainObjectDTORepository domainObjectDtoRepository) @@ -68,11 +72,11 @@ private bool FixExternalLinks(XElement xel, string projectName) if (attrLink == null) continue; string value = attrLink.Value; - if (value.StartsWith(FwLinkArgs.kFwUrlPrefix.Substring(1))) - value = FwLinkArgs.kFwUrlPrefix.Substring(0, 1) + value; - if (!value.StartsWith(FwLinkArgs.kFwUrlPrefix)) + if (value.StartsWith(kFwUrlPrefix.Substring(1))) + value = kFwUrlPrefix.Substring(0, 1) + value; + if (!value.StartsWith(kFwUrlPrefix)) continue; - string query = HttpUtility.UrlDecode(value.Substring(FwLinkArgs.kFwUrlPrefix.Length)); + string query = HttpUtility.UrlDecode(value.Substring(kFwUrlPrefix.Length)); string[] rgsProps = query.Split(new char[] {'&'}, StringSplitOptions.RemoveEmptyEntries); string database = null; int idxDatabase = -1; @@ -136,7 +140,7 @@ private bool FixExternalLinks(XElement xel, string projectName) if (!fChange) continue; - value = FwLinkArgs.kFwUrlPrefix + HttpUtility.UrlEncode(rgsProps.ToString("&")); + value = kFwUrlPrefix + HttpUtility.UrlEncode(rgsProps.ToString("&")); if (attrLink.Value != value) { attrLink.Value = value; diff --git a/Src/FDO/FDO.csproj b/Src/FDO/FDO.csproj index 0e49285bd7..a87fba9f58 100644 --- a/Src/FDO/FDO.csproj +++ b/Src/FDO/FDO.csproj @@ -370,6 +370,7 @@ + diff --git a/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs b/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs index ceb5bdf38e..2e634d1379 100644 --- a/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs +++ b/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs @@ -140,7 +140,7 @@ public void RestoreProjectSettings_VerifyExistenceOfHgRepo() Assert.True(restoreSettings.ProjectExists, "Project does not exist but it should."); Assert.False(restoreSettings.UsingSendReceive, "Project is using S/R but it should not be."); - string otherReposDir = Path.Combine(restoreSettings.ProjectPath, FLExBridgeHelper.OtherRepositories); + string otherReposDir = Path.Combine(restoreSettings.ProjectPath, FdoFileHelper.OtherRepositories); // Create a non-repository folder in OtherRepositories and verify the project is not using Send/Receive Directory.CreateDirectory(Path.Combine(otherReposDir, "NotARepo_LIFT", "RandomSubdir")); diff --git a/Src/FDO/FDOTests/PersistingBackendProviderTests.cs b/Src/FDO/FDOTests/PersistingBackendProviderTests.cs index 3ebffaf775..e2746350ab 100644 --- a/Src/FDO/FDOTests/PersistingBackendProviderTests.cs +++ b/Src/FDO/FDOTests/PersistingBackendProviderTests.cs @@ -634,7 +634,7 @@ protected override void CheckAdditionalStuffAfterFirstRename() /// throw an Exception. /// [Test] - [ExpectedException(typeof(FwStartupException))] + [ExpectedException(typeof(StartupException))] public void CorruptedXMLFileTest() { var testDataPath = Path.Combine(DirectoryFinder.FwSourceDirectory, "FDO/FDOTests/TestData"); @@ -645,7 +645,7 @@ public void CorruptedXMLFileTest() using (var xmlBep = new MockXMLBackendProvider(Cache, projName)) { // Should throw an XMLException, but this will be caught and because there's - // no .bak file, an FwStartupException will be thrown instead. + // no .bak file, an StartupException will be thrown instead. xmlBep.Startup(); } } diff --git a/Src/FDO/FdoFileHelper.cs b/Src/FDO/FdoFileHelper.cs index a0f0debd0e..128385512e 100644 --- a/Src/FDO/FdoFileHelper.cs +++ b/Src/FDO/FdoFileHelper.cs @@ -67,6 +67,9 @@ public static class FdoFileHelper /// The name of the folder containing temporary persisted sort sequence info for a project public const string ksSortSequenceTempDir = "Temp"; + /// Constant for locating the other repositories path of a project + public const string OtherRepositories = @"OtherRepositories"; + /// ------------------------------------------------------------------------------------ /// /// Gets the path to the configuration settings for the specified project. @@ -166,6 +169,17 @@ public static string GetDefaultOtherExternalFilesDir(string projectPath) return Path.Combine(projectPath, Path.Combine(ksLinkedFilesDir, ksOtherLinkedFilesDir)); } + /// ------------------------------------------------------------------------------------ + /// + /// Gets the path to the other repositories for the specified project. + /// + /// The path to the project folder. + /// ------------------------------------------------------------------------------------ + public static string GetOtherRepositoriesDir(string projectFolder) + { + return Path.Combine(projectFolder, OtherRepositories); + } + /// ------------------------------------------------------------------------------------ /// /// Gets the path to the media files directory for the project. diff --git a/Src/FDO/FdoNewerVersionException.cs b/Src/FDO/FdoNewerVersionException.cs new file mode 100644 index 0000000000..3016b27635 --- /dev/null +++ b/Src/FDO/FdoNewerVersionException.cs @@ -0,0 +1,27 @@ +// --------------------------------------------------------------------------------------------- +#region // Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Copyright (c) 2013, SIL International. All Rights Reserved. +// +// Distributable under the terms of either the Common Public License or the +// GNU Lesser General Public License, as specified in the LICENSING.txt file. +// +#endregion +// --------------------------------------------------------------------------------------------- +using SIL.CoreImpl; + +namespace SIL.FieldWorks.FDO +{ + /// + /// Exception thrown when we try to open a project that belongs to a newer version of FieldWorks than this. + /// + public class FdoNewerVersionException : StartupException + { + /// + /// Make one. + /// + public FdoNewerVersionException(string message) : base(message) + { + } + } +} \ No newline at end of file diff --git a/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs b/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs index 0317b1365d..5396387978 100644 --- a/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs @@ -25,6 +25,7 @@ using Db4objects.Db4o.CS.Config; using Db4objects.Db4o.Linq; using FwRemoteDatabaseConnector; +using SIL.CoreImpl; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.DomainServices.DataMigration; @@ -242,7 +243,7 @@ protected override int StartupInternal(int currentModelVersion) } catch (SocketException e) { - throw new FwStartupException(string.Format(Strings.ksCannotConnectToServer, "FwRemoteDatabaseConnectorService"), e); + throw new StartupException(string.Format(Strings.ksCannotConnectToServer, "FwRemoteDatabaseConnectorService"), e); } finally { @@ -555,7 +556,7 @@ protected override void CreateInternal() } catch (SocketException e) { - throw new FwStartupException(string.Format(Strings.ksCannotConnectToServer, "FwRemoteDatabaseConnectorService"), e); + throw new StartupException(string.Format(Strings.ksCannotConnectToServer, "FwRemoteDatabaseConnectorService"), e); } catch (Exception err) { @@ -679,19 +680,19 @@ private void RequestDatabaseStart() if (!info.StartServer(ProjectId.Name, out port, out exceptionFromStartingServer)) { // failed to start server - throw new FwStartupException(String.Format(Strings.ksFailedToStartServer, + throw new StartupException(String.Format(Strings.ksFailedToStartServer, exceptionFromStartingServer.Message), exceptionFromStartingServer); } m_port = port; } catch (SocketException e) { - throw new FwStartupException(string.Format(Strings.ksCannotConnectToServer, "FwRemoteDatabaseConnectorService"), e); + throw new StartupException(string.Format(Strings.ksCannotConnectToServer, "FwRemoteDatabaseConnectorService"), e); } catch (RemotingException e) { // on Mono we get a RemotingException instead of a SocketException - throw new FwStartupException(string.Format(Strings.ksCannotConnectToServer, "FwRemoteDatabaseConnectorService"), e); + throw new StartupException(string.Format(Strings.ksCannotConnectToServer, "FwRemoteDatabaseConnectorService"), e); } } diff --git a/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs b/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs index 2945a5c2ad..63f2ebd15a 100644 --- a/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs @@ -355,7 +355,7 @@ protected virtual void StartupInternalWithDataMigrationIfNeeded(IThreadedProgres var currentDataStoreVersion = StartupInternal(ModelVersion); if (currentDataStoreVersion > ModelVersion) - throw new FwNewerVersionException(Properties.Resources.kstidProjectIsForNewerVersionOfFw); + throw new FdoNewerVersionException(Properties.Resources.kstidProjectIsForNewerVersionOfFw); if (currentDataStoreVersion == ModelVersion) return; diff --git a/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs b/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs index 2aa971b72b..82f03a9767 100644 --- a/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs @@ -15,6 +15,7 @@ using System.Text; using System.Xml; using System.Xml.Linq; +using SIL.CoreImpl; using SIL.FieldWorks.FDO.DomainServices.DataMigration; using SIL.Utils; using SIL.FieldWorks.Common.FwUtils; @@ -359,7 +360,7 @@ private void OfferToRestore(string message) } // No backup, or the user didn't want to try. Show Unable to Open Project dialog box. UnlockProject(); - throw new FwStartupException(message); + throw new StartupException(message); } private void BasicInit() @@ -371,7 +372,7 @@ private void BasicInit() } catch (IOException e) { - throw new FwStartupException(String.Format(Properties.Resources.kstidLockFileLocked, ProjectId.Name), e, true); + throw new StartupException(String.Format(Properties.Resources.kstidLockFileLocked, ProjectId.Name), e, true); } } diff --git a/Src/FDO/fdoCache.cs b/Src/FDO/fdoCache.cs index 8b0274a4aa..c593057196 100644 --- a/Src/FDO/fdoCache.cs +++ b/Src/FDO/fdoCache.cs @@ -323,9 +323,9 @@ private void Initialize(string userWsIcuLocale) writingSystemManager.Save(); if (ServiceLocator.WritingSystems.DefaultAnalysisWritingSystem == null) - throw new FwStartupException(string.Format(Strings.ksNoWritingSystems, Strings.ksAnalysis)); + throw new StartupException(string.Format(Strings.ksNoWritingSystems, Strings.ksAnalysis)); if (ServiceLocator.WritingSystems.DefaultVernacularWritingSystem == null) - throw new FwStartupException(string.Format(Strings.ksNoWritingSystems, Strings.ksVernacular)); + throw new StartupException(string.Format(Strings.ksNoWritingSystems, Strings.ksVernacular)); NonUndoableUnitOfWorkHelper.Do(ActionHandlerAccessor, () => DataStoreInitializationServices.PrepareCache(this)); diff --git a/Src/FwCoreDlgs/FwNewLangProject.cs b/Src/FwCoreDlgs/FwNewLangProject.cs index 737854c82d..b1b48df3b7 100644 --- a/Src/FwCoreDlgs/FwNewLangProject.cs +++ b/Src/FwCoreDlgs/FwNewLangProject.cs @@ -730,7 +730,7 @@ protected void CreateNewLangProjWithProgress(IFdoUI ui) m_fIgnoreClose = true; DialogResult = DialogResult.Cancel; } - else if (e is FwStartupException) + else if (e is StartupException) { MessageBox.Show(string.Format(FwCoreDlgs.kstidErrorNewDb, e.Message), FwUtils.ksSuiteName); diff --git a/Src/LexText/Lexicon/FLExBridgeListener.cs b/Src/LexText/Lexicon/FLExBridgeListener.cs index f08a9a7efb..f075cdecf9 100644 --- a/Src/LexText/Lexicon/FLExBridgeListener.cs +++ b/Src/LexText/Lexicon/FLExBridgeListener.cs @@ -393,7 +393,7 @@ public bool OnDisplayFirstLiftBridge(object commandObject, ref UIItemDisplayProp private static bool IsConfiguredForLiftSR(string folder) { - var otherRepoPath = Path.Combine(folder, FLExBridgeHelper.OtherRepositories); + var otherRepoPath = Path.Combine(folder, FdoFileHelper.OtherRepositories); if (!Directory.Exists(otherRepoPath)) return false; var liftFolder = Directory.EnumerateDirectories(otherRepoPath, "*_LIFT").FirstOrDefault(); @@ -932,7 +932,7 @@ private bool DoSendReceiveForLift(string fullProjectFileName, out bool dataChang private static string GetLiftRepositoryFolderFromFwProjectFolder(string projectFolder) { - var otherDir = Path.Combine(projectFolder, FLExBridgeHelper.OtherRepositories); + var otherDir = Path.Combine(projectFolder, FdoFileHelper.OtherRepositories); if (Directory.Exists(otherDir)) { var extantOtherFolders = Directory.GetDirectories(otherDir); @@ -942,7 +942,7 @@ private static string GetLiftRepositoryFolderFromFwProjectFolder(string projectF } var flexProjName = Path.GetFileName(projectFolder); - return Path.Combine(projectFolder, FLExBridgeHelper.OtherRepositories, flexProjName + '_' + FLExBridgeHelper.LIFT); + return Path.Combine(projectFolder, FdoFileHelper.OtherRepositories, flexProjName + '_' + FLExBridgeHelper.LIFT); } void OnDumperSetProgressMessage(object sender, ProgressMessageArgs e) @@ -1534,7 +1534,7 @@ private static bool DetectMainConflicts(string path, Dictionary sa foreach (var file in Directory.GetFiles(path, "*.ChorusNotes", SearchOption.AllDirectories)) { // TODO: Test to see if one conflict tool can do both FLEx and LIFT conflicts. - if (file.Contains(FLExBridgeHelper.OtherRepositories)) + if (file.Contains(FdoFileHelper.OtherRepositories)) continue; // Skip them, since they are part of some other repository. long oldLength; @@ -1556,7 +1556,7 @@ private static Dictionary PrepareToDetectMainConflicts(string proj var result = new Dictionary(); foreach (var file in Directory.GetFiles(projectFolder, "*.ChorusNotes", SearchOption.AllDirectories)) { - if (file.Contains(FLExBridgeHelper.OtherRepositories)) + if (file.Contains(FdoFileHelper.OtherRepositories)) continue; // Skip them, since they are part of some other repository. result[file] = new FileInfo(file).Length; diff --git a/Src/TeDll/TeApp.cs b/Src/TeDll/TeApp.cs index a54981cfc6..9ee112b7f0 100644 --- a/Src/TeDll/TeApp.cs +++ b/Src/TeDll/TeApp.cs @@ -18,7 +18,7 @@ using System.IO; using System.Windows.Forms; using Microsoft.Win32; - +using SIL.CoreImpl; using SIL.FieldWorks.FDO; using SIL.FieldWorks.Common.Framework; using SIL.FieldWorks.Common.RootSites; @@ -403,7 +403,7 @@ public override Form NewMainAppWnd(IProgress progressDlg, bool fNewCache, Form w foreach (Form wnd in MainWindows) { if (!wnd.Enabled && wnd is FwMainWnd) - throw new FwStartupException(Properties.Resources.kstidProjectLocked); + throw new StartupException(Properties.Resources.kstidProjectLocked); } return NewTeMainWnd(wndCopyFrom); } From 2c1d77722d0101032f9f2fa4134132a37f825c5b Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Tue, 10 Dec 2013 15:02:04 +0700 Subject: [PATCH 035/143] Remove xCoreInterfaces reference from FDO Change-Id: I8bbb9839de0dd40416836d962adfb03ecbd5d47a --- Src/FDO/FDO.csproj | 4 ---- Src/FDO/Infrastructure/UndoableUnitOfWorkHelper.cs | 12 ------------ Src/LexText/Lexicon/ReversalIndexEntryMenuHandler.cs | 2 +- Src/LexText/Morphology/InflAffixTemplateControl.cs | 2 +- Src/xWorks/DTMenuHandler.cs | 2 +- .../GlobalSettingServices.cs | 8 ++------ Src/xWorks/xWorks.csproj | 1 + 7 files changed, 6 insertions(+), 25 deletions(-) rename Src/{FDO/DomainServices => xWorks}/GlobalSettingServices.cs (88%) diff --git a/Src/FDO/FDO.csproj b/Src/FDO/FDO.csproj index a87fba9f58..d7b0bc00f1 100644 --- a/Src/FDO/FDO.csproj +++ b/Src/FDO/FDO.csproj @@ -167,9 +167,6 @@ ..\..\Output\Debug\SilUtils.dll - - ..\..\Output\Debug\xCoreInterfaces.dll - @@ -273,7 +270,6 @@ - diff --git a/Src/FDO/Infrastructure/UndoableUnitOfWorkHelper.cs b/Src/FDO/Infrastructure/UndoableUnitOfWorkHelper.cs index 35dc37d900..0bbf50ffc7 100644 --- a/Src/FDO/Infrastructure/UndoableUnitOfWorkHelper.cs +++ b/Src/FDO/Infrastructure/UndoableUnitOfWorkHelper.cs @@ -13,7 +13,6 @@ // --------------------------------------------------------------------------------------------- using System; using SIL.FieldWorks.Common.COMInterfaces; -using XCore; namespace SIL.FieldWorks.FDO.Infrastructure { @@ -85,17 +84,6 @@ public static void Do(string undoText, string redoText, ICmObject obj, Action ta Do(undoText, redoText, obj.Cache.ServiceLocator.GetInstance(), task); } - /// - /// Perform the specified task, making it an undoable task in the action handler - /// associated with the input ICmObject, with the labels determined by the command. The task will - /// automatically be begun and ended if all goes well, and rolled back if an exception - /// is thrown. (The exception will then be rethrown.) - /// - public static void Do(Command command, ICmObject obj, Action task) - { - Do(command.UndoText, command.RedoText, obj, task); - } - /// ------------------------------------------------------------------------------------ /// /// Perform the specified task, making it an undoable task in the action handler if diff --git a/Src/LexText/Lexicon/ReversalIndexEntryMenuHandler.cs b/Src/LexText/Lexicon/ReversalIndexEntryMenuHandler.cs index 7e0359980b..9da278aa30 100644 --- a/Src/LexText/Lexicon/ReversalIndexEntryMenuHandler.cs +++ b/Src/LexText/Lexicon/ReversalIndexEntryMenuHandler.cs @@ -49,7 +49,7 @@ public bool OnPromoteReversalindexEntry(object cmd) FdoCache cache = m_dataEntryForm.Cache; IReversalIndexEntry entry = slice.Object as IReversalIndexEntry; ICmObject newOwner = entry.Owner.Owner; - UndoableUnitOfWorkHelper.Do((Command) cmd, newOwner, + UndoableUnitOfWorkHelper.Do(((Command)cmd).UndoText, ((Command)cmd).RedoText, newOwner, () => { switch (newOwner.ClassID) diff --git a/Src/LexText/Morphology/InflAffixTemplateControl.cs b/Src/LexText/Morphology/InflAffixTemplateControl.cs index 95140e7c50..d7e06bc1f8 100644 --- a/Src/LexText/Morphology/InflAffixTemplateControl.cs +++ b/Src/LexText/Morphology/InflAffixTemplateControl.cs @@ -266,7 +266,7 @@ private void HandleMove(Command cmd, bool bLeft) int index; var slot = m_obj as IMoInflAffixSlot; GetAffixSequenceContainingSlot(slot, out seq, out index); - UndoableUnitOfWorkHelper.Do(cmd, m_template, + UndoableUnitOfWorkHelper.Do(cmd.UndoText, cmd.RedoText, m_template, () => { seq.RemoveAt(index); diff --git a/Src/xWorks/DTMenuHandler.cs b/Src/xWorks/DTMenuHandler.cs index e9e2cb7c5a..d52c6296a4 100644 --- a/Src/xWorks/DTMenuHandler.cs +++ b/Src/xWorks/DTMenuHandler.cs @@ -1199,7 +1199,7 @@ private bool AddNewLexEntryRef(object argument, int flidTypes) var ent = m_dataEntryForm.Root as ILexEntry; if (ent != null) { - UndoableUnitOfWorkHelper.Do(command, ent, + UndoableUnitOfWorkHelper.Do(command.UndoText, command.RedoText, ent, () => { var ler = Cache.ServiceLocator.GetInstance().Create(); diff --git a/Src/FDO/DomainServices/GlobalSettingServices.cs b/Src/xWorks/GlobalSettingServices.cs similarity index 88% rename from Src/FDO/DomainServices/GlobalSettingServices.cs rename to Src/xWorks/GlobalSettingServices.cs index ab5d6cfe66..e6363155a0 100644 --- a/Src/FDO/DomainServices/GlobalSettingServices.cs +++ b/Src/xWorks/GlobalSettingServices.cs @@ -1,12 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.Practices.ServiceLocation; +using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainImpl; using XCore; -namespace SIL.FieldWorks.FDO.DomainServices +namespace SIL.FieldWorks.XWorks { /// /// Global setting services provides a simple API for persisting and restoring global settings that affect all windows. diff --git a/Src/xWorks/xWorks.csproj b/Src/xWorks/xWorks.csproj index 6b6caf3964..41bfe8f2da 100644 --- a/Src/xWorks/xWorks.csproj +++ b/Src/xWorks/xWorks.csproj @@ -256,6 +256,7 @@ + From 3f72e49fd845c889d800f92c7e4fb882ce7d3540 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Tue, 10 Dec 2013 15:36:50 +0700 Subject: [PATCH 036/143] Remove more FwUtils dependencies from FDO Move FwRegistryHelper code from ImportFrom6_0 to the MigrateSqlDbs project. Change-Id: I4b9055dfe0f2012c563748ed426e454b0d4de0c7 --- .../DataMigration/ImportFrom6_0.cs | 16 ---------------- Src/MigrateSqlDbs/Program.cs | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs b/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs index 2abdea2ebc..cb3cc19c8c 100644 --- a/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs +++ b/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs @@ -421,22 +421,6 @@ private string FindComDllIfRegistered(RegistryKey clsidKey, string sClsid, ref s { if (!String.IsNullOrEmpty(version) && version.CompareTo("5.4") < 0) { - string launchesFlex = "0"; - string launchesTE = "0"; - if (RegistryHelper.KeyExists(FwRegistryHelper.FieldWorksRegistryKey, "Language Explorer")) - { - using (RegistryKey keyFlex = FwRegistryHelper.FieldWorksRegistryKey.CreateSubKey("Language Explorer")) - launchesFlex = keyFlex.GetValue("launches", "0") as string; - } - if (RegistryHelper.KeyExists(FwRegistryHelper.FieldWorksRegistryKey, FwSubKey.TE)) - { - using (RegistryKey keyTE = FwRegistryHelper.FieldWorksRegistryKey.CreateSubKey(FwSubKey.TE)) - launchesTE = keyTE.GetValue("launches", "0") as string; - } - if (launchesFlex == "0" && launchesTE == "0") - { - FwRegistryHelper.FieldWorksRegistryKey.SetValue("MigrationTo7Needed", "true"); - } } else if (m_fVerboseDebug) { diff --git a/Src/MigrateSqlDbs/Program.cs b/Src/MigrateSqlDbs/Program.cs index 965d57cb43..6cd0624e27 100644 --- a/Src/MigrateSqlDbs/Program.cs +++ b/Src/MigrateSqlDbs/Program.cs @@ -22,6 +22,7 @@ using System.IO; using System.Reflection; using System.Windows.Forms; +using Microsoft.Win32; using Palaso.WritingSystems.Migration; using Palaso.WritingSystems.Migration.WritingSystemsLdmlV0To1Migration; using SIL.FieldWorks.Common.Controls; @@ -115,6 +116,22 @@ static int Main(string[] rgArgs) { if (!String.IsNullOrEmpty(version) && version.CompareTo("5.4") < 0) { + string launchesFlex = "0"; + string launchesTE = "0"; + if (RegistryHelper.KeyExists(FwRegistryHelper.FieldWorksRegistryKey, "Language Explorer")) + { + using (RegistryKey keyFlex = FwRegistryHelper.FieldWorksRegistryKey.CreateSubKey("Language Explorer")) + launchesFlex = keyFlex.GetValue("launches", "0") as string; + } + if (RegistryHelper.KeyExists(FwRegistryHelper.FieldWorksRegistryKey, FwSubKey.TE)) + { + using (RegistryKey keyTE = FwRegistryHelper.FieldWorksRegistryKey.CreateSubKey(FwSubKey.TE)) + launchesTE = keyTE.GetValue("launches", "0") as string; + } + if (launchesFlex == "0" && launchesTE == "0") + { + FwRegistryHelper.FieldWorksRegistryKey.SetValue("MigrationTo7Needed", "true"); + } using (var dlg = new FWVersionTooOld(version)) { dlg.ShowDialog(); From 2695e40cb82b59778fe93d08265276f9d16966a4 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Tue, 10 Dec 2013 10:40:45 +0700 Subject: [PATCH 037/143] Removed references to FwUtils from FDO Change-Id: I9767131e988eea93520dd598c95f412b7c10b61b --- .../DetailControlsTests/DataTreeTests.cs | 6 +- .../DetailControlsMainWnd.cs | 2 +- .../Controls/DetailControls/SliceFactory.cs | 4 +- .../Controls/DetailControls/StringSlice.cs | 2 +- .../FwControls/ObtainProjectMethod.cs | 22 +- .../FwControls/ProgressDialogWithTask.cs | 4 +- .../ScrControls/FilterTextsDialogTE.cs | 4 +- .../Controls/ScrControls/ScrControls.csproj | 478 +++++++++-------- .../Controls/Widgets/UserInterfaceChooser.cs | 4 +- Src/Common/Controls/XMLViews/LayoutCache.cs | 2 +- .../XMLViews/ReallySimpleListChooser.cs | 2 +- .../TestColumnConfigureDialog.cs | 2 +- .../XMLViewsTests/TestManyOneBrowse.cs | 8 +- Src/Common/CoreImpl/CoreImpl.csproj | 2 + .../CoreImpl/CoreImplStrings.Designer.cs | 40 +- Src/Common/CoreImpl/CoreImplStrings.resx | 18 +- .../CoreImplTests/CoreImplTests.csproj | 1 + .../CoreImplTests/DirectoryFinderTests.cs | 96 ++++ Src/Common/CoreImpl/DirectoryFinder.cs | 124 +++++ .../CoreImpl/GlobalFileWritingSystemStore.cs | 45 +- .../VersionInfoProvider.cs} | 30 +- Src/Common/FieldWorks/FieldWorks.cs | 50 +- .../FieldWorksTests/ProjectIDTests.cs | 18 +- .../FieldWorks/PaObjects/PaLexicalInfo.cs | 21 +- Src/Common/FieldWorks/ProjectId.cs | 8 +- .../FieldWorks/ShareProjectsFolderDlg.cs | 4 +- .../FieldWorks/WelcomeToFieldWorksDlg.cs | 2 +- Src/Common/Framework/FwMainWnd.cs | 2 +- Src/Common/Framework/FwRegistrySettings.cs | 2 +- Src/Common/Framework/HelpTopicProviderBase.cs | 2 +- .../Framework/SettingsXmlAccessorBase.cs | 2 +- .../FwRemoteDatabaseConnectorService.csproj | 17 +- .../Program.cs | 6 + .../Service1.cs | 17 +- Src/Common/FwUtils/FLExBridgeHelper.cs | 6 +- ...irectoryFinder.cs => FwDirectoryFinder.cs} | 260 +++------ Src/Common/FwUtils/FwRegistryHelper.cs | 48 -- Src/Common/FwUtils/FwSubKey.cs | 4 +- Src/Common/FwUtils/FwUtils.cs | 12 +- Src/Common/FwUtils/FwUtils.csproj | 10 +- Src/Common/FwUtils/FwUtilsStrings.Designer.cs | 468 ++++++++-------- Src/Common/FwUtils/FwUtilsStrings.resx | 282 +++++----- .../FwUtilsTests/DirectoryFinderTests.cs | 468 ---------------- .../FwUtilsTests/DummyFwRegistryHelper.cs | 2 +- .../FwUtilsTests/FwDirectoryFinderTests.cs | 252 +++++++++ .../FwUtils/FwUtilsTests/FwUtilsTests.csproj | 2 +- Src/Common/FwUtils/IFwRegistryHelper.cs | 15 +- Src/Common/FwUtils/ShowHelp.cs | 2 +- Src/Common/RootSite/FwBaseVc.cs | 2 +- .../ApplicationServices/XmlTranslatedLists.cs | 11 +- Src/FDO/Application/Impl/DomainDataByFlid.cs | 1 - Src/FDO/DomainImpl/CmObject.cs | 1 - Src/FDO/DomainImpl/FdoFactoryAdditions.cs | 4 +- Src/FDO/DomainImpl/FdoScripture.cs | 5 +- Src/FDO/DomainImpl/OverridesCellar.cs | 4 +- Src/FDO/DomainImpl/OverridesLangProj.cs | 11 +- Src/FDO/DomainImpl/ScrImportSet.cs | 8 +- .../BackupRestore/BackupFileRepository.cs | 5 +- .../BackupRestore/BackupFileSettings.cs | 19 +- .../BackupRestore/BackupProjectSettings.cs | 17 +- .../BackupRestore/BackupSettings.cs | 9 + .../BackupRestore/ProjectBackupService.cs | 3 +- .../BackupRestore/ProjectRestoreService.cs | 38 +- .../BackupRestore/RestoreProjectSettings.cs | 12 +- .../DomainServices/ClientServerServices.cs | 136 +++-- .../DataMigration/DataMigration7000019.cs | 3 +- .../DataMigration/DataMigration7000029.cs | 6 +- .../DataMigration/DataMigration7000030.cs | 6 +- .../DataMigration/DataMigration7000033.cs | 2 +- .../DataMigration/DataMigration7000037.cs | 4 - .../DataMigration/DataMigration7000042.cs | 1 - .../DataMigration/DataMigration7000044.cs | 2 +- .../IDomainObjectDTORepository.cs | 17 +- .../DataMigration/ImportFrom6_0.cs | 30 +- .../DomainServices/DomainObjectServices.cs | 44 -- Src/FDO/DomainServices/FwProjectFinder.cs | 8 +- Src/FDO/DomainServices/ParatextHelper.cs | 39 +- Src/FDO/DomainServices/ScrChecksDataSource.cs | 12 +- Src/FDO/DomainServices/ScrMappingList.cs | 11 +- Src/FDO/DomainServices/StringServices.cs | 2 +- Src/FDO/DomainServices/ValidCharacters.cs | 24 +- Src/FDO/DomainServices/WfiWordformServices.cs | 1 - .../DomainServices/WritingSystemServices.cs | 14 +- Src/FDO/FDO.csproj | 9 +- .../BackupFileRepositoryTests.cs | 14 +- .../BackupRestoreSettingsTests.cs | 38 +- .../ProjectBackupServiceTestForLinkedFiles.cs | 2 +- .../ProjectBackupServiceTests.cs | 2 +- .../ProjectRestoreServiceTests.cs | 27 +- .../ProjectRestoreTestService.cs | 4 +- Src/FDO/FDOTests/CellarTests.cs | 2 +- Src/FDO/FDOTests/ClientServerServicesTests.cs | 41 +- .../CmSemanticDomainRepositoryTests.cs | 2 +- .../DataMigration7000001Tests.cs | 3 +- .../DataMigration7000002Tests.cs | 3 +- .../DataMigration7000003Tests.cs | 3 +- .../DataMigration7000005Tests.cs | 3 +- .../DataMigration7000006Tests.cs | 3 +- .../DataMigration7000007Tests.cs | 3 +- .../DataMigration7000008Tests.cs | 3 +- .../DataMigration7000009Tests.cs | 3 +- .../DataMigration7000010Tests.cs | 5 +- .../DataMigration7000011Tests.cs | 4 +- .../DataMigration7000012Tests.cs | 5 +- .../DataMigration7000013Tests.cs | 3 +- .../DataMigration7000014Tests.cs | 3 +- .../DataMigration7000015Tests.cs | 3 +- .../DataMigration7000016Tests.cs | 6 +- .../DataMigration7000017Tests.cs | 8 +- .../DataMigration7000018Tests.cs | 4 +- .../DataMigration7000019Tests.cs | 5 +- .../DataMigration7000020Tests.cs | 4 +- .../DataMigration7000022Tests.cs | 3 +- .../DataMigration7000023Tests.cs | 14 +- .../DataMigration7000024Tests.cs | 5 +- .../DataMigration7000025Tests.cs | 5 +- .../DataMigration7000026Tests.cs | 3 +- .../DataMigration7000027Tests.cs | 3 +- .../DataMigration7000028Tests.cs | 3 +- .../DataMigration7000029Tests.cs | 3 +- .../DataMigration7000030Tests.cs | 3 +- .../DataMigration7000031Tests.cs | 3 +- .../DataMigration7000032Tests.cs | 3 +- .../DataMigration7000033Tests.cs | 6 +- .../DataMigration7000034Tests.cs | 2 +- .../DataMigration7000035Tests.cs | 3 +- .../DataMigration7000036Tests.cs | 3 +- .../DataMigration7000037Tests.cs | 3 +- .../DataMigration7000040Tests.cs | 3 +- .../DataMigration7000041Tests.cs | 9 +- .../DataMigration7000042Tests.cs | 2 +- .../DataMigration7000044Tests.cs | 4 +- .../DataMigration7000047Tests.cs | 3 +- .../DataMigration7000051Tests.cs | 3 +- .../DataMigration7000052Tests.cs | 3 +- .../DataMigration7000056Tests.cs | 5 +- .../DataMigration7000057Tests.cs | 5 +- .../DataMigration7000058Tests.cs | 5 +- .../DataMigration7000059Tests.cs | 3 +- .../DataMigration7000060Tests.cs | 4 +- .../DataMigration7000061Tests.cs | 3 +- .../DataMigration7000062Tests.cs | 3 +- .../DataMigration7000063Tests.cs | 3 +- .../DataMigration7000065Tests.cs | 3 +- .../DataMigration7000066Tests.cs | 9 +- .../DataMigration7000067Tests.cs | 3 +- .../DataMigrationBasicTests.cs | 3 +- .../DataMigrationTestServices.cs | 2 +- .../IDomainObjectDTORepositoryTests.cs | 25 +- Src/FDO/FDOTests/Db4oServerInfoTests.cs | 8 +- Src/FDO/FDOTests/DummyFdoUI.cs | 5 +- Src/FDO/FDOTests/FDOTests.csproj | 1 + Src/FDO/FDOTests/FdoCacheTests.cs | 66 +-- Src/FDO/FDOTests/FdoScriptureTests.cs | 70 ++- Src/FDO/FDOTests/FdoTestBase.cs | 4 +- .../FDOTests/FwCharacterCategorizerTests.cs | 11 +- Src/FDO/FDOTests/LangProjectTests.cs | 11 +- .../LinkedFilesRelativePathHelperTests.cs | 137 +++++ Src/FDO/FDOTests/ParagraphParserTests.cs | 6 +- Src/FDO/FDOTests/ParatextHelperTests.cs | 9 +- .../PersistingBackendProviderTests.cs | 25 +- .../PersistingLayerTests.BEPPortTests.cs | 10 +- Src/FDO/FDOTests/ScrChecksDataSourceTests.cs | 3 +- Src/FDO/FDOTests/ScrImportFileInfoTests.cs | 3 +- Src/FDO/FDOTests/ScrImportSetTests.cs | 4 +- Src/FDO/FDOTests/ScrMappingListTests.cs | 31 +- Src/FDO/FDOTests/ScrSfFileListTests.cs | 3 +- Src/FDO/FDOTests/ValidCharactersTests.cs | 46 +- .../FDOTests/WritingSystemServicesTests.cs | 32 +- Src/FDO/FDOTests/XmlImportDataTests.cs | 6 +- Src/FDO/FDOTests/XmlListTests.cs | 3 +- Src/FDO/FDOTests/XmlTranslatedListsTests.cs | 2 +- Src/FDO/FdoFactoryInterfaceAdditions.cs | 2 +- Src/FDO/FdoFileHelper.cs | 3 + Src/FDO/FdoInterfaceAdditions.cs | 3 +- Src/FDO/IFdoDirectories.cs | 18 + Src/FDO/IFdoUI.cs | 5 +- Src/FDO/IOC/FdoServiceLocatorFactory.cs | 15 +- .../Impl/ClientServerBackendProvider.cs | 2 +- .../Impl/Db4oClientServerBackendProvider.cs | 11 +- Src/FDO/Infrastructure/Impl/Db4oServerInfo.cs | 96 ++-- .../Infrastructure/Impl/FDOBackendProvider.cs | 29 +- .../Impl/FdoRepositoryAdditions.cs | 1 - .../Impl/MemoryOnlyBackendProvider.cs | 4 +- .../Infrastructure/Impl/SimpleProjectId.cs | 4 +- .../Infrastructure/Impl/XMLBackendProvider.cs | 11 +- ...hs.cs => LinkedFilesRelativePathHelper.cs} | 19 +- Src/{Common/FwUtils => FDO}/ProjectInfo.cs | 34 +- Src/FDO/SilentFdoUI.cs | 5 +- Src/FDO/fdoCache.cs | 120 +++-- Src/FDOBrowser/FDOBrowserForm.cs | 8 +- Src/FDOBrowser/FDOClassList.cs | 2 +- Src/FDOBrowser/ModelWnd.cs | 2 +- Src/FXT/FxtDll/FxtDllTests/FxtTestBase.cs | 2 +- Src/FXT/FxtDll/FxtDllTests/SimpleTests.cs | 2 +- .../FxtDllTests/StandFormatExportTests.cs | 11 +- Src/FdoUi/Dialogs/SummaryDialogForm.cs | 2 +- Src/FdoUi/FwFdoUI.cs | 8 +- Src/FdoUi/LexEntryUi.cs | 6 +- Src/FwCoreDlgs/ArchiveWithRamp.cs | 2 +- .../BackupRestore/BackupProjectDlg.cs | 8 +- .../BackupRestore/BackupProjectPresenter.cs | 6 +- .../BackupRestore/RestoreProjectDlg.cs | 8 +- .../BackupRestore/RestoreProjectPresenter.cs | 3 +- Src/FwCoreDlgs/CharContextCtrl.cs | 9 +- Src/FwCoreDlgs/ChooseLangProjectDialog.cs | 16 +- Src/FwCoreDlgs/FwCheckAnthroListDlg.cs | 10 +- .../FwCoreDlgsTests/FwNewLangProjectTests.cs | 19 +- .../RestoreProjectPresenterTests.cs | 14 +- Src/FwCoreDlgs/FwDeleteProjectDlg.cs | 4 +- Src/FwCoreDlgs/FwFindReplaceDlg.cs | 2 +- Src/FwCoreDlgs/FwHelpAbout.cs | 5 +- Src/FwCoreDlgs/FwNewLangProject.cs | 36 +- Src/FwCoreDlgs/MoveOrCopyFilesDlg.cs | 2 +- Src/FwCoreDlgs/PicturePropertiesDialog.cs | 2 +- Src/FwCoreDlgs/ProjectLocationSharingDlg.cs | 14 +- Src/FwCoreDlgs/PunctuationDlg.cs | 6 +- Src/FwCoreDlgs/RealSplashScreen.cs | 5 +- Src/FwCoreDlgs/UtilityDlg.cs | 4 +- Src/FwCoreDlgs/ValidCharactersDlg.cs | 11 +- Src/LexText/Discourse/ConstChartBody.cs | 2 +- Src/LexText/Discourse/Discourse.csproj | 412 ++++++++------- .../Discourse/DiscourseExportDialog.cs | 2 +- Src/LexText/FlexDePlugin/FlexDePlugin.csproj | 270 +++++----- .../FlexDePluginTests/FlexDePluginTest.cs | 4 +- .../FlexDePluginTests/MyFoldersTest.cs | 4 +- .../Interlinear/BIRDInterlinearImporter.cs | 4 +- .../ITextDllTests/BIRDFormatImportTests.cs | 6 +- .../ITextDllTests/InterlinSfmImportTests.cs | 3 +- .../ITextDllTests/InterlinearExporterTests.cs | 6 +- .../Interlinear/InterlinearExportDialog.cs | 2 +- .../Interlinear/InterlinearImportDlg.cs | 4 +- .../Interlinear/InterlinearSfmImportWizard.cs | 2 +- .../InterlinearTextsRecordClerk.cs | 2 +- .../Interlinear/LinguaLinksImportDlg.cs | 2 +- Src/LexText/Interlinear/WordBreakGuesser.cs | 3 +- .../DataNotebook/NotebookImportWiz.cs | 6 +- Src/LexText/LexTextControls/LexImport.cs | 2 +- .../LexTextControls/LexImportWizard.cs | 6 +- .../LexTextControls/LexImportWizardHelpers.cs | 4 +- .../LexTextControls/LexImportWizardMarker.cs | 4 +- Src/LexText/LexTextControls/LexOptionsDlg.cs | 10 +- .../LexTextControlsTests/LexImportTests.cs | 2 +- .../LexTextControlsTests/LiftExportTests.cs | 2 +- .../LexTextControlsTests/LiftMergerTests.cs | 4 +- .../MsaInflectionFeatureListDlgTests.cs | 4 +- .../WordsSfmImportTests.cs | 3 +- Src/LexText/LexTextControls/LiftMerger.cs | 10 +- .../LiftMergerSupportCodeAndClasses.cs | 2 +- .../LexTextControls/MasterCategoryListDlg.cs | 2 +- Src/LexText/LexTextControls/MasterListDlg.cs | 2 +- Src/LexText/LexTextDll/LexTextApp.cs | 26 +- Src/LexText/LexTextDll/TransductionSample.cs | 2 +- Src/LexText/Lexicon/FLExBridgeListener.cs | 2 +- Src/LexText/Lexicon/ReversalListener.cs | 4 +- Src/LexText/Morphology/BasicIPASymbolSlice.cs | 2 +- Src/LexText/Morphology/MGA/MGADialog.cs | 2 +- .../Morphology/MGA/MGAHtmlHelpDialog.cs | 4 +- .../Morphology/MGA/MGATests/MGATests.cs | 7 +- .../Morphology/MasterPhonFeatDlgListener.cs | 2 +- Src/LexText/Morphology/RespellerDlg.cs | 6 +- .../ParserEngine/ParserCore/HCWorker.cs | 2 +- .../ParserCore/M3ToParserTransformerBase.cs | 2 +- .../M3ToXAmpleTransformerTests.cs | 4 +- .../ParserCoreTests/UpdateParserDataTests.cs | 4 +- .../ParserEngine/ParserCore/XAmpleWorker.cs | 4 +- Src/LexText/ParserUI/ParserTraceBase.cs | 2 +- .../ParserUITests/ConvertFailuresTests.cs | 2 +- .../WordGrammarDebuggingTests.cs | 4 +- Src/LexText/ParserUI/TryAWordDlg.cs | 2 +- Src/MigrateSqlDbs/ExistingProjectDlg.cs | 4 +- Src/MigrateSqlDbs/MigrateProjects.cs | 8 +- Src/MigrateSqlDbs/MigrateSqlDbs.csproj | 5 + Src/MigrateSqlDbs/Program.cs | 5 +- Src/TE/DiffView/DiffDialog.cs | 14 +- Src/TE/NotesView/NotesMainWnd.cs | 6 +- .../EditorialChecksControl.cs | 4 +- .../EditorialChecksRenderingsControl.cs | 4 +- .../InstalledScriptureChecks.cs | 2 +- .../TeEditorialChecks.csproj | 500 +++++++++--------- Src/TE/TeImportExport/ExportUsfm.cs | 10 +- Src/TE/TeImportExport/ExportXhtml.cs | 2 +- Src/TE/TeImportExport/ImportWizard.cs | 4 +- Src/TE/TeImportExport/ScrNoteImportManager.cs | 4 +- Src/TE/TeImportExport/TeImport.cs | 2 +- .../ImportWizardTests.cs | 2 +- .../ImportTests/ImportDialogTests.cs | 3 +- .../ImportTests/TeAnnotationXmlImportTests.cs | 3 +- .../ImportTests/TeImportManagerTests.cs | 5 +- .../ImportTests/TeImportTests.cs | 6 +- .../ImportTests/TeImportTestsBase.cs | 4 +- .../ImportTests/TeXmlImportTests.cs | 5 +- .../TeImportExportTests/SCTextEnumTests.cs | 3 +- .../SFFileListBuilderTests.cs | 5 +- Src/TE/TeImportExport/TeImportManager.cs | 2 +- Src/TE/TeImportExport/TeXmlImport.cs | 2 +- Src/TE/TeScrInitializer/TeKeyTermsInit.cs | 12 +- Src/TE/TeScrInitializer/TePublicationsInit.cs | 2 +- .../TeScrInitializer/TeScrInitializer.csproj | 497 ++++++++--------- .../TeKeyTermsInitTests.cs | 8 +- .../TeScrInitializerTests.cs | 3 +- .../TeScrNoteCategoriesInit.cs | 2 +- Src/TE/TeStylesXml/TeStylesXmlAccessor.cs | 2 +- Src/TeDll/DockableUsfmBrowser.cs | 2 +- Src/TeDll/TeApp.cs | 6 +- Src/TeDll/TeDllTests/ScrObjWrapperTests.cs | 8 +- Src/TeDll/TeMainWnd.cs | 13 +- Src/TestUtils/BaseTest.cs | 1 - Src/UnicodeCharEditor/CharEditorWindow.cs | 2 +- .../PUAInstallerTests.cs | 3 +- Src/Utilities/FixFwDataDll/ErrorFixer.cs | 2 +- Src/Utilities/FixFwDataDll/FixErrorsDlg.cs | 2 +- .../FixFwDataDllTests/FwDataFixerTest.cs | 2 +- Src/XCore/IncludeXml.cs | 4 +- Src/XCore/Inventory.cs | 8 +- Src/XCore/XMessageBoxExManager.cs | 2 +- Src/XCore/xCore.csproj | 4 + Src/XCore/xCoreTests/IncludeXmlTests.cs | 2 +- Src/xWorks/AddCustomFieldDlg.cs | 2 +- Src/xWorks/Archiving/ReapRamp.cs | 4 +- Src/xWorks/ExportDialog.cs | 2 +- Src/xWorks/FwXApp.cs | 6 +- Src/xWorks/FwXWindow.cs | 2 +- Src/xWorks/GeneratedHtmlViewer.cs | 10 +- Src/xWorks/RecordEditView.cs | 2 +- Src/xWorks/xWorksTests/ExportDialogTests.cs | 3 +- Src/xWorks/xWorksTests/XWorksAppTestBase.cs | 2 +- 327 files changed, 3541 insertions(+), 3447 deletions(-) create mode 100644 Src/Common/CoreImpl/CoreImplTests/DirectoryFinderTests.cs create mode 100644 Src/Common/CoreImpl/DirectoryFinder.cs rename Src/Common/{FwUtils/FwVersionInfoProvider.cs => CoreImpl/VersionInfoProvider.cs} (87%) rename Src/Common/FwUtils/{DirectoryFinder.cs => FwDirectoryFinder.cs} (75%) delete mode 100644 Src/Common/FwUtils/FwUtilsTests/DirectoryFinderTests.cs create mode 100644 Src/Common/FwUtils/FwUtilsTests/FwDirectoryFinderTests.cs create mode 100644 Src/FDO/FDOTests/LinkedFilesRelativePathHelperTests.cs create mode 100644 Src/FDO/IFdoDirectories.cs rename Src/FDO/{FdoFileHelperRelativePaths.cs => LinkedFilesRelativePathHelper.cs} (96%) rename Src/{Common/FwUtils => FDO}/ProjectInfo.cs (80%) diff --git a/Src/Common/Controls/DetailControls/DetailControlsTests/DataTreeTests.cs b/Src/Common/Controls/DetailControls/DetailControlsTests/DataTreeTests.cs index b9b757b84b..f9eca42b74 100644 --- a/Src/Common/Controls/DetailControls/DetailControlsTests/DataTreeTests.cs +++ b/Src/Common/Controls/DetailControls/DetailControlsTests/DataTreeTests.cs @@ -32,7 +32,7 @@ public class DataTreeTests : MemoryOnlyBackendProviderRestoredForEachTestTestBas #region Fixture Setup and Teardown internal static StringTable GenerateStringTable() { - string configurationDir = Path.Combine(DirectoryFinder.FWCodeDirectory, + string configurationDir = Path.Combine(FwDirectoryFinder.CodeDirectory, @"Language Explorer/Configuration"); var stringTable = new SIL.Utils.StringTable(configurationDir); @@ -41,7 +41,7 @@ internal static StringTable GenerateStringTable() internal static Inventory GenerateParts() { - string partDirectory = Path.Combine(DirectoryFinder.FwSourceDirectory, + string partDirectory = Path.Combine(FwDirectoryFinder.SourceDirectory, @"Common/Controls/DetailControls/DetailControlsTests"); var keyAttrs = new Dictionary(); @@ -55,7 +55,7 @@ internal static Inventory GenerateParts() internal static Inventory GenerateLayouts() { - string partDirectory = Path.Combine(DirectoryFinder.FwSourceDirectory, + string partDirectory = Path.Combine(FwDirectoryFinder.SourceDirectory, @"Common/Controls/DetailControls/DetailControlsTests"); Dictionary keyAttrs = new Dictionary(); diff --git a/Src/Common/Controls/DetailControls/DetailControlsTests/DetailControlsMainWnd.cs b/Src/Common/Controls/DetailControls/DetailControlsTests/DetailControlsMainWnd.cs index 7af88cb232..2b9b06b86e 100644 --- a/Src/Common/Controls/DetailControls/DetailControlsTests/DetailControlsMainWnd.cs +++ b/Src/Common/Controls/DetailControls/DetailControlsTests/DetailControlsMainWnd.cs @@ -165,7 +165,7 @@ public void InitAndShowClient() m_dataEntryForm = new DataTree(); SuspendLayout(); - string partDirectory = Path.Combine(DirectoryFinder.FWCodeDirectory, + string partDirectory = Path.Combine(FwDirectoryFinder.CodeDirectory, @"Language Explorer\Configuration\Parts"); Dictionary keyAttrs = new Dictionary(); keyAttrs["layout"] = new string[] {"class", "type", "mode", "name" }; diff --git a/Src/Common/Controls/DetailControls/SliceFactory.cs b/Src/Common/Controls/DetailControls/SliceFactory.cs index 9441958d88..66ce5543ac 100644 --- a/Src/Common/Controls/DetailControls/SliceFactory.cs +++ b/Src/Common/Controls/DetailControls/SliceFactory.cs @@ -236,7 +236,7 @@ public static Slice Create(FdoCache cache, string editor, int flid, XmlNode node { try { - slice = new ImageSlice(DirectoryFinder.FWCodeDirectory, XmlUtils.GetManditoryAttributeValue(node, "param1")); + slice = new ImageSlice(FwDirectoryFinder.CodeDirectory, XmlUtils.GetManditoryAttributeValue(node, "param1")); } catch (Exception error) { @@ -385,7 +385,7 @@ public static Slice Create(FdoCache cache, string editor, int flid, XmlNode node //Since the editor has not been implemented yet, //is there a bitmap file that we can show for this editor? //Such bitmaps belong in the distFiles xde directory - string fwCodeDir = DirectoryFinder.FWCodeDirectory; + string fwCodeDir = FwDirectoryFinder.CodeDirectory; string editorBitmapRelativePath = "xde/" + editor + ".bmp"; if(File.Exists(Path.Combine(fwCodeDir, editorBitmapRelativePath))) slice = new ImageSlice(fwCodeDir, editorBitmapRelativePath); diff --git a/Src/Common/Controls/DetailControls/StringSlice.cs b/Src/Common/Controls/DetailControls/StringSlice.cs index f366509aa8..ff8ac8ba6d 100644 --- a/Src/Common/Controls/DetailControls/StringSlice.cs +++ b/Src/Common/Controls/DetailControls/StringSlice.cs @@ -263,7 +263,7 @@ private ITsString NameOfWs(int ws) m_wsLabel = ws; var sWs = m_cache.WritingSystemFactory.GetStrFromWs(ws); IWritingSystem wsys; - WritingSystemServices.FindOrCreateWritingSystem(m_cache, sWs, false, false, out wsys); + WritingSystemServices.FindOrCreateWritingSystem(m_cache, FwDirectoryFinder.TemplateDirectory, sWs, false, false, out wsys); var result = wsys.Abbreviation; if (string.IsNullOrEmpty(result)) result = "??"; diff --git a/Src/Common/Controls/FwControls/ObtainProjectMethod.cs b/Src/Common/Controls/FwControls/ObtainProjectMethod.cs index 45a10fd42f..98338572d2 100644 --- a/Src/Common/Controls/FwControls/ObtainProjectMethod.cs +++ b/Src/Common/Controls/FwControls/ObtainProjectMethod.cs @@ -24,11 +24,11 @@ public static class ObtainProjectMethod /// The repo may be a lift or full FW repo, but it can be from any source source, as long as the code can create an FW project from it. /// /// Null if the operation was cancelled or otherwise did not work. The full pathname of an fwdata file, if it did work. - public static string ObtainProjectFromAnySource(Form parent, IHelpTopicProvider helpTopicProvider, out ObtainedProjectType obtainedProjectType, IFdoUI ui) + public static string ObtainProjectFromAnySource(Form parent, IHelpTopicProvider helpTopicProvider, out ObtainedProjectType obtainedProjectType) { bool dummy; string fwdataFileFullPathname; - var success = FLExBridgeHelper.LaunchFieldworksBridge(DirectoryFinder.ProjectsDirectory, null, FLExBridgeHelper.Obtain, null, + var success = FLExBridgeHelper.LaunchFieldworksBridge(FwDirectoryFinder.ProjectsDirectory, null, FLExBridgeHelper.Obtain, null, FDOBackendProvider.ModelVersion, "0.13", null, out dummy, out fwdataFileFullPathname); if (!success) { @@ -45,7 +45,7 @@ public static string ObtainProjectFromAnySource(Form parent, IHelpTopicProvider if (fwdataFileFullPathname.EndsWith("lift")) { - fwdataFileFullPathname = CreateProjectFromLift(parent, helpTopicProvider, fwdataFileFullPathname, ui); + fwdataFileFullPathname = CreateProjectFromLift(parent, helpTopicProvider, fwdataFileFullPathname); obtainedProjectType = ObtainedProjectType.Lift; } @@ -55,7 +55,7 @@ public static string ObtainProjectFromAnySource(Form parent, IHelpTopicProvider /// /// Create a new Fieldworks project and import a lift file into it. Return the .fwdata path. /// - private static string CreateProjectFromLift(Form parent, IHelpTopicProvider helpTopicProvider, string liftPath, IFdoUI ui) + private static string CreateProjectFromLift(Form parent, IHelpTopicProvider helpTopicProvider, string liftPath) { string projectPath; FdoCache cache; @@ -72,7 +72,7 @@ private static string CreateProjectFromLift(Form parent, IHelpTopicProvider help progressDlg.Title = FwControls.ksCreatingLiftProject; var cacheReceiver = new FdoCache[1]; // a clumsy way of handling an out parameter, consistent with RunTask projectPath = (string)progressDlg.RunTask(true, CreateProjectTask, - new[] { liftPath, parent, ui, anthroListFile, cacheReceiver }); + new[] { liftPath, parent, anthroListFile, cacheReceiver }); cache = cacheReceiver[0]; } @@ -102,20 +102,19 @@ private static object CreateProjectTask(IThreadedProgress progress, object[] par // Get required parameters. Ideally these would just be the signature of the method, but RunTask requires object[]. var liftPathname = (string) parameters[0]; var synchronizeInvoke = (ISynchronizeInvoke) parameters[1]; - var userAction = (IFdoUI) parameters[2]; - var anthroFile = (string) parameters[3]; - var cacheReceiver = (FdoCache[]) parameters[4]; + var anthroFile = (string) parameters[2]; + var cacheReceiver = (FdoCache[]) parameters[3]; IWritingSystem wsVern, wsAnalysis; RetrieveDefaultWritingSystemsFromLift(liftPathname, out wsVern, out wsAnalysis); string projectPath = FdoCache.CreateNewLangProj(progress, Directory.GetParent(Path.GetDirectoryName(liftPathname)).Parent.Name, // Get the new Flex project name from the Lift pathname. - synchronizeInvoke, userAction, wsAnalysis, wsVern, null, null, null, anthroFile); + FwDirectoryFinder.FdoDirectories, synchronizeInvoke, wsAnalysis, wsVern, null, null, null, anthroFile); // This is a temporary cache, just to do the import, and AFAIK we have no access to the current // user WS. So create it as "English". Put it in the array to return to the caller. - cacheReceiver[0] = FdoCache.CreateCacheFromLocalProjectFile(projectPath, "en", progress, userAction); + cacheReceiver[0] = FdoCache.CreateCacheFromLocalProjectFile(projectPath, "en", new SilentFdoUI(synchronizeInvoke), FwDirectoryFinder.FdoDirectories, progress); return projectPath; } @@ -127,8 +126,7 @@ private static void RetrieveDefaultWritingSystemsFromLift(string liftPath, out I string vernWsId, analysisWsId; using (var reader = XmlReader.Create(liftReader)) RetrieveDefaultWritingSystemIdsFromLift(reader, out vernWsId, out analysisWsId); - var wsManager = new PalasoWritingSystemManager( - new GlobalFileWritingSystemStore(DirectoryFinder.GlobalWritingSystemStoreDirectory)); + var wsManager = new PalasoWritingSystemManager(new GlobalFileWritingSystemStore()); wsManager.GetOrSet(vernWsId, out wsVern); wsManager.GetOrSet(analysisWsId, out wsAnalysis); } diff --git a/Src/Common/Controls/FwControls/ProgressDialogWithTask.cs b/Src/Common/Controls/FwControls/ProgressDialogWithTask.cs index bdfd6a40bf..a8b7fd6811 100644 --- a/Src/Common/Controls/FwControls/ProgressDialogWithTask.cs +++ b/Src/Common/Controls/FwControls/ProgressDialogWithTask.cs @@ -711,7 +711,7 @@ private void DialogShown() /// public static void ImportTranslatedListsForWs(Form parentWindow, FdoCache cache, string ws) { - string path = XmlTranslatedLists.TranslatedListsPathForWs(ws); + string path = XmlTranslatedLists.TranslatedListsPathForWs(ws, FwDirectoryFinder.TemplateDirectory); if (!File.Exists(path)) return; using (var dlg = new ProgressDialogWithTask(parentWindow)) @@ -736,7 +736,7 @@ private static object ImportTranslatedListsForWs(IThreadedProgress dlg, object[] { var ws = (string)args[0]; var cache = (FdoCache) args[1]; - XmlTranslatedLists.ImportTranslatedListsForWs(ws, cache, dlg); + XmlTranslatedLists.ImportTranslatedListsForWs(ws, cache, FwDirectoryFinder.TemplateDirectory, dlg); return null; } #endregion diff --git a/Src/Common/Controls/ScrControls/FilterTextsDialogTE.cs b/Src/Common/Controls/ScrControls/FilterTextsDialogTE.cs index b5ee9c9e12..07d35088a7 100644 --- a/Src/Common/Controls/ScrControls/FilterTextsDialogTE.cs +++ b/Src/Common/Controls/ScrControls/FilterTextsDialogTE.cs @@ -58,12 +58,12 @@ public FilterTextsDialogTE(FdoCache cache, IStText[] objList, IHelpTopicProvider helpProvider; if (FwUtils.FwUtils.IsTEInstalled) { - helpProvider = (IHelpTopicProvider) DynamicLoader.CreateObject(DirectoryFinder.TeDll, + helpProvider = (IHelpTopicProvider) DynamicLoader.CreateObject(FwDirectoryFinder.TeDll, "SIL.FieldWorks.TE.TeHelpTopicProvider"); } else { - helpProvider = (IHelpTopicProvider)DynamicLoader.CreateObject(DirectoryFinder.FlexDll, + helpProvider = (IHelpTopicProvider)DynamicLoader.CreateObject(FwDirectoryFinder.FlexDll, "SIL.FieldWorks.XWorks.LexText.FlexHelpTopicProvider"); } NonUndoableUnitOfWorkHelper.Do(cache.ActionHandlerAccessor, () => diff --git a/Src/Common/Controls/ScrControls/ScrControls.csproj b/Src/Common/Controls/ScrControls/ScrControls.csproj index 8b6f48a707..f72c327a3d 100644 --- a/Src/Common/Controls/ScrControls/ScrControls.csproj +++ b/Src/Common/Controls/ScrControls/ScrControls.csproj @@ -1,257 +1,267 @@ - + - Local - 9.0.30729 - 2.0 - {330F1096-A67E-4A08-9A09-D4CFE8FC4079} - SAK - SAK - SAK - Debug - AnyCPU - - - - - ScrControls - - - JScript - Grid - IE50 - false - Library - SIL.FieldWorks.Common.Controls - OnBuildSuccess - - - - - - - SAK - 3.5 - false - v4.0 - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - true - + Local + 9.0.30729 + 2.0 + {330F1096-A67E-4A08-9A09-D4CFE8FC4079} + + + + + + + Debug + AnyCPU + + + + + ScrControls + + + JScript + Grid + IE50 + false + Library + SIL.FieldWorks.Common.Controls + OnBuildSuccess + + + + + + + + + 3.5 + false + v4.0 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + - ..\..\..\..\Output\Debug\ - false - 285212672 - false - - - DEBUG;TRACE - ..\..\..\..\Output\Debug\ScrControls.xml - true - 4096 - false - 168,169,219,414,649,1635,1702,1701 - false - false - false - true - 4 - full - prompt - AllRules.ruleset - x86 + ..\..\..\..\Output\Debug\ + false + 285212672 + false + + + DEBUG;TRACE + ..\..\..\..\Output\Debug\ScrControls.xml + true + 4096 + false + 168,169,219,414,649,1635,1702,1701 + false + false + false + true + 4 + full + prompt + AllRules.ruleset + x86 - ..\..\..\..\Output\Release\ - false - 285212672 - false - - - TRACE - - - true - 4096 - false - 168,169,219,414,649,1635,1702,1701 - true - false - false - false - 4 - full - prompt - AllRules.ruleset - x86 + ..\..\..\..\Output\Release\ + false + 285212672 + false + + + TRACE + + + true + 4096 + false + 168,169,219,414,649,1635,1702,1701 + true + false + false + false + 4 + full + prompt + AllRules.ruleset + x86 - - False - ..\..\..\..\Output\Debug\BasicUtils.dll - - - COMInterfaces - ..\..\..\..\Output\Debug\COMInterfaces.dll - - - FDO - ..\..\..\..\Output\debug\FDO.dll - - - Framework - ..\..\..\..\Output\Debug\Framework.dll - - - FwControls - ..\..\..\..\Output\Debug\FwControls.dll - - - FwResources - ..\..\..\..\Output\Debug\FwResources.dll - - - FwUtils - ..\..\..\..\Output\Debug\FwUtils.dll - - - False - ..\..\..\..\DistFiles\Microsoft.Practices.ServiceLocation.dll - - - Reporting - ..\..\..\..\Output\Debug\Reporting.dll - - - RootSite - ..\..\..\..\Output\Debug\RootSite.dll - - - ScriptureUtils - ..\..\..\..\Output\debug\ScriptureUtils.dll - - - ScrUtilsInterfaces - ..\..\..\..\Output\Debug\ScrUtilsInterfaces.dll - - - False - - - False - ..\..\..\..\Output\Debug\SharedScrUtils.dll - - - System - - - System.Data - - - System.Drawing - - - System.Windows.Forms - - - System.XML - - - False - - - xCoreInterfaces - ..\..\..\..\Output\Debug\xCoreInterfaces.dll - - - False - + + False + ..\..\..\..\Output\Debug\BasicUtils.dll + + + COMInterfaces + ..\..\..\..\Output\Debug\COMInterfaces.dll + + + FDO + ..\..\..\..\Output\debug\FDO.dll + + + Framework + ..\..\..\..\Output\Debug\Framework.dll + + + FwControls + ..\..\..\..\Output\Debug\FwControls.dll + + + FwResources + ..\..\..\..\Output\Debug\FwResources.dll + + + FwUtils + ..\..\..\..\Output\Debug\FwUtils.dll + + + False + ..\..\..\..\DistFiles\Microsoft.Practices.ServiceLocation.dll + + + Reporting + ..\..\..\..\Output\Debug\Reporting.dll + + + RootSite + ..\..\..\..\Output\Debug\RootSite.dll + + + ScriptureUtils + ..\..\..\..\Output\debug\ScriptureUtils.dll + + + ScrUtilsInterfaces + ..\..\..\..\Output\Debug\ScrUtilsInterfaces.dll + + + False + + + False + ..\..\..\..\Output\Debug\SharedScrUtils.dll + + + System + + + System.Data + + + System.Drawing + + + System.Windows.Forms + + + System.XML + + + False + + + xCoreInterfaces + ..\..\..\..\Output\Debug\xCoreInterfaces.dll + + + False + - - Code - - - - CommonAssemblyInfo.cs - - - - - True - True - ScrControls.resx - - - - - FilterTextsDialogTE.cs - - - ResXFileCodeGenerator - ScrControls.Designer.cs - Designer - - - DbScrPassageControl.cs - Designer - - - DbScrPassageDropDown.cs - Designer - + + CommonAssemblyInfo.cs + + + + Form + + + True + True + ScrControls.resx + + + UserControl + + + Form + + + FilterTextsDialogTE.cs + + + ResXFileCodeGenerator + ScrControls.Designer.cs + Designer + + + DbScrPassageControl.cs + Designer + + + DbScrPassageDropDown.cs + Designer + - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 2.0 %28x86%29 - true - - - False - .NET Framework 3.0 %28x86%29 - false - - - False - .NET Framework 3.5 - false - - - False - .NET Framework 3.5 SP1 - false - + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + true + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + False + .NET Framework 3.5 SP1 + false + - + - - - - + + + + \ No newline at end of file diff --git a/Src/Common/Controls/Widgets/UserInterfaceChooser.cs b/Src/Common/Controls/Widgets/UserInterfaceChooser.cs index 111e3c5a10..b88300d2e1 100644 --- a/Src/Common/Controls/Widgets/UserInterfaceChooser.cs +++ b/Src/Common/Controls/Widgets/UserInterfaceChooser.cs @@ -180,10 +180,10 @@ private void AddAvailableLangsFromSatelliteDlls() /// ------------------------------------------------------------------------------------ private void AddAvailableLangsFromKeyTermsLocalizations() { - foreach (string file in DirectoryFinder.KeyTermsLocalizationFiles) + foreach (string file in FwDirectoryFinder.KeyTermsLocalizationFiles) { if (!String.IsNullOrEmpty(file)) - AddLanguage(DirectoryFinder.GetLocaleFromKeyTermsLocFile(file)); + AddLanguage(FwDirectoryFinder.GetLocaleFromKeyTermsLocFile(file)); } } diff --git a/Src/Common/Controls/XMLViews/LayoutCache.cs b/Src/Common/Controls/XMLViews/LayoutCache.cs index 5f54ea89fb..8d5feabcf0 100644 --- a/Src/Common/Controls/XMLViews/LayoutCache.cs +++ b/Src/Common/Controls/XMLViews/LayoutCache.cs @@ -91,7 +91,7 @@ public static void InitializePartInventories(string sDatabase, { Debug.Assert(app != null, "app cannot be null"); - string partDirectory = Path.Combine(DirectoryFinder.FlexFolder, + string partDirectory = Path.Combine(FwDirectoryFinder.FlexFolder, Path.Combine("Configuration", "Parts")); var keyAttrs = new Dictionary(); keyAttrs["layout"] = new[] {"class", "type", "name", "choiceGuid" }; diff --git a/Src/Common/Controls/XMLViews/ReallySimpleListChooser.cs b/Src/Common/Controls/XMLViews/ReallySimpleListChooser.cs index cfe5a6e002..989baf1078 100644 --- a/Src/Common/Controls/XMLViews/ReallySimpleListChooser.cs +++ b/Src/Common/Controls/XMLViews/ReallySimpleListChooser.cs @@ -1221,7 +1221,7 @@ private void NavigateToSelectedTopic() if (!Path.IsPathRooted(helpFile)) { // Helps are part of the installed code files. See FWR-1002. - string helpsPath = Path.Combine(DirectoryFinder.FWCodeDirectory, "Helps"); + string helpsPath = Path.Combine(FwDirectoryFinder.CodeDirectory, "Helps"); helpFile = Path.Combine(helpsPath, helpFile); } #if __MonoCS__ diff --git a/Src/Common/Controls/XMLViews/XMLViewsTests/TestColumnConfigureDialog.cs b/Src/Common/Controls/XMLViews/XMLViewsTests/TestColumnConfigureDialog.cs index 3888706df4..a012c01d72 100644 --- a/Src/Common/Controls/XMLViews/XMLViewsTests/TestColumnConfigureDialog.cs +++ b/Src/Common/Controls/XMLViews/XMLViewsTests/TestColumnConfigureDialog.cs @@ -36,7 +36,7 @@ public void SetUp() m_mediator = new Mediator(); m_mediator.StringTbl = new StringTable("../../DistFiles/Language Explorer/Configuration"); m_cache = FdoCache.CreateCacheWithNewBlankLangProj( - new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "en", "en", new DummyFdoUI()); + new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "en", "en", new DummyFdoUI(), FwDirectoryFinder.FdoDirectories); m_mediator.PropertyTable.SetProperty("cache", m_cache); } diff --git a/Src/Common/Controls/XMLViews/XMLViewsTests/TestManyOneBrowse.cs b/Src/Common/Controls/XMLViews/XMLViewsTests/TestManyOneBrowse.cs index b5951895e6..2eb67b9a97 100644 --- a/Src/Common/Controls/XMLViews/XMLViewsTests/TestManyOneBrowse.cs +++ b/Src/Common/Controls/XMLViews/XMLViewsTests/TestManyOneBrowse.cs @@ -63,7 +63,7 @@ public void Setup() // - MoMorphSynAnalysis // - MoStemMsa // - MoDerivationalMsa - string m_sTestPath = Path.Combine(DirectoryFinder.FwSourceDirectory, + string m_sTestPath = Path.Combine(FwDirectoryFinder.SourceDirectory, Path.Combine("Common", Path.Combine("Controls", Path.Combine("XMLViews", @@ -85,7 +85,7 @@ public void Setup() m_sda.WritingSystemFactory = m_wsManager; var parser = new SimpleDataParser(m_mdc, m_cda); - parser.Parse(Path.Combine(DirectoryFinder.FwSourceDirectory, + parser.Parse(Path.Combine(FwDirectoryFinder.SourceDirectory, Path.Combine("Common", Path.Combine("Controls", Path.Combine("XMLViews", @@ -105,7 +105,7 @@ public void Setup() // - Semantic domains (pair of strings in para in seq in seq, using layout refs) // - MSAs (simplified, but polymorphic with one having and one to CmPossibility XmlDocument docColumns = new XmlDocument(); - docColumns.Load(Path.Combine(DirectoryFinder.FwSourceDirectory, + docColumns.Load(Path.Combine(FwDirectoryFinder.SourceDirectory, Path.Combine("Common", Path.Combine("Controls", Path.Combine("XMLViews", @@ -113,7 +113,7 @@ public void Setup() m_columnList = docColumns.DocumentElement.ChildNodes; // Parts just has what those columns need. - string partDirectory = Path.Combine(DirectoryFinder.FwSourceDirectory, + string partDirectory = Path.Combine(FwDirectoryFinder.SourceDirectory, Path.Combine("Common", Path.Combine("Controls", Path.Combine("XMLViews", "XMLViewsTests")))); diff --git a/Src/Common/CoreImpl/CoreImpl.csproj b/Src/Common/CoreImpl/CoreImpl.csproj index 45155a9f03..67368ec091 100644 --- a/Src/Common/CoreImpl/CoreImpl.csproj +++ b/Src/Common/CoreImpl/CoreImpl.csproj @@ -99,7 +99,9 @@ CommonAssemblyInfo.cs + + diff --git a/Src/Common/CoreImpl/CoreImplStrings.Designer.cs b/Src/Common/CoreImpl/CoreImplStrings.Designer.cs index 37cec1c86e..ee90a048b7 100644 --- a/Src/Common/CoreImpl/CoreImplStrings.Designer.cs +++ b/Src/Common/CoreImpl/CoreImplStrings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.1008 +// Runtime Version:4.0.30319.18052 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -61,7 +61,7 @@ internal CoreImplStrings() { } /// - /// Looks up a localized string similar to FieldWorks is unable to save some writing system settings because access to {0} is not authorized. This may cause unexpected behavior, and may be indicative of a wider problem with access permissions that could cause program crashes.. + /// Looks up a localized string similar to Unable to save some writing system settings because access to {0} is not authorized. This may cause unexpected behavior, and may be indicative of a wider problem with access permissions that could cause program crashes.. /// internal static string ksCannotWriteWritingSystemInfo { get { @@ -114,6 +114,42 @@ internal static string ksGenDateBefore { } } + /// + /// Looks up a localized string similar to Version: {0} {1} {2}. + /// + internal static string kstidAppVersionFmt { + get { + return ResourceManager.GetString("kstidAppVersionFmt", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This software is licensed under the MIT License. + /// + internal static string kstidLicense { + get { + return ResourceManager.GetString("kstidLicense", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (http://opensource.org/licenses/MIT). + /// + internal static string kstidLicenseURL { + get { + return ResourceManager.GetString("kstidLicenseURL", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Version: {0}. + /// + internal static string kstidMajorVersionFmt { + get { + return ResourceManager.GetString("kstidMajorVersionFmt", resourceCulture); + } + } + /// /// Looks up a localized string similar to Warning. /// diff --git a/Src/Common/CoreImpl/CoreImplStrings.resx b/Src/Common/CoreImpl/CoreImplStrings.resx index 911ca34a7f..7eb7997a16 100644 --- a/Src/Common/CoreImpl/CoreImplStrings.resx +++ b/Src/Common/CoreImpl/CoreImplStrings.resx @@ -118,7 +118,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - FieldWorks is unable to save some writing system settings because access to {0} is not authorized. This may cause unexpected behavior, and may be indicative of a wider problem with access permissions that could cause program crashes. + Unable to save some writing system settings because access to {0} is not authorized. This may cause unexpected behavior, and may be indicative of a wider problem with access permissions that could cause program crashes. AD @@ -135,6 +135,22 @@ Before + + Version: {0} {1} {2} + Displays in the Help/About box and the splash screen + + + Version: {0} + Displays in the Help/About box and the splash screen + + + This software is licensed under the MIT License + Displays in the Help/About box and the splash screen + + + (http://opensource.org/licenses/MIT) + Displays in the Help/About box + Warning diff --git a/Src/Common/CoreImpl/CoreImplTests/CoreImplTests.csproj b/Src/Common/CoreImpl/CoreImplTests/CoreImplTests.csproj index 064b81cf59..ba03fa5fc3 100644 --- a/Src/Common/CoreImpl/CoreImplTests/CoreImplTests.csproj +++ b/Src/Common/CoreImpl/CoreImplTests/CoreImplTests.csproj @@ -110,6 +110,7 @@ AssemblyInfoForTests.cs + diff --git a/Src/Common/CoreImpl/CoreImplTests/DirectoryFinderTests.cs b/Src/Common/CoreImpl/CoreImplTests/DirectoryFinderTests.cs new file mode 100644 index 0000000000..920dfa3c4a --- /dev/null +++ b/Src/Common/CoreImpl/CoreImplTests/DirectoryFinderTests.cs @@ -0,0 +1,96 @@ +using System; +using NUnit.Framework; + +namespace SIL.CoreImpl +{ + /// + /// Base class for testing CommonApplicationData. This base class deals with setting + /// and resetting the environment variable. + /// + public class GetCommonAppDataBaseTest + { + private string PreviousEnvironment; + + /// + /// Setup the tests. + /// + [TestFixtureSetUp] + public void FixtureSetup() + { + DirectoryFinder.ResetStaticVars(); + PreviousEnvironment = Environment.GetEnvironmentVariable("FW_CommonAppData"); + var properties = (PropertyAttribute[])GetType().GetCustomAttributes(typeof(PropertyAttribute), true); + Assert.That(properties.Length, Is.GreaterThan(0)); + Environment.SetEnvironmentVariable("FW_CommonAppData", (string)properties[0].Properties["Value"]); + } + + /// + /// Reset environment variable to previous value + /// + [TestFixtureTearDown] + public void FixtureTeardown() + { + Environment.SetEnvironmentVariable("FW_CommonAppData", PreviousEnvironment); + } + } + + /// + /// Tests the GetFolderPath method for CommonApplicationData when no environment variable + /// is set. + /// + [TestFixture] + [Property("Value", null)] + public class GetCommonAppDataNormalTests: GetCommonAppDataBaseTest + { + /// Tests the GetFolderPath method for CommonApplicationData when no environment + /// variable is set + [Test] + [Platform(Include="Linux", Reason="Test is Linux specific")] + public void Linux() + { + Assert.AreEqual("/var/lib/fieldworks", + DirectoryFinder.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)); + } + + /// Tests the GetFolderPath method for CommonApplicationData when no environment + /// variable is set + [Test] + [Platform(Exclude="Linux", Reason="Test is Windows specific")] + public void Windows() + { + Assert.AreEqual( + Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), + DirectoryFinder.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)); + } + } + + /// + /// Tests the GetFolderPath method for CommonApplicationData when the environment variable + /// is set. + /// + [TestFixture] + [Property("Value", "/bla")] + public class GetCommonAppDataOverrideTests: GetCommonAppDataBaseTest + { + /// Tests the GetFolderPath method for CommonApplicationData when the environment + /// variable is set + [Test] + [Platform(Include="Linux", Reason="Test is Linux specific")] + public void Linux() + { + Assert.AreEqual("/bla", + DirectoryFinder.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)); + } + + /// Tests the GetFolderPath method for CommonApplicationData when the environment + /// variable is set + [Test] + [Platform(Exclude="Linux", Reason="Test is Windows specific")] + public void Windows() + { + Assert.AreEqual( + Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), + DirectoryFinder.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)); + } + } +} diff --git a/Src/Common/CoreImpl/DirectoryFinder.cs b/Src/Common/CoreImpl/DirectoryFinder.cs new file mode 100644 index 0000000000..31fcfc40f3 --- /dev/null +++ b/Src/Common/CoreImpl/DirectoryFinder.cs @@ -0,0 +1,124 @@ +using System; +using System.IO; +using System.Reflection; +using SIL.Utils; + +namespace SIL.CoreImpl +{ + /// + /// This class is used to find files and directories for an SIL app. + /// + public static class DirectoryFinder + { + private static string s_CommonAppDataFolder; + + /// + /// Resets the static variables. Used for unit tests. + /// + internal static void ResetStaticVars() + { + s_CommonAppDataFolder = null; + } + + + /// + /// Gets the company name (should be SIL). + /// + public static string CompanyName + { + get + { + return ((AssemblyCompanyAttribute)Attribute.GetCustomAttribute( + Assembly.GetExecutingAssembly(), typeof(AssemblyCompanyAttribute), false)) + .Company; + } + } + + /// ------------------------------------------------------------------------------------ + /// + /// Gets the path for storing user-specific application data. + /// + /// Name of the application. + /// ------------------------------------------------------------------------------------ + public static string UserAppDataFolder(string appName) + { + string path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + return Path.Combine(Path.Combine(path, CompanyName), appName); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Gets the path for storing common application data that might be shared between + /// multiple applications and multiple users on the same machine. + /// + /// On Windows this returns Environment.SpecialFolder.CommonApplicationData + /// (C:\ProgramData),on Linux /var/lib/fieldworks. + /// + /// ------------------------------------------------------------------------------------ + private static string CommonApplicationData + { + get + { + if (s_CommonAppDataFolder == null) + { + if (MiscUtils.IsUnix) + { + // allow to override the /var/lib/fieldworks path by setting the + // environment variable FW_CommonAppData. Is this is needed on our CI + // build machines. + s_CommonAppDataFolder = + Environment.GetEnvironmentVariable("FW_CommonAppData") ?? + "/var/lib/fieldworks"; + } + else + { + s_CommonAppDataFolder = + Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData); + } + } + return s_CommonAppDataFolder; + } + } + + /// ------------------------------------------------------------------------------------ + /// + /// Gets a special folder, very similar to Environment.GetFolderPath. The main + /// difference is that this method works cross-platform and does some translations. + /// For example CommonApplicationData (/usr/share) is not writeable on Linux, so we + /// translate that to /var/lib/fieldworks instead. + /// + /// ------------------------------------------------------------------------------------ + public static string GetFolderPath(Environment.SpecialFolder folder) + { + if (folder == Environment.SpecialFolder.CommonApplicationData) + return CommonApplicationData; + return Environment.GetFolderPath(folder); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Gets the path for storing common application data that might be shared between + /// multiple applications and multiple users on the same machine. + /// + /// On Windows this returns a subdirectory of + /// Environment.SpecialFolder.CommonApplicationData (C:\ProgramData),on Linux + /// /var/lib/fieldworks. + /// + /// Name of the application. + /// ------------------------------------------------------------------------------------ + public static string CommonAppDataFolder(string appName) + { + return Path.Combine(Path.Combine(CommonApplicationData, CompanyName), appName); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Gets the global writing system store directory. The directory is guaranteed to exist. + /// + /// ------------------------------------------------------------------------------------ + public static string GlobalWritingSystemStoreDirectory + { + get { return CommonAppDataFolder("WritingSystemStore"); } + } + } +} diff --git a/Src/Common/CoreImpl/GlobalFileWritingSystemStore.cs b/Src/Common/CoreImpl/GlobalFileWritingSystemStore.cs index 914349f7ea..dcae8cba80 100644 --- a/Src/Common/CoreImpl/GlobalFileWritingSystemStore.cs +++ b/Src/Common/CoreImpl/GlobalFileWritingSystemStore.cs @@ -3,13 +3,11 @@ using System.Globalization; using System.IO; using System.Linq; -using System.Runtime.InteropServices; +using System.Security.AccessControl; +using System.Security.Principal; using System.Threading; -using System.Xml; using System.Collections.Generic; -using System.Xml.Linq; using Palaso.WritingSystems; -using SIL.FieldWorks.Common.COMInterfaces; using SIL.Utils; namespace SIL.CoreImpl @@ -25,14 +23,49 @@ public class GlobalFileWritingSystemStore : IFwWritingSystemStore /// Reference to a mutex. The owner of the mutex is the SingletonContainer private readonly Mutex m_mutex; + /// + /// Initializes a new instance of the class. + /// + public GlobalFileWritingSystemStore() + : this(DirectoryFinder.GlobalWritingSystemStoreDirectory) + { + } + /// /// Initializes a new instance of the class. /// /// The path. - public GlobalFileWritingSystemStore(string path) + [SuppressMessage("Gendarme.Rules.Portability", "MonoCompatibilityReviewRule", + Justification="Offending code is not executed on Linux")] + internal GlobalFileWritingSystemStore(string path) { m_path = path; - Directory.CreateDirectory(m_path); + if (!Directory.Exists(m_path)) + { + DirectoryInfo di; + + // Provides FW on Linux multi-user access. Overrides the system + // umask and creates the directory with the permissions "775". + // The "fieldworks" group was created outside the app during + // configuration of the package which allows group access. + using(new FileModeOverride()) + { + di = Directory.CreateDirectory(m_path); + } + + if (!MiscUtils.IsUnix) + { + // NOTE: GetAccessControl/ModifyAccessRule/SetAccessControl is not implemented in Mono + DirectorySecurity ds = di.GetAccessControl(); + var sid = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null); + AccessRule rule = new FileSystemAccessRule(sid, FileSystemRights.Write | FileSystemRights.ReadAndExecute + | FileSystemRights.Modify, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, + PropagationFlags.InheritOnly, AccessControlType.Allow); + bool modified; + ds.ModifyAccessRule(AccessControlModification.Add, rule, out modified); + di.SetAccessControl(ds); + } + } m_mutex = SingletonsContainer.Get(typeof(Mutex).FullName + m_path, () => new Mutex(false, m_path.Replace('\\', '_').Replace('/', '_'))); } diff --git a/Src/Common/FwUtils/FwVersionInfoProvider.cs b/Src/Common/CoreImpl/VersionInfoProvider.cs similarity index 87% rename from Src/Common/FwUtils/FwVersionInfoProvider.cs rename to Src/Common/CoreImpl/VersionInfoProvider.cs index 77fa70c892..5ca50ace71 100644 --- a/Src/Common/FwUtils/FwVersionInfoProvider.cs +++ b/Src/Common/CoreImpl/VersionInfoProvider.cs @@ -1,4 +1,4 @@ -// --------------------------------------------------------------------------------------------- +// --------------------------------------------------------------------------------------------- #region // Copyright (c) 2013, SIL International. All Rights Reserved. // // Copyright (c) 2013, SIL International. All Rights Reserved. @@ -8,7 +8,7 @@ // #endregion // -// File: FwVersionInfoProvider.cs +// File: VersionInfoProvider.cs // Responsibility: FW Team // --------------------------------------------------------------------------------------------- using System; @@ -16,14 +16,14 @@ using System.Reflection; using System.Windows.Forms; -namespace SIL.FieldWorks.Common.FwUtils +namespace SIL.CoreImpl { /// ---------------------------------------------------------------------------------------- /// - /// Class for getting version information out of a FieldWorks assembly + /// Class for getting version information out of an assembly /// /// ---------------------------------------------------------------------------------------- - public class FwVersionInfoProvider + public class VersionInfoProvider { /// Default copyright string if no assembly could be found public const string kDefaultCopyrightString = "Copyright (c) 2002-2013 SIL International"; @@ -36,13 +36,13 @@ public class FwVersionInfoProvider /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The assembly used to get the information. /// if set to false, any SIL-identifying information /// will be hidden. /// ------------------------------------------------------------------------------------ - public FwVersionInfoProvider(Assembly assembly, bool fShowSILInfo) + public VersionInfoProvider(Assembly assembly, bool fShowSILInfo) { if (assembly == null) throw new ArgumentNullException("assembly"); @@ -128,9 +128,9 @@ public string ApplicationVersion } } #if DEBUG - return string.Format(FwUtilsStrings.kstidAppVersionFmt, appVersion, productDate, "(Debug version)"); + return string.Format(CoreImplStrings.kstidAppVersionFmt, appVersion, productDate, "(Debug version)"); #else - return string.Format(FwUtilsStrings.kstidAppVersionFmt, appVersion, productDate, ""); + return string.Format(CoreImplStrings.kstidAppVersionFmt, appVersion, productDate, ""); #endif } } @@ -140,17 +140,17 @@ public string ApplicationVersion /// Gets the version of FieldWorks. /// /// ------------------------------------------------------------------------------------ - public string FieldWorksVersion + public string MajorVersion { get { // Set the Fieldworks version text object[] attributes = m_assembly.GetCustomAttributes( typeof(AssemblyInformationalVersionAttribute), false); - string fwVersion = (attributes != null && attributes.Length > 0) ? + string version = (attributes != null && attributes.Length > 0) ? ((AssemblyInformationalVersionAttribute)attributes[0]).InformationalVersion : Application.ProductVersion; - return string.Format(FwUtilsStrings.kstidFwVersionFmt, fwVersion); + return string.Format(CoreImplStrings.kstidMajorVersionFmt, version); } } @@ -180,7 +180,7 @@ public string CopyrightString copyRight = kDefaultCopyrightString; } } - return copyRight.Replace("(c)", "©"); + return copyRight.Replace("(c)", ""); } } @@ -191,7 +191,7 @@ public string LicenseString { get { - return FwUtilsStrings.kstidLicense; + return CoreImplStrings.kstidLicense; } } @@ -200,7 +200,7 @@ public string LicenseURL { get { - return FwUtilsStrings.kstidLicenseURL; + return CoreImplStrings.kstidLicenseURL; } } } diff --git a/Src/Common/FieldWorks/FieldWorks.cs b/Src/Common/FieldWorks/FieldWorks.cs index c2dfcb6b60..c46fd3d052 100644 --- a/Src/Common/FieldWorks/FieldWorks.cs +++ b/Src/Common/FieldWorks/FieldWorks.cs @@ -288,6 +288,10 @@ static int Main(string[] rgArgs) // from HKCU/Software/SIL/FieldWorks/7.0 -> FieldWorks/8. FwRegistryHelper.UpgradeUserSettingsIfNeeded(); + // initialize client-server services to use Db4O backend + ClientServerServices.SetCurrentToDb4OBackend(s_ui, FwDirectoryFinder.FdoDirectories, + () => FwDirectoryFinder.ProjectsDirectory == FwDirectoryFinder.ProjectsDirectoryLocalMachine); + if (appArgs.ShowHelp) { ShowCommandLineHelp(); @@ -481,7 +485,7 @@ private static void LaunchRestoreFromCommandLine(FwAppArgs appArgs) // There is no need to re-show the dialog since the user has already chosen // the options and confirmed to overwrite any existing database. Logger.WriteEvent("Restoring project: " + appArgs.BackupFile); - RestoreProjectSettings restoreSettings = new RestoreProjectSettings(appArgs.Database, + RestoreProjectSettings restoreSettings = new RestoreProjectSettings(FwDirectoryFinder.ProjectsDirectory, appArgs.Database, appArgs.BackupFile, appArgs.RestoreOptions); RestoreCurrentProject(new FwRestoreProjectSettings(appArgs.AppAbbrev, restoreSettings), null); } @@ -807,7 +811,7 @@ private static FdoCache CreateCache(ProjectId projectId) Form owner = s_splashScreen != null ? s_splashScreen.Form : Form.ActiveForm; using (var progressDlg = new ProgressDialogWithTask(owner)) { - FdoCache cache = FdoCache.CreateCacheFromExistingData(projectId, s_sWsUser, progressDlg, s_ui); + FdoCache cache = FdoCache.CreateCacheFromExistingData(projectId, s_sWsUser, s_ui, FwDirectoryFinder.FdoDirectories, progressDlg); EnsureValidLinkedFilesFolder(cache); cache.ProjectNameChanged += ProjectNameChanged; cache.ServiceLocator.GetInstance().OnSave += FieldWorks_OnSave; @@ -1701,7 +1705,7 @@ private static ProjectId ShowWelcomeDialog(FwAppArgs args, FwApp startingApp, Pr projectToTry = null; // If the user cancels the send/receive, this null will result in a return to the welcome dialog. // Hard to say what Form.ActiveForm is here. The splash and welcome dlgs are both gone. var projectDataPathname = ObtainProjectMethod.ObtainProjectFromAnySource(Form.ActiveForm, - helpTopicProvider, out obtainedProjectType, s_ui); + helpTopicProvider, out obtainedProjectType); if (!string.IsNullOrEmpty(projectDataPathname)) { projectToTry = new ProjectId(FDOBackendProviderType.kXML, projectDataPathname, null); @@ -1773,7 +1777,7 @@ internal static ProjectId ChooseLangProject(Form dialogOwner, IHelpTopicProvider { return null; } - using (var dlg = new ChooseLangProjectDialog(helpTopicProvider, false, s_ui)) + using (var dlg = new ChooseLangProjectDialog(helpTopicProvider, false)) { dlg.ShowDialog(dialogOwner); var app = helpTopicProvider as IApp; @@ -1805,7 +1809,7 @@ internal static ProjectId ChooseLangProject(Form dialogOwner, IHelpTopicProvider /// ------------------------------------------------------------------------------------ internal static ProjectId CreateNewProject(Form dialogOwner, FwApp app, IHelpTopicProvider helpTopicProvider) { - using (var dlg = new FwNewLangProject(s_ui)) + using (var dlg = new FwNewLangProject()) { dlg.SetDialogProperties(helpTopicProvider); switch (dlg.DisplayDialog(dialogOwner)) @@ -1973,7 +1977,7 @@ internal static void FileProjectSharingLocation(Form dialogOwner, FwApp fwApp) return; string projectPath = fwApp.Cache.ProjectId.Path; string parentDirectory = Path.GetDirectoryName(fwApp.Cache.ProjectId.ProjectFolder); - string projectsDirectory = DirectoryFinder.ProjectsDirectory; + string projectsDirectory = FwDirectoryFinder.ProjectsDirectory; if (!MiscUtils.IsUnix) { parentDirectory = parentDirectory.ToLowerInvariant(); @@ -1987,7 +1991,7 @@ internal static void FileProjectSharingLocation(Form dialogOwner, FwApp fwApp) if (!ClientServerServices.Current.Local.ShareMyProjects) UpdateProjectsLocation(dlg.ProjectsFolder, fwApp, projectPath); if (!MiscUtils.IsUnix) - projectsDirectory = DirectoryFinder.ProjectsDirectory.ToLowerInvariant(); + projectsDirectory = FwDirectoryFinder.ProjectsDirectory.ToLowerInvariant(); if (UpdateProjectsSharing(true, dialogOwner, fwApp, projectPath, parentDirectory, projectsDirectory)) { using (var dlgShare = new ShareProjectsFolderDlg()) @@ -2035,7 +2039,7 @@ private static bool UpdateProjectsSharing(bool fShareProjects, Form dialogOwner // Both these setters check and do nothing if not changed. using (var progressDlg = new ProgressDialogWithTask(s_threadHelper)) { - return ClientServerServices.Current.Local.SetProjectSharing(fShareProjects, progressDlg, s_ui); + return ClientServerServices.Current.Local.SetProjectSharing(fShareProjects, progressDlg); } } @@ -2044,7 +2048,7 @@ private static bool UpdateProjectsSharing(bool fShareProjects, Form dialogOwner { using (var progressDlg = new ProgressDialogWithTask(s_threadHelper)) { - fSuccess = ClientServerServices.Current.Local.SetProjectSharing(fShareProjects, progressDlg, s_ui); + fSuccess = ClientServerServices.Current.Local.SetProjectSharing(fShareProjects, progressDlg); } return new ProjectId(ClientServerServices.Current.Local.IdForLocalProject(Path.GetFileNameWithoutExtension(projectPath)), null); }); @@ -2062,7 +2066,7 @@ private static bool UpdateProjectsSharing(bool fShareProjects, Form dialogOwner private static void UpdateProjectsLocation(string newFolderForProjects, FwApp fwApp, string projectPath) { - if (newFolderForProjects == null || newFolderForProjects == DirectoryFinder.ProjectsDirectory || + if (newFolderForProjects == null || newFolderForProjects == FwDirectoryFinder.ProjectsDirectory || !FileUtils.EnsureDirectoryExists(newFolderForProjects)) return; @@ -2071,10 +2075,10 @@ private static void UpdateProjectsLocation(string newFolderForProjects, FwApp fw { fMoveFiles = dlg.ShowDialog(fwApp.ActiveMainWindow) == DialogResult.Yes; } - string oldFolderForProjects = DirectoryFinder.ProjectsDirectory; + string oldFolderForProjects = FwDirectoryFinder.ProjectsDirectory; try { - DirectoryFinder.ProjectsDirectory = newFolderForProjects; + FwDirectoryFinder.ProjectsDirectory = newFolderForProjects; } catch (Exception) { @@ -2279,7 +2283,7 @@ private static ProjectId MoveProjectFolders(string oldFolderForProjects, string { if (projectPath.StartsWith(oldFolderForProjects)) { - // This is perhaps a temporary workaround. On Linux, DirectoryFinder.ProjectsDirectory + // This is perhaps a temporary workaround. On Linux, FwDirectoryFinder.ProjectsDirectory // isn't returning the updated value, but rather the original value. This seems to // last for the duration of the program, but if you exit and restart the program, it // gets the correct (updated) value!? @@ -2385,7 +2389,7 @@ private static bool MigrateProjectsTo70() // TODO (TimS): We should probably put FW into single process mode for these // migrations. It would probably be very bad to have two processes attempting to // do migrations at the same time. - ProcessStartInfo info = new ProcessStartInfo(DirectoryFinder.MigrateSqlDbsExe); + ProcessStartInfo info = new ProcessStartInfo(FwDirectoryFinder.MigrateSqlDbsExe); info.UseShellExecute = false; using (Process proc = Process.Start(info)) { @@ -2507,7 +2511,7 @@ private static void RestoreCurrentProject(FwRestoreProjectSettings restoreSettin retry = false; try { - var restoreService = new ProjectRestoreService(restoreSettings.Settings, s_ui); + var restoreService = new ProjectRestoreService(restoreSettings.Settings, s_ui, FwDirectoryFinder.ConverterConsoleExe, FwDirectoryFinder.DbExe); Logger.WriteEvent("Restoring from " + restoreSettings.Settings.Backup.File); if (RestoreProjectDlg.HandleRestoreFileErrors(null, ResourceHelper.GetResourceString("ksRestoreFailed"), restoreSettings.Settings.Backup.File, () => DoRestore(restoreService))) @@ -2573,12 +2577,12 @@ private static bool BackupProjectForRestore(FwRestoreProjectSettings restoreSett { FdoCache cache = existingCache ?? FdoCache.CreateCacheFromExistingData( new ProjectId(restoreSettings.Settings.FullProjectPath, null), - s_sWsUser, progressDlg, s_ui); + s_sWsUser, s_ui, FwDirectoryFinder.FdoDirectories, progressDlg); try { - BackupProjectSettings settings = new BackupProjectSettings(cache, restoreSettings.Settings); - settings.DestinationFolder = DirectoryFinder.DefaultBackupDirectory; + BackupProjectSettings settings = new BackupProjectSettings(cache, restoreSettings.Settings, FwDirectoryFinder.DefaultBackupDirectory); + settings.DestinationFolder = FwDirectoryFinder.DefaultBackupDirectory; settings.AppAbbrev = restoreSettings.FwAppCommandLineAbbrev; ProjectBackupService backupService = new ProjectBackupService(cache, settings); @@ -2751,7 +2755,7 @@ private static void CheckForMovingExternalLinkDirectory(FwApp app) if (oldDir == null) { // e.g. "C:\\ProgramData\\SIL\\FieldWorks" - oldDir = DirectoryFinder.CommonAppDataFolder("SIL/FieldWorks"); + oldDir = DirectoryFinder.CommonAppDataFolder("FieldWorks"); } oldDir = oldDir.TrimEnd(new [] {Path.PathSeparator}); var newDir = app.Cache.LangProject.LinkedFilesRootDir; @@ -3003,7 +3007,7 @@ private static FwApp GetOrCreateApplication(FwAppArgs args) { if (s_teApp == null) { - s_teApp = (FwApp)DynamicLoader.CreateObject(DirectoryFinder.TeDll, + s_teApp = (FwApp)DynamicLoader.CreateObject(FwDirectoryFinder.TeDll, FwUtils.ksFullTeAppObjectName, s_fwManager, GetHelpTopicProvider(appAbbrev), args); s_teAppKey = s_teApp.SettingsKey; } @@ -3016,7 +3020,7 @@ private static FwApp GetOrCreateApplication(FwAppArgs args) { if (s_flexApp == null) { - s_flexApp = (FwApp)DynamicLoader.CreateObject(DirectoryFinder.FlexDll, + s_flexApp = (FwApp)DynamicLoader.CreateObject(FwDirectoryFinder.FlexDll, FwUtils.ksFullFlexAppObjectName, s_fwManager, GetHelpTopicProvider(appAbbrev), args); s_flexAppKey = s_flexApp.SettingsKey; } @@ -3615,10 +3619,10 @@ internal static IHelpTopicProvider GetHelpTopicProvider(string appAbbrev) if ((appAbbrev.Equals(FwUtils.ksTeAbbrev, StringComparison.InvariantCultureIgnoreCase) && FwUtils.IsTEInstalled) || !FwUtils.IsFlexInstalled) { - return s_teApp ?? (IHelpTopicProvider)DynamicLoader.CreateObject(DirectoryFinder.TeDll, + return s_teApp ?? (IHelpTopicProvider)DynamicLoader.CreateObject(FwDirectoryFinder.TeDll, "SIL.FieldWorks.TE.TeHelpTopicProvider"); } - return s_flexApp ?? (IHelpTopicProvider)DynamicLoader.CreateObject(DirectoryFinder.FlexDll, + return s_flexApp ?? (IHelpTopicProvider)DynamicLoader.CreateObject(FwDirectoryFinder.FlexDll, "SIL.FieldWorks.XWorks.LexText.FlexHelpTopicProvider"); } diff --git a/Src/Common/FieldWorks/FieldWorksTests/ProjectIDTests.cs b/Src/Common/FieldWorks/FieldWorksTests/ProjectIDTests.cs index 8dad54a244..fd17a78b1a 100644 --- a/Src/Common/FieldWorks/FieldWorksTests/ProjectIDTests.cs +++ b/Src/Common/FieldWorks/FieldWorksTests/ProjectIDTests.cs @@ -62,7 +62,7 @@ public override void FixtureSetup() public override void FixtureTeardown() { base.FixtureTeardown(); - ReflectionHelper.CallMethod(typeof(ClientServerServices), "SetCurrentToDefaultBackend"); + ReflectionHelper.CallMethod(typeof(ClientServerServices), "SetCurrentToDb4OBackend"); } /// ------------------------------------------------------------------------------------ @@ -201,7 +201,7 @@ public void CleanUpNameForType_EmptyName() public void CleanUpNameForType_Default_onlyName() { m_defaultBepType = FDOBackendProviderType.kDb4oClientServer; - string expectedPath = Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, "ape"), + string expectedPath = Path.Combine(Path.Combine(FwDirectoryFinder.ProjectsDirectory, "ape"), FdoFileHelper.GetDb4oDataFileName("ape")); m_localCsSvcs.Stub(cs => cs.IdForLocalProject("ape")).Return(expectedPath); m_mockFileOs.AddExistingFile(expectedPath); @@ -222,7 +222,7 @@ public void CleanUpNameForType_Default_onlyName() [Test] public void CleanUpNameForType_Default_NameWithPeriod_Exists() { - string expectedPath = Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, "my.monkey"), "my.monkey"); + string expectedPath = Path.Combine(Path.Combine(FwDirectoryFinder.ProjectsDirectory, "my.monkey"), "my.monkey"); m_localCsSvcs.Stub(cs => cs.IdForLocalProject("my.monkey")).Return(expectedPath); m_mockFileOs.AddExistingFile(expectedPath); @@ -242,7 +242,7 @@ public void CleanUpNameForType_Default_NameWithPeriod_Exists() [Test] public void CleanUpNameForType_XML_NameWithPeriod_FilesWithAndWithoutExtensionExist() { - string myMonkeyProjectFolder = Path.Combine(DirectoryFinder.ProjectsDirectory, "my.monkey"); + string myMonkeyProjectFolder = Path.Combine(FwDirectoryFinder.ProjectsDirectory, "my.monkey"); string expectedPath = Path.Combine(myMonkeyProjectFolder, FdoFileHelper.GetXmlDataFileName("my.monkey")); m_mockFileOs.AddExistingFile(expectedPath); m_mockFileOs.AddExistingFile(Path.Combine(myMonkeyProjectFolder, "my.monkey")); @@ -318,7 +318,7 @@ public void CleanUpNameForType_XML_onlyNameWithExtension() [Test] public void CleanUpNameForType_XML_FullPath() { - string expectedPath = Path.Combine(DirectoryFinder.ProjectsDirectory, FdoFileHelper.GetXmlDataFileName("monkey")); + string expectedPath = Path.Combine(FwDirectoryFinder.ProjectsDirectory, FdoFileHelper.GetXmlDataFileName("monkey")); m_mockFileOs.AddExistingFile(expectedPath); var proj = new ProjectId(expectedPath, null); @@ -338,7 +338,7 @@ public void CleanUpNameForType_XML_FullPath() public void CleanUpNameForType_XML_RelativePath() { string relativePath = Path.Combine("primate", FdoFileHelper.GetXmlDataFileName("monkey")); - string expectedPath = Path.Combine(DirectoryFinder.ProjectsDirectory, relativePath); + string expectedPath = Path.Combine(FwDirectoryFinder.ProjectsDirectory, relativePath); m_mockFileOs.AddExistingFile(expectedPath); ProjectId proj = new ProjectId(relativePath, null); @@ -459,7 +459,7 @@ public void AssertValid_Invalid_SharedFolderNotFound() [Test] public void CheckProperties() { - string expectedProjectDir = Path.Combine(DirectoryFinder.ProjectsDirectory, "SomeTest"); + string expectedProjectDir = Path.Combine(FwDirectoryFinder.ProjectsDirectory, "SomeTest"); m_mockFileOs.ExistingDirectories.Add(expectedProjectDir); const string type = "db4ocs"; @@ -483,7 +483,7 @@ public void CheckProperties() [Test] public void NameAndPath() { - string myProjectFolder = Path.Combine(DirectoryFinder.ProjectsDirectory, "My.Project"); + string myProjectFolder = Path.Combine(FwDirectoryFinder.ProjectsDirectory, "My.Project"); ProjectId projId = new ProjectId(FDOBackendProviderType.kXML, "My.Project", null); Assert.AreEqual(Path.Combine(myProjectFolder, FdoFileHelper.GetXmlDataFileName("My.Project")), projId.Path); Assert.AreEqual("My.Project", projId.Name); @@ -505,7 +505,7 @@ public void NameAndPath() /// ------------------------------------------------------------------------------------ public static string GetXmlProjectFilename(string projectName) { - return Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, projectName), + return Path.Combine(Path.Combine(FwDirectoryFinder.ProjectsDirectory, projectName), FdoFileHelper.GetXmlDataFileName(projectName)); } #endregion diff --git a/Src/Common/FieldWorks/PaObjects/PaLexicalInfo.cs b/Src/Common/FieldWorks/PaObjects/PaLexicalInfo.cs index b03a5a6203..a9924dd5ca 100644 --- a/Src/Common/FieldWorks/PaObjects/PaLexicalInfo.cs +++ b/Src/Common/FieldWorks/PaObjects/PaLexicalInfo.cs @@ -21,14 +21,11 @@ using System.Drawing; using System.Threading; using System.Windows.Forms; -using SIL.FieldWorks.FDO; -using SIL.FieldWorks.FdoUi; using SIL.PaToFdoInterfaces; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FwCoreDlgs; using SIL.Utils; -using XCore; namespace SIL.FieldWorks.PaObjects { @@ -37,18 +34,6 @@ public class PaLexicalInfo : IPaLexicalInfo, IDisposable { private List m_writingSystems; private List m_lexEntries; - private ThreadHelper m_threadHelper; - private readonly IFdoUI m_ui; - - /// - /// Initializes a new instance of the class. - /// - public PaLexicalInfo() - { - m_threadHelper = new ThreadHelper(); - var helpTopicProvider = (IHelpTopicProvider) DynamicLoader.CreateObject(DirectoryFinder.FlexDll, "SIL.FieldWorks.XWorks.LexText.FlexHelpTopicProvider"); - m_ui = new FwFdoUI(helpTopicProvider, m_threadHelper); - } #region Disposable stuff #if DEBUG @@ -81,13 +66,9 @@ protected virtual void Dispose(bool fDisposing) if (m_writingSystems != null) m_writingSystems.Clear(); - - if (m_threadHelper != null) - m_threadHelper.Dispose(); } m_lexEntries = null; m_writingSystems = null; - m_threadHelper = null; IsDisposed = true; } #endregion @@ -104,7 +85,7 @@ public bool ShowOpenProject(Form owner, ref Rectangle dialogBounds, Icu.InitIcuDataDir(); RegistryHelper.ProductName = "FieldWorks"; // inorder to find correct Registry keys - using (var dlg = new ChooseLangProjectDialog(dialogBounds, dialogSplitterPos, m_ui)) + using (var dlg = new ChooseLangProjectDialog(dialogBounds, dialogSplitterPos)) { if (dlg.ShowDialog(owner) == DialogResult.OK) { diff --git a/Src/Common/FieldWorks/ProjectId.cs b/Src/Common/FieldWorks/ProjectId.cs index 11e375dc20..d173a78582 100644 --- a/Src/Common/FieldWorks/ProjectId.cs +++ b/Src/Common/FieldWorks/ProjectId.cs @@ -200,7 +200,7 @@ public string Handle { get { - return !IsLocal || (DirectoryFinder.IsSubFolderOfProjectsDirectory(ProjectFolder) && + return !IsLocal || (FwDirectoryFinder.IsSubFolderOfProjectsDirectory(ProjectFolder) && SysPath.GetExtension(m_path) == ClientServerServices.Current.Local.DefaultBackendType.GetExtension()) ? Name : m_path; } @@ -248,7 +248,7 @@ public string ProjectFolder get { return IsLocal ? SysPath.GetDirectoryName(m_path) : - SysPath.Combine(SysPath.Combine(DirectoryFinder.ProjectsDirectory, ServerName), Name); + SysPath.Combine(SysPath.Combine(FwDirectoryFinder.ProjectsDirectory, ServerName), Name); } } @@ -266,7 +266,7 @@ public string SharedProjectFolder return ProjectFolder; // TODO-Linux FWNX-446: Implement alternative way of getting path to shared folder // Currently assumes projects also exist in the local Project Directory. - string baseDir = (MiscUtils.IsUnix) ? DirectoryFinder.ProjectsDirectory : + string baseDir = (MiscUtils.IsUnix) ? FwDirectoryFinder.ProjectsDirectory : @"\\" + ServerName + @"\Projects"; return SysPath.Combine(baseDir, Name); } @@ -545,7 +545,7 @@ private static string CleanUpNameForType(FDOBackendProviderType type, string nam if (!SysPath.IsPathRooted(name)) { string sProjName = (SysPath.GetExtension(name) == ext) ? SysPath.GetFileNameWithoutExtension(name) : name; - name = SysPath.Combine(SysPath.Combine(DirectoryFinder.ProjectsDirectory, sProjName), name); + name = SysPath.Combine(SysPath.Combine(FwDirectoryFinder.ProjectsDirectory, sProjName), name); } // If the file doesn't have the expected extension and exists with the extension or // does not exist without it, we add the expected extension. diff --git a/Src/Common/FieldWorks/ShareProjectsFolderDlg.cs b/Src/Common/FieldWorks/ShareProjectsFolderDlg.cs index a1c632d0c7..e8c578d9a0 100644 --- a/Src/Common/FieldWorks/ShareProjectsFolderDlg.cs +++ b/Src/Common/FieldWorks/ShareProjectsFolderDlg.cs @@ -34,7 +34,7 @@ public partial class ShareProjectsFolderDlg : Form { /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// ------------------------------------------------------------------------------------ public ShareProjectsFolderDlg() @@ -45,7 +45,7 @@ public ShareProjectsFolderDlg() private void m_btnViewFolder_Click(object sender, EventArgs e) { // This fires up Windows Explorer, showing the owner of the projects folder. - using (Process.Start(Path.GetDirectoryName(DirectoryFinder.ProjectsDirectory))) + using (Process.Start(Path.GetDirectoryName(FwDirectoryFinder.ProjectsDirectory))) { } } diff --git a/Src/Common/FieldWorks/WelcomeToFieldWorksDlg.cs b/Src/Common/FieldWorks/WelcomeToFieldWorksDlg.cs index a952728914..a9d1004c3c 100644 --- a/Src/Common/FieldWorks/WelcomeToFieldWorksDlg.cs +++ b/Src/Common/FieldWorks/WelcomeToFieldWorksDlg.cs @@ -108,7 +108,7 @@ public WelcomeToFieldWorksDlg(IHelpTopicProvider helpTopicProvider, string appAb m_helpTopicProvider = helpTopicProvider; helpProvider = new HelpProvider(); - helpProvider.HelpNamespace = DirectoryFinder.FWCodeDirectory + m_helpTopicProvider.GetHelpString("UserHelpFile"); + helpProvider.HelpNamespace = FwDirectoryFinder.CodeDirectory + m_helpTopicProvider.GetHelpString("UserHelpFile"); helpProvider.SetHelpKeyword(this, m_helpTopicProvider.GetHelpString(m_helpTopic)); helpProvider.SetHelpNavigator(this, HelpNavigator.Topic); receiveButton.Enabled = diff --git a/Src/Common/Framework/FwMainWnd.cs b/Src/Common/Framework/FwMainWnd.cs index 3cc21d0e96..2229e30c9d 100644 --- a/Src/Common/Framework/FwMainWnd.cs +++ b/Src/Common/Framework/FwMainWnd.cs @@ -412,7 +412,7 @@ protected virtual void CreateMenusAndToolBars() // Use this to initialize combo box items. m_tmAdapter.InitializeComboItem += InitializeToolBarCombos; - string sMenuToolBarDefinition = Path.Combine(DirectoryFinder.FWCodeDirectory, "FwTMDefinition.xml"); + string sMenuToolBarDefinition = Path.Combine(FwDirectoryFinder.CodeDirectory, "FwTMDefinition.xml"); m_tmAdapter.Initialize(this, AdapterContentControl, m_mediator, m_app.ProjectSpecificSettingsKey.ToString(), new string[] { sMenuToolBarDefinition, GetAppSpecificMenuToolBarDefinition() }); diff --git a/Src/Common/Framework/FwRegistrySettings.cs b/Src/Common/Framework/FwRegistrySettings.cs index 011cff424f..bac48e52ec 100644 --- a/Src/Common/Framework/FwRegistrySettings.cs +++ b/Src/Common/Framework/FwRegistrySettings.cs @@ -337,7 +337,7 @@ public void AddErrorReportingInfo() ErrorReporter.AddProperty("AutoOpenLastEditedProjectSetting", AutoOpenLastEditedProject.ToString()); ErrorReporter.AddProperty("DisableSplashScreenSetting", DisableSplashScreenSetting.ToString()); ErrorReporter.AddProperty("MeasurementUnitSetting", ((MsrSysType)MeasurementUnitSetting).ToString()); - ErrorReporter.AddProperty("BackupDirectorySetting", DirectoryFinder.DefaultBackupDirectory); + ErrorReporter.AddProperty("BackupDirectorySetting", FwDirectoryFinder.DefaultBackupDirectory); } } } diff --git a/Src/Common/Framework/HelpTopicProviderBase.cs b/Src/Common/Framework/HelpTopicProviderBase.cs index 49ae2d0567..5685f8767b 100644 --- a/Src/Common/Framework/HelpTopicProviderBase.cs +++ b/Src/Common/Framework/HelpTopicProviderBase.cs @@ -46,7 +46,7 @@ public string HelpFile { get { - return DirectoryFinder.FWCodeDirectory + GetHelpString("UserHelpFile"); + return FwDirectoryFinder.CodeDirectory + GetHelpString("UserHelpFile"); } } #endregion diff --git a/Src/Common/Framework/SettingsXmlAccessorBase.cs b/Src/Common/Framework/SettingsXmlAccessorBase.cs index 9b07ee29c5..c99a29e510 100644 --- a/Src/Common/Framework/SettingsXmlAccessorBase.cs +++ b/Src/Common/Framework/SettingsXmlAccessorBase.cs @@ -89,7 +89,7 @@ protected override Guid GetVersion(XmlNode baseNode) Justification = "TODO-Linux: XmlReaderSettings.DtdProcessing is missing from Mono")] protected override XmlNode LoadDoc() { - string sXmlFilePath = DirectoryFinder.FWCodeDirectory + ResourceFilePathFromFwInstall; + string sXmlFilePath = FwDirectoryFinder.CodeDirectory + ResourceFilePathFromFwInstall; try { XmlReaderSettings settings = new XmlReaderSettings(); diff --git a/Src/Common/FwRemoteDatabaseConnectorService/FwRemoteDatabaseConnectorService.csproj b/Src/Common/FwRemoteDatabaseConnectorService/FwRemoteDatabaseConnectorService.csproj index 45d854a45f..c7c8ee46c5 100644 --- a/Src/Common/FwRemoteDatabaseConnectorService/FwRemoteDatabaseConnectorService.csproj +++ b/Src/Common/FwRemoteDatabaseConnectorService/FwRemoteDatabaseConnectorService.csproj @@ -12,11 +12,14 @@ FwRemoteDatabaseConnectorService v4.0 512 - - + + + + - + + 3.5 @@ -70,6 +73,14 @@ ..\..\..\Output\Debug\FDO.dll + + False + ..\..\..\Output\Debug\FwUtils.dll + + + False + ..\..\..\Output\Debug\SilUtils.dll + diff --git a/Src/Common/FwRemoteDatabaseConnectorService/Program.cs b/Src/Common/FwRemoteDatabaseConnectorService/Program.cs index 0ae61801fa..55a5a7dc5b 100644 --- a/Src/Common/FwRemoteDatabaseConnectorService/Program.cs +++ b/Src/Common/FwRemoteDatabaseConnectorService/Program.cs @@ -1,4 +1,5 @@ using System.ServiceProcess; +using SIL.Utils; namespace FwRemoteDatabaseConnectorService { @@ -9,6 +10,11 @@ static class Program /// static void Main() { + // We need FieldWorks here to get the correct registry key HKLM\Software\SIL\FieldWorks. + // The default without this would be HKLM\Software\SIL\SIL FieldWorks, + // which breaks FwRemoteDatabaseConnectorService.exe. + RegistryHelper.ProductName = "FieldWorks"; + ServiceBase[] ServicesToRun; ServicesToRun = new ServiceBase[] { diff --git a/Src/Common/FwRemoteDatabaseConnectorService/Service1.cs b/Src/Common/FwRemoteDatabaseConnectorService/Service1.cs index fade05db75..90af05799b 100644 --- a/Src/Common/FwRemoteDatabaseConnectorService/Service1.cs +++ b/Src/Common/FwRemoteDatabaseConnectorService/Service1.cs @@ -4,12 +4,15 @@ using System.ServiceProcess; using System.Threading; using FwRemoteDatabaseConnector; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices; namespace FwRemoteDatabaseConnectorService { public partial class FwRemoteDatabaseConnectorService : ServiceBase { + private const string ksSharedProjectKey = "ProjectShared"; + private Thread m_clientListenerThread; private Socket m_clientListenerSocket; @@ -55,7 +58,7 @@ protected override void OnStart(string[] args) { try { - RemotingServer.Start(); + RemotingServer.Start(FwDirectoryFinder.RemotingTcpServerConfigFile, FwDirectoryFinder.FdoDirectories, GetSharedProject, SetSharedProject); } catch (Exception e) { @@ -67,6 +70,18 @@ protected override void OnStart(string[] args) m_clientListenerThread.Start(); } + private static bool GetSharedProject() + { + bool result; + var value = FwRegistryHelper.FieldWorksRegistryKey.GetValue(ksSharedProjectKey, "false"); + return (bool.TryParse((string)value, out result) && result); + } + + private static void SetSharedProject(bool v) + { + FwRegistryHelper.FieldWorksRegistryKey.SetValue(ksSharedProjectKey, v); + } + protected override void OnStop() { if (m_clientListenerSocket != null) diff --git a/Src/Common/FwUtils/FLExBridgeHelper.cs b/Src/Common/FwUtils/FLExBridgeHelper.cs index b63bc0326c..d681c456c5 100644 --- a/Src/Common/FwUtils/FLExBridgeHelper.cs +++ b/Src/Common/FwUtils/FLExBridgeHelper.cs @@ -191,7 +191,7 @@ public static bool LaunchFieldworksBridge(string projectFolder, string userName, if (!String.IsNullOrEmpty(projectFolder)) { // can S/R multiple projects simultaneously AddArg(ref args, "-p", projectFolder); - if (projectFolder != DirectoryFinder.ProjectsDirectory) + if (projectFolder != FwDirectoryFinder.ProjectsDirectory) _sFwProjectName = Path.GetFileNameWithoutExtension(projectFolder); } @@ -208,7 +208,7 @@ public static bool LaunchFieldworksBridge(string projectFolder, string userName, } // Add two paths: to FW projDir & FW apps folder. Then, FB won't have to look in a zillion registry entries - AddArg(ref args, "-projDir", DirectoryFinder.ProjectsDirectory); + AddArg(ref args, "-projDir", FwDirectoryFinder.ProjectsDirectory); AddArg(ref args, "-fwAppsDir", FieldWorksAppsDir); // Tell Flex Bridge which model version of data are expected by FLEx. AddArg(ref args, "-fwmodel", fwmodelVersionNumber.ToString()); @@ -346,7 +346,7 @@ private static void AddArg(ref string extant, string flag, string value) /// public static string FullFieldWorksBridgePath() { - return Path.Combine(DirectoryFinder.FlexBridgeFolder, FLExBridgeName); + return Path.Combine(FwDirectoryFinder.FlexBridgeFolder, FLExBridgeName); } /// diff --git a/Src/Common/FwUtils/DirectoryFinder.cs b/Src/Common/FwUtils/FwDirectoryFinder.cs similarity index 75% rename from Src/Common/FwUtils/DirectoryFinder.cs rename to Src/Common/FwUtils/FwDirectoryFinder.cs index f7f295910a..325d4f78b3 100644 --- a/Src/Common/FwUtils/DirectoryFinder.cs +++ b/Src/Common/FwUtils/FwDirectoryFinder.cs @@ -8,7 +8,7 @@ // #endregion // -// File: DirectoryFinder.cs +// File: FwDirectoryFinder.cs // // // To find the current user's "My Documents" folder, use something like: @@ -17,28 +17,23 @@ // // -------------------------------------------------------------------------------------------- using System; -using System.Diagnostics.CodeAnalysis; using System.IO; using System.Diagnostics; using System.Reflection; using System.Security; -using System.Security.AccessControl; -using System.Security.Principal; -using System.Text; -using System.Windows.Forms; using Microsoft.Win32; +using SIL.CoreImpl; +using SIL.FieldWorks.FDO; using SIL.FieldWorks.Resources; using SIL.Utils; namespace SIL.FieldWorks.Common.FwUtils { /// - /// Summary description for DirectoryFinder. + /// This class is used to find files and directories for FW apps. /// - public static class DirectoryFinder + public static class FwDirectoryFinder { - private static string s_CommonAppDataFolder; - /// /// The name of the Translation Editor folder (Even though this is the same as /// FwUtils.ksTeAppName and FwSubKey.TE, PLEASE do not use them interchangeably. Use @@ -54,8 +49,6 @@ public static class DirectoryFinder /// The Scripture-specific stylesheet (ideally, this would be in a TE-specific place, but FDO needs it) public const string kTeStylesFilename = "TeStyles.xml"; - /// The filename of the backup settings file - public const string kBackupSettingsFilename = "BackupSettings.xml"; /// The name of the folder containing global writing systems. /// Also see SIL.FieldWorks.FDO.FdoFileHelper.ksWritingSystemsDir @@ -66,13 +59,7 @@ public static class DirectoryFinder private const string ksBiblicaltermsLocFileExtension = ".xml"; private const string ksProjectsDir = "ProjectsDir"; - /// - /// Resets the static variables. Used for unit tests. - /// - internal static void ResetStaticVars() - { - s_CommonAppDataFolder = null; - } + private static readonly IFdoDirectories s_fdoDirs = new FwFdoDirectories(); /// ------------------------------------------------------------------------------------ /// @@ -83,7 +70,7 @@ internal static void ResetStaticVars() /// ------------------------------------------------------------------------------------ public static string TeStylesPath { - get { return Path.Combine(FWCodeDirectory, kTeStylesFilename); } + get { return Path.Combine(CodeDirectory, kTeStylesFilename); } } /// ------------------------------------------------------------------------------------ @@ -93,7 +80,7 @@ public static string TeStylesPath /// ------------------------------------------------------------------------------------ public static string TeFolder { - get { return GetFWCodeSubDirectory(ksTeFolderName); } + get { return GetCodeSubDirectory(ksTeFolderName); } } /// ------------------------------------------------------------------------------------ @@ -103,7 +90,7 @@ public static string TeFolder /// ------------------------------------------------------------------------------------ public static string FlexFolder { - get { return GetFWCodeSubDirectory(ksFlexFolderName); } + get { return GetCodeSubDirectory(ksFlexFolderName); } } /// @@ -114,106 +101,6 @@ public static string FlexBridgeFolder get { return GetFLExBridgeFolderPath(); } } - /// ------------------------------------------------------------------------------------ - /// - /// Gets the path for storing user-specific application data. - /// - /// Name of the application. - /// ------------------------------------------------------------------------------------ - public static string UserAppDataFolder(string appName) - { - string path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); - return Path.Combine(Path.Combine(path, CompanyName), appName); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets the path for storing common application data that might be shared between - /// multiple applications and multiple users on the same machine. - /// - /// On Windows this returns Environment.SpecialFolder.CommonApplicationData - /// (C:\ProgramData),on Linux /var/lib/fieldworks. - /// - /// ------------------------------------------------------------------------------------ - private static string CommonApplicationData - { - get - { - if (s_CommonAppDataFolder == null) - { - if (MiscUtils.IsUnix) - { - // allow to override the /var/lib/fieldworks path by setting the - // environment variable FW_CommonAppData. Is this is needed on our CI - // build machines. - s_CommonAppDataFolder = - Environment.GetEnvironmentVariable("FW_CommonAppData") ?? - "/var/lib/fieldworks"; - } - else - { - s_CommonAppDataFolder = - Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData); - } - } - return s_CommonAppDataFolder; - } - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets a special folder, very similar to Environment.GetFolderPath. The main - /// difference is that this method works cross-platform and does some translations. - /// For example CommonApplicationData (/usr/share) is not writeable on Linux, so we - /// translate that to /var/lib/fieldworks instead. - /// - /// ------------------------------------------------------------------------------------ - public static string GetFolderPath(Environment.SpecialFolder folder) - { - if (folder == Environment.SpecialFolder.CommonApplicationData) - return CommonApplicationData; - return Environment.GetFolderPath(folder); - } - - static string s_companyName = Application.CompanyName; // default for real use; tests may override. - /// ------------------------------------------------------------------------------------ - /// - /// Sets the name of the company used for registry settings (replaces - /// Application.CompanyName) - /// NOTE: THIS SHOULD ONLY BE SET IN TESTS AS THE DEFAULT Application.CompanyName IN - /// TESTS WILL BE "nunit.org" or jetbrains.something!!! - /// - /// ------------------------------------------------------------------------------------ - public static string CompanyName - { - set { s_companyName = value; } - private get - { - // This might be a good idea but will require all unit tests that depend on these functions to set one. Many of them - // don't seem to affected by using an NUnit or JetBrains application name. - //if (s_companyName.IndexOf("nunit", StringComparison.InvariantCultureIgnoreCase) >= 0 || s_companyName.IndexOf("jetbrains", StringComparison.InvariantCultureIgnoreCase) >= 0) - // throw new ArgumentException("CompanyName can not be NUnit.org or some variant of NUnit or jetbrains!" + - // " Make sure the test is overriding this property in RegistryHelper"); - return s_companyName; - } - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets the path for storing common application data that might be shared between - /// multiple applications and multiple users on the same machine. - /// - /// On Windows this returns a subdirectory of - /// Environment.SpecialFolder.CommonApplicationData (C:\ProgramData),on Linux - /// /var/lib/fieldworks. - /// - /// Name of the application. - /// ------------------------------------------------------------------------------------ - public static string CommonAppDataFolder(string appName) - { - return Path.Combine(Path.Combine(CommonApplicationData, CompanyName), appName); - } - /// ------------------------------------------------------------------------------------ /// /// Gets the full path of the Translation Editor executable. @@ -264,6 +151,22 @@ public static string MigrateSqlDbsExe get { return ExeOrDllPath("MigrateSqlDbs.exe"); } } + /// + /// Gets the path to MSSQLMigration\Db.exe. + /// + public static string DbExe + { + get { return Path.Combine(GetCodeSubDirectory("MSSQLMigration"), "db.exe"); } + } + + /// + /// Gets the converter console executable. + /// + public static string ConverterConsoleExe + { + get { return ExeOrDllPath("ConverterConsole.exe"); } + } + /// ------------------------------------------------------------------------------------ /// /// Gets the full path of the config file @@ -302,7 +205,7 @@ private static string ExeOrDllPath(string file) #else const string arch = "Release"; #endif - return Path.Combine(Path.Combine(Path.Combine(Path.GetDirectoryName(FwSourceDirectory), "Output"), arch), file); + return Path.Combine(Path.Combine(Path.Combine(Path.GetDirectoryName(SourceDirectory), "Output"), arch), file); } return Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), file); @@ -353,9 +256,9 @@ private static string GetSubDirectory(string directory, string subDirectory) /// examples: "WW\XAMPLE or \WW\XAMPLE" /// /// ------------------------------------------------------------------------------------ - public static string GetFWCodeSubDirectory(string subDirectory) + public static string GetCodeSubDirectory(string subDirectory) { - return GetSubDirectory(FWCodeDirectory, subDirectory); + return GetSubDirectory(CodeDirectory, subDirectory); } private static string GetFLExBridgeFolderPath() @@ -380,9 +283,9 @@ private static string GetFLExBridgeFolderPath() /// examples: "Languages or \Languages" /// /// ------------------------------------------------------------------------------------ - public static string GetFWDataSubDirectory(string subDirectory) + public static string GetDataSubDirectory(string subDirectory) { - return GetSubDirectory(FWDataDirectory, subDirectory); + return GetSubDirectory(DataDirectory, subDirectory); } /// ------------------------------------------------------------------------------------ @@ -392,9 +295,9 @@ public static string GetFWDataSubDirectory(string subDirectory) /// examples: "iso-8859-1.tec" /// /// ------------------------------------------------------------------------------------ - public static string GetFWCodeFile(string filename) + public static string GetCodeFile(string filename) { - return Path.Combine(FWCodeDirectory, filename); + return Path.Combine(CodeDirectory, filename); } /// ------------------------------------------------------------------------------------ @@ -485,11 +388,11 @@ private static string GetDirectory(RegistryKey registryKey, string registryValue /// If an installation directory could not be /// found. /// ------------------------------------------------------------------------------------ - public static string FWCodeDirectory + public static string CodeDirectory { get { - string defaultDir = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), CompanyName), + string defaultDir = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), DirectoryFinder.CompanyName), string.Format("FieldWorks {0}", FwUtils.SuiteVersion)); return GetDirectory("RootCodeDir", defaultDir); } @@ -504,9 +407,9 @@ public static string FWCodeDirectory /// If an installation directory could not be /// found. /// ------------------------------------------------------------------------------------ - public static string FWDataDirectory + public static string DataDirectory { - get { return GetDirectory(ksRootDataDir, CommonAppDataFolder(ksFieldWorks)); } + get { return GetDirectory(ksRootDataDir, DirectoryFinder.CommonAppDataFolder(ksFieldWorks)); } } /// ------------------------------------------------------------------------------------ @@ -517,9 +420,9 @@ public static string FWDataDirectory /// If an installation directory could not be /// found. /// ------------------------------------------------------------------------------------ - public static string FWDataDirectoryLocalMachine + public static string DataDirectoryLocalMachine { - get { return GetDirectoryLocalMachine(ksRootDataDir, CommonAppDataFolder(ksFieldWorks)); } + get { return GetDirectoryLocalMachine(ksRootDataDir, DirectoryFinder.CommonAppDataFolder(ksFieldWorks)); } } private static string m_srcdir; @@ -529,7 +432,7 @@ public static string FWDataDirectoryLocalMachine /// Gets the src dir (for running tests) /// /// ------------------------------------------------------------------------------------ - public static string FwSourceDirectory + public static string SourceDirectory { get { @@ -585,7 +488,7 @@ public static string EditorialChecksDirectory { get { - string directory = GetFWCodeSubDirectory(@"Editorial Checks"); + string directory = GetCodeSubDirectory(@"Editorial Checks"); if (!Directory.Exists(directory)) { string msg = ResourceHelper.GetResourceString("kstidUnableToFindEditorialChecks"); @@ -630,6 +533,17 @@ public static string BasicEditorialChecksDll } } + /// + /// Gets the legacy wordforming character overrides file. + /// + public static string LegacyWordformingCharOverridesFile + { + get + { + return Path.Combine(CodeDirectory, "WordFormingCharOverrides.xml"); + } + } + /// ------------------------------------------------------------------------------------ /// /// Gets the dir where templates are installed @@ -637,7 +551,7 @@ public static string BasicEditorialChecksDll /// ------------------------------------------------------------------------------------ public static string TemplateDirectory { - get { return GetFWCodeSubDirectory("Templates"); } + get { return GetCodeSubDirectory("Templates"); } } private const string ksProjects = "Projects"; @@ -652,7 +566,7 @@ public static string TemplateDirectory /// ------------------------------------------------------------------------------------ public static string ProjectsDirectory { - get { return GetDirectory(ksProjectsDir, Path.Combine(FWDataDirectory, ksProjects)); } + get { return GetDirectory(ksProjectsDir, Path.Combine(DataDirectory, ksProjects)); } set { if (ProjectsDirectory == value) @@ -677,7 +591,7 @@ public static string ProjectsDirectory /// public static string ProjectsDirectoryLocalMachine { - get { return GetDirectoryLocalMachine(ksProjectsDir, Path.Combine(FWDataDirectoryLocalMachine, ksProjects)); } + get { return GetDirectoryLocalMachine(ksProjectsDir, Path.Combine(DataDirectoryLocalMachine, ksProjects)); } } /// ------------------------------------------------------------------------------------ @@ -723,48 +637,6 @@ public static string DefaultBackupDirectory } } - /// ------------------------------------------------------------------------------------ - /// - /// Gets the global writing system store directory. The directory is guaranteed to exist. - /// - /// ------------------------------------------------------------------------------------ - [SuppressMessage("Gendarme.Rules.Portability", "MonoCompatibilityReviewRule", - Justification="Offending code is not executed on Linux")] - public static string GlobalWritingSystemStoreDirectory - { - get - { - string path = CommonAppDataFolder(ksWritingSystemsDir); - if (!Directory.Exists(path)) - { - DirectoryInfo di; - - // Provides FW on Linux multi-user access. Overrides the system - // umask and creates the directory with the permissions "775". - // The "fieldworks" group was created outside the app during - // configuration of the package which allows group access. - using(new FileModeOverride()) - { - di = Directory.CreateDirectory(path); - } - - if (!MiscUtils.IsUnix) - { - // NOTE: GetAccessControl/ModifyAccessRule/SetAccessControl is not implemented in Mono - DirectorySecurity ds = di.GetAccessControl(); - var sid = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null); - AccessRule rule = new FileSystemAccessRule(sid, FileSystemRights.Write | FileSystemRights.ReadAndExecute - | FileSystemRights.Modify, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, - PropagationFlags.InheritOnly, AccessControlType.Allow); - bool modified; - ds.ModifyAccessRule(AccessControlModification.Add, rule, out modified); - di.SetAccessControl(ds); - } - } - return path; - } - } - /// ------------------------------------------------------------------------------------ /// /// Gets the biblical key terms localization files. @@ -804,5 +676,29 @@ static public string GetLocaleFromKeyTermsLocFile(string locFilename) return Path.GetFileName(locFilename).Replace(ksBiblicaltermsLocFilePrefix, String.Empty).Replace(ksBiblicaltermsLocFileExtension, String.Empty); } + + /// + /// Gets the FDO directories service. + /// + public static IFdoDirectories FdoDirectories + { + get { return s_fdoDirs; } + } + + private class FwFdoDirectories : IFdoDirectories + { + /// + /// Gets the projects directory. + /// + public string ProjectsDirectory + { + get { return FwDirectoryFinder.ProjectsDirectory; } + } + + public string TemplateDirectory + { + get { return FwDirectoryFinder.TemplateDirectory; } + } + } } } diff --git a/Src/Common/FwUtils/FwRegistryHelper.cs b/Src/Common/FwUtils/FwRegistryHelper.cs index 8914ecdeea..98e2098836 100644 --- a/Src/Common/FwUtils/FwRegistryHelper.cs +++ b/Src/Common/FwUtils/FwRegistryHelper.cs @@ -195,35 +195,6 @@ public bool Paratext7orLaterInstalled() return false; } } - - /// - /// LT-14787 Database displays error about inaccessible Paratext projects - /// If there is a registry value for this but the folder is not there we need to return false because - /// paratext is not installed correctly. Also if there is no registry entry for this then return false. - /// - public bool ParatextSettingsDirectoryExists() - { - var regValue = ParatextSettingsDirectory(); - return !String.IsNullOrEmpty(regValue) && Directory.Exists(regValue); - } - - /// - /// Returns the path to the Paratext settings (projects) directory as specified in the registry - /// ENHANCE (Hasso) 2013.09: added this to expose the directory for Unix users, because trying to get it from ScrTextCollections - /// always returns null on Unix. This is really a Paratext problem, and this method may have no benefit. - /// - public string ParatextSettingsDirectory() - { - using (var paratextKey = Registry.LocalMachine.OpenSubKey("Software\\ScrChecks\\1.0\\Settings_Directory")) - { - if (paratextKey != null) - { - var keyName = paratextKey.ToString(); - return Registry.GetValue(keyName, "", "") as string; - } - } - return null; - } } /// ------------------------------------------------------------------------------------ @@ -378,25 +349,6 @@ public static bool Paratext7orLaterInstalled() return RegistryHelperImpl.Paratext7orLaterInstalled(); } - /// - /// If there is a registry value for this but the folder is not there we need to return false because - /// paratext is not installed correctly. Also if there is no registry entry for this then return false. - /// - public static bool ParatextSettingsDirectoryExists() - { - return RegistryHelperImpl.ParatextSettingsDirectoryExists(); - } - - /// - /// Returns the path to the Paratext settings (projects) directory as specified in the registry - /// ENHANCE (Hasso) 2013.09: added this to expose the directory for Unix users, because trying to get it from ScrTextCollections - /// always returns null on Unix. This is really a Paratext problem, and this method may have no benefit. - /// - public static string ParatextSettingsDirectory() - { - return RegistryHelperImpl.ParatextSettingsDirectory(); - } - /// /// E.g. the first time the user runs FW8, we need to copy a bunch of registry keys /// from HKCU/Software/SIL/FieldWorks/7.0 -> FieldWorks/8. diff --git a/Src/Common/FwUtils/FwSubKey.cs b/Src/Common/FwUtils/FwSubKey.cs index c3ec39afcd..301290dde6 100644 --- a/Src/Common/FwUtils/FwSubKey.cs +++ b/Src/Common/FwUtils/FwSubKey.cs @@ -23,13 +23,13 @@ public class FwSubKey { /// /// The name of the Translation Editor registry subkey (Even though this is the same as - /// DirectoryFinder.ksTeFolderName and FwUtils.ksTeAppName, PLEASE do not use them interchangeably. + /// FwDirectoryFinder.ksTeFolderName and FwUtils.ksTeAppName, PLEASE do not use them interchangeably. /// Use the one that is correct for your context, in case they need to be changed later.) /// public const string TE = FwUtils.ksTeAppName; /// /// The name of the Language Explorer registry subkey (Even though this is the same as - /// DirectoryFinder.ksFlexFolderName and FwUtils.ksFlexAppName, PLEASE do not use them interchangeably. + /// FwDirectoryFinder.ksFlexFolderName and FwUtils.ksFlexAppName, PLEASE do not use them interchangeably. /// Use the one that is correct for your context, in case they need to be changed later.) /// public const string LexText = FwUtils.ksFlexAppName; diff --git a/Src/Common/FwUtils/FwUtils.cs b/Src/Common/FwUtils/FwUtils.cs index 6780be52dd..866f9f177b 100644 --- a/Src/Common/FwUtils/FwUtils.cs +++ b/Src/Common/FwUtils/FwUtils.cs @@ -36,7 +36,7 @@ public static class FwUtils public const string ksSuiteName = "FieldWorks"; /// /// The name of the Translation Editor folder (Even though this is the same as - /// DirectoryFinder.ksTeFolderName and FwSubKey.TE, PLEASE do not use them interchangeably. + /// FwDirectoryFinder.ksTeFolderName and FwSubKey.TE, PLEASE do not use them interchangeably. /// Use the one that is correct for your context, in case they need to be changed later.) /// public const string ksTeAppName = "Translation Editor"; @@ -48,7 +48,7 @@ public static class FwUtils public const string ksFullTeAppObjectName = "SIL.FieldWorks.TE.TeApp"; /// /// The name of the Language Explorer folder (Even though this is the same as - /// DirectoryFinder.ksFlexFolderName and FwSubKey.LexText, PLEASE do not use them interchangeably. + /// FwDirectoryFinder.ksFlexFolderName and FwSubKey.LexText, PLEASE do not use them interchangeably. /// Use the one that is correct for your context, in case they need to be changed later.) /// public const string ksFlexAppName = "Language Explorer"; @@ -76,7 +76,7 @@ public static bool IsTEInstalled get { if (s_fIsTEInstalled == null) - s_fIsTEInstalled = File.Exists(DirectoryFinder.TeExe); + s_fIsTEInstalled = File.Exists(FwDirectoryFinder.TeExe); return (bool)s_fIsTEInstalled; } } @@ -103,7 +103,7 @@ public static bool IsOkToDisplayScriptureIfPresent /// ------------------------------------------------------------------------------------ public static bool IsFlexInstalled { - get { return File.Exists(DirectoryFinder.FlexExe); } + get { return File.Exists(FwDirectoryFinder.FlexExe); } } /// ------------------------------------------------------------------------------------ @@ -212,13 +212,13 @@ public static string GetFontNameForLanguage(string lang) /// /// Whenever possible use this in place of new PalasoWritingSystemManager. /// It sets the TemplateFolder, which unfortunately the constructor cannot do because - /// the direction of our dependencies does not allow it to reference FwUtils and access DirectoryFinder. + /// the direction of our dependencies does not allow it to reference FwUtils and access FwDirectoryFinder. /// /// public static PalasoWritingSystemManager CreateWritingSystemManager() { var result = new PalasoWritingSystemManager(); - result.TemplateFolder = DirectoryFinder.TemplateDirectory; + result.TemplateFolder = FwDirectoryFinder.TemplateDirectory; return result; } diff --git a/Src/Common/FwUtils/FwUtils.csproj b/Src/Common/FwUtils/FwUtils.csproj index 8dd787356a..0be6681bc0 100644 --- a/Src/Common/FwUtils/FwUtils.csproj +++ b/Src/Common/FwUtils/FwUtils.csproj @@ -114,6 +114,10 @@ False ..\..\..\Output\Debug\CoreImpl.dll + + False + ..\..\..\Output\Debug\FDO.dll + FwResources ..\..\..\Output\Debug\FwResources.dll @@ -173,7 +177,7 @@ - + @@ -183,7 +187,6 @@ True FwUtilsStrings.resx - @@ -192,9 +195,6 @@ - - Code - diff --git a/Src/Common/FwUtils/FwUtilsStrings.Designer.cs b/Src/Common/FwUtils/FwUtilsStrings.Designer.cs index 2bc4fc95a0..8778805662 100644 --- a/Src/Common/FwUtils/FwUtilsStrings.Designer.cs +++ b/Src/Common/FwUtils/FwUtilsStrings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.239 +// Runtime Version:4.0.30319.18052 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -9,255 +9,219 @@ //------------------------------------------------------------------------------ namespace SIL.FieldWorks.Common.FwUtils { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class FwUtilsStrings { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal FwUtilsStrings() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SIL.FieldWorks.Common.FwUtils.FwUtilsStrings", typeof(FwUtilsStrings).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to The help file could not be located.. - /// - internal static string ksCannotFindHelp { - get { - return ResourceManager.GetString("ksCannotFindHelp", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Change Failed. - /// - internal static string ksChangeFailed { - get { - return ResourceManager.GetString("ksChangeFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to AD. - /// - internal static string ksGenDateAD { - get { - return ResourceManager.GetString("ksGenDateAD", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to After. - /// - internal static string ksGenDateAfter { - get { - return ResourceManager.GetString("ksGenDateAfter", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to About. - /// - internal static string ksGenDateApprox { - get { - return ResourceManager.GetString("ksGenDateApprox", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to BC. - /// - internal static string ksGenDateBC { - get { - return ResourceManager.GetString("ksGenDateBC", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Before. - /// - internal static string ksGenDateBefore { - get { - return ResourceManager.GetString("ksGenDateBefore", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The help topic is not available for topic: {0}. - /// - internal static string ksNoHelpTopicX { - get { - return ResourceManager.GetString("ksNoHelpTopicX", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The project you are opening will not communicate with Paratext - ///because a project with the same name is already open. - ///If you want to use Paratext with this project, make a change in this project (so that it will start first), close both projects, then restart Flex.. - /// - internal static string ksPtCommunicationProblem { - get { - return ResourceManager.GetString("ksPtCommunicationProblem", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to You do not have permission to change the setting "{0}". Administrator privileges are required to make changes affecting all users of this computer.. - /// - internal static string ksRegChangeFailed { - get { - return ResourceManager.GetString("ksRegChangeFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Version: {0} {1} {2}. - /// - internal static string kstidAppVersionFmt { - get { - return ResourceManager.GetString("kstidAppVersionFmt", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to FieldWorks has unexpectedly timed out trying to determine whether the spelling dictionary {0} exists. FieldWorks will assume there is no such dictionary, which may affect spell-checking. If you think this dictionary should exist, we recommend restarting your computer. If you see this message regularly, please report it as a bug.. - /// - internal static string kstIdCantDoDictExists { - get { - return ResourceManager.GetString("kstIdCantDoDictExists", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Spelling Dictionary Problem. - /// - internal static string kstidCantDoDictExistsCaption { - get { - return ResourceManager.GetString("kstidCantDoDictExistsCaption", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to cm. - /// - internal static string kstidCm { - get { - return ResourceManager.GetString("kstidCm", resourceCulture); - } - } - - /// - /// Looks up a localized string - /// - internal static string kstidLicense { - get { - return ResourceManager.GetString("kstidLicense", resourceCulture); - } - } - - /// - /// Looks up a localized string - /// - internal static string kstidLicenseURL { - get { - return ResourceManager.GetString("kstidLicenseURL", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Version: {0}. - /// - internal static string kstidFwVersionFmt { - get { - return ResourceManager.GetString("kstidFwVersionFmt", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to in. - /// - internal static string kstidIn { - get { - return ResourceManager.GetString("kstidIn", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to ". - /// - internal static string kstidInches { - get { - return ResourceManager.GetString("kstidInches", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The writing system {0} specifies an invalid spelling dictionary ({1}). Valid spelling dictionary IDs must only contain ASCII alphanumeric characters or underline. Spell checking will not work for this writing system until you correct this in the Writing System Properties dialog.. - /// - internal static string kstidInvalidDictId { - get { - return ResourceManager.GetString("kstidInvalidDictId", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to mm. - /// - internal static string kstidMm { - get { - return ResourceManager.GetString("kstidMm", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to pt. - /// - internal static string kstidPt { - get { - return ResourceManager.GetString("kstidPt", resourceCulture); - } - } - } + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class FwUtilsStrings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal FwUtilsStrings() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SIL.FieldWorks.Common.FwUtils.FwUtilsStrings", typeof(FwUtilsStrings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to The help file could not be located.. + /// + internal static string ksCannotFindHelp { + get { + return ResourceManager.GetString("ksCannotFindHelp", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Change Failed. + /// + internal static string ksChangeFailed { + get { + return ResourceManager.GetString("ksChangeFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to AD. + /// + internal static string ksGenDateAD { + get { + return ResourceManager.GetString("ksGenDateAD", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to After. + /// + internal static string ksGenDateAfter { + get { + return ResourceManager.GetString("ksGenDateAfter", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to About. + /// + internal static string ksGenDateApprox { + get { + return ResourceManager.GetString("ksGenDateApprox", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to BC. + /// + internal static string ksGenDateBC { + get { + return ResourceManager.GetString("ksGenDateBC", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Before. + /// + internal static string ksGenDateBefore { + get { + return ResourceManager.GetString("ksGenDateBefore", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The help topic is not available for topic: {0}. + /// + internal static string ksNoHelpTopicX { + get { + return ResourceManager.GetString("ksNoHelpTopicX", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The project you are opening will not communicate with Paratext + ///because a project with the same name is already open. + ///If you want to use Paratext with this project, make a change in this project (so that it will start first), close both projects, then restart FLEx.. + /// + internal static string ksPtCommunicationProblem { + get { + return ResourceManager.GetString("ksPtCommunicationProblem", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You do not have permission to change the setting "{0}". Administrator privileges are required to make changes affecting all users of this computer.. + /// + internal static string ksRegChangeFailed { + get { + return ResourceManager.GetString("ksRegChangeFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to FieldWorks has unexpectedly timed out trying to determine whether the spelling dictionary {0} exists. FieldWorks will assume there is no such dictionary, which may affect spell-checking. If you think this dictionary should exist, we recommend restarting your computer. If you see this message regularly, please report it as a bug.. + /// + internal static string kstIdCantDoDictExists { + get { + return ResourceManager.GetString("kstIdCantDoDictExists", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spelling Dictionary Problem. + /// + internal static string kstidCantDoDictExistsCaption { + get { + return ResourceManager.GetString("kstidCantDoDictExistsCaption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to cm. + /// + internal static string kstidCm { + get { + return ResourceManager.GetString("kstidCm", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to in. + /// + internal static string kstidIn { + get { + return ResourceManager.GetString("kstidIn", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ". + /// + internal static string kstidInches { + get { + return ResourceManager.GetString("kstidInches", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The writing system {0} specifies an invalid spelling dictionary ({1}). Valid spelling dictionary IDs must only contain ASCII alphanumeric characters or underline. Spell checking will not work for this writing system until you correct this in the Writing System Properties dialog.. + /// + internal static string kstidInvalidDictId { + get { + return ResourceManager.GetString("kstidInvalidDictId", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to mm. + /// + internal static string kstidMm { + get { + return ResourceManager.GetString("kstidMm", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to pt. + /// + internal static string kstidPt { + get { + return ResourceManager.GetString("kstidPt", resourceCulture); + } + } + } } diff --git a/Src/Common/FwUtils/FwUtilsStrings.resx b/Src/Common/FwUtils/FwUtilsStrings.resx index dbd122db72..2d65e11b8e 100644 --- a/Src/Common/FwUtils/FwUtilsStrings.resx +++ b/Src/Common/FwUtils/FwUtilsStrings.resx @@ -1,200 +1,184 @@  - + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - text/microsoft-resx + text/microsoft-resx - 2.0 + 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - The help file could not be located. + The help file could not be located. - The help topic is not available for topic: {0} + The help topic is not available for topic: {0} - AD + AD - After + After - About + About - BC + BC - Before + Before - cm - Measurement unit abbreviation for Centimeters (Localized string should preserve leading space if needed in formatted display.) + cm + Measurement unit abbreviation for Centimeters (Localized string should preserve leading space if needed in formatted display.) - in - Measurement unit abbreviation for Inches (Localized string should preserve leading space if needed in formatted display.) + in + Measurement unit abbreviation for Inches (Localized string should preserve leading space if needed in formatted display.) - " - Measurement unit symbol for Inches (If culture doesn't have a separate symbol for specifying inches, localized value for this string should be set to match value of kstidIn.) + " + Measurement unit symbol for Inches (If culture doesn't have a separate symbol for specifying inches, localized value for this string should be set to match value of kstidIn.) - mm - Measurement unit abbreviation for Millimeters (Localized string should preserve leading space if needed in formatted display.) + mm + Measurement unit abbreviation for Millimeters (Localized string should preserve leading space if needed in formatted display.) - pt - Measurement unit abbreviation for Points (Localized string should preserve leading space if needed in formatted display.) - - - Version: {0} {1} {2} - Displays in the Help/About box and the splash screen - - - This software is licensed under the MIT License - Displays in the Help/About box and the splash screen - - - (http://opensource.org/licenses/MIT) - Displays in the Help/About box - - - Version: {0} - Displays in the Help/About box and the splash screen + pt + Measurement unit abbreviation for Points (Localized string should preserve leading space if needed in formatted display.) - Change Failed - Caption for dialog reporting failure to update. + Change Failed + Caption for dialog reporting failure to update. - You do not have permission to change the setting "{0}". Administrator privileges are required to make changes affecting all users of this computer. - Error message when writing a registry setting for "local machine" fails. + You do not have permission to change the setting "{0}". Administrator privileges are required to make changes affecting all users of this computer. + Error message when writing a registry setting for "local machine" fails. - FieldWorks has unexpectedly timed out trying to determine whether the spelling dictionary {0} exists. FieldWorks will assume there is no such dictionary, which may affect spell-checking. If you think this dictionary should exist, we recommend restarting your computer. If you see this message regularly, please report it as a bug. + FieldWorks has unexpectedly timed out trying to determine whether the spelling dictionary {0} exists. FieldWorks will assume there is no such dictionary, which may affect spell-checking. If you think this dictionary should exist, we recommend restarting your computer. If you see this message regularly, please report it as a bug. - Spelling Dictionary Problem + Spelling Dictionary Problem - The writing system {0} specifies an invalid spelling dictionary ({1}). Valid spelling dictionary IDs must only contain ASCII alphanumeric characters or underline. Spell checking will not work for this writing system until you correct this in the Writing System Properties dialog. - Error message. {0} might be a code like "fr" and {1} a bad ID, typically a short string like "frn[". + The writing system {0} specifies an invalid spelling dictionary ({1}). Valid spelling dictionary IDs must only contain ASCII alphanumeric characters or underline. Spell checking will not work for this writing system until you correct this in the Writing System Properties dialog. + Error message. {0} might be a code like "fr" and {1} a bad ID, typically a short string like "frn[". - The project you are opening will not communicate with Paratext + The project you are opening will not communicate with Paratext because a project with the same name is already open. If you want to use Paratext with this project, make a change in this project (so that it will start first), close both projects, then restart FLEx. - + \ No newline at end of file diff --git a/Src/Common/FwUtils/FwUtilsTests/DirectoryFinderTests.cs b/Src/Common/FwUtils/FwUtilsTests/DirectoryFinderTests.cs deleted file mode 100644 index 8c467d6815..0000000000 --- a/Src/Common/FwUtils/FwUtilsTests/DirectoryFinderTests.cs +++ /dev/null @@ -1,468 +0,0 @@ -// -------------------------------------------------------------------------------------------- -//#region // Copyright (c) 2008, SIL International. All Rights Reserved. -// -// Copyright (c) 2008, SIL International. All Rights Reserved. -// -// Distributable under the terms of either the Common Public License or the -// GNU Lesser General Public License, as specified in the LICENSING.txt file. -// -//#endregion -// -// File: DirectoryFinderTests.cs -// Responsibility: Eberhard Beilharz -// Last reviewed: -// -//-------------------------------------------------------------------------------------------- - -using System; -using System.IO; -using NUnit.Framework; -using SIL.FieldWorks.FDO; -using SIL.FieldWorks.Test.TestUtils; -using SIL.Utils; - -namespace SIL.FieldWorks.Common.FwUtils -{ - - ///----------------------------------------------------------------------------------------- - /// - /// Tests for the DirectoryFinder class - /// - ///----------------------------------------------------------------------------------------- - [TestFixture] - public class DirectoryFinderTests : BaseTest - { - /// - /// Resets the registry helper - /// - [TestFixtureTearDown] - public void TearDown() - { - FwRegistryHelper.Manager.Reset(); - } - - /// - /// Fixture setup - /// - [TestFixtureSetUp] - public void TestFixtureSetup() - { - DirectoryFinder.CompanyName = "SIL"; - FwRegistryHelper.Manager.SetRegistryHelper(new DummyFwRegistryHelper()); - FwRegistryHelper.FieldWorksRegistryKey.SetValue("RootDataDir", Path.GetFullPath(Path.Combine(UtilsAssemblyDir, "../../DistFiles"))); - FwRegistryHelper.FieldWorksRegistryKey.SetValue("RootCodeDir", Path.GetFullPath(Path.Combine(UtilsAssemblyDir, "../../DistFiles"))); - } - - ///------------------------------------------------------------------------------------- - /// - /// Gets the directory where the Utils assembly is - /// - ///------------------------------------------------------------------------------------- - private string UtilsAssemblyDir - { - get - { - return Path.GetDirectoryName(typeof(DirectoryFinder).Assembly.CodeBase - .Substring(MiscUtils.IsUnix ? 7 : 8)); - } - } - - ///------------------------------------------------------------------------------------- - /// - /// Tests the FWCodeDirectory property. This should return the DistFiles directory. - /// - ///------------------------------------------------------------------------------------- - [Test] - public void FWCodeDirectory() - { - var currentDir = Path.GetFullPath(Path.Combine(UtilsAssemblyDir, "../../DistFiles")); - Assert.That(DirectoryFinder.FWCodeDirectory, Is.SamePath(currentDir)); - } - - /// - /// Verify that the user project key falls back to the local machine. - /// - [Test] - public void GettingProjectDirWithEmptyUserKeyReturnsLocalMachineKey() - { - using (var fwHKCU = FwRegistryHelper.FieldWorksRegistryKey) - using (var fwHKLM = FwRegistryHelper.FieldWorksRegistryKeyLocalMachine) - { - if (fwHKCU.GetValue("ProjectsDir") != null) - { - fwHKCU.DeleteValue("ProjectsDir"); - } - fwHKLM.SetValue("ProjectsDir", "HKLM_TEST"); - Assert.That(DirectoryFinder.ProjectsDirectory, Is.EqualTo(DirectoryFinder.ProjectsDirectoryLocalMachine)); - Assert.That(DirectoryFinder.ProjectsDirectory, Is.EqualTo("HKLM_TEST")); - } - } - - /// - /// Verify that the user project key overrides the local machine. - /// - [Test] - public void GettingProjectDirWithUserDifferentFromLMReturnsUser() - { - DirectoryFinder.ProjectsDirectory = "NewHKCU_TEST_Value"; - Assert.That(DirectoryFinder.ProjectsDirectory, Is.Not.EqualTo(DirectoryFinder.ProjectsDirectoryLocalMachine)); - Assert.That(DirectoryFinder.ProjectsDirectory, Is.EqualTo("NewHKCU_TEST_Value")); - } - - /// - /// Verify that setting the user key to null deletes the user setting and falls back to local machine. - /// - [Test] - public void SettingProjectDirToNullDeletesUserKey() - { - DirectoryFinder.ProjectsDirectory = null; - Assert.That(DirectoryFinder.ProjectsDirectory, Is.EqualTo(DirectoryFinder.ProjectsDirectoryLocalMachine)); - - using (var fwHKCU = FwRegistryHelper.FieldWorksRegistryKey) - using (var fwHKLM = FwRegistryHelper.FieldWorksRegistryKeyLocalMachine) - { - Assert.Null(fwHKCU.GetValue("ProjectsDir")); - Assert.NotNull(fwHKLM.GetValue("ProjectsDir")); - } - } - - ///------------------------------------------------------------------------------------- - /// - /// Tests the FWDataDirectory property. This should return the DistFiles directory. - /// - ///------------------------------------------------------------------------------------- - [Test] - public void FWDataDirectory() - { - var currentDir = Path.GetFullPath(Path.Combine(UtilsAssemblyDir, "../../DistFiles")); - Assert.That(DirectoryFinder.FWDataDirectory, Is.SamePath(currentDir)); - } - - ///------------------------------------------------------------------------------------- - /// - /// Tests the FwSourceDirectory property. This should return the DistFiles directory. - /// - ///------------------------------------------------------------------------------------- - [Test] - public void FwSourceDirectory() - { - string expectedDir = Path.GetFullPath(Path.Combine(UtilsAssemblyDir, "../../Src")); - Assert.That(DirectoryFinder.FwSourceDirectory, Is.SamePath(expectedDir)); - } - - ///------------------------------------------------------------------------------------- - /// - /// Tests the GetFWCodeSubDirectory method when we pass a subdirectory without a - /// leading directory separator - /// - ///------------------------------------------------------------------------------------- - [Test] - public void GetFWCodeSubDirectory_NoLeadingSlash() - { - Assert.That(DirectoryFinder.GetFWCodeSubDirectory("Translation Editor/Configuration"), - Is.SamePath(Path.Combine(DirectoryFinder.FWCodeDirectory, "Translation Editor/Configuration"))); - } - - ///------------------------------------------------------------------------------------- - /// - /// Tests the GetFWCodeSubDirectory method when we pass a subdirectory with a - /// leading directory separator - /// - ///------------------------------------------------------------------------------------- - [Test] - public void GetFWCodeSubDirectory_LeadingSlash() - { - Assert.That(DirectoryFinder.GetFWCodeSubDirectory("/Translation Editor/Configuration"), - Is.SamePath(Path.Combine(DirectoryFinder.FWCodeDirectory, "Translation Editor/Configuration"))); - } - - ///------------------------------------------------------------------------------------- - /// - /// Tests the GetFWCodeSubDirectory method when we pass an invalid subdirectory - /// - ///------------------------------------------------------------------------------------- - [Test] - public void GetFWCodeSubDirectory_InvalidDir() - { - Assert.That(DirectoryFinder.GetFWCodeSubDirectory("NotExisting"), - Is.SamePath("NotExisting")); - } - - ///------------------------------------------------------------------------------------- - /// - /// Tests the GetFWDataSubDirectory method when we pass a subdirectory without a - /// leading directory separator - /// - ///------------------------------------------------------------------------------------- - [Test] - public void GetFWDataSubDirectory_NoLeadingSlash() - { - Assert.That(DirectoryFinder.GetFWDataSubDirectory("Translation Editor/Configuration"), - Is.SamePath(Path.Combine(DirectoryFinder.FWDataDirectory, "Translation Editor/Configuration"))); - } - - ///------------------------------------------------------------------------------------- - /// - /// Tests the GetFWDataSubDirectory method when we pass a subdirectory with a - /// leading directory separator - /// - ///------------------------------------------------------------------------------------- - [Test] - public void GetFWDataSubDirectory_LeadingSlash() - { - Assert.That(DirectoryFinder.GetFWDataSubDirectory("/Translation Editor/Configuration"), - Is.SamePath(Path.Combine(DirectoryFinder.FWDataDirectory, "Translation Editor/Configuration"))); - } - - ///------------------------------------------------------------------------------------- - /// - /// Tests the GetFWDataSubDirectory method when we pass an invalid subdirectory - /// - ///------------------------------------------------------------------------------------- - [Test] - public void GetFWDataSubDirectory_InvalidDir() - { - Assert.That(DirectoryFinder.GetFWDataSubDirectory("NotExisting"), - Is.SamePath("NotExisting")); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Tests the GetLinkedFilesRelativePathFromFullPath method - /// - /// ------------------------------------------------------------------------------------ - [Test] - public void GetLinkedFilesRelativePathFromFullPath() - { - Assert.AreEqual(String.Format("%proj%{0}LinkedFiles", Path.DirectorySeparatorChar), - FdoFileHelperRelativePaths.GetLinkedFilesRelativePathFromFullPath(String.Format("%proj%{0}LinkedFiles", Path.DirectorySeparatorChar), - Path.Combine(DirectoryFinder.FwSourceDirectory, "FDO/FDOTests/BackupRestore/Project"), - "Project")); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Tests the GetLinkedFilesFullPathFromRelativePath method - /// - /// ------------------------------------------------------------------------------------ - [Test] - public void GetLinkedFilesFullPathFromRelativePath() - { - var projectPath = Path.Combine(DirectoryFinder.ProjectsDirectory, "TestProject"); - var linkedFilesRootDir = Path.Combine(projectPath, "LinkedFiles"); - var linkedFilesPath = - FdoFileHelperRelativePaths.GetLinkedFilesFullPathFromRelativePath(String.Format("%proj%{0}LinkedFiles", Path.DirectorySeparatorChar), projectPath); - - Assert.AreEqual(linkedFilesRootDir, linkedFilesPath); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Tests the GetFullFilePathFromRelativeLFPath method - /// - /// ------------------------------------------------------------------------------------ - [Test] - public void GetFullFilePathFromRelativeLFPath() - { - var linkedFilesRootDir = Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, "TestProject"), "LinkedFiles"); - var fullLFPath = FdoFileHelperRelativePaths.GetFullFilePathFromRelativeLFPath(String.Format("%lf%{0}AudioVisual{0}StarWars.mvi", Path.DirectorySeparatorChar), linkedFilesRootDir); - var audioVisualFile = Path.Combine(Path.Combine(linkedFilesRootDir, "AudioVisual"), "StarWars.mvi"); - Assert.AreEqual(audioVisualFile, fullLFPath); - - //if a fully rooted path is passed in the return value should be null. - var projectRootDir = DirectoryFinder.FWDataDirectory; - fullLFPath = FdoFileHelperRelativePaths.GetFullFilePathFromRelativeLFPath(projectRootDir, linkedFilesRootDir); - Assert.True(string.IsNullOrEmpty(fullLFPath)); - - } - - /// ------------------------------------------------------------------------------------ - /// - /// Tests the GetRelativeLFPathFromFullFilePath method - /// - /// ------------------------------------------------------------------------------------ - [Test] - public void GetRelativeLFPathFromFullFilePath() - { - var linkedFilesRootDir = Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, "TestProject"), "LinkedFiles"); - var audioVisualFile = Path.Combine(Path.Combine(linkedFilesRootDir, "AudioVisual"), "StarWars.mvi"); - var relativeLFPath = FdoFileHelperRelativePaths.GetRelativeLFPathFromFullFilePath(audioVisualFile, linkedFilesRootDir); - Assert.AreEqual(String.Format("%lf%{0}AudioVisual{0}StarWars.mvi", Path.DirectorySeparatorChar), relativeLFPath); - - //Ensure empty string is returned when the path is not relative to the LinkedFiles directory. - var pathNotUnderLinkedFiles = Path.Combine(DirectoryFinder.FWDataDirectory, "LordOfTheRings.mvi"); - relativeLFPath = FdoFileHelperRelativePaths.GetRelativeLFPathFromFullFilePath(pathNotUnderLinkedFiles, linkedFilesRootDir); - Assert.True(string.IsNullOrEmpty(relativeLFPath)); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Tests the GetRelativeLinkedFilesPath method - /// - /// ------------------------------------------------------------------------------------ - [Test] - public void GetRelativeLinkedFilesPath() - { - var linkedFilesRootDir = Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, "TestProject"), "LinkedFiles"); - var audioVisualFile = Path.Combine(Path.Combine(linkedFilesRootDir, "AudioVisual"), "StarWars.mvi"); - var relativeLFPath = FdoFileHelperRelativePaths.GetRelativeLinkedFilesPath(audioVisualFile, linkedFilesRootDir); - Assert.True(String.Equals(String.Format("AudioVisual{0}StarWars.mvi", Path.DirectorySeparatorChar), relativeLFPath)); - - //Ensure ORIGINAL path is returned when the path is not relative to the LinkedFiles directory. - var pathNotUnderLinkedFiles = Path.Combine(DirectoryFinder.FWDataDirectory, "LordOfTheRings.mvi"); - relativeLFPath = FdoFileHelperRelativePaths.GetRelativeLinkedFilesPath(pathNotUnderLinkedFiles, linkedFilesRootDir); - Assert.True(String.Equals(pathNotUnderLinkedFiles,relativeLFPath)); - Assert.That(FdoFileHelperRelativePaths.GetRelativeLinkedFilesPath( - "silfw:\\localhost\\link?app%3dflex%26database%3dc%3a%5cTestLangProj%5cTestLangProj.fwdata%26server%3d%26tool%3dnaturalClassedit%26guid%3d43c9ba97-2883-4f95-aa5d-ef9309e85025%26tag%3d", - relativeLFPath), Is.Null, "hyperlinks should be left well alone!!"); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Tests the GetFullPathFromRelativeLFPath method - /// - /// ------------------------------------------------------------------------------------ - [Test] - public void GetFullPathFromRelativeLFPath() - { - var linkedFilesRootDir = Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, "TestProject"), "LinkedFiles"); - var fullLFPath = FdoFileHelperRelativePaths.GetFullPathFromRelativeLFPath(String.Format("AudioVisual{0}StarWars.mvi", Path.DirectorySeparatorChar), linkedFilesRootDir); - var audioVisualFile = Path.Combine(Path.Combine(linkedFilesRootDir, "AudioVisual"), "StarWars.mvi"); - Assert.AreEqual(audioVisualFile, fullLFPath); - - //if a fully rooted path is passed in the return value should be the path that was passed in. - var fileUnderProjectRootDir = String.Format("{1}{0}AudioVisual{0}StarWars.mvi", Path.DirectorySeparatorChar, DirectoryFinder.FWDataDirectory); - fullLFPath = FdoFileHelperRelativePaths.GetFullPathFromRelativeLFPath(fileUnderProjectRootDir, linkedFilesRootDir); - Assert.AreEqual(fullLFPath, fileUnderProjectRootDir); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Tests the GetFullPathFromRelativeLFPath method with illegal characters - /// - /// ------------------------------------------------------------------------------------ - [Test] - public void GetFullPathFromRelativeLFPath_WithIllegalCharacters_ReturnsSpecialPath() - { - var linkedFilesRootDir = Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, "TestProject"), "LinkedFiles"); - var fullLFPath = FdoFileHelperRelativePaths.GetFullPathFromRelativeLFPath("1\";1\"", linkedFilesRootDir); - Assert.That(fullLFPath, Is.EqualTo(Path.Combine(linkedFilesRootDir,"__ILLEGALCHARS__"))); - } - - /// - /// Tests the DefaultBackupDirectory property for use on Windows. - /// - [Test] - [Platform(Exclude="Linux", Reason="Test is Windows specific")] - public void DefaultBackupDirectory_Windows() - { - Assert.AreEqual(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), - Path.Combine("My FieldWorks", "Backups")), DirectoryFinder.DefaultBackupDirectory); - } - - /// - /// Tests the DefaultBackupDirectory property for use on Linux - /// - [Test] - [Platform(Include="Linux", Reason="Test is Linux specific")] - public void DefaultBackupDirectory_Linux() - { - // SpecialFolder.MyDocuments returns $HOME on Linux! - Assert.AreEqual(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), - "Documents/fieldworks/backups"), DirectoryFinder.DefaultBackupDirectory); - } - - /// - /// Base class for testing CommonApplicationData. This base class deals with setting - /// and resetting the environment variable. - /// - public class GetCommonAppDataBaseTest: BaseTest - { - private string PreviousEnvironment; - - /// - /// Setup the tests. - /// - public override void FixtureSetup() - { - base.FixtureSetup(); - - DirectoryFinder.ResetStaticVars(); - PreviousEnvironment = Environment.GetEnvironmentVariable("FW_CommonAppData"); - var properties = (PropertyAttribute[])GetType().GetCustomAttributes(typeof(PropertyAttribute), true); - Assert.That(properties.Length, Is.GreaterThan(0)); - Environment.SetEnvironmentVariable("FW_CommonAppData", (string)properties[0].Properties["Value"]); - } - - /// - /// Reset environment variable to previous value - /// - public override void FixtureTeardown() - { - Environment.SetEnvironmentVariable("FW_CommonAppData", PreviousEnvironment); - - base.FixtureTeardown(); - } - } - - /// - /// Tests the GetFolderPath method for CommonApplicationData when no environment variable - /// is set. - /// - [TestFixture] - [Property("Value", null)] - public class GetCommonAppDataNormalTests: GetCommonAppDataBaseTest - { - /// Tests the GetFolderPath method for CommonApplicationData when no environment - /// variable is set - [Test] - [Platform(Include="Linux", Reason="Test is Linux specific")] - public void Linux() - { - Assert.AreEqual("/var/lib/fieldworks", - DirectoryFinder.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)); - } - - /// Tests the GetFolderPath method for CommonApplicationData when no environment - /// variable is set - [Test] - [Platform(Exclude="Linux", Reason="Test is Windows specific")] - public void Windows() - { - Assert.AreEqual( - Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), - DirectoryFinder.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)); - } - } - - /// - /// Tests the GetFolderPath method for CommonApplicationData when the environment variable - /// is set. - /// - [TestFixture] - [Property("Value", "/bla")] - public class GetCommonAppDataOverrideTests: GetCommonAppDataBaseTest - { - /// Tests the GetFolderPath method for CommonApplicationData when the environment - /// variable is set - [Test] - [Platform(Include="Linux", Reason="Test is Linux specific")] - public void Linux() - { - Assert.AreEqual("/bla", - DirectoryFinder.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)); - } - - /// Tests the GetFolderPath method for CommonApplicationData when the environment - /// variable is set - [Test] - [Platform(Exclude="Linux", Reason="Test is Windows specific")] - public void Windows() - { - Assert.AreEqual( - Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), - DirectoryFinder.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)); - } - } - } -} diff --git a/Src/Common/FwUtils/FwUtilsTests/DummyFwRegistryHelper.cs b/Src/Common/FwUtils/FwUtilsTests/DummyFwRegistryHelper.cs index 4b307d92ec..7c48635939 100644 --- a/Src/Common/FwUtils/FwUtilsTests/DummyFwRegistryHelper.cs +++ b/Src/Common/FwUtils/FwUtilsTests/DummyFwRegistryHelper.cs @@ -83,7 +83,7 @@ public RegistryKey FieldWorksRegistryKey { get { - return Registry.CurrentUser.CreateSubKey(@"Software\SIL\FieldWorks\UnitTests\DirectoryFinderTests"); + return Registry.CurrentUser.CreateSubKey(@"Software\SIL\FieldWorks\UnitTests\FwDirectoryFinderTests"); } } diff --git a/Src/Common/FwUtils/FwUtilsTests/FwDirectoryFinderTests.cs b/Src/Common/FwUtils/FwUtilsTests/FwDirectoryFinderTests.cs new file mode 100644 index 0000000000..37a897be61 --- /dev/null +++ b/Src/Common/FwUtils/FwUtilsTests/FwDirectoryFinderTests.cs @@ -0,0 +1,252 @@ +// -------------------------------------------------------------------------------------------- +//#region // Copyright (c) 2008, SIL International. All Rights Reserved. +// +// Copyright (c) 2008, SIL International. All Rights Reserved. +// +// Distributable under the terms of either the Common Public License or the +// GNU Lesser General Public License, as specified in the LICENSING.txt file. +// +//#endregion +// +// File: FwDirectoryFinderTests.cs +// Responsibility: Eberhard Beilharz +// Last reviewed: +// +//-------------------------------------------------------------------------------------------- + +using System; +using System.IO; +using NUnit.Framework; +using SIL.FieldWorks.FDO; +using SIL.FieldWorks.Test.TestUtils; +using SIL.Utils; + +namespace SIL.FieldWorks.Common.FwUtils +{ + + ///----------------------------------------------------------------------------------------- + /// + /// Tests for the FwDirectoryFinder class + /// + ///----------------------------------------------------------------------------------------- + [TestFixture] + public class FwDirectoryFinderTests : BaseTest + { + /// + /// Resets the registry helper + /// + [TestFixtureTearDown] + public void TearDown() + { + FwRegistryHelper.Manager.Reset(); + } + + /// + /// Fixture setup + /// + [TestFixtureSetUp] + public void TestFixtureSetup() + { + //FwDirectoryFinder.CompanyName = "SIL"; + FwRegistryHelper.Manager.SetRegistryHelper(new DummyFwRegistryHelper()); + FwRegistryHelper.FieldWorksRegistryKey.SetValue("RootDataDir", Path.GetFullPath(Path.Combine(UtilsAssemblyDir, "../../DistFiles"))); + FwRegistryHelper.FieldWorksRegistryKey.SetValue("RootCodeDir", Path.GetFullPath(Path.Combine(UtilsAssemblyDir, "../../DistFiles"))); + } + + ///------------------------------------------------------------------------------------- + /// + /// Gets the directory where the Utils assembly is + /// + ///------------------------------------------------------------------------------------- + private string UtilsAssemblyDir + { + get + { + return Path.GetDirectoryName(typeof(FwDirectoryFinder).Assembly.CodeBase + .Substring(MiscUtils.IsUnix ? 7 : 8)); + } + } + + ///------------------------------------------------------------------------------------- + /// + /// Tests the CodeDirectory property. This should return the DistFiles directory. + /// + ///------------------------------------------------------------------------------------- + [Test] + public void CodeDirectory() + { + var currentDir = Path.GetFullPath(Path.Combine(UtilsAssemblyDir, "../../DistFiles")); + Assert.That(FwDirectoryFinder.CodeDirectory, Is.SamePath(currentDir)); + } + + /// + /// Verify that the user project key falls back to the local machine. + /// + [Test] + public void GettingProjectDirWithEmptyUserKeyReturnsLocalMachineKey() + { + using (var fwHKCU = FwRegistryHelper.FieldWorksRegistryKey) + using (var fwHKLM = FwRegistryHelper.FieldWorksRegistryKeyLocalMachine) + { + if (fwHKCU.GetValue("ProjectsDir") != null) + { + fwHKCU.DeleteValue("ProjectsDir"); + } + fwHKLM.SetValue("ProjectsDir", "HKLM_TEST"); + Assert.That(FwDirectoryFinder.ProjectsDirectory, Is.EqualTo(FwDirectoryFinder.ProjectsDirectoryLocalMachine)); + Assert.That(FwDirectoryFinder.ProjectsDirectory, Is.EqualTo("HKLM_TEST")); + } + } + + /// + /// Verify that the user project key overrides the local machine. + /// + [Test] + public void GettingProjectDirWithUserDifferentFromLMReturnsUser() + { + FwDirectoryFinder.ProjectsDirectory = "NewHKCU_TEST_Value"; + Assert.That(FwDirectoryFinder.ProjectsDirectory, Is.Not.EqualTo(FwDirectoryFinder.ProjectsDirectoryLocalMachine)); + Assert.That(FwDirectoryFinder.ProjectsDirectory, Is.EqualTo("NewHKCU_TEST_Value")); + } + + /// + /// Verify that setting the user key to null deletes the user setting and falls back to local machine. + /// + [Test] + public void SettingProjectDirToNullDeletesUserKey() + { + FwDirectoryFinder.ProjectsDirectory = null; + Assert.That(FwDirectoryFinder.ProjectsDirectory, Is.EqualTo(FwDirectoryFinder.ProjectsDirectoryLocalMachine)); + + using (var fwHKCU = FwRegistryHelper.FieldWorksRegistryKey) + using (var fwHKLM = FwRegistryHelper.FieldWorksRegistryKeyLocalMachine) + { + Assert.Null(fwHKCU.GetValue("ProjectsDir")); + Assert.NotNull(fwHKLM.GetValue("ProjectsDir")); + } + } + + ///------------------------------------------------------------------------------------- + /// + /// Tests the DataDirectory property. This should return the DistFiles directory. + /// + ///------------------------------------------------------------------------------------- + [Test] + public void DataDirectory() + { + var currentDir = Path.GetFullPath(Path.Combine(UtilsAssemblyDir, "../../DistFiles")); + Assert.That(FwDirectoryFinder.DataDirectory, Is.SamePath(currentDir)); + } + + ///------------------------------------------------------------------------------------- + /// + /// Tests the SourceDirectory property. This should return the DistFiles directory. + /// + ///------------------------------------------------------------------------------------- + [Test] + public void SourceDirectory() + { + string expectedDir = Path.GetFullPath(Path.Combine(UtilsAssemblyDir, "../../Src")); + Assert.That(FwDirectoryFinder.SourceDirectory, Is.SamePath(expectedDir)); + } + + ///------------------------------------------------------------------------------------- + /// + /// Tests the GetCodeSubDirectory method when we pass a subdirectory without a + /// leading directory separator + /// + ///------------------------------------------------------------------------------------- + [Test] + public void GetCodeSubDirectory_NoLeadingSlash() + { + Assert.That(FwDirectoryFinder.GetCodeSubDirectory("Translation Editor/Configuration"), + Is.SamePath(Path.Combine(FwDirectoryFinder.CodeDirectory, "Translation Editor/Configuration"))); + } + + ///------------------------------------------------------------------------------------- + /// + /// Tests the GetCodeSubDirectory method when we pass a subdirectory with a + /// leading directory separator + /// + ///------------------------------------------------------------------------------------- + [Test] + public void GetCodeSubDirectory_LeadingSlash() + { + Assert.That(FwDirectoryFinder.GetCodeSubDirectory("/Translation Editor/Configuration"), + Is.SamePath(Path.Combine(FwDirectoryFinder.CodeDirectory, "Translation Editor/Configuration"))); + } + + ///------------------------------------------------------------------------------------- + /// + /// Tests the GetCodeSubDirectory method when we pass an invalid subdirectory + /// + ///------------------------------------------------------------------------------------- + [Test] + public void GetCodeSubDirectory_InvalidDir() + { + Assert.That(FwDirectoryFinder.GetCodeSubDirectory("NotExisting"), + Is.SamePath("NotExisting")); + } + + ///------------------------------------------------------------------------------------- + /// + /// Tests the GetDataSubDirectory method when we pass a subdirectory without a + /// leading directory separator + /// + ///------------------------------------------------------------------------------------- + [Test] + public void GetDataSubDirectory_NoLeadingSlash() + { + Assert.That(FwDirectoryFinder.GetDataSubDirectory("Translation Editor/Configuration"), + Is.SamePath(Path.Combine(FwDirectoryFinder.DataDirectory, "Translation Editor/Configuration"))); + } + + ///------------------------------------------------------------------------------------- + /// + /// Tests the GetDataSubDirectory method when we pass a subdirectory with a + /// leading directory separator + /// + ///------------------------------------------------------------------------------------- + [Test] + public void GetDataSubDirectory_LeadingSlash() + { + Assert.That(FwDirectoryFinder.GetDataSubDirectory("/Translation Editor/Configuration"), + Is.SamePath(Path.Combine(FwDirectoryFinder.DataDirectory, "Translation Editor/Configuration"))); + } + + ///------------------------------------------------------------------------------------- + /// + /// Tests the GetDataSubDirectory method when we pass an invalid subdirectory + /// + ///------------------------------------------------------------------------------------- + [Test] + public void GetDataSubDirectory_InvalidDir() + { + Assert.That(FwDirectoryFinder.GetDataSubDirectory("NotExisting"), + Is.SamePath("NotExisting")); + } + + /// + /// Tests the DefaultBackupDirectory property for use on Windows. + /// + [Test] + [Platform(Exclude="Linux", Reason="Test is Windows specific")] + public void DefaultBackupDirectory_Windows() + { + Assert.AreEqual(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), + Path.Combine("My FieldWorks", "Backups")), FwDirectoryFinder.DefaultBackupDirectory); + } + + /// + /// Tests the DefaultBackupDirectory property for use on Linux + /// + [Test] + [Platform(Include="Linux", Reason="Test is Linux specific")] + public void DefaultBackupDirectory_Linux() + { + // SpecialFolder.MyDocuments returns $HOME on Linux! + Assert.AreEqual(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), + "Documents/fieldworks/backups"), FwDirectoryFinder.DefaultBackupDirectory); + } + } +} diff --git a/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj b/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj index fd071f2d9a..75a205cbf9 100644 --- a/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj +++ b/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj @@ -158,7 +158,7 @@ AssemblyInfoForTests.cs - + diff --git a/Src/Common/FwUtils/IFwRegistryHelper.cs b/Src/Common/FwUtils/IFwRegistryHelper.cs index ba3fd0367c..6ffa07b4c7 100644 --- a/Src/Common/FwUtils/IFwRegistryHelper.cs +++ b/Src/Common/FwUtils/IFwRegistryHelper.cs @@ -6,7 +6,7 @@ // GNU Lesser General Public License, as specified in the LICENSING.txt file. // // -------------------------------------------------------------------------------------------- -using System; + using Microsoft.Win32; namespace SIL.FieldWorks.Common.FwUtils @@ -74,18 +74,5 @@ public interface IFwRegistryHelper /// /// ------------------------------------------------------------------------------------ bool Paratext7orLaterInstalled(); - - /// - /// If there is a registry value for this but the folder is not there we need to return false because - /// paratext is not installed correctly. Also if there is no registry entry for this then return false. - /// - bool ParatextSettingsDirectoryExists(); - - /// - /// Returns the path to the Paratext settings (projects) directory as specified in the registry - /// ENHANCE (Hasso) 2013.09: added this to expose the directory for Unix users, because trying to get it from ScrTextCollections - /// always returns null on Unix. This is really a Paratext problem, and this method may have no benefit. - /// - string ParatextSettingsDirectory(); } } diff --git a/Src/Common/FwUtils/ShowHelp.cs b/Src/Common/FwUtils/ShowHelp.cs index cff6a5f0e5..d4a562bc16 100644 --- a/Src/Common/FwUtils/ShowHelp.cs +++ b/Src/Common/FwUtils/ShowHelp.cs @@ -81,7 +81,7 @@ public static void ShowHelpTopic(IHelpTopicProvider helpTopicProvider, string he // try to get a path to the help file. try { - helpFile = DirectoryFinder.FWCodeDirectory + + helpFile = FwDirectoryFinder.CodeDirectory + helpTopicProvider.GetHelpString(helpFileKey); } catch diff --git a/Src/Common/RootSite/FwBaseVc.cs b/Src/Common/RootSite/FwBaseVc.cs index 6aab466b41..a5ff406897 100644 --- a/Src/Common/RootSite/FwBaseVc.cs +++ b/Src/Common/RootSite/FwBaseVc.cs @@ -197,7 +197,7 @@ public override void DisplayEmbeddedObject(IVwEnv vwenv, int hvo) } string linkedFilesRoot = sda.get_UnicodeProp(m_hvoLangProject, LangProjectTags.kflidLinkedFilesRootDir); if (String.IsNullOrEmpty(linkedFilesRoot)) - path = Path.Combine(DirectoryFinder.FWDataDirectory, fileName); + path = Path.Combine(FwDirectoryFinder.DataDirectory, fileName); else path = Path.Combine(linkedFilesRoot, fileName); } diff --git a/Src/FDO/Application/ApplicationServices/XmlTranslatedLists.cs b/Src/FDO/Application/ApplicationServices/XmlTranslatedLists.cs index b831608f00..485f15998a 100644 --- a/Src/FDO/Application/ApplicationServices/XmlTranslatedLists.cs +++ b/Src/FDO/Application/ApplicationServices/XmlTranslatedLists.cs @@ -20,7 +20,6 @@ using ICSharpCode.SharpZipLib.Zip; using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Infrastructure; using System.Globalization; using SIL.Utils; @@ -117,10 +116,11 @@ public bool ImportTranslatedLists(TextReader reader, FdoCache cache, IProgress p /// /// /// + /// /// - public static void ImportTranslatedListsForWs(string ws, FdoCache cache, IProgress progress) + public static void ImportTranslatedListsForWs(string ws, FdoCache cache, string templateDir, IProgress progress) { - string path = TranslatedListsPathForWs(ws); + string path = TranslatedListsPathForWs(ws, templateDir); if (File.Exists(path)) { var instance = new XmlTranslatedLists(); @@ -141,10 +141,11 @@ public static string ProgressDialogCaption /// Call before ImportTranslatedListsForWs. Call that only if the file exists. /// /// + /// /// - public static string TranslatedListsPathForWs(string ws) + public static string TranslatedListsPathForWs(string ws, string templateDir) { - return Path.Combine(DirectoryFinder.TemplateDirectory, Path.ChangeExtension(LocalizedListPrefix + ws, "zip")); + return Path.Combine(templateDir, Path.ChangeExtension(LocalizedListPrefix + ws, "zip")); } private int GetWsFromStr(string sWs) diff --git a/Src/FDO/Application/Impl/DomainDataByFlid.cs b/Src/FDO/Application/Impl/DomainDataByFlid.cs index 6e48b2eb46..ddaa821384 100644 --- a/Src/FDO/Application/Impl/DomainDataByFlid.cs +++ b/Src/FDO/Application/Impl/DomainDataByFlid.cs @@ -15,7 +15,6 @@ using System.Diagnostics; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Common.ScriptureUtils; using SIL.FieldWorks.FDO.DomainImpl; using SIL.FieldWorks.FDO.DomainServices; diff --git a/Src/FDO/DomainImpl/CmObject.cs b/Src/FDO/DomainImpl/CmObject.cs index 492bd1a211..5907d5da2e 100644 --- a/Src/FDO/DomainImpl/CmObject.cs +++ b/Src/FDO/DomainImpl/CmObject.cs @@ -27,7 +27,6 @@ using System.IO; // MemoryStream. using System.Xml.Linq; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Application; using SIL.FieldWorks.FDO.Infrastructure; using SIL.Utils; diff --git a/Src/FDO/DomainImpl/FdoFactoryAdditions.cs b/Src/FDO/DomainImpl/FdoFactoryAdditions.cs index cdfd601c3c..7a198204a2 100644 --- a/Src/FDO/DomainImpl/FdoFactoryAdditions.cs +++ b/Src/FDO/DomainImpl/FdoFactoryAdditions.cs @@ -2627,9 +2627,9 @@ public IText Create(FdoCache cache, Guid guid) internal partial class ScrImportSetFactory { - public IScrImportSet Create(string defaultParaCharsStyleName) + public IScrImportSet Create(string defaultParaCharsStyleName, string stylesPath) { - var settings = new ScrImportSet(defaultParaCharsStyleName); + var settings = new ScrImportSet(defaultParaCharsStyleName, stylesPath); ((ICmObjectInternal) settings).InitializeNewOwnerlessCmObject(m_cache); return settings; } diff --git a/Src/FDO/DomainImpl/FdoScripture.cs b/Src/FDO/DomainImpl/FdoScripture.cs index 1abf5740fa..9ac5841d32 100644 --- a/Src/FDO/DomainImpl/FdoScripture.cs +++ b/Src/FDO/DomainImpl/FdoScripture.cs @@ -408,8 +408,9 @@ private IScrImportSet DefaultImportSettings_internal /// /// type of import type to find /// The default paragraph characters style name. + /// /// ------------------------------------------------------------------------------------ - public IScrImportSet FindOrCreateDefaultImportSettings(TypeOfImport importType, string defaultParaCharsStyleName) + public IScrImportSet FindOrCreateDefaultImportSettings(TypeOfImport importType, string defaultParaCharsStyleName, string stylesPath) { IScrImportSet settings = DefaultImportSettings_internal; @@ -435,7 +436,7 @@ public IScrImportSet FindOrCreateDefaultImportSettings(TypeOfImport importType, // Didn't find the specified type of settings, so create a new set. IScrImportSet newSettings = - m_cache.ServiceLocator.GetInstance().Create(defaultParaCharsStyleName); + m_cache.ServiceLocator.GetInstance().Create(defaultParaCharsStyleName, stylesPath); ImportSettingsOC.Add(newSettings); newSettings.ImportType = (int)importType; return newSettings; diff --git a/Src/FDO/DomainImpl/OverridesCellar.cs b/Src/FDO/DomainImpl/OverridesCellar.cs index b702e61eed..d1f18fb2c8 100644 --- a/Src/FDO/DomainImpl/OverridesCellar.cs +++ b/Src/FDO/DomainImpl/OverridesCellar.cs @@ -1978,7 +1978,7 @@ public string InternalPath if (value == null) throw new ArgumentNullException("value"); - string srcFilename = FdoFileHelperRelativePaths.GetRelativeLinkedFilesPath(value, m_cache.LangProject.LinkedFilesRootDir); + string srcFilename = LinkedFilesRelativePathHelper.GetRelativeLinkedFilesPath(value, m_cache.LangProject.LinkedFilesRootDir); InternalPath_Generated = srcFilename; } @@ -2009,7 +2009,7 @@ public string AbsoluteInternalPath string internalPath = InternalPath; if (String.IsNullOrEmpty(internalPath)) internalPath = DomainObjectServices.EmptyFileName; - return FdoFileHelperRelativePaths.GetFullPathFromRelativeLFPath(internalPath, m_cache.LangProject.LinkedFilesRootDir); + return LinkedFilesRelativePathHelper.GetFullPathFromRelativeLFPath(internalPath, m_cache.LangProject.LinkedFilesRootDir); } } diff --git a/Src/FDO/DomainImpl/OverridesLangProj.cs b/Src/FDO/DomainImpl/OverridesLangProj.cs index 2d6287f5ca..a5094ff263 100644 --- a/Src/FDO/DomainImpl/OverridesLangProj.cs +++ b/Src/FDO/DomainImpl/OverridesLangProj.cs @@ -23,7 +23,6 @@ using SIL.FieldWorks.Common.COMInterfaces; using SIL.Utils; // Needed for Set class. -using SIL.FieldWorks.Common.FwUtils; // for LanguageDefinitionFactory using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.Infrastructure; using SIL.CoreImpl; @@ -84,7 +83,7 @@ public IEnumerable AllWordforms /// ------------------------------------------------------------------------------------ /// - /// Return LinkedFilesRootDir if explicitly set, otherwise FWDataDirectory. + /// Return LinkedFilesRootDir if explicitly set, otherwise DataDirectory. /// /// ------------------------------------------------------------------------------------ [ModelProperty(CellarPropertyType.Unicode, 6001042, "string")] @@ -94,13 +93,13 @@ public string LinkedFilesRootDir { return String.IsNullOrEmpty(LinkedFilesRootDir_Generated) ? Path.Combine(m_cache.ProjectId.SharedProjectFolder, FdoFileHelper.ksLinkedFilesDir) - : FdoFileHelperRelativePaths.GetLinkedFilesFullPathFromRelativePath(LinkedFilesRootDir_Generated, - m_cache.ProjectId.SharedProjectFolder); + : LinkedFilesRelativePathHelper.GetLinkedFilesFullPathFromRelativePath(Services.GetInstance().ProjectsDirectory, + LinkedFilesRootDir_Generated, m_cache.ProjectId.SharedProjectFolder); } set { - string relativePath = FdoFileHelperRelativePaths.GetLinkedFilesRelativePathFromFullPath(value, - m_cache.ProjectId.SharedProjectFolder, ShortName); + string relativePath = LinkedFilesRelativePathHelper.GetLinkedFilesRelativePathFromFullPath(Services.GetInstance().ProjectsDirectory, + value, m_cache.ProjectId.SharedProjectFolder, ShortName); LinkedFilesRootDir_Generated = relativePath; } diff --git a/Src/FDO/DomainImpl/ScrImportSet.cs b/Src/FDO/DomainImpl/ScrImportSet.cs index bb64f11e4f..ff3c966591 100644 --- a/Src/FDO/DomainImpl/ScrImportSet.cs +++ b/Src/FDO/DomainImpl/ScrImportSet.cs @@ -52,6 +52,7 @@ internal partial class ScrImportSet private Hashtable m_notesFileInfoLists = new Hashtable(); private readonly string m_defaultParaCharsStyleName; + private readonly string m_stylesPath; private IOverlappingFileResolver m_resolver; @@ -76,9 +77,10 @@ internal partial class ScrImportSet #region Construction & initialization - internal ScrImportSet(string defaultParaStylesName) + internal ScrImportSet(string defaultParaStylesName, string stylesPath) { m_defaultParaCharsStyleName = defaultParaStylesName; + m_stylesPath = stylesPath; } /// ------------------------------------------------------------------------------------ @@ -96,8 +98,8 @@ protected override void SetDefaultValuesAfterInit() private void DoCommonNonModelSetup() { - m_scrMappingsList = new ScrMappingList(MappingSet.Main, m_stylesheet, m_defaultParaCharsStyleName); - m_notesMappingsList = new ScrMappingList(MappingSet.Notes, m_stylesheet, m_defaultParaCharsStyleName); + m_scrMappingsList = new ScrMappingList(MappingSet.Main, m_stylesheet, m_defaultParaCharsStyleName, m_stylesPath); + m_notesMappingsList = new ScrMappingList(MappingSet.Notes, m_stylesheet, m_defaultParaCharsStyleName, m_stylesPath); LoadInMemoryMappingLists(); LoadSources(false); diff --git a/Src/FDO/DomainServices/BackupRestore/BackupFileRepository.cs b/Src/FDO/DomainServices/BackupRestore/BackupFileRepository.cs index 9618c564ec..65ef9af87b 100644 --- a/Src/FDO/DomainServices/BackupRestore/BackupFileRepository.cs +++ b/Src/FDO/DomainServices/BackupRestore/BackupFileRepository.cs @@ -14,7 +14,6 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; -using SIL.FieldWorks.Common.FwUtils; using System.Collections.Generic; using SIL.Utils; using System.Globalization; @@ -41,12 +40,12 @@ public class BackupFileRepository /// we'll need to pass in the directory name or have a way to change it. /// /// ------------------------------------------------------------------------------------ - public BackupFileRepository() + public BackupFileRepository(string defaultBackupDir) { string[] backups; try { - backups = FileUtils.GetFilesInDirectory(DirectoryFinder.DefaultBackupDirectory); + backups = FileUtils.GetFilesInDirectory(defaultBackupDir); } catch (Exception) { diff --git a/Src/FDO/DomainServices/BackupRestore/BackupFileSettings.cs b/Src/FDO/DomainServices/BackupRestore/BackupFileSettings.cs index 2cc0fa0bdc..d334731220 100644 --- a/Src/FDO/DomainServices/BackupRestore/BackupFileSettings.cs +++ b/Src/FDO/DomainServices/BackupRestore/BackupFileSettings.cs @@ -16,7 +16,6 @@ using System.Runtime.Serialization; using ICSharpCode.SharpZipLib; using ICSharpCode.SharpZipLib.Zip; -using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; using SIL.FieldWorks.FDO.Infrastructure.Impl; @@ -128,7 +127,7 @@ private BackupFileSettings(BackupProjectSettings settings) m_spellCheckAdditions = settings.IncludeSpellCheckAdditions; m_dbVersion = settings.DbVersion; m_fwVersion = settings.FwVersion; - m_linkedFilesPathRelative = FdoFileHelperRelativePaths.GetLinkedFilesRelativePathFromFullPath(settings.LinkedFilesPath, settings.ProjectPath, settings.ProjectName); + m_linkedFilesPathRelative = LinkedFilesRelativePathHelper.GetLinkedFilesRelativePathFromFullPath(settings.ProjectsRootFolder, settings.LinkedFilesPath, settings.ProjectPath, settings.ProjectName); m_linkedFilesPathActual = settings.LinkedFilesPath; m_appAbbrev = settings.AppAbbrev; } @@ -326,7 +325,7 @@ public string LinkedFilesPathRelativePersisted [DataMember] public string AppAbbrev { - get { PopulateSettingsFromZipFileIfNeeded(); return m_appAbbrev ?? FwUtils.ksFlexAbbrev; } + get { PopulateSettingsFromZipFileIfNeeded(); return m_appAbbrev; } private set { m_appAbbrev = value; } } @@ -422,11 +421,11 @@ private void PopulateSettingsFromZipFileIfNeeded() if (String.IsNullOrEmpty(fileName)) continue; - if (fileName.Equals(DirectoryFinder.kBackupSettingsFilename)) + if (fileName.Equals(FdoFileHelper.kBackupSettingsFilename)) { if (foundBackupSettingsFile) throw new InvalidOperationException("Zip file " + m_sZipFileName + " contained multiple " + - DirectoryFinder.kBackupSettingsFilename + " files."); + FdoFileHelper.kBackupSettingsFilename + " files."); foundBackupSettingsFile = true; InitializeFromStream(zipIn); } @@ -443,9 +442,9 @@ private void PopulateSettingsFromZipFileIfNeeded() if (!foundBackupSettingsFile) throw new InvalidOperationException("Zip file " + m_sZipFileName + " did not contain the " + - DirectoryFinder.kBackupSettingsFilename + " file."); + FdoFileHelper.kBackupSettingsFilename + " file."); if (m_projectName == null) - throw new InvalidOperationException(DirectoryFinder.kBackupSettingsFilename + " in " + + throw new InvalidOperationException(FdoFileHelper.kBackupSettingsFilename + " in " + m_sZipFileName + " did not contain a project name."); string expectedProjectFile = FdoFileHelper.GetXmlDataFileName(m_projectName); if (dataFileName == null || dataFileName != expectedProjectFile) @@ -544,9 +543,9 @@ private void InitializeFromStream(Stream persistenceStream) m_backupTime = settings.BackupTime; m_comment = settings.Comment; m_projectName = settings.ProjectName; - m_linkedFilesPathRelative = FdoFileHelperRelativePaths.FixPathSlashesIfNeeded(settings.LinkedFilesPathRelativePersisted); - m_linkedFilesPathActual = FdoFileHelperRelativePaths.FixPathSlashesIfNeeded(settings.LinkedFilesPathActualPersisted); - m_projectPathPersisted = FdoFileHelperRelativePaths.FixPathSlashesIfNeeded(settings.ProjectPathPersisted); + m_linkedFilesPathRelative = LinkedFilesRelativePathHelper.FixPathSlashesIfNeeded(settings.LinkedFilesPathRelativePersisted); + m_linkedFilesPathActual = LinkedFilesRelativePathHelper.FixPathSlashesIfNeeded(settings.LinkedFilesPathActualPersisted); + m_projectPathPersisted = LinkedFilesRelativePathHelper.FixPathSlashesIfNeeded(settings.ProjectPathPersisted); m_configurationSettings = settings.IncludeConfigurationSettings; m_linkedFiles = settings.IncludeLinkedFiles; m_supportingFiles = settings.IncludeSupportingFiles; diff --git a/Src/FDO/DomainServices/BackupRestore/BackupProjectSettings.cs b/Src/FDO/DomainServices/BackupRestore/BackupProjectSettings.cs index 10e8deaae4..91f8ae9f4a 100644 --- a/Src/FDO/DomainServices/BackupRestore/BackupProjectSettings.cs +++ b/Src/FDO/DomainServices/BackupRestore/BackupProjectSettings.cs @@ -13,7 +13,7 @@ // --------------------------------------------------------------------------------------------- using System; using System.IO; -using SIL.FieldWorks.Common.FwUtils; +using SIL.CoreImpl; using SIL.FieldWorks.FDO.Infrastructure.Impl; using System.Reflection; using SIL.Utils; @@ -27,17 +27,19 @@ namespace SIL.FieldWorks.FDO.DomainServices.BackupRestore public class BackupProjectSettings : BackupSettings { #region Constructors + /// ------------------------------------------------------------------------------------ /// /// Constructor /// /// The cache. /// The backup info. + /// The destination folder. /// ------------------------------------------------------------------------------------ - public BackupProjectSettings(FdoCache cache, IBackupInfo backupInfo) : + public BackupProjectSettings(FdoCache cache, IBackupInfo backupInfo, string destFolder) : this(Path.GetDirectoryName(cache.ProjectId.ProjectFolder), cache.ProjectId.Name, cache.LanguageProject.LinkedFilesRootDir, cache.ProjectId.SharedProjectFolder, - cache.ProjectId.Type) + cache.ProjectId.Type, destFolder) { if (backupInfo != null) { @@ -61,19 +63,20 @@ public BackupProjectSettings(FdoCache cache, IBackupInfo backupInfo) : /// A possibly alternate project path that /// should be used for things that should be shared. /// Type of the project before converting for backup. + /// The destination folder. /// ------------------------------------------------------------------------------------ protected BackupProjectSettings(string projectsRootFolder, string projectName, - string linkedFilesPath, string sharedProjectFolder, FDOBackendProviderType originalProjType) : + string linkedFilesPath, string sharedProjectFolder, FDOBackendProviderType originalProjType, string destFolder) : base(projectsRootFolder, linkedFilesPath, sharedProjectFolder) { ProjectName = projectName; DbVersion = FDOBackendProvider.ModelVersion; - FwVersion = new FwVersionInfoProvider(Assembly.GetExecutingAssembly(), false).FieldWorksVersion; + FwVersion = new VersionInfoProvider(Assembly.GetExecutingAssembly(), false).MajorVersion; // For DB4o projects, we need to convert them over to XML. We can't put the // converted project in the same directory so we convert them to a temporary // directory (see FWR-2813). DatabaseFolder = (originalProjType == FDOBackendProviderType.kXML) ? ProjectPath : Path.GetTempPath(); - DestinationFolder = DirectoryFinder.DefaultBackupDirectory; + DestinationFolder = destFolder; BackupTime = DateTime.Now; } #endregion @@ -166,7 +169,7 @@ public string BackupSettingsFile get { return Path.Combine(FdoFileHelper.GetBackupSettingsDir(ProjectPath), - DirectoryFinder.kBackupSettingsFilename); + FdoFileHelper.kBackupSettingsFilename); } } #endregion diff --git a/Src/FDO/DomainServices/BackupRestore/BackupSettings.cs b/Src/FDO/DomainServices/BackupRestore/BackupSettings.cs index 8c78bdec4f..949734183b 100644 --- a/Src/FDO/DomainServices/BackupRestore/BackupSettings.cs +++ b/Src/FDO/DomainServices/BackupRestore/BackupSettings.cs @@ -157,6 +157,15 @@ public bool IncludeSpellCheckAdditions #endregion #region Paths + + /// + /// Gets the projects root folder. + /// + public string ProjectsRootFolder + { + get { return m_projectsRootFolder; } + } + /// /// This is the path of the project being (or about to be) backed up or restored. /// diff --git a/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs b/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs index 352f7f7c3c..296714a13f 100644 --- a/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs +++ b/Src/FDO/DomainServices/BackupRestore/ProjectBackupService.cs @@ -17,7 +17,6 @@ using System.Linq; using ICSharpCode.SharpZipLib.Zip; using SIL.CoreImpl; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Infrastructure; using SIL.Utils; @@ -99,7 +98,7 @@ public bool BackupProject(IThreadedProgress progressDlg, out string backupFile) private void PersistBackupFileSettings() { string backupSettingsFile = Path.Combine(FdoFileHelper.GetBackupSettingsDir( - m_settings.ProjectPath), DirectoryFinder.kBackupSettingsFilename); + m_settings.ProjectPath), FdoFileHelper.kBackupSettingsFilename); string settingsDir = Path.GetDirectoryName(backupSettingsFile); if (!Directory.Exists(settingsDir)) diff --git a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs index 3b0897401a..80b1e8a0ba 100644 --- a/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs +++ b/Src/FDO/DomainServices/BackupRestore/ProjectRestoreService.cs @@ -19,7 +19,6 @@ using System.Text; using ICSharpCode.SharpZipLib.Zip; using SIL.CoreImpl; -using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; @@ -36,6 +35,8 @@ public class ProjectRestoreService private bool m_fRestoreOverProject; private string m_sLinkDirChangedTo; private readonly IFdoUI m_ui; + private readonly string m_converterConsolePath; + private readonly string m_dbPath; #endregion #region Constructor @@ -44,27 +45,22 @@ public class ProjectRestoreService /// Constructor /// /// The restore settings. - /// + /// The UI service. + /// + /// /// ------------------------------------------------------------------------------------ - public ProjectRestoreService(RestoreProjectSettings settings, IFdoUI ui) + public ProjectRestoreService(RestoreProjectSettings settings, IFdoUI ui, string converterConsolePath, string dbPath) { m_restoreSettings = settings; m_ui = ui; + m_converterConsolePath = converterConsolePath; + m_dbPath = dbPath; } - /// ------------------------------------------------------------------------------------ - /// - /// Constructor used in Tests where we do not need to have a helpTopicProvider. - /// - /// The restore settings. - /// ------------------------------------------------------------------------------------ - public ProjectRestoreService(RestoreProjectSettings settings) - { - m_restoreSettings = settings; - } #endregion #region Public methods + /// ------------------------------------------------------------------------------------ /// /// Perform a restore of the project specified in the settings. @@ -117,20 +113,20 @@ public void RestoreProject(IThreadedProgress progressDlg) } // switch to the desired backend (if it's in the projects directory...anything else stays XML for now). - if (DirectoryFinder.IsSubFolderOfProjectsDirectory(m_restoreSettings.ProjectPath) && !suppressConversion) - ClientServerServices.Current.Local.ConvertToDb4oBackendIfNeeded(progressDlg, m_restoreSettings.FullProjectPath, m_ui); + if (Path.GetDirectoryName(m_restoreSettings.ProjectPath) == m_restoreSettings.ProjectsRootFolder && !suppressConversion) + ClientServerServices.Current.Local.ConvertToDb4oBackendIfNeeded(progressDlg, m_restoreSettings.FullProjectPath); CleanupAfterRestore(true); } private void ImportFrom6_0Backup(BackupFileSettings fileSettings, IThreadedProgress progressDlg) { - var importer = new ImportFrom6_0(progressDlg); + var importer = new ImportFrom6_0(progressDlg, m_converterConsolePath, m_dbPath); bool importSuccessful; try { string projFile; - importSuccessful = importer.Import(fileSettings.File, m_restoreSettings.ProjectName, out projFile); + importSuccessful = importer.Import(fileSettings.File, m_restoreSettings.ProjectName, m_restoreSettings.ProjectsRootFolder, out projFile); } catch (CannotConvertException e) { @@ -215,7 +211,7 @@ private void CleanupFrom6_0FailedRestore(ImportFrom6_0 importer) var fileName = Path.GetFileName(entry.Name); if (!String.IsNullOrEmpty(fileName)) { - string filePath = Path.Combine(DirectoryFinder.ProjectsDirectory, fileName); + string filePath = Path.Combine(m_restoreSettings.ProjectsRootFolder, fileName); if (FileUtils.TrySimilarFileExists(filePath, out filePath)) FileUtils.Delete(filePath); } @@ -307,16 +303,16 @@ private void RestoreLinkedFiles(BackupFileSettings fileSettings) "The option to include linked files should not be allowed if they aren't available in the backup settings"); var proposedDestinationLinkedFilesPath = - FdoFileHelperRelativePaths.GetLinkedFilesFullPathFromRelativePath( + LinkedFilesRelativePathHelper.GetLinkedFilesFullPathFromRelativePath(m_restoreSettings.ProjectsRootFolder, fileSettings.LinkedFilesPathRelativePersisted, m_restoreSettings.ProjectPath); var linkedFilesPathInZip = fileSettings.LinkedFilesPathActualPersisted; - if (fileSettings.LinkedFilesPathRelativePersisted.StartsWith(FdoFileHelperRelativePaths.ksProjectRelPath)) + if (fileSettings.LinkedFilesPathRelativePersisted.StartsWith(LinkedFilesRelativePathHelper.ksProjectRelPath)) { // We store any files inside the project folder as a relative path from the project's directory. // Make sure we don't attempt to search for the whole directory structure in the zip file. (FWR-2909) linkedFilesPathInZip = fileSettings.LinkedFilesPathRelativePersisted.Substring( - FdoFileHelperRelativePaths.ksProjectRelPath.Length + 1); + LinkedFilesRelativePathHelper.ksProjectRelPath.Length + 1); } var filesContainedInLinkdFilesFolder = GetAllFilesUnderFolderInZipFileAndDateTimes(linkedFilesPathInZip); diff --git a/Src/FDO/DomainServices/BackupRestore/RestoreProjectSettings.cs b/Src/FDO/DomainServices/BackupRestore/RestoreProjectSettings.cs index c82f4067fa..e876dd400b 100644 --- a/Src/FDO/DomainServices/BackupRestore/RestoreProjectSettings.cs +++ b/Src/FDO/DomainServices/BackupRestore/RestoreProjectSettings.cs @@ -14,7 +14,6 @@ using System; using System.IO; using System.Linq; -using SIL.FieldWorks.Common.FwUtils; using System.Text; using SIL.Utils; @@ -38,7 +37,7 @@ public class RestoreProjectSettings : BackupSettings /// Initializes a new instance of the class. /// /// ------------------------------------------------------------------------------------ - public RestoreProjectSettings() : base (DirectoryFinder.ProjectsDirectory, null, null) + public RestoreProjectSettings(string projectsRootFolder) : base (projectsRootFolder, null, null) { } @@ -48,12 +47,13 @@ public RestoreProjectSettings() : base (DirectoryFinder.ProjectsDirectory, null, /// a list of command-line options as created from the /// property. /// - /// The command line options. - /// Name of the backup zip file. + /// /// Name of the project. + /// Name of the backup zip file. + /// The command line options. /// ------------------------------------------------------------------------------------ - public RestoreProjectSettings(string projectName, string backupZipFileName, - string commandLineOptions) : this() + public RestoreProjectSettings(string projectsRootFolder, string projectName, string backupZipFileName, + string commandLineOptions) : this(projectsRootFolder) { if (string.IsNullOrEmpty(projectName)) throw new ArgumentNullException("projectName"); diff --git a/Src/FDO/DomainServices/ClientServerServices.cs b/Src/FDO/DomainServices/ClientServerServices.cs index e6893be354..578ab4db86 100644 --- a/Src/FDO/DomainServices/ClientServerServices.cs +++ b/Src/FDO/DomainServices/ClientServerServices.cs @@ -22,8 +22,6 @@ using System.Net.Sockets; using System.Text; using FwRemoteDatabaseConnector; -using SIL.CoreImpl; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.FDO.Infrastructure.Impl; using SIL.Utils; @@ -47,27 +45,18 @@ public static class ClientServerServices /// ------------------------------------------------------------------------------------ public static IClientServerServices Current { get; internal set; } - /// ------------------------------------------------------------------------------------ - /// - /// Initializes the class. - /// - /// ------------------------------------------------------------------------------------ - static ClientServerServices() - { - SetCurrentToDefaultBackend(); - } - /// ------------------------------------------------------------------------------------ /// /// This is the implementation for the static constructor. It is in a separate method /// to allow tests to reset it (using reflection). /// /// ------------------------------------------------------------------------------------ - private static void SetCurrentToDefaultBackend() + public static void SetCurrentToDb4OBackend(IFdoUI ui, IFdoDirectories dirs, + Func usingDefaultProjectsDirAccessor) { // This is the "one line" that should need to be changed to configure a different backend :-). // Typically a new implementation of IClientServerServices will be needed, as well as the backend itself. - Current = new Db4OClientServerServices(); + Current = new Db4OClientServerServices(ui, dirs, usingDefaultProjectsDirAccessor); } /// ------------------------------------------------------------------------------------ @@ -206,9 +195,8 @@ public interface ILocalClientServerServices /// /// if set to true, turn sharing on. /// The progress dialog. - /// /// Indication of whether the request was performed successfully. - bool SetProjectSharing(bool fShare, IThreadedProgress progress, IFdoUI ui); + bool SetProjectSharing(bool fShare, IThreadedProgress progress); /// /// Return true if the specified project (in the specified parent directory) will be @@ -226,11 +214,10 @@ public interface ILocalClientServerServices /// The progress dialog for getting a message box owner and/or /// ensuring we're invoking on the uI thread. /// The full path of the existing XML file for the project - /// /// The project identifier, typically the path to the converted file (or the /// original, if not configured for the client-server backend) /// ------------------------------------------------------------------------------------ - string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string filename, IFdoUI ui); + string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string filename); /// /// Copies the specified project (assumed to be in the current Projects directory) @@ -290,15 +277,17 @@ internal class Db4OClientServerServices : IClientServerServices private const char ksServerHostSeperatorChar = ':'; private Db4OServerFinder m_serverFinder; private FwProjectFinder m_projectFinder; + private readonly IFdoDirectories m_dirs; /// ------------------------------------------------------------------------------------ /// /// Initializes a new instance of the class. /// /// ------------------------------------------------------------------------------------ - internal Db4OClientServerServices() + internal Db4OClientServerServices(IFdoUI ui, IFdoDirectories dirs, Func usingDefaultProjectsDirAccessor) { - Local = new Db4OLocalClientServerServices(); + m_dirs = dirs; + Local = new Db4OLocalClientServerServices(ui, dirs, usingDefaultProjectsDirAccessor); } /// ------------------------------------------------------------------------------------ @@ -350,7 +339,7 @@ public void BeginFindProjects(string host, Action foundProject, if (m_projectFinder != null) throw new InvalidOperationException("Can not start a new find projects before the previous one finishes."); m_projectFinder = new FwProjectFinder(host, foundProject, () => m_projectFinder = null, - exceptionCallback, showLocalProjects); + exceptionCallback, showLocalProjects, m_dirs.ProjectsDirectory); } /// ------------------------------------------------------------------------------------ @@ -537,6 +526,17 @@ internal class Db4OLocalClientServerServices : ILocalClientServerServices { internal const string kLocalService = "localhost"; internal const string ksDoNotShareProjectTxt = "do_not_share_project.txt"; + private readonly Func m_projectsDirAccessor; + private readonly Func m_usingDefaultProjectsDirAccessor; + private readonly IFdoUI m_ui; + private readonly IFdoDirectories m_dirs; + + public Db4OLocalClientServerServices(IFdoUI ui, IFdoDirectories dirs, Func usingDefaultProjectsDirAccessor) + { + m_ui = ui; + m_dirs = dirs; + m_usingDefaultProjectsDirAccessor = usingDefaultProjectsDirAccessor; + } /// ------------------------------------------------------------------------------------ /// @@ -558,7 +558,7 @@ public bool ShareMyProjects // their personal projects directory. I'm not sure whether such a user will even see that the // first user has turned on sharing. But in any case, the second user (who did not turn sharing on, // and has their own projects folder) will just go on seeing their own unshared projects. - && DirectoryFinder.ProjectsDirectory == DirectoryFinder.ProjectsDirectoryLocalMachine; + && m_usingDefaultProjectsDirAccessor(); } catch (SocketException) { @@ -574,9 +574,8 @@ public bool ShareMyProjects /// /// if set to true, turn sharing on. /// The progress dialog. - /// /// ------------------------------------------------------------------------------------ - public bool SetProjectSharing(bool fShare, IThreadedProgress progress, IFdoUI ui) + public bool SetProjectSharing(bool fShare, IThreadedProgress progress) { Db4oServerInfo serverInfo = null; do @@ -590,7 +589,7 @@ public bool SetProjectSharing(bool fShare, IThreadedProgress progress, IFdoUI ui } } while (serverInfo == null && - ui.Retry(string.Format(Strings.ksLocalConnectorServiceNotStarted, "FwRemoteDatabaseConnectorService"), + m_ui.Retry(string.Format(Strings.ksLocalConnectorServiceNotStarted, "FwRemoteDatabaseConnectorService"), fShare ? Strings.ksConvertingToShared : Strings.ksConvertingToNonShared)); if (serverInfo == null || serverInfo.AreProjectShared() == fShare) @@ -602,7 +601,7 @@ public bool SetProjectSharing(bool fShare, IThreadedProgress progress, IFdoUI ui if (fShare) { // Turning sharing on. - if (!ConvertAllProjectsToDb4o(progress, ui)) + if (!ConvertAllProjectsToDb4o(progress)) { LocalDb4OServerInfoConnection.ShareProjects(false); // could not switch return false; @@ -610,7 +609,7 @@ public bool SetProjectSharing(bool fShare, IThreadedProgress progress, IFdoUI ui } else { - if (!ConvertAllProjectsToXml(progress, ui)) + if (!ConvertAllProjectsToXml(progress)) { // If ConvertAllProjectsToXml failed then leave sharing on. LocalDb4OServerInfoConnection.ShareProjects(true); @@ -645,7 +644,7 @@ public bool WillProjectBeConverted(string projectPath, string parentDirectory, s /// /// false if clients are still connected. /// ------------------------------------------------------------------------------------ - private static bool EnsureNoClientsAreConnected(IFdoUI ui) + private bool EnsureNoClientsAreConnected() { var localService = LocalDb4OServerInfoConnection; if (localService == null) @@ -660,7 +659,7 @@ private static bool EnsureNoClientsAreConnected(IFdoUI ui) connectedClientsMsg.AppendFormat("{2}{0} : {1}", client, Dns.GetHostEntry(client).HostName, Environment.NewLine); } - if (!ui.Retry(String.Format(Strings.ksAllProjectsMustDisconnectClients, connectedClientsMsg), + if (!m_ui.Retry(String.Format(Strings.ksAllProjectsMustDisconnectClients, connectedClientsMsg), Strings.ksAllProjectsMustDisconnectCaption)) return false; @@ -679,10 +678,9 @@ private static bool EnsureNoClientsAreConnected(IFdoUI ui) /// TODO: as an enhancement connected clients could be messaged and asked to disconnect. /// /// project name. - /// /// false if clients are still connected. /// ------------------------------------------------------------------------------------ - private static bool EnsureNoClientsAreConnected(string projectName, IFdoUI ui) + private bool EnsureNoClientsAreConnected(string projectName) { Db4oServerInfo localService = LocalDb4OServerInfoConnection; if (localService == null) @@ -694,7 +692,7 @@ private static bool EnsureNoClientsAreConnected(string projectName, IFdoUI ui) foreach (string client in connectedClients) connectedClientsMsg.AppendFormat("{2}{0} : {1}", client, Dns.GetHostEntry(client).HostName, Environment.NewLine); - if (!WarnOfOtherConnectedClients(projectName, connectedClientsMsg.ToString(), ui)) + if (!WarnOfOtherConnectedClients(projectName, connectedClientsMsg.ToString())) return false; connectedClients = localService.ListConnectedClients(projectName); @@ -710,14 +708,13 @@ private static bool EnsureNoClientsAreConnected(string projectName, IFdoUI ui) /// Name of the project. /// The message to show about the connected clients. /// - /// /// ------------------------------------------------------------------------------------ - private static bool WarnOfOtherConnectedClients(string projectName, string connectedClientsMsg, IFdoUI ui) + private bool WarnOfOtherConnectedClients(string projectName, string connectedClientsMsg) { var msg = String.Format(Strings.ksMustDisconnectClients, projectName, connectedClientsMsg); var caption = String.Format(Strings.ksMustDisconnectCaption, projectName); - return ui.Retry(msg, caption); + return m_ui.Retry(msg, caption); } /// ------------------------------------------------------------------------------------ @@ -727,22 +724,21 @@ private static bool WarnOfOtherConnectedClients(string projectName, string conne /// true if successful; false if other clients are connected, /// which prevents conversion of shared projects. /// ------------------------------------------------------------------------------------ - private bool ConvertAllProjectsToXml(IThreadedProgress progressDlg, IFdoUI ui) + private bool ConvertAllProjectsToXml(IThreadedProgress progressDlg) { - if (!EnsureNoClientsAreConnected(ui)) + if (!EnsureNoClientsAreConnected()) return false; progressDlg.Title = Strings.ksConvertingToNonShared; progressDlg.AllowCancel = false; - progressDlg.Maximum = Directory.GetDirectories(DirectoryFinder.ProjectsDirectory).Count(); - progressDlg.RunTask(true, ConvertAllProjectsToXmlTask, ui); + progressDlg.Maximum = Directory.GetDirectories(m_projectsDirAccessor()).Count(); + progressDlg.RunTask(true, ConvertAllProjectsToXmlTask); return true; } private object ConvertAllProjectsToXmlTask(IThreadedProgress progress, object[] args) { - var userAction = (IFdoUI) args[0]; - foreach (var projectFolder in Directory.GetDirectories(DirectoryFinder.ProjectsDirectory)) + foreach (string projectFolder in Directory.GetDirectories(m_projectsDirAccessor())) { var projectName = Path.GetFileName(projectFolder); var projectPath = Path.Combine(projectFolder, FdoFileHelper.GetDb4oDataFileName(projectName)); @@ -754,8 +750,9 @@ private object ConvertAllProjectsToXmlTask(IThreadedProgress progress, object[] // The zero in the object array is for db4o and causes it not to open a port. // This is fine since we aren't yet trying to start up on this restored database. // The null says we are creating the file on the local host. - using (var tempCache = FdoCache.CreateCacheFromExistingData( - new SimpleProjectId(FDOBackendProviderType.kDb4oClientServer, projectPath), "en", progress, userAction)) + using (FdoCache tempCache = FdoCache.CreateCacheFromExistingData( + new SimpleProjectId(FDOBackendProviderType.kDb4oClientServer, projectPath), "en", new SilentFdoUI(progress.SynchronizeInvoke), + m_dirs, progress)) { CopyToXmlFile(tempCache, tempCache.ProjectId.ProjectFolder); // Enhance JohnT: how can we tell this succeeded? @@ -764,7 +761,7 @@ private object ConvertAllProjectsToXmlTask(IThreadedProgress progress, object[] } catch (Exception e) { - ReportConversionError(userAction, projectPath, e); + ReportConversionError(projectPath, e); } } progress.Step(1); @@ -777,23 +774,21 @@ private object ConvertAllProjectsToXmlTask(IThreadedProgress progress, object[] /// Converts all projects to db4o. /// /// The progress dialog box. - /// /// ------------------------------------------------------------------------------------ - private bool ConvertAllProjectsToDb4o(IThreadedProgress progressDlg, IFdoUI ui) + private bool ConvertAllProjectsToDb4o(IThreadedProgress progressDlg) { progressDlg.Title = Strings.ksConvertingToShared; progressDlg.AllowCancel = false; - progressDlg.Maximum = Directory.GetDirectories(DirectoryFinder.ProjectsDirectory).Count(); - return (bool)progressDlg.RunTask(true, ConvertAllProjectsToDb4o, ui); + progressDlg.Maximum = Directory.GetDirectories(m_projectsDirAccessor()).Count(); + return (bool)progressDlg.RunTask(true, ConvertAllProjectsToDb4o); } private object ConvertAllProjectsToDb4o(IThreadedProgress progress, object[] args) { - var userAction = (IFdoUI) args[0]; for (; ; ) { string projects = ""; - foreach (var projectFolder in Directory.GetDirectories(DirectoryFinder.ProjectsDirectory)) + foreach (string projectFolder in Directory.GetDirectories(m_projectsDirAccessor())) { var projectName = Path.GetFileName(projectFolder); var projectPath = Path.Combine(projectFolder, FdoFileHelper.GetXmlDataFileName(projectName)); @@ -807,10 +802,10 @@ private object ConvertAllProjectsToDb4o(IThreadedProgress progress, object[] arg break; projects = projects.Substring(0, projects.Length - ", ".Length); - if (!userAction.Retry(string.Format(Strings.ksMustCloseProjectsToShare, projects), Strings.ksConvertingToShared)) + if (!m_ui.Retry(string.Format(Strings.ksMustCloseProjectsToShare, projects), Strings.ksConvertingToShared)) return false; } - foreach (string projectFolder in Directory.GetDirectories(DirectoryFinder.ProjectsDirectory)) + foreach (string projectFolder in Directory.GetDirectories(m_projectsDirAccessor())) { string projectName = Path.GetFileName(projectFolder); string projectPath = Path.Combine(projectFolder, FdoFileHelper.GetXmlDataFileName(projectName)); @@ -820,11 +815,11 @@ private object ConvertAllProjectsToDb4o(IThreadedProgress progress, object[] arg { try { - ConvertToDb4oBackendIfNeeded(progress, projectPath, userAction); + ConvertToDb4oBackendIfNeeded(progress, projectPath); } catch (Exception e) { - ReportConversionError(userAction, projectPath, e); + ReportConversionError(projectPath, e); } } progress.Step(1); @@ -832,7 +827,7 @@ private object ConvertAllProjectsToDb4o(IThreadedProgress progress, object[] arg return true; } - private static void ReportConversionError(IFdoUI ui, string projectPath, Exception e) + private void ReportConversionError(string projectPath, Exception e) { string message; if (e is FdoNewerVersionException) @@ -845,7 +840,7 @@ private static void ReportConversionError(IFdoUI ui, string projectPath, Excepti message = string.Format(Strings.ksConvertFailedDetails, Path.GetFileName(projectPath), Path.GetDirectoryName(projectPath), e.Message); } - ui.DisplayMessage(MessageType.Error, message, Strings.ksCannotConvert, null); + m_ui.DisplayMessage(MessageType.Error, message, Strings.ksCannotConvert, null); } /// ------------------------------------------------------------------------------------ @@ -857,29 +852,28 @@ private static void ReportConversionError(IFdoUI ui, string projectPath, Excepti /// The progress dialog (for getting a message box owner and/or /// ensuring we're invoking on the UI thread). /// The full path of the existing XML file for the project - /// /// The project identifier, typically the path to the converted file (or the /// original, if not configured for the client-server backend) /// ------------------------------------------------------------------------------------ - public string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string xmlFilename, IFdoUI ui) + public string ConvertToDb4oBackendIfNeeded(IThreadedProgress progressDlg, string xmlFilename) { if (!ShareMyProjects) return xmlFilename; // no conversion needed. string desiredPath = Path.ChangeExtension(xmlFilename, FdoFileHelper.ksFwDataDb4oFileExtension); - if (!EnsureNoClientsAreConnected(Path.GetFileNameWithoutExtension(desiredPath), ui)) + if (!EnsureNoClientsAreConnected(Path.GetFileNameWithoutExtension(desiredPath))) return null; // fail try { - using (var tempCache = FdoCache.CreateCacheFromExistingData(new SimpleProjectId(FDOBackendProviderType.kXML, xmlFilename), - "en", progressDlg, new SilentFdoUI(progressDlg.SynchronizeInvoke))) + using (FdoCache tempCache = FdoCache.CreateCacheFromExistingData(new SimpleProjectId(FDOBackendProviderType.kXML, xmlFilename), + "en", new SilentFdoUI(progressDlg.SynchronizeInvoke), m_dirs, progressDlg)) { // The zero in the object array is for db4o and causes it not to open a port. // This is fine since we aren't yet trying to start up on this restored database. // The null says we are creating the file on the local host. - using (var copyCache = FdoCache.CreateCacheCopy(new SimpleProjectId(FDOBackendProviderType.kDb4oClientServer, desiredPath), - "en", tempCache, new SilentFdoUI(progressDlg.SynchronizeInvoke))) + using (FdoCache copyCache = FdoCache.CreateCacheCopy(new SimpleProjectId(FDOBackendProviderType.kDb4oClientServer, desiredPath), + "en", new SilentFdoUI(progressDlg.SynchronizeInvoke), m_dirs, tempCache)) { copyCache.ServiceLocator.GetInstance().Commit(new HashSet(), new HashSet(), new HashSet()); // Enhance JohnT: how can we tell this succeeded? @@ -919,14 +913,14 @@ public string CopyToXmlFile(FdoCache source, string destDir) File.Delete(newFilePath); // Can't create a new file with FDO if the file already exists. try { - using (var copyCache = FdoCache.CreateCacheCopy( - new SimpleProjectId(FDOBackendProviderType.kXML, newFilePath), "en", source, source.ServiceLocator.GetInstance())) + using (FdoCache copyCache = FdoCache.CreateCacheCopy(new SimpleProjectId(FDOBackendProviderType.kXML, newFilePath), + "en", new SilentFdoUI(source.ServiceLocator.GetInstance().SynchronizeInvoke), m_dirs, source)) { - copyCache.ServiceLocator.GetInstance().Commit( - new HashSet(), - new HashSet(), - new HashSet()); - // Enhance JohnT: how can we tell this succeeded? + copyCache.ServiceLocator.GetInstance().Commit( + new HashSet(), + new HashSet(), + new HashSet()); + // Enhance JohnT: how can we tell this succeeded? return newFilePath; } } @@ -948,7 +942,7 @@ public string IdForLocalProject(string projectName) // Project Name must not have an extension. Can't use ChangeExtension because // the project name might contain some other period. Debug.Assert(!projectName.EndsWith(".fwdata") && !projectName.EndsWith(".fwdb")); - string projectDirectory = Path.Combine(DirectoryFinder.ProjectsDirectory, projectName); + string projectDirectory = Path.Combine(m_projectsDirAccessor(), projectName); var result = Path.Combine(projectDirectory, projectName + DefaultBackendType.GetExtension()); if (!File.Exists(result)) { diff --git a/Src/FDO/DomainServices/DataMigration/DataMigration7000019.cs b/Src/FDO/DomainServices/DataMigration/DataMigration7000019.cs index 19866d26da..567191cf9d 100644 --- a/Src/FDO/DomainServices/DataMigration/DataMigration7000019.cs +++ b/Src/FDO/DomainServices/DataMigration/DataMigration7000019.cs @@ -12,7 +12,6 @@ using Palaso.Xml; using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration { @@ -152,7 +151,7 @@ public void PerformMigration(IDomainObjectDTORepository domainObjectDtoRepositor // FieldWorks 6 data directory, and this is looking in the FW 7 one. No one has complained // so we decided not to try to fix it for the new implementation of the migration. - //string langDefPath = Path.Combine(DirectoryFinder.GetFWDataSubDirectory("Languages"), + //string langDefPath = Path.Combine(FwDirectoryFinder.GetDataSubDirectory("Languages"), // Path.ChangeExtension(langTag, "xml")); //if (File.Exists(langDefPath)) // FillWritingSystemFromLangDef(XElement.Load(langDefPath), ws); diff --git a/Src/FDO/DomainServices/DataMigration/DataMigration7000029.cs b/Src/FDO/DomainServices/DataMigration/DataMigration7000029.cs index e205301234..0c9856445b 100644 --- a/Src/FDO/DomainServices/DataMigration/DataMigration7000029.cs +++ b/Src/FDO/DomainServices/DataMigration/DataMigration7000029.cs @@ -77,8 +77,8 @@ public void PerformMigration(IDomainObjectDTORepository domainObjectDtoRepositor { persistedLinkedFilesRootDir = linkedFilesRootDirElement.Value; } - var linkedFilesRootDir = FdoFileHelperRelativePaths.GetLinkedFilesFullPathFromRelativePath(persistedLinkedFilesRootDir, - domainObjectDtoRepository.ProjectFolder); + var linkedFilesRootDir = LinkedFilesRelativePathHelper.GetLinkedFilesFullPathFromRelativePath(domainObjectDtoRepository.Directories.ProjectsDirectory, + persistedLinkedFilesRootDir, domainObjectDtoRepository.ProjectFolder); //Get the Elements for class="CmFile" var CmFileDtosBeforeMigration = domainObjectDtoRepository.AllInstancesSansSubclasses("CmFile"); @@ -86,7 +86,7 @@ public void PerformMigration(IDomainObjectDTORepository domainObjectDtoRepositor { XElement cmFileXML = XElement.Parse(fileDto.Xml); var filePath = cmFileXML.XPathSelectElement("InternalPath").XPathSelectElement("Uni").Value; - var fileAsRelativePath = FdoFileHelperRelativePaths.GetRelativeLinkedFilesPath(filePath, + var fileAsRelativePath = LinkedFilesRelativePathHelper.GetRelativeLinkedFilesPath(filePath, linkedFilesRootDir); //If these two strings do not match then a full path was converted to a LinkedFiles relative path //so replace the path in the CmFile object. diff --git a/Src/FDO/DomainServices/DataMigration/DataMigration7000030.cs b/Src/FDO/DomainServices/DataMigration/DataMigration7000030.cs index a783acdd50..9fa6ec8848 100644 --- a/Src/FDO/DomainServices/DataMigration/DataMigration7000030.cs +++ b/Src/FDO/DomainServices/DataMigration/DataMigration7000030.cs @@ -82,8 +82,8 @@ public void PerformMigration(IDomainObjectDTORepository domainObjectDtoRepositor { persistedLinkedFilesRootDir = linkedFilesRootDirElement.Value; } - var linkedFilesRootDir = FdoFileHelperRelativePaths.GetLinkedFilesFullPathFromRelativePath(persistedLinkedFilesRootDir, - domainObjectDtoRepository.ProjectFolder); + var linkedFilesRootDir = LinkedFilesRelativePathHelper.GetLinkedFilesFullPathFromRelativePath(domainObjectDtoRepository.Directories.ProjectsDirectory, + persistedLinkedFilesRootDir, domainObjectDtoRepository.ProjectFolder); //------------------------------------------------- var langProjectGuid = langProjElement.Attribute("guid").Value; @@ -221,7 +221,7 @@ private List ProcessExternalLinksRelativePaths(IDomainObjectDTORepositor var filePath = FileUtils.ChangeWindowsPathIfLinux(externalLinkAttributeForThisRun.Value); //Check the path and if it is a rooted path which is relative to the LinkedFilesRootDir //then we will have to confirm that is was changed to a relative path after the migration. - var fileAsRelativePath = FdoFileHelperRelativePaths.GetRelativeLinkedFilesPath(filePath, + var fileAsRelativePath = LinkedFilesRelativePathHelper.GetRelativeLinkedFilesPath(filePath, linkedFilesRootDir); //Save the file paths so they can be turned into CmFiles filePathsInTsStrings.Add(fileAsRelativePath); diff --git a/Src/FDO/DomainServices/DataMigration/DataMigration7000033.cs b/Src/FDO/DomainServices/DataMigration/DataMigration7000033.cs index 048e01f6dc..5e5fe949f8 100644 --- a/Src/FDO/DomainServices/DataMigration/DataMigration7000033.cs +++ b/Src/FDO/DomainServices/DataMigration/DataMigration7000033.cs @@ -61,7 +61,7 @@ public void PerformMigration(IDomainObjectDTORepository repoDto) { DataMigrationServices.CheckVersionNumber(repoDto, 7000032); var projectFolder = repoDto.ProjectFolder; - // This is equivalent to DirectoryFinder.GetConfigSettingsDir(projectFolder) at the time of creating + // This is equivalent to FwDirectoryFinder.GetConfigSettingsDir(projectFolder) at the time of creating // the migration, but could conceivably change later. var targetDir = Path.Combine(projectFolder, "ConfigurationSettings"); if (Directory.Exists(targetDir)) diff --git a/Src/FDO/DomainServices/DataMigration/DataMigration7000037.cs b/Src/FDO/DomainServices/DataMigration/DataMigration7000037.cs index ec19117d00..d247eb0f84 100644 --- a/Src/FDO/DomainServices/DataMigration/DataMigration7000037.cs +++ b/Src/FDO/DomainServices/DataMigration/DataMigration7000037.cs @@ -13,14 +13,10 @@ // --------------------------------------------------------------------------------------------- using System; using System.IO; -using System.Linq; using System.Text; using System.Web; -using System.Xml; using System.Xml.Linq; using System.Xml.XPath; - -using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration diff --git a/Src/FDO/DomainServices/DataMigration/DataMigration7000042.cs b/Src/FDO/DomainServices/DataMigration/DataMigration7000042.cs index 2620e727f1..e727a48cdb 100644 --- a/Src/FDO/DomainServices/DataMigration/DataMigration7000042.cs +++ b/Src/FDO/DomainServices/DataMigration/DataMigration7000042.cs @@ -16,7 +16,6 @@ using System.Text; using System.Xml.Linq; using System.Xml.XPath; -using SIL.FieldWorks.Common.FwUtils; using System; using SIL.Utils; diff --git a/Src/FDO/DomainServices/DataMigration/DataMigration7000044.cs b/Src/FDO/DomainServices/DataMigration/DataMigration7000044.cs index e7abfc4a2d..8b1854d1af 100644 --- a/Src/FDO/DomainServices/DataMigration/DataMigration7000044.cs +++ b/Src/FDO/DomainServices/DataMigration/DataMigration7000044.cs @@ -21,7 +21,7 @@ using System.Xml.XPath; using Palaso.WritingSystems.Migration; using Palaso.WritingSystems.Migration.WritingSystemsLdmlV0To1Migration; -using SIL.FieldWorks.Common.FwUtils; +using SIL.CoreImpl; using System; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration diff --git a/Src/FDO/DomainServices/DataMigration/IDomainObjectDTORepository.cs b/Src/FDO/DomainServices/DataMigration/IDomainObjectDTORepository.cs index 76824c86ba..4948b10246 100644 --- a/Src/FDO/DomainServices/DataMigration/IDomainObjectDTORepository.cs +++ b/Src/FDO/DomainServices/DataMigration/IDomainObjectDTORepository.cs @@ -219,6 +219,11 @@ void CreateCustomField(string className, string fieldName, SIL.CoreImpl.CellarPr /// /// ------------------------------------------------------------------------------------ string ProjectFolder { get; } + + /// + /// Gets the directories service. + /// + IFdoDirectories Directories { get; } } internal sealed class DomainObjectDtoRepository : IDomainObjectDTORepository @@ -239,6 +244,7 @@ internal sealed class DomainObjectDtoRepository : IDomainObjectDTORepository private int m_currentModelVersionNumber; private readonly HashSet m_oldTimers = new HashSet(); private readonly string m_projectFolder; + private readonly IFdoDirectories m_dirs; private readonly IFwMetaDataCacheManaged m_mdc; // needed for some data migrations changing over to custom fields. @@ -253,9 +259,10 @@ internal sealed class DomainObjectDtoRepository : IDomainObjectDTORepository /// The project folder (don't even think about trying to /// pass a path on a server other than the local machine, and -- yes -- I CAN control /// your thoughts!). + /// /// ------------------------------------------------------------------------------------ internal DomainObjectDtoRepository(int startingModelVersionNumber, HashSet dtos, - IFwMetaDataCacheManaged mdc, string projectFolder) + IFwMetaDataCacheManaged mdc, string projectFolder, IFdoDirectories dirs) { if (dtos == null) throw new ArgumentNullException("dtos"); if (mdc == null) throw new ArgumentNullException("mdc"); @@ -264,6 +271,7 @@ internal DomainObjectDtoRepository(int startingModelVersionNumber, HashSet + /// Gets the directories service. + /// + public IFdoDirectories Directories + { + get { return m_dirs; } + } #endregion } } diff --git a/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs b/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs index cb3cc19c8c..c6077ca878 100644 --- a/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs +++ b/Src/FDO/DomainServices/DataMigration/ImportFrom6_0.cs @@ -15,8 +15,6 @@ using System.Text; using ICSharpCode.SharpZipLib.Zip; using Microsoft.Win32; - -using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; namespace SIL.FieldWorks.FDO.DomainServices.DataMigration @@ -46,6 +44,7 @@ public class ImportFrom6_0 bool m_fHaveSqlServer; bool m_fHaveOldFieldWorks; + private readonly string m_converterConsolePath; readonly bool m_fVerboseDebug; private readonly IThreadedProgress m_progressDlg; #endregion @@ -54,16 +53,19 @@ public class ImportFrom6_0 /// /// Constructor for run-time debugging. /// - public ImportFrom6_0(IThreadedProgress progressDlg, bool fDebug) + public ImportFrom6_0(IThreadedProgress progressDlg, string converterConsolePath, string dbPath, bool fDebug) { m_progressDlg = progressDlg; + m_converterConsolePath = converterConsolePath; + m_dbPath = dbPath; m_fVerboseDebug = fDebug; } /// /// Constructor. /// - public ImportFrom6_0(IThreadedProgress progressDlg) : this(progressDlg, false) + public ImportFrom6_0(IThreadedProgress progressDlg, string converterConsolePath, string dbPath) + : this(progressDlg, converterConsolePath, dbPath, false) { } #endregion @@ -71,9 +73,8 @@ public ImportFrom6_0(IThreadedProgress progressDlg) : this(progressDlg, false) /// /// Do the import of the specified zip or XML file. Return true if successful and the caller should open the database. /// - public bool Import(string pathname, string projectName, out string projectFile) + public bool Import(string pathname, string projectName, string destFolder, out string projectFile) { - var destFolder = DirectoryFinder.ProjectsDirectory; var folderName = Path.Combine(destFolder, projectName); projectFile = Path.Combine(folderName, projectName + FdoFileHelper.ksFwDataXmlFileExtension); string extension = Path.GetExtension(pathname); @@ -101,7 +102,7 @@ public bool Import(string pathname, string projectName, out string projectFile) if (fCreateFolder) Directory.CreateDirectory(folderName); string message = String.Format(Strings.ksExtractingFromZip, Path.GetFileName(entry.Name)); - if (!UnzipFile(zipFile, entry, message, out tempPath)) + if (!UnzipFile(destFolder, zipFile, entry, message, out tempPath)) { return false; } @@ -147,7 +148,7 @@ public bool Import(string pathname, string projectName, out string projectFile) { string tempPath; string message = String.Format(Strings.ksExtractingFromZip, Path.GetFileName(entry.Name)); - if (!UnzipFile(zipFile, entry, message, out tempPath)) + if (!UnzipFile(destFolder, zipFile, entry, message, out tempPath)) { return false; } @@ -194,9 +195,8 @@ public bool Import(string pathname, string projectName, out string projectFile) } } - private bool UnzipFile(ZipFile zipFile, ZipEntry entry, string message, out string tempPath) + private bool UnzipFile(string folderName, ZipFile zipFile, ZipEntry entry, string message, out string tempPath) { - string folderName = DirectoryFinder.ProjectsDirectory; if (!Directory.Exists(folderName)) Directory.CreateDirectory(folderName); // We will extract the file to here. @@ -358,7 +358,6 @@ public bool IsValidOldFwInstalled(out string version) return false; } } - m_dbPath = Path.Combine(DirectoryFinder.GetFWCodeSubDirectory("MSSQLMigration"), "db.exe"); if (!File.Exists(m_dbPath)) { if (m_fVerboseDebug) @@ -419,10 +418,7 @@ private string FindComDllIfRegistered(RegistryKey clsidKey, string sClsid, ref s } if (String.IsNullOrEmpty(version) || version.CompareTo("5.4") < 0 || version.CompareTo("6.1") >= 0) { - if (!String.IsNullOrEmpty(version) && version.CompareTo("5.4") < 0) - { - } - else if (m_fVerboseDebug) + if (m_fVerboseDebug) { string msg = String.Format("Invalid version found in a registered COM DLL: {0} [{1}]", version, dllPath); @@ -643,9 +639,7 @@ public bool ImportFrom6_0Xml(string pathname, string folderName, string projectF File.Delete(replacedProj); File.Move(projectFile, replacedProj); } - using (var process = CreateAndInitProcess( - Path.Combine(DirectoryFinder.FWCodeDirectory, "ConverterConsole.exe"), - '"' + pathname + "\" \"" + projectFile + '"')) + using (var process = CreateAndInitProcess(m_converterConsolePath, '"' + pathname + "\" \"" + projectFile + '"')) { m_progressDlg.IsIndeterminate = true; // Can't get actual progress from external program m_progressDlg.Title = Strings.ksConverting; diff --git a/Src/FDO/DomainServices/DomainObjectServices.cs b/Src/FDO/DomainServices/DomainObjectServices.cs index f12d04a377..337d60da77 100644 --- a/Src/FDO/DomainServices/DomainObjectServices.cs +++ b/Src/FDO/DomainServices/DomainObjectServices.cs @@ -23,7 +23,6 @@ using SIL.FieldWorks.FDO.Infrastructure; using SILUBS.SharedScrUtils; using SIL.CoreImpl; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainImpl; namespace SIL.FieldWorks.FDO.DomainServices @@ -2328,49 +2327,6 @@ public static ICmFile FindOrCreateFile(ICmFolder folder, string srcFile) return cmFile; } - /// ------------------------------------------------------------------------------------ - /// - /// Copy source file to a unique file in FW\pictures directory. - /// - /// The path to the original filename (an internal copy will - /// be made in this method) - /// The subfolder of the FW Data directory in which the - /// internal copy of the file should be created, if necessary (no backslashes needed) - /// - /// Destination file path, relative to the FW data directory, or ".__NONE__" - /// if source file doesn't exist. - /// - /// ------------------------------------------------------------------------------------ - public static string CopyFileToInternal(string srcFilename, string dstSubdir) - { - string srcFilenameCorrected; - if (!FileUtils.TrySimilarFileExists(srcFilename, out srcFilenameCorrected)) - return EmptyFileName; - - var strDestFolder = Path.Combine(DirectoryFinder.FWDataDirectory, dstSubdir); - if (!Directory.Exists(strDestFolder)) - Directory.CreateDirectory(strDestFolder); - - var strDestFileRelPath = Path.Combine(dstSubdir, Path.GetFileName(srcFilenameCorrected)); - var strDestFileAbsPath = Path.Combine(DirectoryFinder.FWDataDirectory, strDestFileRelPath); - - // (The case-independent comparison is valid only for Microsoft Windows.) - if (srcFilenameCorrected.Equals(strDestFileAbsPath, StringComparison.OrdinalIgnoreCase)) - return strDestFileRelPath; // don't copy files already in internal directory. - - var strFile = Path.GetFileNameWithoutExtension(srcFilenameCorrected); - var strExt = Path.GetExtension(srcFilenameCorrected); - var iQual = 0; - while (FileUtils.FileExists(strDestFileAbsPath)) - { - iQual++; - strDestFileRelPath = Path.Combine(dstSubdir, strFile + iQual + strExt); - strDestFileAbsPath = Path.Combine(DirectoryFinder.FWDataDirectory, strDestFileRelPath); - } - File.Copy(srcFilenameCorrected, strDestFileAbsPath); - return strDestFileRelPath; - } - /// ------------------------------------------------------------------------------------ /// /// Gets the empty name of the file. diff --git a/Src/FDO/DomainServices/FwProjectFinder.cs b/Src/FDO/DomainServices/FwProjectFinder.cs index 932f04e8b1..bd8c30474b 100644 --- a/Src/FDO/DomainServices/FwProjectFinder.cs +++ b/Src/FDO/DomainServices/FwProjectFinder.cs @@ -14,7 +14,6 @@ using System; using System.IO; using System.Threading; -using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; namespace SIL.FieldWorks.FDO.DomainServices @@ -32,6 +31,7 @@ internal class FwProjectFinder private readonly Action m_projectFoundCallback; private readonly Action m_onCompletedCallback; private volatile bool m_forceStop = false; + private readonly string m_projectsDir; /// ------------------------------------------------------------------------------------ /// @@ -42,9 +42,10 @@ internal class FwProjectFinder /// Callback to run when the search is completed. /// The exception callback. /// true if we want to show local fwdata projects + /// The projects directory. /// ------------------------------------------------------------------------------------ public FwProjectFinder(string host, Action projectFoundCallback, - Action onCompletedCallback, Action exceptionCallback, bool showLocalProjects) + Action onCompletedCallback, Action exceptionCallback, bool showLocalProjects, string projectsDir) { if (string.IsNullOrEmpty(host)) throw new ArgumentNullException("host"); @@ -56,6 +57,7 @@ public FwProjectFinder(string host, Action projectFoundCallback, m_onCompletedCallback = onCompletedCallback; m_exceptionCallback = exceptionCallback; m_fShowLocalProjects = showLocalProjects; + m_projectsDir = projectsDir; m_projectFinderThread = new Thread(FindProjects); m_projectFinderThread.Name = "Project Finder"; @@ -79,7 +81,7 @@ private void FindProjects() if (m_fShowLocalProjects) { // search sub dirs - string[] dirs = Directory.GetDirectories(DirectoryFinder.ProjectsDirectory); + string[] dirs = Directory.GetDirectories(m_projectsDir); foreach (string dir in dirs) { string file = Path.Combine(dir, FdoFileHelper.GetXmlDataFileName(Path.GetFileName(dir))); diff --git a/Src/FDO/DomainServices/ParatextHelper.cs b/Src/FDO/DomainServices/ParatextHelper.cs index 4409023352..ed37f59341 100644 --- a/Src/FDO/DomainServices/ParatextHelper.cs +++ b/Src/FDO/DomainServices/ParatextHelper.cs @@ -14,10 +14,10 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.IO; using System.Linq; +using Microsoft.Win32; using Paratext; -using Paratext.DerivedTranslation; -using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; using SILUBS.SharedScrUtils; @@ -150,6 +150,35 @@ public ParatextHelperAdapter() RefreshProjects(); } + /// + /// LT-14787 Database displays error about inaccessible Paratext projects + /// If there is a registry value for this but the folder is not there we need to return false because + /// paratext is not installed correctly. Also if there is no registry entry for this then return false. + /// + private bool ParatextSettingsDirectoryExists() + { + var regValue = ParatextSettingsDirectory(); + return !String.IsNullOrEmpty(regValue) && Directory.Exists(regValue); + } + + /// + /// Returns the path to the Paratext settings (projects) directory as specified in the registry + /// ENHANCE (Hasso) 2013.09: added this to expose the directory for Unix users, because trying to get it from ScrTextCollections + /// always returns null on Unix. This is really a Paratext problem, and this method may have no benefit. + /// + private string ParatextSettingsDirectory() + { + using (var paratextKey = Registry.LocalMachine.OpenSubKey("Software\\ScrChecks\\1.0\\Settings_Directory")) + { + if (paratextKey != null) + { + var keyName = paratextKey.ToString(); + return Registry.GetValue(keyName, "", "") as string; + } + } + return null; + } + /// ------------------------------------------------------------------------------------ /// /// Gets the Paratext projects directory (null if none) @@ -165,7 +194,7 @@ public string ProjectsDirectory { // TODO FWNX-1235: Why does SrcTextCollection.SettingsDirectory not work in Unix? // Does ScrTextCollection work at all in Unix? - return FwRegistryHelper.ParatextSettingsDirectory(); + return ParatextSettingsDirectory(); } return ScrTextCollection.SettingsDirectory; } @@ -182,7 +211,7 @@ public void RefreshProjects() { try { - if (FwRegistryHelper.ParatextSettingsDirectoryExists()) + if (ParatextSettingsDirectoryExists()) { if (!m_IsParatextInitialized) { @@ -192,7 +221,7 @@ public void RefreshProjects() // We pass the directory (rather than passing no arguments, and letting the paratext dll figure // it out) because the figuring out goes wrong on Linux, where both programs are simulating // the registry. - ScrTextCollection.Initialize(FwRegistryHelper.ParatextSettingsDirectory(), false); + ScrTextCollection.Initialize(ParatextSettingsDirectory(), false); m_IsParatextInitialized = true; } else diff --git a/Src/FDO/DomainServices/ScrChecksDataSource.cs b/Src/FDO/DomainServices/ScrChecksDataSource.cs index 43d889bebb..cfad2e1fc3 100644 --- a/Src/FDO/DomainServices/ScrChecksDataSource.cs +++ b/Src/FDO/DomainServices/ScrChecksDataSource.cs @@ -52,6 +52,7 @@ public class ScrChecksDataSource : IChecksDataSource private readonly IScripture m_scr; private readonly string m_styleSheetFileName; private readonly string m_punctWhitespaceChar; + private readonly string m_legacyOverridesFile; private static StyleMarkupInfo s_styleMarkupInfo = null; @@ -66,8 +67,9 @@ public class ScrChecksDataSource : IChecksDataSource /// /// The cache. /// + /// /// ------------------------------------------------------------------------------------ - public ScrChecksDataSource(FdoCache cache, string punctWhitespaceChar) : this(cache, punctWhitespaceChar, null) + public ScrChecksDataSource(FdoCache cache, string punctWhitespaceChar, string legacyOverridesFile) : this(cache, punctWhitespaceChar, legacyOverridesFile, null) { } @@ -77,14 +79,16 @@ public ScrChecksDataSource(FdoCache cache, string punctWhitespaceChar) : this(ca /// /// The cache. /// + /// /// Path to the stylesheet definition XML file /// ------------------------------------------------------------------------------------ - public ScrChecksDataSource(FdoCache cache, string punctWhitespaceChar, string styleSheetFileName) + public ScrChecksDataSource(FdoCache cache, string punctWhitespaceChar, string legacyOverridesFile, string styleSheetFileName) { m_cache = cache; m_scr = cache.LangProject.TranslatedScriptureOA; m_punctWhitespaceChar = punctWhitespaceChar; m_styleSheetFileName = styleSheetFileName; + m_legacyOverridesFile = legacyOverridesFile; } /// ------------------------------------------------------------------------------------ @@ -707,7 +711,7 @@ private string GetValidCharactersList(string key, IWritingSystem ws) return bldr.ToString(); } - var validChars = ValidCharacters.Load(ws, LoadException ?? NoErrorReport); + var validChars = ValidCharacters.Load(ws, LoadException ?? NoErrorReport, m_legacyOverridesFile); return (validChars != null ? validChars.SpaceDelimitedList : string.Empty); } @@ -722,7 +726,7 @@ private ValidCharacters ValidCharacters { // Get the writing system and valid characters list return ValidCharacters.Load(m_cache.ServiceLocator.WritingSystemManager.Get(m_cache.DefaultVernWs), - LoadException ?? NoErrorReport); + LoadException ?? NoErrorReport, m_legacyOverridesFile); } } diff --git a/Src/FDO/DomainServices/ScrMappingList.cs b/Src/FDO/DomainServices/ScrMappingList.cs index 5e11b8647f..170f9abc16 100644 --- a/Src/FDO/DomainServices/ScrMappingList.cs +++ b/Src/FDO/DomainServices/ScrMappingList.cs @@ -18,7 +18,6 @@ using System.Xml; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.Common.ScriptureUtils; -using SIL.FieldWorks.Common.FwUtils; namespace SIL.FieldWorks.FDO.DomainServices { @@ -38,6 +37,7 @@ public class ScrMappingList : IEnumerable private IVwStylesheet m_stylesheet; private readonly string m_defaultParaCharsStyleName; + private readonly string m_stylesPath; private static Dictionary s_defaultMappings = new Dictionary(); private static Dictionary s_defaultProperties = new Dictionary(); @@ -63,12 +63,15 @@ public class ScrMappingList : IEnumerable /// /// The stylesheet /// + /// /// ------------------------------------------------------------------------------------ - public ScrMappingList(MappingSet mappingSet, IVwStylesheet stylesheet, string defaultParaCharsStyleName) + public ScrMappingList(MappingSet mappingSet, IVwStylesheet stylesheet, string defaultParaCharsStyleName, + string stylesPath) { m_mappingSet = mappingSet; m_stylesheet = stylesheet; m_defaultParaCharsStyleName = defaultParaCharsStyleName; + m_stylesPath = stylesPath; } #endregion @@ -433,10 +436,10 @@ public IVwStylesheet StyleSheet /// ------------------------------------------------------------------------------------ [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] - private static void ReadDefaultMappings() + private void ReadDefaultMappings() { XmlDocument doc = new XmlDocument(); - doc.Load(DirectoryFinder.TeStylesPath); + doc.Load(m_stylesPath); XmlNode mappingNode = doc.SelectSingleNode("Styles/ImportMappingSets/ImportMapping[@name='TE Default']"); foreach (XmlNode mapNode in mappingNode.SelectNodes("mapping")) { diff --git a/Src/FDO/DomainServices/StringServices.cs b/Src/FDO/DomainServices/StringServices.cs index 06834d0efc..f0fbde662f 100644 --- a/Src/FDO/DomainServices/StringServices.cs +++ b/Src/FDO/DomainServices/StringServices.cs @@ -76,7 +76,7 @@ public static void MarkTextInBldrAsHyperlink(ITsStrBldr strBldr, int ichStart, public static string MarkTextInBldrAsHyperlink(ITsStrBldr strBldr, int ichStart, int ichLim, string url, IStStyle linkStyle, string linkedFilesRootDir) { - var relativeUrl = FdoFileHelperRelativePaths.GetRelativeLinkedFilesPath(url, linkedFilesRootDir); + var relativeUrl = LinkedFilesRelativePathHelper.GetRelativeLinkedFilesPath(url, linkedFilesRootDir); if (string.IsNullOrEmpty(relativeUrl)) { MarkTextInBldrAsHyperlink(strBldr, ichStart, ichLim, url, linkStyle); diff --git a/Src/FDO/DomainServices/ValidCharacters.cs b/Src/FDO/DomainServices/ValidCharacters.cs index 8d5e34860d..da0632faec 100644 --- a/Src/FDO/DomainServices/ValidCharacters.cs +++ b/Src/FDO/DomainServices/ValidCharacters.cs @@ -13,13 +13,11 @@ // --------------------------------------------------------------------------------------------- using System; using System.Collections.Generic; -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Text; using System.IO; using System.Xml; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; using System.Xml.Serialization; using SIL.CoreImpl; @@ -99,6 +97,7 @@ public class ValidCharacters private List m_OtherCharacters; private ILgCharacterPropertyEngine m_cpe; private TsStringComparer m_comparer; + private string m_legacyOverridesFile; #endregion @@ -125,6 +124,7 @@ protected ValidCharacters() } #region Methods and Properties to load and initialize the class + /// ------------------------------------------------------------------------------------ /// /// Loads the valid characters from the specified language definition into a new @@ -133,13 +133,14 @@ protected ValidCharacters() /// The writing system. /// The exception handler to use if valid character data /// cannot be loaded. + /// /// A initialized with the valid characters data /// from the language definition. /// ------------------------------------------------------------------------------------ - public static ValidCharacters Load(IWritingSystem ws, LoadExceptionDelegate exceptionHandler) + public static ValidCharacters Load(IWritingSystem ws, LoadExceptionDelegate exceptionHandler, string legacyOverridesFile) { ValidCharacters validChars = Load(ws.ValidChars, ws.DisplayLabel, ws, - exceptionHandler); + exceptionHandler, legacyOverridesFile); if (validChars != null) validChars.InitSortComparer(ws); @@ -156,10 +157,11 @@ public static ValidCharacters Load(IWritingSystem ws, LoadExceptionDelegate exce /// The writing system /// The exception handler to use if valid character data /// cannot be loaded. + /// /// /// ------------------------------------------------------------------------------------ public static ValidCharacters Load(string xmlSrc, string wsName, - IWritingSystem ws, LoadExceptionDelegate exceptionHandler) + IWritingSystem ws, LoadExceptionDelegate exceptionHandler, string legacyOverridesFile) { Exception e; var validChars = XmlSerializationHelper.DeserializeFromString(xmlSrc, out e); @@ -167,7 +169,9 @@ public static ValidCharacters Load(string xmlSrc, string wsName, bool fTryOldStyleList = false; if (validChars != null) + { validChars.LoadException += exceptionHandler; + } else { validChars = new ValidCharacters(); @@ -177,14 +181,14 @@ public static ValidCharacters Load(string xmlSrc, string wsName, if (!fTryOldStyleList && !String.IsNullOrEmpty(xmlSrc)) { var bldr = new StringBuilder(); - bldr.AppendFormat("Invalid ValidChars field while loading the {0} writing system:", - wsName); + bldr.AppendFormat("Invalid ValidChars field while loading the {0} writing system:", wsName); bldr.Append(Environment.NewLine); bldr.Append("\t"); bldr.Append(xmlSrc); validChars.ReportError(new ArgumentException(bldr.ToString(), "xmlSrc", e)); } } + validChars.m_legacyOverridesFile = legacyOverridesFile; List invalidChars = validChars.Init(); @@ -290,15 +294,13 @@ private List Init() /// Gets the default word forming overrides. /// /// ------------------------------------------------------------------------------------ - private static IEnumerable DefaultWordFormingOverrides + private IEnumerable DefaultWordFormingOverrides { get { if (s_fTestingMode) return s_defaultWordformingChars; - string legacyOverrides = Path.Combine(DirectoryFinder.FWCodeDirectory, - "WordFormingCharOverrides.xml"); - return ParseLegacyWordFormingCharOverrides(legacyOverrides) ?? + return ParseLegacyWordFormingCharOverrides(m_legacyOverridesFile) ?? (IEnumerable)s_defaultWordformingChars; } } diff --git a/Src/FDO/DomainServices/WfiWordformServices.cs b/Src/FDO/DomainServices/WfiWordformServices.cs index 59a0ca9b09..86e28f9e53 100644 --- a/Src/FDO/DomainServices/WfiWordformServices.cs +++ b/Src/FDO/DomainServices/WfiWordformServices.cs @@ -19,7 +19,6 @@ using System.Diagnostics; using System.Linq; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.CoreImpl; using SIL.FieldWorks.FDO.DomainImpl; using SIL.Utils; diff --git a/Src/FDO/DomainServices/WritingSystemServices.cs b/Src/FDO/DomainServices/WritingSystemServices.cs index 6f8a989890..af76ddff45 100644 --- a/Src/FDO/DomainServices/WritingSystemServices.cs +++ b/Src/FDO/DomainServices/WritingSystemServices.cs @@ -1329,12 +1329,13 @@ private static List AnalysisVernacularWss(FdoCache cache, bool f /// to the requested collection(s). /// /// The cache. + /// The template directory. /// The identifier. /// if set to true ***new*** writing systems will be added to the list of analysis writing systems. /// if set to true ***new*** writing systems will be added to the list of vernacular writing systems. /// The writing system. /// true if the writing system already exists, false if it had to be created - public static bool FindOrCreateWritingSystem(FdoCache cache, string identifier, bool addAnalWss, bool addVernWss, out IWritingSystem ws) + public static bool FindOrCreateWritingSystem(FdoCache cache, string templateDir, string identifier, bool addAnalWss, bool addVernWss, out IWritingSystem ws) { if (cache.ServiceLocator.WritingSystemManager.GetOrSet(identifier, out ws)) return true; @@ -1346,7 +1347,8 @@ public static bool FindOrCreateWritingSystem(FdoCache cache, string identifier, // If the new writing system is one for which we have localized versions of lists, import them. // We can't easily put up a progress dialog here, because the code is in a project we can't reference. // However this routine is used in relatively long operations anyway so there should already be some kind of progress bar. - XmlTranslatedLists.ImportTranslatedListsForWs(identifier, cache, null); + if (templateDir != null) + XmlTranslatedLists.ImportTranslatedListsForWs(identifier, cache, templateDir, null); return false; } @@ -1357,7 +1359,7 @@ public static bool FindOrCreateWritingSystem(FdoCache cache, string identifier, /// systems if the appropriate flag is set. /// /// true if the writing system already exists, false if it had to be created - public static bool FindOrCreateSomeWritingSystem(FdoCache cache, string identifier, bool addAnalWss, bool addVernWss, out IWritingSystem ws) + public static bool FindOrCreateSomeWritingSystem(FdoCache cache, string templateDir, string identifier, bool addAnalWss, bool addVernWss, out IWritingSystem ws) { if (cache.ServiceLocator.WritingSystemManager.TryGet(identifier, out ws)) return true; @@ -1368,12 +1370,12 @@ public static bool FindOrCreateSomeWritingSystem(FdoCache cache, string identifi if (LangTagUtils.GetSubtags(identifier, out languageSubtag, out scriptSubtag, out regionSubtag, out variantSubtag)) { // It's a good identifier; we can do this straightforwardly. - return FindOrCreateWritingSystem(cache, identifier, addAnalWss, addVernWss, out ws); + return FindOrCreateWritingSystem(cache, templateDir, identifier, addAnalWss, addVernWss, out ws); } // See if we can convert an old-style identifier to a new one. string newIdentifier = LangTagUtils.ToLangTag(identifier); if (LangTagUtils.GetSubtags(identifier, out languageSubtag, out scriptSubtag, out regionSubtag, out variantSubtag)) - return FindOrCreateWritingSystem(cache, newIdentifier, addAnalWss, addVernWss, out ws); + return FindOrCreateWritingSystem(cache, templateDir, newIdentifier, addAnalWss, addVernWss, out ws); // No, it's nothing we know how to deal with. Get drastic. @@ -1392,7 +1394,7 @@ public static bool FindOrCreateSomeWritingSystem(FdoCache cache, string identifi parts = new [] {"qaa"}.Concat(parts); // Can't start with x, we always use qaa for unknown WS. newIdentifier = parts.Aggregate((first, second) => first + "-" + second); // This should now qualify as a private-use writing system identifier. - return FindOrCreateWritingSystem(cache, newIdentifier, addAnalWss, addVernWss, out ws); + return FindOrCreateWritingSystem(cache, templateDir, newIdentifier, addAnalWss, addVernWss, out ws); } /// diff --git a/Src/FDO/FDO.csproj b/Src/FDO/FDO.csproj index d7b0bc00f1..759fae2489 100644 --- a/Src/FDO/FDO.csproj +++ b/Src/FDO/FDO.csproj @@ -134,9 +134,6 @@ ..\..\Output\Debug\Db4objects.Db4o.Linq.dll - - ..\..\Output\Debug\FwUtils.dll - ..\..\Lib\debug\ICSharpCode.SharpZipLib.dll @@ -186,7 +183,8 @@ - + + @@ -310,7 +308,6 @@ - @@ -364,9 +361,11 @@ + + diff --git a/Src/FDO/FDOTests/BackupRestore/BackupFileRepositoryTests.cs b/Src/FDO/FDOTests/BackupRestore/BackupFileRepositoryTests.cs index 649c37e2df..1cec4eb336 100644 --- a/Src/FDO/FDOTests/BackupRestore/BackupFileRepositoryTests.cs +++ b/Src/FDO/FDOTests/BackupRestore/BackupFileRepositoryTests.cs @@ -70,9 +70,9 @@ public void Teardown() [Test] public void NoBackupFilesAvailable() { - m_fileOs.ExistingDirectories.Add(DirectoryFinder.DefaultBackupDirectory); + m_fileOs.ExistingDirectories.Add(FwDirectoryFinder.DefaultBackupDirectory); - BackupFileRepository repo = new BackupFileRepository(); + BackupFileRepository repo = new BackupFileRepository(FwDirectoryFinder.DefaultBackupDirectory); Assert.AreEqual(0, repo.AvailableProjectNames.Count()); Assert.Throws(typeof(KeyNotFoundException), () => repo.GetAvailableVersions("monkey")); Assert.Throws(typeof(KeyNotFoundException), () => repo.GetBackupFile("monkey", DateTime.Now, false)); @@ -97,7 +97,7 @@ public void BackupsForSingleProjectExists() string backupFileName2 = backupSettings.ZipFileName; m_fileOs.AddExistingFile(backupFileName2); - BackupFileRepository repo = new BackupFileRepository(); + BackupFileRepository repo = new BackupFileRepository(FwDirectoryFinder.DefaultBackupDirectory); Assert.AreEqual(1, repo.AvailableProjectNames.Count()); Assert.AreEqual(2, repo.GetAvailableVersions("Floozy").Count()); Assert.AreEqual(backupFileName2, repo.GetBackupFile("Floozy", backupSettings.BackupTime, false).File); @@ -126,7 +126,7 @@ public void InavlidBackupFile() string backupFileName2 = backupSettings.ZipFileName; m_fileOs.AddExistingFile(backupFileName2); - BackupFileRepository repo = new BackupFileRepository(); + BackupFileRepository repo = new BackupFileRepository(FwDirectoryFinder.DefaultBackupDirectory); BackupFileSettings invalidFileSettings = repo.GetMostRecentBackup("Floozy"); BackupFileSettings validFileSettings = repo.GetBackupFile("Floozy", backupSettings.BackupTime, false); ReflectionHelper.SetProperty(validFileSettings, "ProjectName", "Floozy"); // Force it to think it's already loaded and happy. @@ -162,7 +162,7 @@ public void BackupsForMultipleProjects() string backupFileName3 = backupSettings.ZipFileName; m_fileOs.AddExistingFile(backupFileName3); - BackupFileRepository repo = new BackupFileRepository(); + BackupFileRepository repo = new BackupFileRepository(FwDirectoryFinder.DefaultBackupDirectory); Assert.AreEqual(2, repo.AvailableProjectNames.Count()); Assert.AreEqual(2, repo.GetAvailableVersions("AAA").Count()); Assert.AreEqual(1, repo.GetAvailableVersions("ZZZ").Count()); @@ -188,11 +188,11 @@ public void BackupHasOldStyleDatetimeFormat() { DummyBackupProjectSettings backupSettings = new DummyBackupProjectSettings("monkey", "Floozy", null, FDOBackendProviderType.kXML); - string backupFileName1 = Path.Combine(DirectoryFinder.DefaultBackupDirectory, + string backupFileName1 = Path.Combine(FwDirectoryFinder.DefaultBackupDirectory, Path.ChangeExtension("Floozy 2010-8-21-0506", FdoFileHelper.ksFwBackupFileExtension)); m_fileOs.AddExistingFile(backupFileName1); - BackupFileRepository repo = new BackupFileRepository(); + BackupFileRepository repo = new BackupFileRepository(FwDirectoryFinder.DefaultBackupDirectory); Assert.AreEqual(1, repo.AvailableProjectNames.Count()); Assert.AreEqual(1, repo.GetAvailableVersions("Floozy").Count()); Assert.AreEqual(backupFileName1, repo.GetMostRecentBackup("Floozy").File); diff --git a/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs b/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs index 2e634d1379..fd5f7ae3ad 100644 --- a/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs +++ b/Src/FDO/FDOTests/BackupRestore/BackupRestoreSettingsTests.cs @@ -36,7 +36,7 @@ internal class DummyBackupProjectSettings : BackupProjectSettings /// ------------------------------------------------------------------------------------ internal DummyBackupProjectSettings(string projectsRootFolder, string projectName, string linkedFilesRootDir, FDOBackendProviderType originalProjType) : - base(projectsRootFolder, projectName, linkedFilesRootDir, null, originalProjType) + base(projectsRootFolder, projectName, linkedFilesRootDir, null, originalProjType, FwDirectoryFinder.DefaultBackupDirectory) { } } @@ -56,7 +56,7 @@ public class BackupRestoreSettingsTests : MemoryOnlyBackendProviderBasicTestBase [Test] public void DefaultRestoreSettings() { - var settings = new RestoreProjectSettings(); + var settings = new RestoreProjectSettings(FwDirectoryFinder.ProjectsDirectory); Assert.IsNull(settings.Backup); Assert.True(string.IsNullOrEmpty(settings.ProjectName)); @@ -76,10 +76,10 @@ public void DefaultRestoreSettings() [Test] public void RestoreProjectSettings_VerifyExistenceOfProject() { - string restoreTestsZipFileDir = Path.Combine(DirectoryFinder.FwSourceDirectory, + string restoreTestsZipFileDir = Path.Combine(FwDirectoryFinder.SourceDirectory, "FDO/FDOTests/BackupRestore/RestoreServiceTestsZipFileDir"); - RestoreProjectSettings restoreSettings = new RestoreProjectSettings() + RestoreProjectSettings restoreSettings = new RestoreProjectSettings(FwDirectoryFinder.ProjectsDirectory) { Backup = new BackupFileSettings(Path.Combine(restoreTestsZipFileDir, Path.ChangeExtension("TestRestoreFWProject", FdoFileHelper.ksFwBackupFileExtension))), @@ -92,7 +92,8 @@ public void RestoreProjectSettings_VerifyExistenceOfProject() }; ProjectRestoreServiceTests.RemoveAnyFilesAndFoldersCreatedByTests(restoreSettings); - ProjectRestoreService restoreProjectService = new ProjectRestoreService(restoreSettings); + ProjectRestoreService restoreProjectService = new ProjectRestoreService(restoreSettings, new DummyFdoUI(), + FwDirectoryFinder.ConverterConsoleExe, FwDirectoryFinder.DbExe); Assert.False(restoreSettings.ProjectExists, "Project exists but it should not."); @@ -116,10 +117,10 @@ public void RestoreProjectSettings_VerifyExistenceOfProject() [Test] public void RestoreProjectSettings_VerifyExistenceOfHgRepo() { - string restoreTestsZipFileDir = Path.Combine(DirectoryFinder.FwSourceDirectory, + string restoreTestsZipFileDir = Path.Combine(FwDirectoryFinder.SourceDirectory, "FDO/FDOTests/BackupRestore/RestoreServiceTestsZipFileDir"); - RestoreProjectSettings restoreSettings = new RestoreProjectSettings() + RestoreProjectSettings restoreSettings = new RestoreProjectSettings(FwDirectoryFinder.ProjectsDirectory) { Backup = new BackupFileSettings(Path.Combine(restoreTestsZipFileDir, Path.ChangeExtension("TestRestoreFWProject", FdoFileHelper.ksFwBackupFileExtension))), @@ -131,7 +132,8 @@ public void RestoreProjectSettings_VerifyExistenceOfHgRepo() BackupOfExistingProjectRequested = false, }; - ProjectRestoreService restoreProjectService = new ProjectRestoreService(restoreSettings); + ProjectRestoreService restoreProjectService = new ProjectRestoreService(restoreSettings, new DummyFdoUI(), + FwDirectoryFinder.ConverterConsoleExe, FwDirectoryFinder.DbExe); try { @@ -170,7 +172,7 @@ public void RestoreProjectSettings_VerifyExistenceOfHgRepo() [Test] public void RestoreProjectSettings_CommandLineOptions() { - RestoreProjectSettings settings = new RestoreProjectSettings(); + RestoreProjectSettings settings = new RestoreProjectSettings(FwDirectoryFinder.ProjectsDirectory); Assert.AreEqual(string.Empty, settings.CommandLineOptions); settings.IncludeConfigurationSettings = true; Assert.AreEqual("c", settings.CommandLineOptions.ToLower()); @@ -197,15 +199,15 @@ public void RestoreProjectSettings_CommandLineOptions() [Test] public void RestoreProjectSettings_CreateFromCommandLineOptions() { - RestoreProjectSettings settings = new RestoreProjectSettings("project", "notThere.fwbackup", string.Empty); + RestoreProjectSettings settings = new RestoreProjectSettings(FwDirectoryFinder.ProjectsDirectory, "project", "notThere.fwbackup", string.Empty); CheckSettings(settings, false, false, false, false); - settings = new RestoreProjectSettings("project", "notThere.fwbackup", "fl"); + settings = new RestoreProjectSettings(FwDirectoryFinder.ProjectsDirectory, "project", "notThere.fwbackup", "fl"); CheckSettings(settings, false, true, true, false); - settings = new RestoreProjectSettings("project", "notThere.fwbackup", "cls"); + settings = new RestoreProjectSettings(FwDirectoryFinder.ProjectsDirectory, "project", "notThere.fwbackup", "cls"); CheckSettings(settings, true, false, true, true); - settings = new RestoreProjectSettings("project", "notThere.fwbackup", "cfls"); + settings = new RestoreProjectSettings(FwDirectoryFinder.ProjectsDirectory, "project", "notThere.fwbackup", "cfls"); CheckSettings(settings, true, true, true, true); - settings = new RestoreProjectSettings("project", "notThere.fwbackup", "CFLS"); + settings = new RestoreProjectSettings(FwDirectoryFinder.ProjectsDirectory, "project", "notThere.fwbackup", "CFLS"); CheckSettings(settings, true, true, true, true); } @@ -219,7 +221,7 @@ public void RestoreProjectSettings_CreateFromCommandLineOptions() [Test] public void BackupFileSettings_InitializeFromZipfileMetadata() { - string zipFilePath = Path.Combine(Path.Combine(DirectoryFinder.FwSourceDirectory, "FDO/FDOTests/BackupRestore/RestoreProjectPresenterTests"), + string zipFilePath = Path.Combine(Path.Combine(FwDirectoryFinder.SourceDirectory, "FDO/FDOTests/BackupRestore/RestoreProjectPresenterTests"), Path.ChangeExtension("RestoreProjectPresenterTests", FdoFileHelper.ksFwBackupFileExtension)); BackupFileSettings backupSettings = new BackupFileSettings(zipFilePath); @@ -243,7 +245,7 @@ public void BackupFileSettings_InitializeFromZipfileMetadata() public void BackupProjectSettings_DefaultValues() { var settings = new DummyBackupProjectSettings("whatever", "Blah", null, FDOBackendProviderType.kXML); - Assert.AreEqual(DirectoryFinder.DefaultBackupDirectory, settings.DestinationFolder); + Assert.AreEqual(FwDirectoryFinder.DefaultBackupDirectory, settings.DestinationFolder); } /// ------------------------------------------------------------------------------------ @@ -255,7 +257,7 @@ public void BackupProjectSettings_DefaultValues() public void BackupProjectSettings_Values() { var backupSettings = new DummyBackupProjectSettings( - Path.Combine(DirectoryFinder.FwSourceDirectory, "FDO/FDOTests/BackupRestore"), + Path.Combine(FwDirectoryFinder.SourceDirectory, "FDO/FDOTests/BackupRestore"), "FieldWorksLanguageProject", null, FDOBackendProviderType.kXML) { Comment = "Test comment", @@ -280,7 +282,7 @@ public void BackupProjectSettings_Values() public void BackupFileSettings_SerializationAndDeserialization() { var backupSettings = new DummyBackupProjectSettings( - Path.Combine(DirectoryFinder.FwSourceDirectory, "FDO/FDOTests/BackupRestore"), + Path.Combine(FwDirectoryFinder.SourceDirectory, "FDO/FDOTests/BackupRestore"), "FieldWorksLanguageProject", null, FDOBackendProviderType.kXML) { Comment = "Test comment", diff --git a/Src/FDO/FDOTests/BackupRestore/ProjectBackupServiceTestForLinkedFiles.cs b/Src/FDO/FDOTests/BackupRestore/ProjectBackupServiceTestForLinkedFiles.cs index c41318876e..35ef15bc5d 100644 --- a/Src/FDO/FDOTests/BackupRestore/ProjectBackupServiceTestForLinkedFiles.cs +++ b/Src/FDO/FDOTests/BackupRestore/ProjectBackupServiceTestForLinkedFiles.cs @@ -53,7 +53,7 @@ public override void FixtureSetup() { base.FixtureSetup(); var backupRestoreFolder = Path.Combine("FDO",Path.Combine("FDOTests", "BackupRestore")); - m_testProjectsRoot = Path.Combine(DirectoryFinder.FwSourceDirectory, backupRestoreFolder); + m_testProjectsRoot = Path.Combine(FwDirectoryFinder.SourceDirectory, backupRestoreFolder); m_linkedFilesRootDir = Path.Combine(m_testProjectsRoot, "LinkedFilesTestProjectFiles"); } diff --git a/Src/FDO/FDOTests/BackupRestore/ProjectBackupServiceTests.cs b/Src/FDO/FDOTests/BackupRestore/ProjectBackupServiceTests.cs index e949e3b226..870662adb0 100644 --- a/Src/FDO/FDOTests/BackupRestore/ProjectBackupServiceTests.cs +++ b/Src/FDO/FDOTests/BackupRestore/ProjectBackupServiceTests.cs @@ -48,7 +48,7 @@ public override void FixtureSetup() { base.FixtureSetup(); var backupRestoreFolder = Path.Combine("FDO", Path.Combine("FDOTests", "BackupRestore")); - m_testProjectsRoot = Path.Combine(DirectoryFinder.FwSourceDirectory, backupRestoreFolder); + m_testProjectsRoot = Path.Combine(FwDirectoryFinder.SourceDirectory, backupRestoreFolder); } /// ------------------------------------------------------------------------------------ diff --git a/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs b/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs index 77069d085a..c81f2026c1 100644 --- a/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs +++ b/Src/FDO/FDOTests/BackupRestore/ProjectRestoreServiceTests.cs @@ -13,13 +13,11 @@ // --------------------------------------------------------------------------------------------- using System; using System.IO; -using System.Text; using System.Threading; using NUnit.Framework; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.BackupRestore; -using SIL.FieldWorks.Resources; using SIL.Utils; using FwRemoteDatabaseConnector; @@ -34,26 +32,18 @@ public class ProjectRestoreServiceTests : MemoryOnlyBackendProviderBasicTestBase { private ProjectRestoreService m_restoreProjectService; private RestoreProjectSettings m_restoreSettings; - private bool m_fResetSharedProjectValue; /// Setup for db4o client server tests. [TestFixtureSetUp] public void Init() { // Allow db4o client server unit test to work without running the window service. - RemotingServer.Start(); - if (Db4oServerInfo.AreProjectsShared_Internal) - { - m_fResetSharedProjectValue = true; - Db4oServerInfo.AreProjectsShared_Internal = false; - } + RemotingServer.Start(FwDirectoryFinder.RemotingTcpServerConfigFile, FwDirectoryFinder.FdoDirectories, () => false, v => {}); } /// Stop db4o client server. [TestFixtureTearDown] public void UnInit() { - if (m_fResetSharedProjectValue) - Db4oServerInfo.AreProjectsShared_Internal = m_fResetSharedProjectValue; RemotingServer.Stop(); } @@ -63,10 +53,10 @@ public void UnInit() [SetUp] public void Initialize() { - var restoreTestsZipFileDir = Path.Combine(DirectoryFinder.FwSourceDirectory, "FDO", "FDOTests", + var restoreTestsZipFileDir = Path.Combine(FwDirectoryFinder.SourceDirectory, "FDO", "FDOTests", "BackupRestore","RestoreServiceTestsZipFileDir"); - m_restoreSettings = new RestoreProjectSettings() + m_restoreSettings = new RestoreProjectSettings(FwDirectoryFinder.ProjectsDirectory) { Backup = new BackupFileSettings(Path.Combine(restoreTestsZipFileDir, Path.ChangeExtension("TestRestoreFWProject", FdoFileHelper.ksFwBackupFileExtension))), @@ -97,7 +87,8 @@ public void RestoreProject_CreateNew_OnlyDataFileAndWsFiles() { m_restoreSettings.ProjectName = "TestRestoreFWProject 01"; - m_restoreProjectService = new ProjectRestoreService(m_restoreSettings); + m_restoreProjectService = new ProjectRestoreService(m_restoreSettings, new DummyFdoUI(), + FwDirectoryFinder.ConverterConsoleExe, FwDirectoryFinder.DbExe); m_restoreProjectService.RestoreProject(new DummyProgressDlg()); @@ -113,7 +104,8 @@ public void RestoreProject_CreateNew_DataFileAndConfigurationSettings() { m_restoreSettings.ProjectName = "TestRestoreFWProject 01"; m_restoreSettings.IncludeConfigurationSettings = true; - m_restoreProjectService = new ProjectRestoreService(m_restoreSettings); + m_restoreProjectService = new ProjectRestoreService(m_restoreSettings, new DummyFdoUI(), + FwDirectoryFinder.ConverterConsoleExe, FwDirectoryFinder.DbExe); m_restoreProjectService.RestoreProject(new DummyProgressDlg()); @@ -220,7 +212,7 @@ public void RestoreProject_PutLinkedFilesInOldLocation_CancelSelected() private string GetFullVersionOfRelativeNonStdDir(string nonStdLinkedFilesDir) { - return Path.Combine(Directory.GetParent(DirectoryFinder.FwSourceDirectory).ToString(), nonStdLinkedFilesDir); + return Path.Combine(Directory.GetParent(FwDirectoryFinder.SourceDirectory).ToString(), nonStdLinkedFilesDir); } /// @@ -234,7 +226,8 @@ public void RestoreProject_OverwriteOnlyDataRestored() IThreadedProgress progressDlg = new DummyProgressDlg(); m_restoreSettings.IncludeConfigurationSettings = false; - m_restoreProjectService = new ProjectRestoreService(m_restoreSettings); + m_restoreProjectService = new ProjectRestoreService(m_restoreSettings, new DummyFdoUI(), + FwDirectoryFinder.ConverterConsoleExe, FwDirectoryFinder.DbExe); //Restore the project once and do not delete it so that we can restore the project over the previous one. m_restoreProjectService.RestoreProject(progressDlg); diff --git a/Src/FDO/FDOTests/BackupRestore/ProjectRestoreTestService.cs b/Src/FDO/FDOTests/BackupRestore/ProjectRestoreTestService.cs index 7f14c972db..e7e07ea832 100644 --- a/Src/FDO/FDOTests/BackupRestore/ProjectRestoreTestService.cs +++ b/Src/FDO/FDOTests/BackupRestore/ProjectRestoreTestService.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.BackupRestore; namespace SIL.FieldWorks.FDO.FDOTests.BackupRestore @@ -14,7 +15,8 @@ public class ProjectRestoreTestService : ProjectRestoreService /// we don't want to show up in tests (a dialog). /// /// - public ProjectRestoreTestService(RestoreProjectSettings settings) : base(settings) + public ProjectRestoreTestService(RestoreProjectSettings settings) + : base(settings, new DummyFdoUI(), FwDirectoryFinder.ConverterConsoleExe, FwDirectoryFinder.DbExe) { PutFilesInProject = false; SimulateOKResult = true; diff --git a/Src/FDO/FDOTests/CellarTests.cs b/Src/FDO/FDOTests/CellarTests.cs index b61476f7fc..d34064cfa8 100644 --- a/Src/FDO/FDOTests/CellarTests.cs +++ b/Src/FDO/FDOTests/CellarTests.cs @@ -497,7 +497,7 @@ public void AddComplexFeaturesToFeatureSystemAndThenToAFeatureStructure() // Set up the xml fs description XmlDocument doc = new XmlDocument(); - string sFileDir = Path.Combine(DirectoryFinder.FwSourceDirectory, @"FDO/FDOTests/TestData"); + string sFileDir = Path.Combine(FwDirectoryFinder.SourceDirectory, @"FDO/FDOTests/TestData"); string sFile = Path.Combine(sFileDir, "FeatureSystem2.xml"); doc.Load(sFile); diff --git a/Src/FDO/FDOTests/ClientServerServicesTests.cs b/Src/FDO/FDOTests/ClientServerServicesTests.cs index 998cfcc00d..b829da1a0d 100644 --- a/Src/FDO/FDOTests/ClientServerServicesTests.cs +++ b/Src/FDO/FDOTests/ClientServerServicesTests.cs @@ -20,22 +20,25 @@ public class ClientServerServicesTests : BaseTest private Db4oServerInfo m_db4OServerInfo; private string m_oldProjectDirectory; + private bool m_projectShared; private IThreadedProgress m_progress; - private IFdoUI m_ui; - /// [SetUp] public void StartFwRemoteDatabaseConnector() { // Change the Project Directory to some temporary directory to ensure, other units tests don't add projects // which would slow these tests down. - m_oldProjectDirectory = DirectoryFinder.ProjectsDirectory; - DirectoryFinder.ProjectsDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - Directory.CreateDirectory(DirectoryFinder.ProjectsDirectory); + m_oldProjectDirectory = FwDirectoryFinder.ProjectsDirectory; + FwDirectoryFinder.ProjectsDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + Directory.CreateDirectory(FwDirectoryFinder.ProjectsDirectory); + + ClientServerServices.SetCurrentToDb4OBackend(new DummyFdoUI(), FwDirectoryFinder.FdoDirectories, + () => FwDirectoryFinder.ProjectsDirectory == FwDirectoryFinder.ProjectsDirectoryLocalMachine); - RemotingServer.Start(); + m_projectShared = false; + RemotingServer.Start(FwDirectoryFinder.RemotingTcpServerConfigFile, FwDirectoryFinder.FdoDirectories, () => m_projectShared, v => m_projectShared = v); var connectString = String.Format("tcp://{0}:{1}/FwRemoteDatabaseConnector.Db4oServerInfo", "127.0.0.1", Db4OPorts.ServerPort); @@ -45,8 +48,6 @@ public void StartFwRemoteDatabaseConnector() m_db4OServerInfo.AreProjectShared(); m_progress = new DummyProgressDlg(); - - m_ui = new DummyFdoUI(); } /// @@ -55,8 +56,8 @@ public void StopFwRemoteDatabaseConnector() { RemotingServer.Stop(); - Directory.Delete(DirectoryFinder.ProjectsDirectory, true); - DirectoryFinder.ProjectsDirectory = m_oldProjectDirectory; + Directory.Delete(FwDirectoryFinder.ProjectsDirectory, true); + FwDirectoryFinder.ProjectsDirectory = m_oldProjectDirectory; m_db4OServerInfo = null; } @@ -80,7 +81,7 @@ public void ProjectNames_NullServer_ThrowsArgumentExeception() [Test] public void ProjectNames_LocalhostServiceIsRunning_ProjectsReturned() { - ClientServerServices.Current.Local.SetProjectSharing(true, m_progress, m_ui); + ClientServerServices.Current.Local.SetProjectSharing(true, m_progress); using (var db4OServerFile = new TemporaryDb4OServerFile(m_db4OServerInfo)) { @@ -97,9 +98,9 @@ public void ProjectNames_LocalhostServiceIsRunning_ProjectsReturned() [Test] public void ShareMyProjects_TurningShareMyProjectOff_ShareMyProjectsReturnedFalse() { - ClientServerServices.Current.Local.SetProjectSharing(true, m_progress, m_ui); + ClientServerServices.Current.Local.SetProjectSharing(true, m_progress); - Assert.IsTrue(ClientServerServices.Current.Local.SetProjectSharing(false, m_progress, m_ui)); + Assert.IsTrue(ClientServerServices.Current.Local.SetProjectSharing(false, m_progress)); Assert.AreEqual(false, ClientServerServices.Current.Local.ShareMyProjects); } @@ -107,15 +108,15 @@ public void ShareMyProjects_TurningShareMyProjectOff_ShareMyProjectsReturnedFals [Test] public void ShareMyProjects_TurningShareMyProjectOn_ShareMyProjectsReturnedTrue() { - ClientServerServices.Current.Local.SetProjectSharing(false, m_progress, m_ui); + ClientServerServices.Current.Local.SetProjectSharing(false, m_progress); - Assert.IsTrue(ClientServerServices.Current.Local.SetProjectSharing(true, m_progress, m_ui)); + Assert.IsTrue(ClientServerServices.Current.Local.SetProjectSharing(true, m_progress)); Assert.IsTrue(Db4OLocalClientServerServices.LocalDb4OServerInfoConnection.AreProjectShared()); Assert.IsFalse(ClientServerServices.Current.Local.ShareMyProjects, "ShareMyProjects should not be true unless HKCU projects dir same as HKLM"); - var temp = DirectoryFinder.ProjectsDirectory; - DirectoryFinder.ProjectsDirectory = DirectoryFinder.ProjectsDirectoryLocalMachine; + var temp = FwDirectoryFinder.ProjectsDirectory; + FwDirectoryFinder.ProjectsDirectory = FwDirectoryFinder.ProjectsDirectoryLocalMachine; Assert.IsTrue(ClientServerServices.Current.Local.ShareMyProjects); - DirectoryFinder.ProjectsDirectory = temp; + FwDirectoryFinder.ProjectsDirectory = temp; } /// @@ -129,14 +130,14 @@ public void ConvertToCurrentBackend_ConvertFromFwDataToClientServer_ValidFwDataF [Test] public void IdForLocalProject_SimpleNameProjectsAreNotShared_ReturnedFilenameHasFwdataExtenstionAndExistsInProjectDirectory() { - ClientServerServices.Current.Local.SetProjectSharing(false, m_progress, m_ui); + ClientServerServices.Current.Local.SetProjectSharing(false, m_progress); string filename = ClientServerServices.Current.Local.IdForLocalProject("tom"); // Assert ends with .fwdata Assert.AreEqual(FdoFileHelper.ksFwDataXmlFileExtension, Path.GetExtension(filename)); // Check file is in ProjectDirectory. - Assert.That(filename, Is.SubPath(DirectoryFinder.ProjectsDirectory)); + Assert.That(filename, Is.SubPath(FwDirectoryFinder.ProjectsDirectory)); } /// diff --git a/Src/FDO/FDOTests/CmSemanticDomainRepositoryTests.cs b/Src/FDO/FDOTests/CmSemanticDomainRepositoryTests.cs index a6fa5b432c..ed8ef6e531 100644 --- a/Src/FDO/FDOTests/CmSemanticDomainRepositoryTests.cs +++ b/Src/FDO/FDOTests/CmSemanticDomainRepositoryTests.cs @@ -403,7 +403,7 @@ public void FindDomains_TimingOnLargerDataSet() const string expectedNum2 = "8.3.3"; // group3 match 'sunshine', under 'Light' const string expectedName2 = "Light"; const string filePath = @"Templates\semdom.xml"; - var homeDir = DirectoryFinder.FWCodeDirectory; + var homeDir = FwDirectoryFinder.CodeDirectory; LoadSemDomTestDataFromFile(Path.Combine(homeDir, filePath)); // SUT diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000001Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000001Tests.cs index bd2931b390..70d8d4a4d8 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000001Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000001Tests.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Xml.Linq; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -128,7 +129,7 @@ public void DataMigration7000001_and_Delint_Tests() mockMDC.AddClass(3, "Text", "CmObject", new List()); mockMDC.AddClass(4, "WfiWordform", "CmObject", new List()); mockMDC.AddClass(5, "LexSense", "CmObject", new List()); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000000, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000000, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000001, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000002Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000002Tests.cs index e5f8e6fb09..621be816f8 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000002Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000002Tests.cs @@ -16,6 +16,7 @@ using System.Text; using System.Xml.Linq; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -182,7 +183,7 @@ public void DataMigration7000002Test() mockMDC.AddClass(9, "ScrFootnote", "CmObject", new List()); mockMDC.AddClass(10, "ScrTxtPara", "CmObject", new List()); mockMDC.AddClass(11, "StPara", "CmObject", new List { "StTxtPara" }); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000001, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000001, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000002, new DummyProgressDlg()); Assert.AreEqual(7000002, dtoRepos.CurrentModelVersion, "Wrong updated version."); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000003Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000003Tests.cs index 6bc1f1186b..2af15fddc6 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000003Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000003Tests.cs @@ -2,6 +2,7 @@ using System.Text; using System.Xml.Linq; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -91,7 +92,7 @@ public void DataMigration7000003Test() mockMDC.AddClass(9, "ScrFootnote", "CmObject", new List()); mockMDC.AddClass(10, "ScrTxtPara", "CmObject", new List()); mockMDC.AddClass(11, "StPara", "CmObject", new List { "StTxtPara" }); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000002, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000002, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000003, new DummyProgressDlg()); Assert.AreEqual(7000003, dtoRepos.CurrentModelVersion, "Wrong updated version."); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000005Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000005Tests.cs index 2aa7698a9a..737fbf08c9 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000005Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000005Tests.cs @@ -3,6 +3,7 @@ using System.Xml.Linq; using System.Xml.XPath; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -44,7 +45,7 @@ public void DataMigration7000005Test() mockMDC.AddClass(13, "RnAnalysis", "RnGenericRec", new List()); mockMDC.AddClass(14, "CmPerson", "CmPossibility", new List()); mockMDC.AddClass(15, "CmAnthroItem", "CmPossibility", new List()); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000004, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000004, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000005, new DummyProgressDlg()); var nbkDto = dtoRepos.AllInstancesSansSubclasses("RnResearchNbk").First(); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000006Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000006Tests.cs index 5f7d31fd3b..92e632d258 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000006Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000006Tests.cs @@ -3,6 +3,7 @@ using System.Xml.Linq; using System.Xml.XPath; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -29,7 +30,7 @@ public void DataMigration7000006Test() mockMDC.AddClass(1, "CmObject", null, new List { "CmProject" }); mockMDC.AddClass(2, "CmProject", "CmObject", new List { "LangProject" }); mockMDC.AddClass(3, "LangProject", "CmProject", new List()); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000005, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000005, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000006, new DummyProgressDlg()); var cmProjDto = dtoRepos.AllInstancesSansSubclasses("LangProject").First(); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000007Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000007Tests.cs index 650e975df0..0fe6fa831d 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000007Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000007Tests.cs @@ -3,6 +3,7 @@ using System.Xml.Linq; using System.Xml.XPath; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -35,7 +36,7 @@ public void DataMigration7000007Test() mockMDC.AddClass(7, "StTxtPara", "StPara", new List()); mockMDC.AddClass(9, "StFootnote", "StText", new List {"ScrFootnote"}); mockMDC.AddClass(10, "ScrFootnote", "StFootnote", new List()); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000006, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000006, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000007, new DummyProgressDlg()); var ScrInpDto = dtoRepos.AllInstancesSansSubclasses("ScrImportSet").First(); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000008Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000008Tests.cs index 07582429c3..0da1b59962 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000008Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000008Tests.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -33,7 +34,7 @@ public void DataMigration7000008Test() mockMDC.AddClass(2, "LangProject", "CmObject", new List()); mockMDC.AddClass(3, "CmBaseAnnotation", "CmObject", new List { "ScrScriptureNote" }); mockMDC.AddClass(4, "ScrScriptureNote", "CmBaseAnnotation", new List()); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000007, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000007, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000008, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000009Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000009Tests.cs index bd1d01983d..f8e447cafb 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000009Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000009Tests.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Text; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -64,7 +65,7 @@ public void DataMigration7000009Test() mockMDC.AddClass(1, "CmObject", null, new List { "LangProject", "Scripture" }); mockMDC.AddClass(2, "LangProject", "CmObject", new List()); mockMDC.AddClass(4, "Scripture", "CmObject", new List()); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000008, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000008, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000009, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000010Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000010Tests.cs index 9bcefab21e..2e44900f98 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000010Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000010Tests.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Xml.Linq; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -76,7 +77,7 @@ public void DataMigration7000010_AnnotationDefns_Removed_Test() mockMDC.AddClass(3, "CmAnnotationDefn", "CmObject", new List()); mockMDC.AddClass(4, "StText", "CmObject", new List()); mockMDC.AddClass(5, "StTxtPara", "CmObject", new List()); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000009, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000009, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); // Collect the various annotation defns. var annDefnDtos = new Dictionary(); @@ -1160,7 +1161,7 @@ private static IDomainObjectDTORepository SetupMDC(HashSet dtos mockMDC.AddClass(16, "ConstChartMovedTextMarker", "ConstituentChartCellPart", new List()); mockMDC.AddClass(17, "ConstChartClauseMarker", "ConstituentChartCellPart", new List()); mockMDC.AddClass(18, "ConstChartTag", "ConstituentChartCellPart", new List()); - return new DomainObjectDtoRepository(7000009, dtos, mockMDC, null); + return new DomainObjectDtoRepository(7000009, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); } private static void CheckXfics(IDomainObjectDTORepository dtoRepos, diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000011Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000011Tests.cs index 33193000a4..3680fb1552 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000011Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000011Tests.cs @@ -4,7 +4,7 @@ using System.Xml.Linq; using System.Xml.XPath; using NUnit.Framework; - +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -98,7 +98,7 @@ public void DataMigration7000011Test() mockMDC.AddClass(3, "CmPossibilityList", "CmObject", new List()); mockMDC.AddClass(4, "CmPossibility", "CmObject", new List()); mockMDC.AddClass(5, "RnGenericRec", "CmObject", new List()); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000010, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000010, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000011, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000012Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000012Tests.cs index 747ea57112..be6ab580f2 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000012Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000012Tests.cs @@ -1,10 +1,9 @@ -using System; using System.Collections.Generic; -using System.Text; using NUnit.Framework; using System.Linq; using System.Xml.Linq; using System.Xml.XPath; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -56,7 +55,7 @@ public void DataMigration7000012_Unneeded_UserViewField_Removed_Test() var mockMDC = new MockMDCForDataMigration(); mockMDC.AddClass(1, "CmObject", null, new List { "UserViewField" }); mockMDC.AddClass(2, "UserViewField", "CmObject", new List()); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000011, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000011, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); Assert.AreEqual(40, dtoRepos.AllInstancesWithSubclasses("UserViewField").Count()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000013Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000013Tests.cs index 76fb108a07..56982bd5ac 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000013Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000013Tests.cs @@ -3,6 +3,7 @@ using System.Xml.Linq; using System.Xml.XPath; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -95,7 +96,7 @@ private static IDomainObjectDTORepository DoCommonBasics(IEnumerable ext var mockMDC = SetupMDC(); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000012, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000012, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); return dtoRepos; } diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000014Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000014Tests.cs index 434939b523..4b58ea39e1 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000014Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000014Tests.cs @@ -3,6 +3,7 @@ using System.Xml.Linq; using System.Xml.XPath; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -26,7 +27,7 @@ public void DataMigration7000014Test() var mockMDC = SetupMDC(); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000013, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000013, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); // SUT; Do the migration. m_dataMigrationManager.PerformMigration(dtoRepos, 7000014, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000015Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000015Tests.cs index 221ad7122d..b6eef2503d 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000015Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000015Tests.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Xml.Linq; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -25,7 +26,7 @@ public void DataMigration7000015Test() var mockMdc = SetupMdc(); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000014, dtos, mockMdc, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000014, dtos, mockMdc, null, FwDirectoryFinder.FdoDirectories); // SUT: Do the migration. m_dataMigrationManager.PerformMigration(dtoRepos, 7000015, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000016Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000016Tests.cs index aaecec8858..b62a25dc52 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000016Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000016Tests.cs @@ -21,7 +21,7 @@ using System.Xml.XPath; using NUnit.Framework; - +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -63,7 +63,7 @@ public void DataMigration7000016Test() var mockMdc = SetupMdc(); - IDomainObjectDTORepository repoDTO = new DomainObjectDtoRepository(7000015, dtos, mockMdc, null); + IDomainObjectDTORepository repoDTO = new DomainObjectDtoRepository(7000015, dtos, mockMdc, null, FwDirectoryFinder.FdoDirectories); // SUT: Do the migration. m_dataMigrationManager.PerformMigration(repoDTO, 7000016, new DummyProgressDlg()); @@ -123,7 +123,7 @@ public void CheckOnNoPossibilitiesInListAtStart() @"") }; var mockMdc = SetupMdc(); - IDomainObjectDTORepository repoDto = new DomainObjectDtoRepository(7000015, dtos, mockMdc, null); + IDomainObjectDTORepository repoDto = new DomainObjectDtoRepository(7000015, dtos, mockMdc, null, FwDirectoryFinder.FdoDirectories); // SUT: Do the migration. m_dataMigrationManager.PerformMigration(repoDto, 7000016, new DummyProgressDlg()); // Verification Phase diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000017Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000017Tests.cs index 4628bc90aa..dd2212c4a8 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000017Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000017Tests.cs @@ -14,11 +14,9 @@ // // // --------------------------------------------------------------------------------------------- -using System; using System.Collections.Generic; -using System.Text; using NUnit.Framework; -using SIL.FieldWorks.Test.TestUtils; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -43,7 +41,7 @@ public void DeleteWeatherListAndField() var mockMdc = SetupMdc(); - IDomainObjectDTORepository repoDTO = new DomainObjectDtoRepository(7000016, dtos, mockMdc, null); + IDomainObjectDTORepository repoDTO = new DomainObjectDtoRepository(7000016, dtos, mockMdc, null, FwDirectoryFinder.FdoDirectories); // SUT: Do the migration. m_dataMigrationManager.PerformMigration(repoDTO, 7000017, new DummyProgressDlg()); @@ -144,7 +142,7 @@ private void ConvertWeatherToCustomListAndField(string datafile) var mockMdc = SetupMdc(); - IDomainObjectDTORepository repoDTO = new DomainObjectDtoRepository(7000016, dtos, mockMdc, null); + IDomainObjectDTORepository repoDTO = new DomainObjectDtoRepository(7000016, dtos, mockMdc, null, FwDirectoryFinder.FdoDirectories); // SUT: Do the migration. m_dataMigrationManager.PerformMigration(repoDTO, 7000017, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000018Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000018Tests.cs index 6e8a10a710..6e4c6bd5c6 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000018Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000018Tests.cs @@ -18,7 +18,7 @@ using System.Text; using System.Xml.Linq; using NUnit.Framework; - +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; using SIL.Utils; @@ -44,7 +44,7 @@ public void PerformMigration7000018() var mockMdc = SetupMdc(); - IDomainObjectDTORepository repoDTO = new DomainObjectDtoRepository(7000017, dtos, mockMdc, null); + IDomainObjectDTORepository repoDTO = new DomainObjectDtoRepository(7000017, dtos, mockMdc, null, FwDirectoryFinder.FdoDirectories); // SUT: Do the migration. m_dataMigrationManager.PerformMigration(repoDTO, 7000018, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000019Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000019Tests.cs index e887677cd0..cec6515696 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000019Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000019Tests.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; @@ -47,7 +46,7 @@ public void DataMigration7000019Test() IFwMetaDataCacheManaged mockMdc = SetupMdc(); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000018, dtos, mockMdc, Path.GetTempPath()); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000018, dtos, mockMdc, Path.GetTempPath(), FwDirectoryFinder.FdoDirectories); // Do the migration. m_dataMigrationManager.PerformMigration(dtoRepos, 7000019, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000020Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000020Tests.cs index 20ee76368f..7e986c80ea 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000020Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000020Tests.cs @@ -19,7 +19,7 @@ using System.Linq; using NUnit.Framework; - +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; using SIL.FieldWorks.FDO.Infrastructure; @@ -44,7 +44,7 @@ public void DataMigration7000020Test() IFwMetaDataCacheManaged mockMdc = SetupMdc(); IDomainObjectDTORepository repoDto = new DomainObjectDtoRepository(7000019, dtos, mockMdc, - Path.GetTempPath()); + Path.GetTempPath(), FwDirectoryFinder.FdoDirectories); // Initial check that data was read properly. var cObjects = repoDto.AllInstances().Count(); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000022Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000022Tests.cs index f43696fae6..3dd6ed2488 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000022Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000022Tests.cs @@ -4,6 +4,7 @@ using System.Xml.Linq; using System.Xml.XPath; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -39,7 +40,7 @@ public void DataMigration7000022Test() mockMDC.AddClass(5, "RnResearchNbk", "CmMajorObject", new List()); mockMDC.AddClass(6, "LexDb", "CmMajorObject", new List()); mockMDC.AddClass(7, "CmPossibilityList", "CmMajorObject", new List()); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000021, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000021, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); // SUT m_dataMigrationManager.PerformMigration(dtoRepos, 7000022, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000023Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000023Tests.cs index 06bf304299..1936a7a0a2 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000023Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000023Tests.cs @@ -1,9 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Collections.Generic; using System.Xml.Linq; -using System.Xml.XPath; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -38,10 +36,10 @@ public void DataMigration7000023Test() mockMDC.AddClass(6, "CmFilter", "CmObject", new List()); mockMDC.AddClass(7, "UserView", "CmObject", new List()); mockMDC.AddClass(8, "UserAppFeatAct", "CmObject", new List()); - mockMDC.AddClass(9, "CmResource", "CmObject", new List()); ; - mockMDC.AddClass(10, "ScrCheckRun", "CmObject", new List()); ; - mockMDC.AddClass(11, "RnResearchNbk", "CmObject", new List()); ; - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000022, dtos, mockMDC, null); + mockMDC.AddClass(9, "CmResource", "CmObject", new List()); + mockMDC.AddClass(10, "ScrCheckRun", "CmObject", new List()); + mockMDC.AddClass(11, "RnResearchNbk", "CmObject", new List()); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000022, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); //SUT m_dataMigrationManager.PerformMigration(dtoRepos, 7000023, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000024Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000024Tests.cs index 099f9b2e15..5c0e4a2799 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000024Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000024Tests.cs @@ -3,6 +3,7 @@ using System.Xml.Linq; using System.Xml.XPath; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -47,7 +48,7 @@ public void DataMigration7000024Test() mockMDC.AddClass(9, "LexEntry", "CmObject", new List()); mockMDC.AddClass(10, "LexSense", "CmObject", new List()); mockMDC.AddClass(11, "CmPossibility", "CmObject", new List()); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000023, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000023, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000024, new DummyProgressDlg()); //This object should contain a 'Status' property @@ -233,7 +234,7 @@ public void DataMigration7000024Test1() mockMDC.AddClass(5, "RnResearchNbk", "CmMajorObject", new List()); mockMDC.AddClass(6, "RnGenericRec", "CmObject", new List()); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000023, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000023, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000024, new DummyProgressDlg()); //This object should contain a 'Status' property diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000025Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000025Tests.cs index 6e67fbff6b..347d9849eb 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000025Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000025Tests.cs @@ -1,9 +1,8 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Xml.Linq; -using System.Xml.XPath; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -98,7 +97,7 @@ public void DataMigration7000025Test() mockMdc.AddClass(13, "RnGenericRec", "CmObject", new List()); mockMdc.AddClass(14, "ScrDraft", "CmObject", new List()); mockMdc.AddClass(15, "ScrCheckRun", "CmObject", new List()); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000024, dtos, mockMdc, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000024, dtos, mockMdc, null, FwDirectoryFinder.FdoDirectories); // SUT m_dataMigrationManager.PerformMigration(dtoRepos, 7000025, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000026Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000026Tests.cs index d3393ae0d0..3f19bb81f8 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000026Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000026Tests.cs @@ -3,6 +3,7 @@ using System.Xml.Linq; using System.Xml.XPath; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -31,7 +32,7 @@ public void DataMigration7000026Test() mockMDC.AddClass(2, "CmProject", "CmObject", new List { "LangProject" }); mockMDC.AddClass(3, "LangProject", "CmProject", new List()); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000025, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000025, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); //Before the migration there should be a ExtLinkRootDir element in the project. var langProjDto = dtoRepos.AllInstancesSansSubclasses("LangProject").First(); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000027Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000027Tests.cs index a47338e9b5..c63a054f2f 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000027Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000027Tests.cs @@ -15,6 +15,7 @@ using System.Text; using System.Xml.Linq; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -158,7 +159,7 @@ public void DataMigration7000027Test() mockMDC.AddClass(9, "ScrFootnote", "StFootnote", new List()); mockMDC.AddClass(10, "ScrTxtPara", "StTxtPara", new List()); mockMDC.AddClass(11, "StPara", "CmObject", new List { "StTxtPara" }); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000026, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000026, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000027, new DummyProgressDlg()); Assert.AreEqual(7000027, dtoRepos.CurrentModelVersion, "Wrong updated version."); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000028Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000028Tests.cs index fb8efc203a..7f63610d55 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000028Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000028Tests.cs @@ -3,6 +3,7 @@ using System.Xml.Linq; using System.Xml.XPath; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -33,7 +34,7 @@ public void DataMigration7000028Test() mockMDC.AddClass(4, "LexDb", "CmObject", new List ()); mockMDC.AddClass(5, "LexEntry", "CmObject", new List()); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000027, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000027, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000028, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000029Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000029Tests.cs index 3340e58b10..2e93c0b428 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000029Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000029Tests.cs @@ -4,6 +4,7 @@ using System.Xml.Linq; using System.Xml.XPath; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; using SIL.Utils; @@ -54,7 +55,7 @@ public void DataMigration7000029Test() mockMDC.AddClass(10, "CmFile", "CmObject", new List()); //-------------------+++++++++++++++++++++++++= - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000028, dtos, mockMDC, @"C:\FwWW\DistFiles\Projects\Sena 3"); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000028, dtos, mockMDC, @"C:\FwWW\DistFiles\Projects\Sena 3", FwDirectoryFinder.FdoDirectories); //Get the Element var langProjDto = dtoRepos.AllInstancesSansSubclasses("LangProject").First(); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000030Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000030Tests.cs index 6a4e36cc09..1ac8a2123a 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000030Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000030Tests.cs @@ -6,6 +6,7 @@ using System.Xml.XPath; using NUnit.Framework; using SIL.CoreImpl; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; using SIL.Utils; @@ -71,7 +72,7 @@ public void DataMigration7000030Test() //-------------------+++++++++++++++++++++++++= - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000029, dtos, mockMDC, @"C:\FwWW\DistFiles\Projects\Sena 3"); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000029, dtos, mockMDC, @"C:\FwWW\DistFiles\Projects\Sena 3", FwDirectoryFinder.FdoDirectories); //Get the Element diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000031Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000031Tests.cs index 8639af0bbd..9fc5383255 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000031Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000031Tests.cs @@ -1,5 +1,6 @@ using System.Linq; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; using SIL.FieldWorks.FDO.Infrastructure; using System.IO; @@ -26,7 +27,7 @@ public void DataMigration7000031Test() IFwMetaDataCacheManaged mockMdc = DataMigrationTests7000020.SetupMdc(); IDomainObjectDTORepository repoDto = new DomainObjectDtoRepository(7000030, dtos, mockMdc, - Path.GetTempPath()); + Path.GetTempPath(), FwDirectoryFinder.FdoDirectories); // Initial check that data was read properly. var cObjects = repoDto.AllInstances().Count(); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000032Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000032Tests.cs index 8318692a35..0ef6ab3188 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000032Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000032Tests.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using NUnit.Framework; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; @@ -28,7 +27,7 @@ public void DataMigration7000032Test() IFwMetaDataCacheManaged mockMdc = DataMigrationTests7000020.SetupMdc(); IDomainObjectDTORepository repoDto = new DomainObjectDtoRepository(7000030, dtos, mockMdc, - Path.Combine(Path.GetTempPath(), "Wildly-testing_Away~Migration7000032")); + Path.Combine(Path.GetTempPath(), "Wildly-testing_Away~Migration7000032"), FwDirectoryFinder.FdoDirectories); var projectFolder = repoDto.ProjectFolder; var projectName = Path.GetFileNameWithoutExtension(projectFolder); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000033Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000033Tests.cs index 507df6ab6e..8197bbb6b0 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000033Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000033Tests.cs @@ -1,6 +1,4 @@ -using System; -using System.Linq; -using System.Xml; +using System.Linq; using System.Xml.Linq; using NUnit.Framework; using SIL.FieldWorks.Common.FwUtils; @@ -30,7 +28,7 @@ public void DataMigration7000032Test() IFwMetaDataCacheManaged mockMdc = DataMigrationTests7000020.SetupMdc(); IDomainObjectDTORepository repoDto = new DomainObjectDtoRepository(7000032, dtos, mockMdc, - Path.GetTempPath()); + Path.GetTempPath(), FwDirectoryFinder.FdoDirectories); var projectFolder = repoDto.ProjectFolder; var projectName = Path.GetFileNameWithoutExtension(projectFolder); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000034Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000034Tests.cs index c6ffdba512..e80784720e 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000034Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000034Tests.cs @@ -47,7 +47,7 @@ public void DataMigration7000034Test() mockMDC.AddClass(9, "CmFolder", "CmObject", new List()); mockMDC.AddClass(10, "CmFile", "CmObject", new List()); IDomainObjectDTORepository repoDto = new DomainObjectDtoRepository(7000033, dtos, mockMDC, - Path.GetTempPath()); + Path.GetTempPath(), FwDirectoryFinder.FdoDirectories); // Do the migration. m_dataMigrationManager.PerformMigration(repoDto, 7000034, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000035Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000035Tests.cs index 6f3c374a05..8a42f68413 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000035Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000035Tests.cs @@ -15,6 +15,7 @@ using System.Text; using System.Xml.Linq; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -165,7 +166,7 @@ public void DataMigration7000035Test() mockMDC.AddClass(9, "ScrFootnote", "StFootnote", new List()); mockMDC.AddClass(10, "ScrTxtPara", "StTxtPara", new List()); mockMDC.AddClass(11, "StPara", "CmObject", new List { "StTxtPara" }); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000034, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000034, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000035, new DummyProgressDlg()); Assert.AreEqual(7000035, dtoRepos.CurrentModelVersion, "Wrong updated version."); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000036Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000036Tests.cs index 2cf19b9c1d..44c571ec4a 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000036Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000036Tests.cs @@ -16,6 +16,7 @@ using System.Text; using System.Xml.Linq; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; using System; using SIL.FieldWorks.FDO.DomainImpl; @@ -177,7 +178,7 @@ public void DataMigration7000036Test() mockMDC.AddClass(10, "ScrTxtPara", "StTxtPara", new List()); mockMDC.AddClass(11, "StPara", "CmObject", new List { "StTxtPara" }); mockMDC.AddClass(12, "StJounalText", "StText", new List()); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000035, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000035, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); DateTime beforeMigration = DateTime.Now.AddSeconds(-1); // avoid tick problem diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000037Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000037Tests.cs index 1951f3b2a9..c5351232cd 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000037Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000037Tests.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text; using System.Web; using System.Xml.Linq; using System.Xml.XPath; @@ -40,7 +39,7 @@ public void DataMigration7000037Test() mockMDC.AddClass(16, "StTxtPara", "StPara", new List()); IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000036, dtos, mockMDC, - FileUtils.ChangePathToPlatform("C:\\WW\\DistFiles\\Projects\\TokPisin")); + FileUtils.ChangePathToPlatform("C:\\WW\\DistFiles\\Projects\\TokPisin"), FwDirectoryFinder.FdoDirectories); // Check that the version is correct. Assert.AreEqual(7000036, dtoRepos.CurrentModelVersion, "Wrong original version."); // Collect the link values that shouldn't change. diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000040Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000040Tests.cs index 24ec9a9d2c..70bdb87e0b 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000040Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000040Tests.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Web; using System.Xml.Linq; using System.Xml.XPath; @@ -40,7 +39,7 @@ public void DataMigration7000040Test() mockMDC.AddClass(3, "LexEntry", "CmObject", new List()); IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000039, dtos, mockMDC, - FileUtils.ChangePathToPlatform("C:\\WW\\DistFiles\\Projects\\TokPisin")); + FileUtils.ChangePathToPlatform("C:\\WW\\DistFiles\\Projects\\TokPisin"), FwDirectoryFinder.FdoDirectories); // Do Migration m_dataMigrationManager.PerformMigration(dtoRepos, 7000040, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000041Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000041Tests.cs index 1227cf8cc2..e3ac57ee6b 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000041Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000041Tests.cs @@ -1,14 +1,9 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Web; using System.Xml.Linq; -using System.Xml.XPath; using NUnit.Framework; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; -using SIL.Utils; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests { @@ -49,7 +44,7 @@ public void DataMigration7000041Test() private void TryThisProject(HashSet dtos, MockMDCForDataMigration mockMDC, int numOfPubs) { IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000040, dtos, mockMDC, - @"C:\Path\Not\Used"); + @"C:\Path\Not\Used", FwDirectoryFinder.FdoDirectories); // Do Migration m_dataMigrationManager.PerformMigration(dtoRepos, 7000041, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000042Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000042Tests.cs index f06e76aab6..c746d2561c 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000042Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000042Tests.cs @@ -163,7 +163,7 @@ private void VerifyMigration(HashSet dtos) // Create the DTO repository. IDomainObjectDTORepository repoDto = new DomainObjectDtoRepository(7000041, dtos, mockMDC, - FileUtils.ChangePathToPlatform("C:\\WW\\DistFiles\\Projects\\TokPisin")); + FileUtils.ChangePathToPlatform("C:\\WW\\DistFiles\\Projects\\TokPisin"), FwDirectoryFinder.FdoDirectories); // Do Migration m_dataMigrationManager.PerformMigration(repoDto, 7000042, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000044Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000044Tests.cs index 4e58ccc65e..f4f3afa06c 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000044Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000044Tests.cs @@ -75,7 +75,7 @@ public void DataMigration7000044Test() var projectFolder = Path.GetTempPath(); var storePath = Path.Combine(projectFolder, FdoFileHelper.ksWritingSystemsDir); PrepareStore(storePath); - var testDataPath = Path.Combine(DirectoryFinder.FwSourceDirectory, "FDO/FDOTests/TestData"); + var testDataPath = Path.Combine(FwDirectoryFinder.SourceDirectory, "FDO/FDOTests/TestData"); var testEnglishPath = Path.Combine(storePath, "en.ldml"); File.Copy(Path.Combine(testDataPath, "en_7000043.ldml"), testEnglishPath); File.SetAttributes(testEnglishPath, FileAttributes.Normal); // don't want to copy readonly property. @@ -107,7 +107,7 @@ public void DataMigration7000044Test() var sampleSettings = Path.Combine(settingsFolder, "db$local$Settings.xml"); File.WriteAllText(sampleSettings, sampleLocalSettingsData, Encoding.UTF8); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000043, dtos, mockMDC, projectFolder); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000043, dtos, mockMDC, projectFolder, FwDirectoryFinder.FdoDirectories); // Do the migration. m_dataMigrationManager.PerformMigration(dtoRepos, 7000044, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000047Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000047Tests.cs index f3534b2056..b36964bcbd 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000047Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000047Tests.cs @@ -14,6 +14,7 @@ using System.Collections.Generic; using System.Text; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -122,7 +123,7 @@ public void DataMigration7000047Test() mockMDC.AddClass(5, "ChkTerm", "CmObject", new List()); mockMDC.AddClass(6, "CkRendering", "CmObject", new List()); mockMDC.AddClass(7, "WfiWordform", "CmObject", new List()); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000046, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000046, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000047, new DummyProgressDlg()); Assert.AreEqual(7000047, dtoRepos.CurrentModelVersion, "Wrong updated version."); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000051Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000051Tests.cs index d31a960251..cb73166f9b 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000051Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000051Tests.cs @@ -16,6 +16,7 @@ using System.Text; using System.Xml.Linq; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -58,7 +59,7 @@ public void DataMigration7000051Test() mockMDC.AddClass(1, "CmObject", null, new List { "LangProject", "CmPossibilityList" }); // Not true, but no matter. mockMDC.AddClass(2, "LangProject", "CmObject", new List()); mockMDC.AddClass(3, "CmPossibilityList", "CmObject", new List()); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000050, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000050, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000051, new DummyProgressDlg()); Assert.AreEqual(7000051, dtoRepos.CurrentModelVersion, "Wrong updated version."); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000052Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000052Tests.cs index 2f19919a9b..17601f75bf 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000052Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000052Tests.cs @@ -16,6 +16,7 @@ using System.Text; using System.Xml.Linq; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -82,7 +83,7 @@ public void DataMigration7000052Test() mockMDC.AddClass(1, "CmObject", null, new List { "WfiMorphBundle", "MoAffixAllomorph" }); // Not true, but no matter. mockMDC.AddClass(2, "WfiMorphBundle", "CmObject", new List()); mockMDC.AddClass(3, "MoAffixAllomorph", "CmObject", new List()); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000051, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000051, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000052, new DummyProgressDlg()); Assert.AreEqual(7000052, dtoRepos.CurrentModelVersion, "Wrong updated version."); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000056Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000056Tests.cs index 54b37695a2..ef950b76ad 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000056Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000056Tests.cs @@ -16,6 +16,7 @@ using System.Text; using System.Xml.Linq; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -38,7 +39,7 @@ public void DataMigration7000056Test() var dtos = DataMigrationTestServices.ParseProjectFile("DataMigration7000056.xml"); // Set up mock MDC. var mockMDC = new MockMDCForDataMigration(); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000055, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000055, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000056, new DummyProgressDlg()); Assert.AreEqual(7000056, dtoRepos.CurrentModelVersion, "Wrong updated version."); @@ -65,7 +66,7 @@ public void DataMigration7000056Test() sb.Length = 0; mockMDC = new MockMDCForDataMigration(); - dtoRepos = new DomainObjectDtoRepository(7000055, dtos, mockMDC, null); + dtoRepos = new DomainObjectDtoRepository(7000055, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000056, new DummyProgressDlg()); Assert.AreEqual(7000056, dtoRepos.CurrentModelVersion, "Wrong updated version."); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000057Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000057Tests.cs index 38923233e1..1e7a2ed704 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000057Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000057Tests.cs @@ -15,6 +15,7 @@ using System.Xml.Linq; using System.Xml.XPath; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -45,7 +46,7 @@ public void DataMigration7000057Test_Normal() var dtos = DataMigrationTestServices.ParseProjectFile("DataMigration7000057_Normal.xml"); // Set up mock MDC. var mockMdc = new MockMDCForDataMigration(); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000056, dtos, mockMdc, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000056, dtos, mockMdc, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000057, new DummyProgressDlg()); Assert.AreEqual(7000057, dtoRepos.CurrentModelVersion, "Wrong updated version."); @@ -99,7 +100,7 @@ public void DataMigration7000057Test_SubInflTypes() var dtos = DataMigrationTestServices.ParseProjectFile("DataMigration7000057_SubInflTypes.xml"); // Set up mock MDC. var mockMdc = new MockMDCForDataMigration(); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000056, dtos, mockMdc, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000056, dtos, mockMdc, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000057, new DummyProgressDlg()); Assert.AreEqual(7000057, dtoRepos.CurrentModelVersion, "Wrong updated version."); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000058Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000058Tests.cs index 4cc0c4731f..bf21c0add3 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000058Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000058Tests.cs @@ -15,6 +15,7 @@ using System.Xml.Linq; using System.Xml.XPath; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -42,7 +43,7 @@ public void DataMigration7000058Test_FillEmptyGlossAppend() var dtos = DataMigrationTestServices.ParseProjectFile("DataMigration7000058_EmptyGlossAppend.xml"); // Set up mock MDC. var mockMdc = new MockMDCForDataMigration(); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000057, dtos, mockMdc, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000057, dtos, mockMdc, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000058, new DummyProgressDlg()); Assert.AreEqual(7000058, dtoRepos.CurrentModelVersion, "Wrong updated version."); @@ -76,7 +77,7 @@ public void DataMigration7000058Test_SkipNonEmptyGlossAppend() var dtos = DataMigrationTestServices.ParseProjectFile("DataMigration7000058_NonEmptyGlossAppend.xml"); // Set up mock MDC. var mockMdc = new MockMDCForDataMigration(); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000057, dtos, mockMdc, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000057, dtos, mockMdc, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000058, new DummyProgressDlg()); Assert.AreEqual(7000058, dtoRepos.CurrentModelVersion, "Wrong updated version."); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000059Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000059Tests.cs index 697170797c..86817f9389 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000059Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000059Tests.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Xml.Linq; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -35,7 +36,7 @@ public void DataMigration7000059Test() mockMDC.AddClass(6, "Text", "CmMajorObject", new List()); mockMDC.AddClass(7, "RnGenericRec", "CmObject", new List ()); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000058, dtos, mockMDC, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000058, dtos, mockMDC, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000059, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000060Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000060Tests.cs index 313d268b02..791ffd56cf 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000060Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000060Tests.cs @@ -1,8 +1,6 @@ using System.Collections.Generic; using System.IO; -using System.Linq; using System.Text; -using System.Xml.Linq; using NUnit.Framework; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; @@ -40,7 +38,7 @@ public void DataMigration7000060Test() var mockMDC = new MockMDCForDataMigration(); // no classes to migrate here var dtos = new HashSet(); // no objects to migrate - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000059, dtos, mockMDC, projectFolder); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000059, dtos, mockMDC, projectFolder, FwDirectoryFinder.FdoDirectories); // Do the migration. m_dataMigrationManager.PerformMigration(dtoRepos, 7000060, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000061Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000061Tests.cs index ea77e9415f..cd8ac4a536 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000061Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000061Tests.cs @@ -4,6 +4,7 @@ using System.Xml.Linq; using NUnit.Framework; using SIL.CoreImpl; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -42,7 +43,7 @@ public void DataMigration7000061Test() mockMdc.AddField(6001, "StemName", CellarPropertyType.ReferenceAtomic, 7); var dtos = DataMigrationTestServices.ParseProjectFile("DataMigration7000061.xml"); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000060, dtos, mockMdc, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000060, dtos, mockMdc, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000061, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000062Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000062Tests.cs index 4c8917b486..8136b8e474 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000062Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000062Tests.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Xml.Linq; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -26,7 +27,7 @@ public void DataMigration7000062Test() mockMdc.AddClass(4, "CmResource", "CmObject", new List()); var dtos = DataMigrationTestServices.ParseProjectFile("DataMigration7000062.xml"); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000061, dtos, mockMdc, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000061, dtos, mockMdc, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000062, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000063Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000063Tests.cs index 529f9f5f4b..f9377e411f 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000063Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000063Tests.cs @@ -15,6 +15,7 @@ using System.Linq; using System.Xml.Linq; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -38,7 +39,7 @@ public void DataMigration7000063Test() mockMdc.AddClass(2, "LangProject", "CmObject", new List()); var dtos = DataMigrationTestServices.ParseProjectFile("DataMigration7000063.xml"); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000062, dtos, mockMdc, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000062, dtos, mockMdc, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000063, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000065Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000065Tests.cs index fb030e9248..2fbee8a2eb 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000065Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000065Tests.cs @@ -15,6 +15,7 @@ using System.Linq; using System.Xml.Linq; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -43,7 +44,7 @@ public void DataMigration7000065Test() mockMdc.AddClass(7, "PartOfSpeech", "CmPossibility", new List()); var dtos = DataMigrationTestServices.ParseProjectFile("DataMigration7000065.xml"); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000064, dtos, mockMdc, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000064, dtos, mockMdc, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000065, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000066Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000066Tests.cs index 3baaacb4b3..436e2dd7fc 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000066Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000066Tests.cs @@ -17,6 +17,7 @@ using System.Xml.Linq; using NUnit.Framework; using SIL.CoreImpl; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -62,7 +63,7 @@ public void AllRegularBasicDataPropertiesExistAfterDataMigration66() mockMdc.AddField(++currentFlid, "NewTimeProperty", CellarPropertyType.Time, 0); var dtos = DataMigrationTestServices.ParseProjectFile("DataMigration7000066_RegularPropertyMagnet.xml"); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000065, dtos, mockMdc, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000065, dtos, mockMdc, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000066, new DummyProgressDlg()); @@ -126,7 +127,7 @@ public void AllInheritedRegularBasicDataPropertiesExistAfterDataMigration66() mockMdc.AddField(++currentFlid, "NewTimeProperty", CellarPropertyType.Time, 0); var dtos = DataMigrationTestServices.ParseProjectFile("DataMigration7000066_RegularPropertyMagnet.xml"); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000065, dtos, mockMdc, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000065, dtos, mockMdc, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000066, new DummyProgressDlg()); @@ -190,7 +191,7 @@ public void AllCustomBasicDataPropertiesExistAfterDataMigration66() var missingTimeFlid = mockMdc.AddCustomField("CustomPropertyMagnet", "NewTimeProperty", CellarPropertyType.Time, 0); var dtos = DataMigrationTestServices.ParseProjectFile("DataMigration7000066_CustomPropertyMagnet.xml"); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000065, dtos, mockMdc, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000065, dtos, mockMdc, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000066, new DummyProgressDlg()); @@ -248,7 +249,7 @@ public void AllInheritedCustomBasicDataPropertiesExistAfterDataMigration66() var missingTimeFlid = mockMdc.AddCustomField("CmObject", "NewTimeProperty", CellarPropertyType.Time, 0); var dtos = DataMigrationTestServices.ParseProjectFile("DataMigration7000066_CustomPropertyMagnet.xml"); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000065, dtos, mockMdc, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000065, dtos, mockMdc, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000066, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000067Tests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000067Tests.cs index 9ed18e2755..8a1af61891 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000067Tests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigration7000067Tests.cs @@ -3,6 +3,7 @@ using System.Xml.Linq; using NUnit.Framework; using SIL.CoreImpl; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -35,7 +36,7 @@ public void UniElementPropertiesAreRemoved() mockMdc.AddClass(4, "ClassWithInheritedUnicodeProperties", "AbstractClassWithUnicodeProperties", new List()); var dtos = DataMigrationTestServices.ParseProjectFile("DataMigration7000067TestData.xml"); - IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000066, dtos, mockMdc, null); + IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7000066, dtos, mockMdc, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000067, new DummyProgressDlg()); diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigrationBasicTests.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigrationBasicTests.cs index 93e8f4a11c..972b17b67e 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigrationBasicTests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigrationBasicTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; namespace SIL.FieldWorks.FDO.FDOTests.DataMigrationTests @@ -34,7 +35,7 @@ public void DowngradeMigrationTest() { var mockMDC = new MockMDCForDataMigration(); IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(7100000, - new HashSet(), mockMDC, null); + new HashSet(), mockMDC, null, FwDirectoryFinder.FdoDirectories); m_dataMigrationManager.PerformMigration(dtoRepos, 7000000, null); } diff --git a/Src/FDO/FDOTests/DataMigrationTests/DataMigrationTestServices.cs b/Src/FDO/FDOTests/DataMigrationTests/DataMigrationTestServices.cs index 51ec39f79a..758cd6aac4 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/DataMigrationTestServices.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/DataMigrationTestServices.cs @@ -32,7 +32,7 @@ internal static void CheckDtoRemoved(IDomainObjectDTORepository dtoRepos, Domain /// ------------------------------------------------------------------------------------ internal static HashSet ParseProjectFile(string filename) { - var testDataPath = Path.Combine(DirectoryFinder.FwSourceDirectory, "FDO/FDOTests/TestData"); + var testDataPath = Path.Combine(FwDirectoryFinder.SourceDirectory, "FDO/FDOTests/TestData"); var lpElement = XElement.Load(Path.Combine(testDataPath, filename)); return new HashSet( from elem in lpElement.Elements("rt") diff --git a/Src/FDO/FDOTests/DataMigrationTests/IDomainObjectDTORepositoryTests.cs b/Src/FDO/FDOTests/DataMigrationTests/IDomainObjectDTORepositoryTests.cs index 4548801d7a..71e1772c36 100644 --- a/Src/FDO/FDOTests/DataMigrationTests/IDomainObjectDTORepositoryTests.cs +++ b/Src/FDO/FDOTests/DataMigrationTests/IDomainObjectDTORepositoryTests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.DataMigration; using SIL.FieldWorks.FDO.Infrastructure; @@ -45,7 +46,7 @@ public void FixtureSetup() [ExpectedException(typeof(ArgumentNullException))] public void NulldtosParamTest() { - new DomainObjectDtoRepository(1, null, m_mdc, null); + new DomainObjectDtoRepository(1, null, m_mdc, null, FwDirectoryFinder.FdoDirectories); } /// ------------------------------------------------------------------------------------ @@ -58,7 +59,7 @@ public void NulldtosParamTest() public void NullmdcParamTest() { new DomainObjectDtoRepository(1, new HashSet(), - null, null); + null, null, FwDirectoryFinder.FdoDirectories); } /// ------------------------------------------------------------------------------------ @@ -74,7 +75,7 @@ public void NonExistantGuidTest() 1, new HashSet(), m_mdc, - null); + null, FwDirectoryFinder.FdoDirectories); dtoRepos.GetDTO(Guid.NewGuid().ToString()); } @@ -91,7 +92,7 @@ public void ExtantGuidFindsDTOTest() const string lpGuid = "9719A466-2240-4DEA-9722-9FE0746A30A6"; var lpDto = CreatoDTO(dtos, lpGuid, "LangProject", null); IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(1, dtos, - m_mdc, null); + m_mdc, null, FwDirectoryFinder.FdoDirectories); var resultDto = dtoRepos.GetDTO(lpGuid); Assert.AreSame(lpDto, resultDto, "Wrong DTO."); } @@ -109,7 +110,7 @@ public void TryGetValueTests() const string lpGuid = "9719A466-2240-4DEA-9722-9FE0746A30A6"; CreatoDTO(dtos, lpGuid, "LangProject", null); IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(1, dtos, - m_mdc, null); + m_mdc, null, FwDirectoryFinder.FdoDirectories); DomainObjectDTO dto; var retval = dtoRepos.TryGetValue(Guid.NewGuid().ToString().ToLower(), out dto); Assert.IsNull(dto, "Oops.It does exist."); @@ -147,7 +148,7 @@ public void DtosByClassButNoSubclassesTest() const string lpGuid = "9719A466-2240-4DEA-9722-9FE0746A30A6"; CreatoDTO(dtos, lpGuid, "LangProject", null); IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(1, dtos, - m_mdc, null); + m_mdc, null, FwDirectoryFinder.FdoDirectories); var result = new List(dtoRepos.AllInstancesSansSubclasses("CmObject")); Assert.AreEqual(0, result.Count, "Wrong number of DTOs (expected 0)."); result = new List(dtoRepos.AllInstancesSansSubclasses("LangProject")); @@ -169,7 +170,7 @@ public void DtosByClassWithSubclassesTest() const string lexDbGuid = "6C84F84A-5B99-4CF5-A7D5-A308DDC604E0"; CreatoDTO(dtos, lexDbGuid, "LexDb", null); IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(1, dtos, - m_mdc, null); + m_mdc, null, FwDirectoryFinder.FdoDirectories); var result = new List(dtoRepos.AllInstancesWithSubclasses("CmObject")); Assert.AreEqual(2, result.Count, "Wrong number of DTOs (expected 2)."); } @@ -189,7 +190,7 @@ public void OwningDtoTest() const string lexDbGuid = "6C84F84A-5B99-4CF5-A7D5-A308DDC604E0"; var ldbDto = CreatoDTO(dtos, lexDbGuid, "LexDb", lpGuid); IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(1, dtos, - m_mdc, null); + m_mdc, null, FwDirectoryFinder.FdoDirectories); Assert.IsNull(dtoRepos.GetOwningDTO(lpDto), "LP has owner?"); var ldbOwner = dtoRepos.GetOwningDTO(ldbDto); @@ -212,7 +213,7 @@ public void AddNewDtoTest() const string lexDbGuid = "6C84F84A-5B99-4CF5-A7D5-A308DDC604E0"; CreatoDTO(dtos, lexDbGuid, "LexDb", null); IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(1, dtos, - m_mdc, null); + m_mdc, null, FwDirectoryFinder.FdoDirectories); // Create new DTO and add it. var newGuid = Guid.NewGuid(); @@ -236,7 +237,7 @@ public void RemoveDtoTest() const string lpGuid = "9719A466-2240-4DEA-9722-9FE0746A30A6"; var lpDto = CreatoDTO(dtos, lpGuid, "LangProject", null); IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(1, dtos, - m_mdc, null); + m_mdc, null, FwDirectoryFinder.FdoDirectories); dtoRepos.Remove(lpDto); Assert.IsTrue(((DomainObjectDtoRepository)dtoRepos).Goners.Contains(lpDto), "Goner not in goners set."); @@ -265,7 +266,7 @@ public void UpdateDtoTest() const string lpGuid = "9719A466-2240-4DEA-9722-9FE0746A30A6"; var lpDto = CreatoDTO(dtos, lpGuid, "LangProject", null); IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(1, dtos, - m_mdc, null); + m_mdc, null, FwDirectoryFinder.FdoDirectories); dtoRepos.Update(lpDto); Assert.IsTrue(((DomainObjectDtoRepository)dtoRepos).Dirtballs.Contains(lpDto), "Dirty DTO not in dirtball set."); @@ -285,7 +286,7 @@ public void UpdateUnknownDtoTest() const string lpGuid = "9719A466-2240-4DEA-9722-9FE0746A30A6"; CreatoDTO(dtos, lpGuid, "LangProject", null); IDomainObjectDTORepository dtoRepos = new DomainObjectDtoRepository(1, dtos, - m_mdc, null); + m_mdc, null, FwDirectoryFinder.FdoDirectories); var newGuid = Guid.NewGuid(); var newby = new DomainObjectDTO(newGuid.ToString(), "LexEntry", ""); diff --git a/Src/FDO/FDOTests/Db4oServerInfoTests.cs b/Src/FDO/FDOTests/Db4oServerInfoTests.cs index c98ff66d59..705b0c4e7d 100644 --- a/Src/FDO/FDOTests/Db4oServerInfoTests.cs +++ b/Src/FDO/FDOTests/Db4oServerInfoTests.cs @@ -178,12 +178,14 @@ public class Db4oServerInfoTests : BaseTest { // Get created a fresh for each unit test private Db4oServerInfo m_db4OServerInfo; + private bool m_sharedProject; /// [SetUp] public void StartFwRemoteDatabaseConnector() { - RemotingServer.Start(); + m_sharedProject = false; + RemotingServer.Start(FwDirectoryFinder.RemotingTcpServerConfigFile, FwDirectoryFinder.FdoDirectories, () => m_sharedProject, v => m_sharedProject = v); var connectString = String.Format("tcp://{0}:{1}/FwRemoteDatabaseConnector.Db4oServerInfo", "localhost", Db4OPorts.ServerPort); @@ -202,13 +204,13 @@ public void StopFwRemoteDatabaseConnector() [Test] public void ListServers_UnknownNumberOfServers_ReturnsAllServersInProjectsDirectory() { - int projectsCount = Directory.GetFiles(DirectoryFinder.ProjectsDirectory, "*" + FdoFileHelper.ksFwDataDb4oFileExtension, + int projectsCount = Directory.GetFiles(FwDirectoryFinder.ProjectsDirectory, "*" + FdoFileHelper.ksFwDataDb4oFileExtension, SearchOption.AllDirectories).Count(); m_db4OServerInfo.RefreshServerList(); Assert.AreEqual(projectsCount, m_db4OServerInfo.ListServers().Count(), - String.Format("ListServer should return all the db4o projects in the DirectoryFinder.ProjectsDirectory : {0}", DirectoryFinder.ProjectsDirectory)); + String.Format("ListServer should return all the db4o projects in the FwDirectoryFinder.ProjectsDirectory : {0}", FwDirectoryFinder.ProjectsDirectory)); } /// diff --git a/Src/FDO/FDOTests/DummyFdoUI.cs b/Src/FDO/FDOTests/DummyFdoUI.cs index 178f6d09cd..7c06698780 100644 --- a/Src/FDO/FDOTests/DummyFdoUI.cs +++ b/Src/FDO/FDOTests/DummyFdoUI.cs @@ -12,7 +12,6 @@ using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using SIL.Utils; -using Microsoft.Win32; namespace SIL.FieldWorks.FDO.FDOTests { @@ -124,10 +123,8 @@ public void ReportException(Exception error, bool isLethal) /// /// Reports duplicate guids to the user /// - /// The application key. - /// The email address. /// The error text. - public void ReportDuplicateGuids(RegistryKey applicationKey, string emailAddress, string errorText) + public void ReportDuplicateGuids(string errorText) { throw new NotImplementedException(); } diff --git a/Src/FDO/FDOTests/FDOTests.csproj b/Src/FDO/FDOTests/FDOTests.csproj index 8659dc2915..38810949b5 100644 --- a/Src/FDO/FDOTests/FDOTests.csproj +++ b/Src/FDO/FDOTests/FDOTests.csproj @@ -330,6 +330,7 @@ + diff --git a/Src/FDO/FDOTests/FdoCacheTests.cs b/Src/FDO/FDOTests/FdoCacheTests.cs index 15ff7d0b2e..bd2aa6b5c1 100644 --- a/Src/FDO/FDOTests/FdoCacheTests.cs +++ b/Src/FDO/FDOTests/FdoCacheTests.cs @@ -42,16 +42,16 @@ public override void FixtureSetup() { base.FixtureSetup(); - m_oldProjectDirectory = DirectoryFinder.ProjectsDirectory; - DirectoryFinder.ProjectsDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - Directory.CreateDirectory(DirectoryFinder.ProjectsDirectory); + m_oldProjectDirectory = FwDirectoryFinder.ProjectsDirectory; + FwDirectoryFinder.ProjectsDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + Directory.CreateDirectory(FwDirectoryFinder.ProjectsDirectory); m_ui = new DummyFdoUI(); try { // Allow db4o client server unit test to work without running the window service. - FwRemoteDatabaseConnector.RemotingServer.Start(); + FwRemoteDatabaseConnector.RemotingServer.Start(FwDirectoryFinder.RemotingTcpServerConfigFile, FwDirectoryFinder.FdoDirectories, () => false, v => {}); } catch (RemotingException e) { @@ -66,8 +66,8 @@ public override void FixtureSetup() public override void FixtureTeardown() { FwRemoteDatabaseConnector.RemotingServer.Stop(); - Directory.Delete(DirectoryFinder.ProjectsDirectory, true); - DirectoryFinder.ProjectsDirectory = m_oldProjectDirectory; + Directory.Delete(FwDirectoryFinder.ProjectsDirectory, true); + FwDirectoryFinder.ProjectsDirectory = m_oldProjectDirectory; base.FixtureTeardown(); } @@ -80,19 +80,19 @@ public override void FixtureTeardown() [ExpectedException(typeof(ArgumentException))] public void CreateNewLangProject_DbFilesExist() { - var preExistingDirs = new List(Directory.GetDirectories(DirectoryFinder.ProjectsDirectory)); + var preExistingDirs = new List(Directory.GetDirectories(FwDirectoryFinder.ProjectsDirectory)); try { // Setup: Create "pre-existing" DB filenames - using (new DummyFileMaker(Path.Combine(DirectoryFinder.ProjectsDirectory, "Gumby", FdoFileHelper.GetXmlDataFileName("Gumby")))) + using (new DummyFileMaker(Path.Combine(FwDirectoryFinder.ProjectsDirectory, "Gumby", FdoFileHelper.GetXmlDataFileName("Gumby")))) { using (var threadHelper = new ThreadHelper()) - FdoCache.CreateNewLangProj(new DummyProgressDlg(), "Gumby", threadHelper, new DummyFdoUI()); + FdoCache.CreateNewLangProj(new DummyProgressDlg(), "Gumby", FwDirectoryFinder.FdoDirectories, threadHelper); } } finally { - RemoveTestDirs(preExistingDirs, Directory.GetDirectories(DirectoryFinder.ProjectsDirectory)); + RemoveTestDirs(preExistingDirs, Directory.GetDirectories(FwDirectoryFinder.ProjectsDirectory)); } } @@ -106,20 +106,20 @@ public void CreateNewLangProject_DbFilesExist() public void CreateNewLangProject_NameWithSingleQuote() { const string dbName = "!!t'st"; - string dbDir = Path.Combine(DirectoryFinder.ProjectsDirectory, dbName); + string dbDir = Path.Combine(FwDirectoryFinder.ProjectsDirectory, dbName); SureRemoveDb(dbName); - var expectedDirs = new List(Directory.GetDirectories(DirectoryFinder.ProjectsDirectory)) { dbDir }; - var writingSystemsCommonDir = Path.Combine(DirectoryFinder.ProjectsDirectory, FdoFileHelper.ksWritingSystemsDir); + var expectedDirs = new List(Directory.GetDirectories(FwDirectoryFinder.ProjectsDirectory)) { dbDir }; + var writingSystemsCommonDir = Path.Combine(FwDirectoryFinder.ProjectsDirectory, FdoFileHelper.ksWritingSystemsDir); List currentDirs = null; try { string dbFileName; using (var threadHelper = new ThreadHelper()) - dbFileName = FdoCache.CreateNewLangProj(new DummyProgressDlg(), dbName, threadHelper, new DummyFdoUI()); + dbFileName = FdoCache.CreateNewLangProj(new DummyProgressDlg(), dbName, FwDirectoryFinder.FdoDirectories, threadHelper); - currentDirs = new List(Directory.GetDirectories(DirectoryFinder.ProjectsDirectory)); + currentDirs = new List(Directory.GetDirectories(FwDirectoryFinder.ProjectsDirectory)); if (currentDirs.Contains(writingSystemsCommonDir) && !expectedDirs.Contains(writingSystemsCommonDir)) expectedDirs.Add(writingSystemsCommonDir); CollectionAssert.AreEquivalent(expectedDirs, currentDirs); @@ -141,16 +141,16 @@ public void CreateNewLangProject_AnthropologyCategoriesExist() { const string dbName = "AnthropologicalTest"; SureRemoveDb(dbName); - var preExistingDirs = new List(Directory.GetDirectories(DirectoryFinder.ProjectsDirectory)); + var preExistingDirs = new List(Directory.GetDirectories(FwDirectoryFinder.ProjectsDirectory)); try { // create project string dbFileName; using (var threadHelper = new ThreadHelper()) - dbFileName = FdoCache.CreateNewLangProj(new DummyProgressDlg(), dbName, threadHelper, new DummyFdoUI()); + dbFileName = FdoCache.CreateNewLangProj(new DummyProgressDlg(), dbName, FwDirectoryFinder.FdoDirectories, threadHelper); - using (var cache = FdoCache.CreateCacheFromLocalProjectFile(dbFileName, "en", new DummyProgressDlg(), m_ui)) + using (var cache = FdoCache.CreateCacheFromLocalProjectFile(dbFileName, "en", m_ui, FwDirectoryFinder.FdoDirectories, new DummyProgressDlg())) { Assert.AreEqual(Strings.ksAnthropologyCategories, cache.LangProject.AnthroListOA.Name.UiString, "Anthropology Categories list was not properly initialized."); @@ -164,7 +164,7 @@ public void CreateNewLangProject_AnthropologyCategoriesExist() } finally { - RemoveTestDirs(preExistingDirs, Directory.GetDirectories(DirectoryFinder.ProjectsDirectory)); + RemoveTestDirs(preExistingDirs, Directory.GetDirectories(FwDirectoryFinder.ProjectsDirectory)); } } @@ -175,8 +175,8 @@ public void CreateNewLangProject_AnthropologyCategoriesExist() /// name of the FW DB to remove private static void SureRemoveDb(string dbName) { - string dbDir = Path.Combine(DirectoryFinder.ProjectsDirectory, dbName); - var tmpDbDir = Path.Combine(DirectoryFinder.ProjectsDirectory, "..", dbName); + string dbDir = Path.Combine(FwDirectoryFinder.ProjectsDirectory, dbName); + var tmpDbDir = Path.Combine(FwDirectoryFinder.ProjectsDirectory, "..", dbName); if (Directory.Exists(dbDir)) { // it might seem strange to move the directory first before deleting it. @@ -220,7 +220,7 @@ public void ChangingLangProjDefaultVernWs_ChangesCacheDefaultVernWs() { using ( var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", m_ui)) + "en", "fr", "en", m_ui, FwDirectoryFinder.FdoDirectories)) { var wsFr = cache.DefaultVernWs; Assert.That(cache.LangProject.DefaultVernacularWritingSystem.Handle, Is.EqualTo(wsFr)); @@ -228,7 +228,7 @@ public void ChangingLangProjDefaultVernWs_ChangesCacheDefaultVernWs() UndoableUnitOfWorkHelper.Do("undoit", "redoit", cache.ActionHandlerAccessor, () => { - WritingSystemServices.FindOrCreateWritingSystem(cache, "de", false, true, out wsObjGerman); + WritingSystemServices.FindOrCreateWritingSystem(cache, FwDirectoryFinder.TemplateDirectory, "de", false, true, out wsObjGerman); Assert.That(cache.DefaultVernWs, Is.EqualTo(wsFr)); cache.LangProject.DefaultVernacularWritingSystem = wsObjGerman; Assert.That(cache.DefaultVernWs, Is.EqualTo(wsObjGerman.Handle)); @@ -253,7 +253,7 @@ public void ChangingLangProjDefaultAnalysisWs_ChangesCacheDefaultAnalWs() { using ( var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", m_ui)) + "en", "fr", "en", m_ui, FwDirectoryFinder.FdoDirectories)) { var wsEn = cache.DefaultAnalWs; Assert.That(cache.LangProject.DefaultAnalysisWritingSystem.Handle, Is.EqualTo(wsEn)); @@ -261,7 +261,7 @@ public void ChangingLangProjDefaultAnalysisWs_ChangesCacheDefaultAnalWs() UndoableUnitOfWorkHelper.Do("undoit", "redoit", cache.ActionHandlerAccessor, () => { - WritingSystemServices.FindOrCreateWritingSystem(cache, "de", true, false, out wsObjGerman); + WritingSystemServices.FindOrCreateWritingSystem(cache, FwDirectoryFinder.TemplateDirectory, "de", true, false, out wsObjGerman); Assert.That(cache.DefaultAnalWs, Is.EqualTo(wsEn)); cache.LangProject.DefaultAnalysisWritingSystem = wsObjGerman; Assert.That(cache.DefaultAnalWs, Is.EqualTo(wsObjGerman.Handle)); @@ -287,7 +287,7 @@ public void ChangingLangProjDefaultPronunciationWs_ChangesCacheDefaultPronunciat { using ( var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", m_ui)) + "en", "fr", "en", m_ui, FwDirectoryFinder.FdoDirectories)) { var wsFr = cache.DefaultPronunciationWs; Assert.That(cache.LangProject.DefaultPronunciationWritingSystem.Handle, Is.EqualTo(wsFr)); @@ -296,7 +296,7 @@ public void ChangingLangProjDefaultPronunciationWs_ChangesCacheDefaultPronunciat UndoableUnitOfWorkHelper.Do("undoit", "redoit", cache.ActionHandlerAccessor, () => { - WritingSystemServices.FindOrCreateWritingSystem(cache, "de", false, true, out wsObjGerman); + WritingSystemServices.FindOrCreateWritingSystem(cache, FwDirectoryFinder.TemplateDirectory, "de", false, true, out wsObjGerman); Assert.That(cache.DefaultPronunciationWs, Is.EqualTo(wsFr)); cache.LangProject.DefaultVernacularWritingSystem = wsObjGerman; cache.LangProject.CurrentPronunciationWritingSystems.Clear(); @@ -311,7 +311,7 @@ public void ChangingLangProjDefaultPronunciationWs_ChangesCacheDefaultPronunciat //Assert.That(cache.DefaultPronunciationWs, Is.EqualTo(wsObjGermanIpa.Handle)); // Unless we clear the list it does not regenerate. - WritingSystemServices.FindOrCreateWritingSystem(cache, "es", false, true, out wsObjSpanish); + WritingSystemServices.FindOrCreateWritingSystem(cache, FwDirectoryFinder.TemplateDirectory, "es", false, true, out wsObjSpanish); // Once we've found a real pronunciation WS, changing the default vernacular should not change it. Assert.That(cache.DefaultPronunciationWs, Is.EqualTo(wsObjGerman.Handle)); }); @@ -348,7 +348,7 @@ public void CacheCheckDisposedTest() { // This can't be in the minimalist class, because it disposes the cache. var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", m_ui); + "en", "fr", "en", m_ui, FwDirectoryFinder.FdoDirectories); // Init backend data provider var dataSetup = cache.ServiceLocator.GetInstance(); dataSetup.LoadDomain(BackendBulkLoadDomain.All); @@ -364,7 +364,7 @@ public void CacheIsDisposedTest() { // This can't be in the minimalist class, because it disposes the cache. var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", m_ui); + "en", "fr", "en", m_ui, FwDirectoryFinder.FdoDirectories); // Init backend data provider var dataSetup = cache.ServiceLocator.GetInstance(); dataSetup.LoadDomain(BackendBulkLoadDomain.All); @@ -380,7 +380,7 @@ public void CacheIsDisposedTest() public void CacheDisposedForFDOObject() { var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", m_ui); + "en", "fr", "en", m_ui, FwDirectoryFinder.FdoDirectories); // Init backend data provider var dataSetup = cache.ServiceLocator.GetInstance(); dataSetup.LoadDomain(BackendBulkLoadDomain.All); @@ -396,7 +396,7 @@ public void CacheDisposedForFDOObject() public void FDOObjectDeleted() { using (var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", m_ui)) + "en", "fr", "en", m_ui, FwDirectoryFinder.FdoDirectories)) { // Init backend data provider var dataSetup = cache.ServiceLocator.GetInstance(); @@ -419,7 +419,7 @@ public void NumberOfRemoteClients_NotClientServer_ReturnsZero() { using ( var cache = FdoCache.CreateCacheWithNewBlankLangProj(new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), - "en", "fr", "en", m_ui)) + "en", "fr", "en", m_ui, FwDirectoryFinder.FdoDirectories)) { Assert.AreEqual(0, cache.NumberOfRemoteClients); } diff --git a/Src/FDO/FDOTests/FdoScriptureTests.cs b/Src/FDO/FDOTests/FdoScriptureTests.cs index c5a61af5ee..c908979b55 100644 --- a/Src/FDO/FDOTests/FdoScriptureTests.cs +++ b/Src/FDO/FDOTests/FdoScriptureTests.cs @@ -18,6 +18,7 @@ using NUnit.Framework; using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Common.ScriptureUtils; using SIL.FieldWorks.Resources; using SIL.Utils; @@ -253,7 +254,8 @@ internal class DummyScrChecksDataSource : ScrChecksDataSource /// The maximum number of identical errors that will /// be allowed for a Scripture check. /// ------------------------------------------------------------------------------------ - public DummyScrChecksDataSource(FdoCache cache, int maxIdenticalErrors) : base(cache, " ") + public DummyScrChecksDataSource(FdoCache cache, int maxIdenticalErrors) : base(cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile) { m_maxIdenticalErrors = maxIdenticalErrors; } @@ -758,7 +760,8 @@ public void AdjustAnnotationReferences_WithQuote() [Test] public void RecordError_ParaContentsToken() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0); Dictionary> bkChkFailedLst = @@ -804,7 +807,8 @@ public void RecordError_ParaContentsToken() [Test] public void RecordError_ParaContentsToken_SecondRun() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 10); Dictionary> bkChkFailedLst = @@ -848,7 +852,8 @@ public void RecordError_ParaContentsToken_SecondRun() [Test] public void RecordError_PictureCaptionToken() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); ScrCheckingToken tok = new DummyPictureCheckingToken(m_scr, Cache.DefaultUserWs, "en"); Dictionary> bkChkFailedLst = @@ -891,7 +896,8 @@ public void RecordError_PictureCaptionToken() [Test] public void RecordError_Duplicate() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0); check.m_ErrorsToReport.Add(new DummyEditorialCheck.DummyError(tok, 5, 8, "Lousy message")); @@ -920,7 +926,8 @@ public void RecordError_Duplicate() [Test] public void RecordError_DuplicateAfterAdjustingReference() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0); tok.MissingStartRef = new BCVRef(tok.StartRef); @@ -1242,7 +1249,8 @@ public void RecordError_ErrorMaxIncreased() [Test] public void RecordError_Duplicate_SameErrorTwiceInVerse() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0); check.m_ErrorsToReport.Add(new DummyEditorialCheck.DummyError(tok, 5, 2, "Lousy message")); @@ -1283,7 +1291,8 @@ public void RecordError_Duplicate_SameErrorTwiceInVerse() [Test] public void RunCheck_ScrCheckRunRecordsWithFixedInconsistency() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0); check.m_ErrorsToReport.Add(new DummyEditorialCheck.DummyError(tok, 5, 2, "Verbification")); @@ -1321,7 +1330,8 @@ public void RunCheck_ScrCheckRunRecordsWithFixedInconsistency() [Test] public void RunCheck_ScrCheckRunRecordsWithOneBookOneCheck() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0); check.m_ErrorsToReport.Add(new DummyEditorialCheck.DummyError(tok, 5, 2, "Verbification")); @@ -1364,7 +1374,8 @@ public void RunCheck_ScrCheckRunRecordsWithOneBookOneCheck() [Test] public void RunCheck_ScrCheckRunRecordsWithOneBookTwoChecks() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); DummyEditorialCheck check1 = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0); check1.m_ErrorsToReport.Add(new DummyEditorialCheck.DummyError(tok, 5, 2, "Verbification")); @@ -1415,7 +1426,8 @@ public void RunCheck_ScrCheckRunRecordsWithOneBookTwoChecks() [Test] public void RunCheck_CorrectedErrorGetsDeleted() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0); check.m_ErrorsToReport.Add(new DummyEditorialCheck.DummyError(tok, 5, 8, "Lousy message")); @@ -1451,7 +1463,8 @@ public void RunCheck_CorrectedErrorGetsDeleted() [Test] public void RecordError_NearDuplicate_DifferByMessage() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0); check.m_ErrorsToReport.Add(new DummyEditorialCheck.DummyError(tok, 5, 8, "Lousy message")); @@ -1486,7 +1499,8 @@ public void RecordError_NearDuplicate_DifferOnlyByParaHvo() BCVRef reference = new BCVRef(1, 2, 3); - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(book, Cache.DefaultVernWs, 0, reference, reference); @@ -1532,7 +1546,8 @@ public void RecordError_NearDuplicate_DifferOnlyByParaHvo() public void RecordError_NearDuplicate_DifferByCheck() { IFdoServiceLocator servloc = Cache.ServiceLocator; - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); ICmAnnotationDefn annDefnChkError = servloc.GetInstance().CheckingError; ICmAnnotationDefn errorCheck1 = servloc.GetInstance().Create( Guid.NewGuid(), annDefnChkError); @@ -1575,7 +1590,8 @@ public void RecordError_NearDuplicate_DifferByStartRef() { BCVRef endRef = new BCVRef(1, 2, 3); - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0, new BCVRef(1, 2, 3), endRef); @@ -1610,7 +1626,8 @@ public void RecordError_NearDuplicate_DifferByEndRef() { BCVRef startRef = new BCVRef(1, 2, 3); - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0, startRef, new BCVRef(1, 2, 3)); @@ -1643,7 +1660,8 @@ public void RecordError_NearDuplicate_DifferByEndRef() [Test] public void RecordError_NearDuplicate_DifferByCitedText() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0); check.m_ErrorsToReport.Add(new DummyEditorialCheck.DummyError(tok, 0, 4, "Message")); @@ -1672,7 +1690,8 @@ public void RecordError_NearDuplicate_DifferByCitedText() [Test] public void GetTextTokens_Chapter0() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); int iExodus = 2; IScrBook exodus = AddBookToMockedScripture(iExodus, "Exodus"); AddTitleToMockedBook(exodus, "Exodus"); @@ -1706,7 +1725,8 @@ public void GetTextTokens_Chapter0() [Test] public void GetTextTokens_WholeBook() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); AddBookToMockedScripture(1, "Genesis"); int iExodus = 2; IScrBook exodus = AddBookToMockedScripture(iExodus, "Exodus"); @@ -1795,7 +1815,8 @@ public void GetTextTokens_FirstChapter() IScrBook exodus = AddBookToMockedScripture(iExodus, "Exodus"); AddTitleToMockedBook(exodus, "Exodus"); - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); IScrSection section = AddSectionToMockedBook(exodus, true); IStTxtPara para = AddParaToMockedText(section.HeadingOA, ScrStyleNames.IntroSectionHead); AddRunToMockedPara(para, "Everything you wanted to know about Exodus but were afraid to ask", null); @@ -1863,7 +1884,8 @@ public void GetTextTokens_DifferentWritingSystem() AddTitleToMockedBook(exodus, "Exodus"); // Get the text (and set the valid characters for each writing system). - var dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + var dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); dataSource.GetText(iExodus, 1); iWs = 0; @@ -1885,7 +1907,8 @@ public void GetTextTokens_DifferentWritingSystem() [Test] public void GetTextTokens_LastChapter() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); AddBookToMockedScripture(1, "Genesis"); int iExodus = 2; IScrBook exodus = AddBookToMockedScripture(iExodus, "Exodus"); @@ -1933,7 +1956,8 @@ public void GetTextTokens_LastChapter() public void GetTextTokens_ChapterStartsAndEndsMidSection() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar")); + ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); AddBookToMockedScripture(1, "Genesis"); int iExodus = 2; IScrBook exodus = AddBookToMockedScripture(iExodus, "Exodus"); diff --git a/Src/FDO/FDOTests/FdoTestBase.cs b/Src/FDO/FDOTests/FdoTestBase.cs index 574579ca4a..2d3c266ac6 100644 --- a/Src/FDO/FDOTests/FdoTestBase.cs +++ b/Src/FDO/FDOTests/FdoTestBase.cs @@ -174,8 +174,8 @@ public virtual void TestTearDown() /// a working FdoCache protected FdoCache BootstrapSystem(IProjectIdentifier projectId, BackendBulkLoadDomain loadType) { - var retval = m_internalRestart ? FdoCache.CreateCacheFromExistingData(projectId, "en", new DummyProgressDlg(), new DummyFdoUI()) : - FdoCache.CreateCacheWithNewBlankLangProj(projectId, "en", "fr", "en", new DummyFdoUI()); + var retval = m_internalRestart ? FdoCache.CreateCacheFromExistingData(projectId, "en", new DummyFdoUI(), FwDirectoryFinder.FdoDirectories, new DummyProgressDlg()) : + FdoCache.CreateCacheWithNewBlankLangProj(projectId, "en", "fr", "en", new DummyFdoUI(), FwDirectoryFinder.FdoDirectories); var dataSetup = retval.ServiceLocator.GetInstance(); dataSetup.LoadDomain(loadType); return retval; diff --git a/Src/FDO/FDOTests/FwCharacterCategorizerTests.cs b/Src/FDO/FDOTests/FwCharacterCategorizerTests.cs index 864078621a..409426f136 100644 --- a/Src/FDO/FDOTests/FwCharacterCategorizerTests.cs +++ b/Src/FDO/FDOTests/FwCharacterCategorizerTests.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using NUnit.Framework; using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.Common.FwUtils; using SILUBS.SharedScrUtils; using SIL.FieldWorks.FDO.DomainServices; @@ -51,7 +52,7 @@ public void SymbolPunctuationOnly() "a\uFFFCb\uFFFCc\uFFFCd\uFFFCe" + "1\uFFFC2\uFFFC3\uFFFC4\uFFFC5" + "'\uFFFC-\uFFFC#" + - "", "Test WS", null, null); + "", "Test WS", null, null, FwDirectoryFinder.LegacyWordformingCharOverridesFile); ILgCharacterPropertyEngine lgCharPropEngineEn = Cache.WritingSystemFactory.get_CharPropEngine( m_wsEn); @@ -73,7 +74,7 @@ public void WordAndPuncs_OverridePunc() "a\uFFFCb\uFFFCc\uFFFCd\uFFFCe\uFFFC." + "1\uFFFC2\uFFFC3\uFFFC4\uFFFC5" + "'\uFFFC-\uFFFC#" + - "", "Test WS", null, null); + "", "Test WS", null, null, FwDirectoryFinder.LegacyWordformingCharOverridesFile); ILgCharacterPropertyEngine lgCharPropEngineEn = Cache.WritingSystemFactory.get_CharPropEngine( m_wsEn); @@ -100,7 +101,7 @@ public void WordAndPuncs_Spaces() "a\uFFFCb\uFFFCc" + "1\uFFFC2\uFFFC3\uFFFC4\uFFFC5" + "-\uFFFCU+0020" + - "", "Test WS", null, null); + "", "Test WS", null, null, FwDirectoryFinder.LegacyWordformingCharOverridesFile); var english = Cache.ServiceLocator.WritingSystemManager.Get("en"); var lgCharPropEngineEn = Cache.WritingSystemFactory.get_CharPropEngine(english.Handle); @@ -126,7 +127,7 @@ public void WordAndPuncs_EmptyString() "a\uFFFCb\uFFFCc" + "1\uFFFC2\uFFFC3\uFFFC4\uFFFC5" + "-\uFFFCU+0020" + - "", "Test WS", null, null); + "", "Test WS", null, null, FwDirectoryFinder.LegacyWordformingCharOverridesFile); var english = Cache.ServiceLocator.WritingSystemManager.Get("en"); var lgCharPropEngineEn = Cache.WritingSystemFactory.get_CharPropEngine( english.Handle); @@ -152,7 +153,7 @@ public void WordAndPuncs_NoOverridePunc() "a\uFFFCb\uFFFCc\uFFFCd\uFFFCe" + "1\uFFFC2\uFFFC3\uFFFC4\uFFFC5" + "'\uFFFC-\uFFFC#" + - "", "Test WS", null, null); + "", "Test WS", null, null, FwDirectoryFinder.LegacyWordformingCharOverridesFile); ILgCharacterPropertyEngine lgCharPropEngineEn = Cache.WritingSystemFactory.get_CharPropEngine( m_wsEn); diff --git a/Src/FDO/FDOTests/LangProjectTests.cs b/Src/FDO/FDOTests/LangProjectTests.cs index 66007fb98f..6a169773d8 100644 --- a/Src/FDO/FDOTests/LangProjectTests.cs +++ b/Src/FDO/FDOTests/LangProjectTests.cs @@ -13,16 +13,9 @@ // -------------------------------------------------------------------------------------------- using System; using System.IO; -using System.Collections; using System.Collections.Generic; -using System.Reflection; -using System.Diagnostics; - using NUnit.Framework; - -using SIL.FieldWorks.FDO; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Test.TestUtils; using SIL.Utils; using SIL.FieldWorks.Common.FwUtils; using SIL.CoreImpl; @@ -185,14 +178,14 @@ public void AddingWritingSystems() public void LinkedFilesRootDirTests() { //test when LinkedFiles is in the project's root folder - var projectFolder = Path.Combine(DirectoryFinder.ProjectsDirectory, "TestProjectName"); + var projectFolder = Path.Combine(FwDirectoryFinder.ProjectsDirectory, "TestProjectName"); var linkedFilesFullPath = Path.Combine(projectFolder, "LinkedFiles"); Cache.LanguageProject.LinkedFilesRootDir = linkedFilesFullPath; var outputLinkedFilesFullPath = Cache.LanguageProject.LinkedFilesRootDir; Assert.True(linkedFilesFullPath.Equals(outputLinkedFilesFullPath)); //test when linked files is in FW Projects folder - linkedFilesFullPath = Path.Combine(DirectoryFinder.ProjectsDirectory, "LinkedFiles"); + linkedFilesFullPath = Path.Combine(FwDirectoryFinder.ProjectsDirectory, "LinkedFiles"); Cache.LanguageProject.LinkedFilesRootDir = linkedFilesFullPath; outputLinkedFilesFullPath = Cache.LanguageProject.LinkedFilesRootDir; Assert.True(linkedFilesFullPath.Equals(outputLinkedFilesFullPath)); diff --git a/Src/FDO/FDOTests/LinkedFilesRelativePathHelperTests.cs b/Src/FDO/FDOTests/LinkedFilesRelativePathHelperTests.cs new file mode 100644 index 0000000000..5184e7d21c --- /dev/null +++ b/Src/FDO/FDOTests/LinkedFilesRelativePathHelperTests.cs @@ -0,0 +1,137 @@ +using System; +using System.IO; +using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; + +namespace SIL.FieldWorks.FDO.FDOTests +{ + /// + /// Test fixture for LinkedFilesRelativePathHelper + /// + [TestFixture] + public class LinkedFilesRelativePathHelperTests + { + /// ------------------------------------------------------------------------------------ + /// + /// Tests the GetLinkedFilesRelativePathFromFullPath method + /// + /// ------------------------------------------------------------------------------------ + [Test] + public void GetLinkedFilesRelativePathFromFullPath() + { + Assert.AreEqual(String.Format("%proj%{0}LinkedFiles", Path.DirectorySeparatorChar), + LinkedFilesRelativePathHelper.GetLinkedFilesRelativePathFromFullPath(FwDirectoryFinder.ProjectsDirectory, String.Format("%proj%{0}LinkedFiles", Path.DirectorySeparatorChar), + Path.Combine(FwDirectoryFinder.SourceDirectory, "FDO/FDOTests/BackupRestore/Project"), + "Project")); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Tests the GetLinkedFilesFullPathFromRelativePath method + /// + /// ------------------------------------------------------------------------------------ + [Test] + public void GetLinkedFilesFullPathFromRelativePath() + { + var projectPath = Path.Combine(FwDirectoryFinder.ProjectsDirectory, "TestProject"); + var linkedFilesRootDir = Path.Combine(projectPath, "LinkedFiles"); + var linkedFilesPath = LinkedFilesRelativePathHelper.GetLinkedFilesFullPathFromRelativePath(FwDirectoryFinder.ProjectsDirectory, + String.Format("%proj%{0}LinkedFiles", Path.DirectorySeparatorChar), projectPath); + + Assert.AreEqual(linkedFilesRootDir, linkedFilesPath); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Tests the GetFullFilePathFromRelativeLFPath method + /// + /// ------------------------------------------------------------------------------------ + [Test] + public void GetFullFilePathFromRelativeLFPath() + { + var linkedFilesRootDir = Path.Combine(Path.Combine(FwDirectoryFinder.ProjectsDirectory, "TestProject"), "LinkedFiles"); + var fullLFPath = LinkedFilesRelativePathHelper.GetFullFilePathFromRelativeLFPath(String.Format("%lf%{0}AudioVisual{0}StarWars.mvi", Path.DirectorySeparatorChar), linkedFilesRootDir); + var audioVisualFile = Path.Combine(Path.Combine(linkedFilesRootDir, "AudioVisual"), "StarWars.mvi"); + Assert.AreEqual(audioVisualFile, fullLFPath); + + //if a fully rooted path is passed in the return value should be null. + var projectRootDir = FwDirectoryFinder.DataDirectory; + fullLFPath = LinkedFilesRelativePathHelper.GetFullFilePathFromRelativeLFPath(projectRootDir, linkedFilesRootDir); + Assert.True(string.IsNullOrEmpty(fullLFPath)); + + } + + /// ------------------------------------------------------------------------------------ + /// + /// Tests the GetRelativeLFPathFromFullFilePath method + /// + /// ------------------------------------------------------------------------------------ + [Test] + public void GetRelativeLFPathFromFullFilePath() + { + var linkedFilesRootDir = Path.Combine(Path.Combine(FwDirectoryFinder.ProjectsDirectory, "TestProject"), "LinkedFiles"); + var audioVisualFile = Path.Combine(Path.Combine(linkedFilesRootDir, "AudioVisual"), "StarWars.mvi"); + var relativeLFPath = LinkedFilesRelativePathHelper.GetRelativeLFPathFromFullFilePath(audioVisualFile, linkedFilesRootDir); + Assert.AreEqual(String.Format("%lf%{0}AudioVisual{0}StarWars.mvi", Path.DirectorySeparatorChar), relativeLFPath); + + //Ensure empty string is returned when the path is not relative to the LinkedFiles directory. + var pathNotUnderLinkedFiles = Path.Combine(FwDirectoryFinder.DataDirectory, "LordOfTheRings.mvi"); + relativeLFPath = LinkedFilesRelativePathHelper.GetRelativeLFPathFromFullFilePath(pathNotUnderLinkedFiles, linkedFilesRootDir); + Assert.True(string.IsNullOrEmpty(relativeLFPath)); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Tests the GetRelativeLinkedFilesPath method + /// + /// ------------------------------------------------------------------------------------ + [Test] + public void GetRelativeLinkedFilesPath() + { + var linkedFilesRootDir = Path.Combine(Path.Combine(FwDirectoryFinder.ProjectsDirectory, "TestProject"), "LinkedFiles"); + var audioVisualFile = Path.Combine(Path.Combine(linkedFilesRootDir, "AudioVisual"), "StarWars.mvi"); + var relativeLFPath = LinkedFilesRelativePathHelper.GetRelativeLinkedFilesPath(audioVisualFile, linkedFilesRootDir); + Assert.True(String.Equals(String.Format("AudioVisual{0}StarWars.mvi", Path.DirectorySeparatorChar), relativeLFPath)); + + //Ensure ORIGINAL path is returned when the path is not relative to the LinkedFiles directory. + var pathNotUnderLinkedFiles = Path.Combine(FwDirectoryFinder.DataDirectory, "LordOfTheRings.mvi"); + relativeLFPath = LinkedFilesRelativePathHelper.GetRelativeLinkedFilesPath(pathNotUnderLinkedFiles, linkedFilesRootDir); + Assert.True(String.Equals(pathNotUnderLinkedFiles,relativeLFPath)); + Assert.That(LinkedFilesRelativePathHelper.GetRelativeLinkedFilesPath( + "silfw:\\localhost\\link?app%3dflex%26database%3dc%3a%5cTestLangProj%5cTestLangProj.fwdata%26server%3d%26tool%3dnaturalClassedit%26guid%3d43c9ba97-2883-4f95-aa5d-ef9309e85025%26tag%3d", + relativeLFPath), Is.Null, "hyperlinks should be left well alone!!"); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Tests the GetFullPathFromRelativeLFPath method + /// + /// ------------------------------------------------------------------------------------ + [Test] + public void GetFullPathFromRelativeLFPath() + { + var linkedFilesRootDir = Path.Combine(Path.Combine(FwDirectoryFinder.ProjectsDirectory, "TestProject"), "LinkedFiles"); + var fullLFPath = LinkedFilesRelativePathHelper.GetFullPathFromRelativeLFPath(String.Format("AudioVisual{0}StarWars.mvi", Path.DirectorySeparatorChar), linkedFilesRootDir); + var audioVisualFile = Path.Combine(Path.Combine(linkedFilesRootDir, "AudioVisual"), "StarWars.mvi"); + Assert.AreEqual(audioVisualFile, fullLFPath); + + //if a fully rooted path is passed in the return value should be the path that was passed in. + var fileUnderProjectRootDir = String.Format("{1}{0}AudioVisual{0}StarWars.mvi", Path.DirectorySeparatorChar, FwDirectoryFinder.DataDirectory); + fullLFPath = LinkedFilesRelativePathHelper.GetFullPathFromRelativeLFPath(fileUnderProjectRootDir, linkedFilesRootDir); + Assert.AreEqual(fullLFPath, fileUnderProjectRootDir); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Tests the GetFullPathFromRelativeLFPath method with illegal characters + /// + /// ------------------------------------------------------------------------------------ + [Test] + public void GetFullPathFromRelativeLFPath_WithIllegalCharacters_ReturnsSpecialPath() + { + var linkedFilesRootDir = Path.Combine(Path.Combine(FwDirectoryFinder.ProjectsDirectory, "TestProject"), "LinkedFiles"); + var fullLFPath = LinkedFilesRelativePathHelper.GetFullPathFromRelativeLFPath("1\";1\"", linkedFilesRootDir); + Assert.That(fullLFPath, Is.EqualTo(Path.Combine(linkedFilesRootDir,"__ILLEGALCHARS__"))); + } + } +} diff --git a/Src/FDO/FDOTests/ParagraphParserTests.cs b/Src/FDO/FDOTests/ParagraphParserTests.cs index fdb9b2738b..836163923b 100644 --- a/Src/FDO/FDOTests/ParagraphParserTests.cs +++ b/Src/FDO/FDOTests/ParagraphParserTests.cs @@ -64,7 +64,7 @@ public object Clone() /// protected string ConfigurationFilePath(string fileRelativePath) { - return Path.Combine(DirectoryFinder.FwSourceDirectory, fileRelativePath); + return Path.Combine(FwDirectoryFinder.SourceDirectory, fileRelativePath); } /// @@ -543,7 +543,7 @@ virtual public IWfiWordform SetAlternateCase(int iSegment, int iSegForm, StringC ITsString tssWordformBaseline = GetBaselineText(iSegment, iSegForm); // Add any relevant 'other case' forms. int nvar; - int ws = tssWordformBaseline.get_Properties(0).GetIntPropValues((int)FwTextPropType.ktptWs, out nvar); ; + int ws = tssWordformBaseline.get_Properties(0).GetIntPropValues((int)FwTextPropType.ktptWs, out nvar); string locale = m_cache.ServiceLocator.WritingSystemManager.Get(ws).IcuLocale; var cf = new CaseFunctions(locale); switch (targetState) @@ -2435,7 +2435,7 @@ void SetupOldWordformingOverrides() { IWritingSystem wsObj = Cache.ServiceLocator.WritingSystems.DefaultVernacularWritingSystem; var validChars = ValidCharacters.Load(wsObj.ValidChars, - wsObj.DisplayLabel, null, null); + wsObj.DisplayLabel, null, null, FwDirectoryFinder.LegacyWordformingCharOverridesFile); var fChangedSomething = false; if (!validChars.IsWordForming('-')) { diff --git a/Src/FDO/FDOTests/ParatextHelperTests.cs b/Src/FDO/FDOTests/ParatextHelperTests.cs index 1eab148ad7..eb8d9584ec 100644 --- a/Src/FDO/FDOTests/ParatextHelperTests.cs +++ b/Src/FDO/FDOTests/ParatextHelperTests.cs @@ -18,6 +18,7 @@ using NUnit.Framework; using Paratext; using Paratext.LexicalClient; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.Resources; using SIL.FieldWorks.Test.ProjectUnpacker; @@ -431,7 +432,7 @@ public void LoadParatextMappings_Normal() FwStyleSheet stylesheet = new FwStyleSheet(); stylesheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); - ScrMappingList mappingList = new ScrMappingList(MappingSet.Main, stylesheet, ResourceHelper.DefaultParaCharsStyleName); + ScrMappingList mappingList = new ScrMappingList(MappingSet.Main, stylesheet, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); Assert.IsTrue(ParatextHelper.LoadProjectMappings("KAM", mappingList, ImportDomain.Main)); @@ -460,7 +461,7 @@ public void LoadParatextMappings_MarkMappingsInUse() { FwStyleSheet stylesheet = new FwStyleSheet(); stylesheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); - ScrMappingList mappingList = new ScrMappingList(MappingSet.Main, stylesheet, ResourceHelper.DefaultParaCharsStyleName); + ScrMappingList mappingList = new ScrMappingList(MappingSet.Main, stylesheet, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); mappingList.Add(new ImportMappingInfo(@"\hahaha", @"\*hahaha", false, MappingTargetType.TEStyle, MarkerDomain.Default, "laughing", null, null, true, ImportDomain.Main)); @@ -492,7 +493,7 @@ public void LoadParatextMappings_MissingEncodingFile() { FwStyleSheet stylesheet = new FwStyleSheet(); stylesheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); - ScrMappingList mappingList = new ScrMappingList(MappingSet.Main, stylesheet, ResourceHelper.DefaultParaCharsStyleName); + ScrMappingList mappingList = new ScrMappingList(MappingSet.Main, stylesheet, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); Unpacker.UnPackMissingFileParatextTestProjects(); Assert.IsFalse(ParatextHelper.LoadProjectMappings("NEC", mappingList, ImportDomain.Main)); @@ -510,7 +511,7 @@ public void LoadParatextMappings_MissingStyleFile() { FwStyleSheet stylesheet = new FwStyleSheet(); stylesheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); - ScrMappingList mappingList = new ScrMappingList(MappingSet.Main, stylesheet, ResourceHelper.DefaultParaCharsStyleName); + ScrMappingList mappingList = new ScrMappingList(MappingSet.Main, stylesheet, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); Unpacker.UnPackMissingFileParatextTestProjects(); Assert.IsFalse(ParatextHelper.LoadProjectMappings("NSF", mappingList, ImportDomain.Main)); diff --git a/Src/FDO/FDOTests/PersistingBackendProviderTests.cs b/Src/FDO/FDOTests/PersistingBackendProviderTests.cs index e2746350ab..e0db8d5121 100644 --- a/Src/FDO/FDOTests/PersistingBackendProviderTests.cs +++ b/Src/FDO/FDOTests/PersistingBackendProviderTests.cs @@ -9,7 +9,6 @@ using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Application; -using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.DomainServices.DataMigration; using SIL.FieldWorks.FDO.FDOTests; using SIL.FieldWorks.FDO.Infrastructure; @@ -415,7 +414,7 @@ public void CustomFieldDataTest() public void RenameDatabaseTest() { string sOrigName = Cache.ProjectId.Name; - string newProjectDir = Path.Combine(DirectoryFinder.ProjectsDirectory, NewProjectName); + string newProjectDir = Path.Combine(FwDirectoryFinder.ProjectsDirectory, NewProjectName); if (Cache.ProjectId.Type != FDOBackendProviderType.kMemoryOnly && Directory.Exists(newProjectDir)) { // make sure database doesn't exist before running the test @@ -520,7 +519,7 @@ protected override FdoCache CreateCache() while (true) { _randomProjectName = "TestLangProjCS" + Path.GetFileNameWithoutExtension(Path.GetRandomFileName()); - var projectDir = Path.Combine(DirectoryFinder.ProjectsDirectory, _randomProjectName); + var projectDir = Path.Combine(FwDirectoryFinder.ProjectsDirectory, _randomProjectName); if (!Directory.Exists(projectDir)) { _projectDir = projectDir; @@ -538,7 +537,7 @@ protected override FdoCache CreateCache() /// ------------------------------------------------------------------------------------ public override void FixtureSetup() { - RemotingServer.Start(); + RemotingServer.Start(FwDirectoryFinder.RemotingTcpServerConfigFile, FwDirectoryFinder.FdoDirectories, () => false, v => {}); base.FixtureSetup(); } @@ -563,7 +562,7 @@ public override void FixtureTeardown() /// ------------------------------------------------------------------------------------ protected override void CheckAdditionalStuffAfterFirstRename() { - Assert.AreEqual(Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, NewProjectName), + Assert.AreEqual(Path.Combine(Path.Combine(FwDirectoryFinder.ProjectsDirectory, NewProjectName), FdoFileHelper.GetDb4oDataFileName(NewProjectName)), Cache.ProjectId.Path); } } @@ -585,7 +584,7 @@ public sealed class XMLTests : PersistingBackendProviderTestBase protected override FdoCache CreateCache() { const string projName = "TestLangProj-test"; - string filename = Path.Combine(DirectoryFinder.ProjectsDirectory, + string filename = Path.Combine(FwDirectoryFinder.ProjectsDirectory, Path.Combine(projName, FdoFileHelper.GetXmlDataFileName(projName))); if (!m_internalRestart) { @@ -615,7 +614,7 @@ public void OnlyOneCacheAllowed() private FdoCache OpenExistingFile(string filename) { return FdoCache.CreateCacheFromExistingData( - new TestProjectId(FDOBackendProviderType.kXMLWithMemoryOnlyWsMgr, filename), "en", new DummyProgressDlg(), new DummyFdoUI()); + new TestProjectId(FDOBackendProviderType.kXMLWithMemoryOnlyWsMgr, filename), "en", new DummyFdoUI(), FwDirectoryFinder.FdoDirectories, new DummyProgressDlg()); } /// ------------------------------------------------------------------------------------ @@ -625,7 +624,7 @@ private FdoCache OpenExistingFile(string filename) /// ------------------------------------------------------------------------------------ protected override void CheckAdditionalStuffAfterFirstRename() { - Assert.AreEqual(Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, NewProjectName), + Assert.AreEqual(Path.Combine(Path.Combine(FwDirectoryFinder.ProjectsDirectory, NewProjectName), FdoFileHelper.GetXmlDataFileName(NewProjectName)), Cache.ProjectId.Path); } @@ -637,7 +636,7 @@ protected override void CheckAdditionalStuffAfterFirstRename() [ExpectedException(typeof(StartupException))] public void CorruptedXMLFileTest() { - var testDataPath = Path.Combine(DirectoryFinder.FwSourceDirectory, "FDO/FDOTests/TestData"); + var testDataPath = Path.Combine(FwDirectoryFinder.SourceDirectory, "FDO/FDOTests/TestData"); var projName = Path.Combine(testDataPath, "CorruptedXMLFileTest.fwdata"); // MockXMLBackendProvider implements IDisposable therefore we need the "using". @@ -664,7 +663,7 @@ public void StartupExtantTest() string testFileName = String.Empty; try { - var testDataPath = Path.Combine(DirectoryFinder.FwSourceDirectory, "FDO/FDOTests/BackupRestore/BackupTestProject"); + var testDataPath = Path.Combine(FwDirectoryFinder.SourceDirectory, "FDO/FDOTests/BackupRestore/BackupTestProject"); var projName = Path.Combine(testDataPath, "BackupTestProject.fwdata"); testFileName = Path.GetTempFileName(); // If we leave the extension as .tmp, we get a sharing violation when the @@ -693,7 +692,7 @@ public void StartupExtantTest() [Test] public void SlightlyCorruptedXMLFileTest() { - var testDataPath = Path.Combine(DirectoryFinder.FwSourceDirectory, "FDO/FDOTests/TestData"); + var testDataPath = Path.Combine(FwDirectoryFinder.SourceDirectory, "FDO/FDOTests/TestData"); var projName = Path.Combine(testDataPath, "SlightlyCorruptedXMLFile.fwdata"); // MockXMLBackendProvider implements IDisposable therefore we need the "using". @@ -712,7 +711,7 @@ public void SlightlyCorruptedXMLFileTest() [Test] public void XMLFileWithDuplicateGuidsTest() { - var testDataPath = Path.Combine(DirectoryFinder.FwSourceDirectory, "FDO/FDOTests/TestData"); + var testDataPath = Path.Combine(FwDirectoryFinder.SourceDirectory, "FDO/FDOTests/TestData"); var projName = Path.Combine(testDataPath, "DuplicateGuids.fwdata"); // MockXMLBackendProvider implements IDisposable therefore we need the "using". @@ -751,7 +750,7 @@ internal class MockXMLBackendProvider : XMLBackendProvider public MockXMLBackendProvider(FdoCache cache, string projName): base(cache, new IdentityMap((IFwMetaDataCacheManaged)cache.MetaDataCache), new CmObjectSurrogateFactory(cache), (IFwMetaDataCacheManagedInternal)cache.MetaDataCache, - new FdoDataMigrationManager(), new DummyFdoUI()) + new FdoDataMigrationManager(), new DummyFdoUI(), FwDirectoryFinder.FdoDirectories) { Project = projName; Cache = cache; diff --git a/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs b/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs index 14357a3b85..7ae6754c60 100644 --- a/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs +++ b/Src/FDO/FDOTests/PersistingLayerTests.BEPPortTests.cs @@ -105,7 +105,7 @@ public BEPPortTests() /// ------------------------------------------------------------------------------------ public override void FixtureSetup() { - RemotingServer.Start(); + RemotingServer.Start(FwDirectoryFinder.RemotingTcpServerConfigFile, FwDirectoryFinder.FdoDirectories, () => false, v => {}); base.FixtureSetup(); } @@ -207,7 +207,7 @@ public void PortAllBEPsTestsUsingAnAlreadyOpenedSource( var sourceGuids = new List(); using (var sourceCache = FdoCache.CreateCacheWithNewBlankLangProj( new TestProjectId(sourceBackendStartupParameters.ProjectId.Type, - sourceBackendStartupParameters.ProjectId.Path), "en", "fr", "en", new DummyFdoUI())) + sourceBackendStartupParameters.ProjectId.Path), "en", "fr", "en", new DummyFdoUI(), FwDirectoryFinder.FdoDirectories)) { // BEP is a singleton, so we shouldn't call Dispose on it. This will be done // by service locator. @@ -222,7 +222,7 @@ public void PortAllBEPsTestsUsingAnAlreadyOpenedSource( // Migrate source data to new BEP. using (var targetCache = FdoCache.CreateCacheCopy( new TestProjectId(targetBackendStartupParameters.ProjectId.Type, - targetBackendStartupParameters.ProjectId.Path), "en", sourceCache, new DummyFdoUI())) + targetBackendStartupParameters.ProjectId.Path), "en", new DummyFdoUI(), FwDirectoryFinder.FdoDirectories, sourceCache)) { // BEP is a singleton, so we shouldn't call Dispose on it. This will be done // by service locator. @@ -271,7 +271,7 @@ public void PortAllBEPsTestsUsingAnUnopenedSource( sourceBackendStartupParameters.ProjectId.Path); IThreadedProgress progressDlg = new DummyProgressDlg(); using (FdoCache sourceCache = FdoCache.CreateCacheWithNewBlankLangProj( - projId, "en", "fr", "en", new DummyFdoUI())) + projId, "en", "fr", "en", new DummyFdoUI(), FwDirectoryFinder.FdoDirectories)) { // BEP is a singleton, so we shouldn't call Dispose on it. This will be done // by service locator. @@ -285,7 +285,7 @@ public void PortAllBEPsTestsUsingAnUnopenedSource( // Migrate source data to new BEP. progressDlg = new DummyProgressDlg(); using (var targetCache = FdoCache.CreateCacheWithNoLangProj( - new TestProjectId(targetBackendStartupParameters.ProjectId.Type, null), "en", new DummyFdoUI())) + new TestProjectId(targetBackendStartupParameters.ProjectId.Type, null), "en", new DummyFdoUI(), FwDirectoryFinder.FdoDirectories)) { // BEP is a singleton, so we shouldn't call Dispose on it. This will be done // by service locator. diff --git a/Src/FDO/FDOTests/ScrChecksDataSourceTests.cs b/Src/FDO/FDOTests/ScrChecksDataSourceTests.cs index 825557bdbf..ab017434e1 100644 --- a/Src/FDO/FDOTests/ScrChecksDataSourceTests.cs +++ b/Src/FDO/FDOTests/ScrChecksDataSourceTests.cs @@ -42,7 +42,8 @@ public class ScrChecksDataSourceTests : ScrInMemoryFdoTestBase public override void TestSetup() { base.TestSetup(); - m_dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), DirectoryFinder.TeStylesPath); + m_dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile, FwDirectoryFinder.TeStylesPath); } ///-------------------------------------------------------------------------------------- diff --git a/Src/FDO/FDOTests/ScrImportFileInfoTests.cs b/Src/FDO/FDOTests/ScrImportFileInfoTests.cs index e45e161af3..ebe9df35f4 100644 --- a/Src/FDO/FDOTests/ScrImportFileInfoTests.cs +++ b/Src/FDO/FDOTests/ScrImportFileInfoTests.cs @@ -15,6 +15,7 @@ using System.IO; using System.Text; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Resources; using SIL.FieldWorks.Common.ScriptureUtils; using SIL.FieldWorks.Test.TestUtils; @@ -128,7 +129,7 @@ protected override TextReader GetReader() [SetUp] public void Init() { - m_mappingList = new ScrMappingList(MappingSet.Main, null, ResourceHelper.DefaultParaCharsStyleName); + m_mappingList = new ScrMappingList(MappingSet.Main, null, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); m_factory = new ScrImportFileInfoFactory(); m_fileOs = new MockFileOS(); FileUtils.Manager.SetFileAdapter(m_fileOs); diff --git a/Src/FDO/FDOTests/ScrImportSetTests.cs b/Src/FDO/FDOTests/ScrImportSetTests.cs index 9955dec742..8c4d603a68 100644 --- a/Src/FDO/FDOTests/ScrImportSetTests.cs +++ b/Src/FDO/FDOTests/ScrImportSetTests.cs @@ -21,7 +21,7 @@ using NUnit.Framework; using Rhino.Mocks; - +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Common.ScriptureUtils; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.Resources; @@ -173,7 +173,7 @@ public override void TestSetup() base.TestSetup(); m_ptHelper.Projects.Clear(); - m_importSettings = Cache.ServiceLocator.GetInstance().Create(ResourceHelper.DefaultParaCharsStyleName); + m_importSettings = Cache.ServiceLocator.GetInstance().Create(ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); m_mockParatextHelper = MockRepository.GenerateMock(); m_scr.ImportSettingsOC.Add(m_importSettings); m_ptHelper.m_loadProjectMappingsImpl = m_mockParatextHelper; diff --git a/Src/FDO/FDOTests/ScrMappingListTests.cs b/Src/FDO/FDOTests/ScrMappingListTests.cs index 65d5309d1b..0ece75e617 100644 --- a/Src/FDO/FDOTests/ScrMappingListTests.cs +++ b/Src/FDO/FDOTests/ScrMappingListTests.cs @@ -17,6 +17,7 @@ using Rhino.Mocks; using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Common.ScriptureUtils; using SIL.FieldWorks.Resources; using SIL.FieldWorks.Test.TestUtils; @@ -42,7 +43,7 @@ public class ScrMappingListTests : BaseTest [Test] public void SetMappings_Main() { - ScrMappingList list = new ScrMappingList(MappingSet.Main, null, ResourceHelper.DefaultParaCharsStyleName); + ScrMappingList list = new ScrMappingList(MappingSet.Main, null, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); list.Add(new ImportMappingInfo(@"\a", null, false, MappingTargetType.TEStyle, MarkerDomain.Default, ScrStyleNames.NormalParagraph, null)); list.Add(new ImportMappingInfo(@"\a", null, false, MappingTargetType.TEStyle, MarkerDomain.BackTrans, ScrStyleNames.NormalParagraph, "es")); list.Add(new ImportMappingInfo(@"\b", null, false, MappingTargetType.TEStyle, MarkerDomain.Default, ScrStyleNames.NormalParagraph, null)); @@ -95,7 +96,7 @@ public void SetMappings_Main() [Test] public void SetMappings_Notes() { - ScrMappingList list = new ScrMappingList(MappingSet.Notes, null, ResourceHelper.DefaultParaCharsStyleName); + ScrMappingList list = new ScrMappingList(MappingSet.Notes, null, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); list.Add(new ImportMappingInfo(@"\a", null, false, MappingTargetType.TEStyle, MarkerDomain.Note, ScrStyleNames.Remark, null)); list.Add(new ImportMappingInfo(@"\b", null, false, MappingTargetType.TEStyle, MarkerDomain.Default, ScrStyleNames.Remark, null)); try @@ -124,7 +125,7 @@ public void SetMappings_Notes() [Test] public void Delete() { - ScrMappingList list = new ScrMappingList(MappingSet.Main, null, ResourceHelper.DefaultParaCharsStyleName); + ScrMappingList list = new ScrMappingList(MappingSet.Main, null, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); list.Add(new ImportMappingInfo(@"\aa", null, false, MappingTargetType.TEStyle, MarkerDomain.Default, ScrStyleNames.Remark, null)); list.Add(new ImportMappingInfo(@"\bb", null, false, MappingTargetType.TEStyle, MarkerDomain.Default, ScrStyleNames.Remark, null)); list.Add(new ImportMappingInfo(@"\cc", null, false, MappingTargetType.TEStyle, MarkerDomain.BackTrans, ScrStyleNames.Remark, null)); @@ -147,7 +148,7 @@ public void Delete() [Test] public void HasChanged() { - ScrMappingList list = new ScrMappingList(MappingSet.Main, null, ResourceHelper.DefaultParaCharsStyleName); + ScrMappingList list = new ScrMappingList(MappingSet.Main, null, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); list.Add(new ImportMappingInfo(@"\aa", null, false, MappingTargetType.TEStyle, MarkerDomain.Default, ScrStyleNames.Remark, null)); list.Add(new ImportMappingInfo(@"\bb", null, false, MappingTargetType.TEStyle, MarkerDomain.Default, ScrStyleNames.Remark, null)); list.Add(new ImportMappingInfo(@"\cc", null, false, MappingTargetType.TEStyle, MarkerDomain.BackTrans, ScrStyleNames.Remark, null)); @@ -174,7 +175,7 @@ public void HasChanged() [ExpectedException(typeof(ArgumentOutOfRangeException))] public void Index_OutOfRange() { - ScrMappingList list = new ScrMappingList(MappingSet.Notes, null, ResourceHelper.DefaultParaCharsStyleName); + ScrMappingList list = new ScrMappingList(MappingSet.Notes, null, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); list.Add(new ImportMappingInfo(@"\a", null, false, MappingTargetType.TEStyle, MarkerDomain.Note, ScrStyleNames.Remark, null)); // Access the second element which should throw an exception @@ -189,7 +190,7 @@ public void Index_OutOfRange() [Test] public void LookupByKey() { - ScrMappingList list = new ScrMappingList(MappingSet.Notes, null, ResourceHelper.DefaultParaCharsStyleName); + ScrMappingList list = new ScrMappingList(MappingSet.Notes, null, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); list.Add(new ImportMappingInfo(@"\aa", null, false, MappingTargetType.TEStyle, MarkerDomain.Note, ScrStyleNames.Remark, null)); list.Add(new ImportMappingInfo(@"\bb", null, false, MappingTargetType.TEStyle, MarkerDomain.Note, ScrStyleNames.Remark, null)); list.Add(new ImportMappingInfo(@"\cc", null, false, MappingTargetType.TEStyle, MarkerDomain.Note, ScrStyleNames.Remark, null)); @@ -207,7 +208,7 @@ public void LookupByKey() [Test] public void LookupByKey_NonExistent() { - ScrMappingList list = new ScrMappingList(MappingSet.Notes, null, ResourceHelper.DefaultParaCharsStyleName); + ScrMappingList list = new ScrMappingList(MappingSet.Notes, null, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); Assert.IsNull(list["moogy"]); } @@ -219,7 +220,7 @@ public void LookupByKey_NonExistent() [Test] public void Enumerator() { - ScrMappingList list = new ScrMappingList(MappingSet.Notes, null, ResourceHelper.DefaultParaCharsStyleName); + ScrMappingList list = new ScrMappingList(MappingSet.Notes, null, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); list.Add(new ImportMappingInfo(@"\aa", null, false, MappingTargetType.TEStyle, MarkerDomain.Note, ScrStyleNames.Remark, null)); list.Add(new ImportMappingInfo(@"\bb", null, false, MappingTargetType.TEStyle, MarkerDomain.Note, ScrStyleNames.Remark, null)); list.Add(new ImportMappingInfo(@"\cc", null, false, MappingTargetType.TEStyle, MarkerDomain.Note, ScrStyleNames.Remark, null)); @@ -243,7 +244,7 @@ public void AddDefaultMappingIfNeeded_FigureMarkers() { IVwStylesheet stylesheet = MockRepository.GenerateMock(); - ScrMappingList list = new ScrMappingList(MappingSet.Main, stylesheet, ResourceHelper.DefaultParaCharsStyleName); + ScrMappingList list = new ScrMappingList(MappingSet.Main, stylesheet, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); list.AddDefaultMappingIfNeeded(@"\cap", ImportDomain.Main, true); list.AddDefaultMappingIfNeeded(@"\cat", ImportDomain.Main, true); list.AddDefaultMappingIfNeeded(@"\gmb", ImportDomain.Main, true); @@ -296,7 +297,7 @@ public void AddDefaultMappingIfNeeded_btMappings() stylesheet.Stub(x => x.GetType("Emphasis")).Return((int)StyleType.kstCharacter); stylesheet.Stub(x => x.GetType(ScrStyleNames.Remark)).Return((int)StyleType.kstParagraph); - ScrMappingList list = new ScrMappingList(MappingSet.Main, stylesheet, ResourceHelper.DefaultParaCharsStyleName); + ScrMappingList list = new ScrMappingList(MappingSet.Main, stylesheet, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); list.AddDefaultMappingIfNeeded(@"\bt", ImportDomain.Main, true); list.AddDefaultMappingIfNeeded(@"\btc", ImportDomain.Main, true); list.AddDefaultMappingIfNeeded(@"\btf", ImportDomain.Main, true); @@ -372,7 +373,7 @@ public void AddDefaultMappingIfNeeded_btMappingsWithNonDefaultMappings() stylesheet.Stub(x => x.GetContext("Emphasis")).Return((int)ContextValues.General); stylesheet.Stub(x => x.GetType("Emphasis")).Return((int)StyleType.kstCharacter); - ScrMappingList list = new ScrMappingList(MappingSet.Main, stylesheet, ResourceHelper.DefaultParaCharsStyleName); + ScrMappingList list = new ScrMappingList(MappingSet.Main, stylesheet, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); list.Add(new ImportMappingInfo(@"\p", null, "Emphasis")); list.AddDefaultMappingIfNeeded(@"\btp", ImportDomain.Main, true); Assert.AreEqual(2, list.Count); @@ -398,7 +399,7 @@ public void AddDefaultMappingIfNeeded_btNotFromTeStyle() { IVwStylesheet stylesheet = MockRepository.GenerateStrictMock(); - ScrMappingList list = new ScrMappingList(MappingSet.Main, stylesheet, ResourceHelper.DefaultParaCharsStyleName); + ScrMappingList list = new ScrMappingList(MappingSet.Main, stylesheet, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); list.Add(new ImportMappingInfo(@"\h", null, false, MappingTargetType.TitleShort, MarkerDomain.Default, null, null)); list.AddDefaultMappingIfNeeded(@"\bth", ImportDomain.Main, true); @@ -433,7 +434,7 @@ public void AddDefaultMappingIfNeeded_btNotFromTeStyle() [ExpectedException(typeof(ArgumentNullException))] public void AddNullMappingInfo() { - ScrMappingList list = new ScrMappingList(MappingSet.Main, null, ResourceHelper.DefaultParaCharsStyleName); + ScrMappingList list = new ScrMappingList(MappingSet.Main, null, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); list.Add(null); } @@ -447,7 +448,7 @@ public void AddNullMappingInfo() [ExpectedException(typeof(ArgumentException))] public void AddInfoWithNullMarker() { - ScrMappingList list = new ScrMappingList(MappingSet.Main, null, ResourceHelper.DefaultParaCharsStyleName); + ScrMappingList list = new ScrMappingList(MappingSet.Main, null, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); list.Add(new ImportMappingInfo(null, null, null)); } @@ -461,7 +462,7 @@ public void AddInfoWithNullMarker() [ExpectedException(typeof(ArgumentException))] public void AddBlankMarker() { - ScrMappingList list = new ScrMappingList(MappingSet.Main, null, ResourceHelper.DefaultParaCharsStyleName); + ScrMappingList list = new ScrMappingList(MappingSet.Main, null, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); list.Add(new ImportMappingInfo(string.Empty, string.Empty, string.Empty)); } #endregion diff --git a/Src/FDO/FDOTests/ScrSfFileListTests.cs b/Src/FDO/FDOTests/ScrSfFileListTests.cs index a986d2f898..f1b7f1d02a 100644 --- a/Src/FDO/FDOTests/ScrSfFileListTests.cs +++ b/Src/FDO/FDOTests/ScrSfFileListTests.cs @@ -13,6 +13,7 @@ // --------------------------------------------------------------------------------------------- using System.Collections.Generic; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices; using Rhino.Mocks; using SIL.FieldWorks.Resources; @@ -32,7 +33,7 @@ public class ScrSfFileListTests: BaseTest { #region data members private IOverlappingFileResolver m_resolver; - private ScrMappingList m_mappingList = new ScrMappingList(MappingSet.Main, null, ResourceHelper.DefaultParaCharsStyleName); + private ScrMappingList m_mappingList = new ScrMappingList(MappingSet.Main, null, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); private ScrSfFileList m_fileList; private List m_expectedRemovedFiles; private int m_callCountForVerifyFileRemoved; diff --git a/Src/FDO/FDOTests/ValidCharactersTests.cs b/Src/FDO/FDOTests/ValidCharactersTests.cs index b6d1c72c47..34622bbaf2 100644 --- a/Src/FDO/FDOTests/ValidCharactersTests.cs +++ b/Src/FDO/FDOTests/ValidCharactersTests.cs @@ -123,7 +123,7 @@ public List OtherCharacters [Test] public void InitializeFromOldValidCharsList() { - var validChars = ValidCharacters.Load(" a b c d . 1 2 3", "Test WS", null, null); + var validChars = ValidCharacters.Load(" a b c d . 1 2 3", "Test WS", null, null, FwDirectoryFinder.CodeDirectory); ValidCharsWrapper validCharsW = new ValidCharsWrapper(validChars); Assert.AreEqual(4, validCharsW.WordFormingCharacters.Count); Assert.IsTrue(validCharsW.WordFormingCharacters.Contains("a")); @@ -161,7 +161,7 @@ public void InitializeFromXml_Valid() "4\uFFFC5" + ",\uFFFC!\uFFFC*" + ""; - var validChars = ValidCharacters.Load(sXml, "Test WS", null, null); + var validChars = ValidCharacters.Load(sXml, "Test WS", null, null, FwDirectoryFinder.LegacyWordformingCharOverridesFile); ValidCharsWrapper validCharsW = new ValidCharsWrapper(validChars); Assert.AreEqual(4, validCharsW.WordFormingCharacters.Count); Assert.IsTrue(validCharsW.WordFormingCharacters.Contains("e")); @@ -191,7 +191,7 @@ public void InitializeFromXml_ValidEmpty() "" + "" + ""; - var validChars = ValidCharacters.Load(sXml, "Test WS", null, RememberError); + var validChars = ValidCharacters.Load(sXml, "Test WS", null, RememberError, FwDirectoryFinder.LegacyWordformingCharOverridesFile); ValidCharsWrapper validCharsW = new ValidCharsWrapper(validChars); Assert.AreEqual(0, validCharsW.WordFormingCharacters.Count); Assert.AreEqual(0, validCharsW.NumericCharacters.Count); @@ -209,7 +209,7 @@ public void InitializeFromXml_ValidEmpty() [Test] public void InitializeFromXml_ValidNull() { - var validChars = ValidCharacters.Load(null, "Test WS", null, RememberError); + var validChars = ValidCharacters.Load(null, "Test WS", null, RememberError, FwDirectoryFinder.LegacyWordformingCharOverridesFile); ValidCharsWrapper validCharsW = new ValidCharsWrapper(validChars); Assert.AreEqual(0, validCharsW.WordFormingCharacters.Count); Assert.AreEqual(0, validCharsW.NumericCharacters.Count); @@ -225,7 +225,7 @@ public void InitializeFromXml_ValidNull() [Test] public void InitializeFromXml_ValidEmptyString() { - var validChars = ValidCharacters.Load(String.Empty, "Test WS", null, RememberError); + var validChars = ValidCharacters.Load(String.Empty, "Test WS", null, RememberError, FwDirectoryFinder.LegacyWordformingCharOverridesFile); ValidCharsWrapper validCharsW = new ValidCharsWrapper(validChars); Assert.AreEqual(0, validCharsW.WordFormingCharacters.Count); Assert.AreEqual(0, validCharsW.NumericCharacters.Count); @@ -246,7 +246,7 @@ public void InitializeFromXml_AllowHardLineBreakCharacter() "" + "\u2028" + ""; - var validChars = ValidCharacters.Load(sXml, "Test WS", null, null); + var validChars = ValidCharacters.Load(sXml, "Test WS", null, null, FwDirectoryFinder.LegacyWordformingCharOverridesFile); ValidCharsWrapper validCharsW = new ValidCharsWrapper(validChars); Assert.AreEqual(1, validCharsW.OtherCharacters.Count); Assert.IsTrue(validCharsW.OtherCharacters.Contains("\u2028")); @@ -269,7 +269,7 @@ public void InitializeFromXml_NumericElementClosedTooEarly() "4\uFFFC5" + ",\uFFFC!\uFFFC*" + ""; - var validChars = ValidCharacters.Load(ws, null); + var validChars = ValidCharacters.Load(ws, null, FwDirectoryFinder.LegacyWordformingCharOverridesFile); ValidCharsWrapper validCharsW = new ValidCharsWrapper(validChars); Assert.AreEqual(4, validCharsW.WordFormingCharacters.Count); Assert.IsTrue(validCharsW.WordFormingCharacters.Contains("e")); @@ -299,7 +299,7 @@ public void InitializeFromXml_BogusFormat() ",\uFFFC!\uFFFC*" + ""; - var validChars = ValidCharacters.Load(ws, RememberError); + var validChars = ValidCharacters.Load(ws, RememberError, FwDirectoryFinder.LegacyWordformingCharOverridesFile); VerifyDefaultWordFormingCharacters(validChars); Assert.AreEqual("Invalid ValidChars field while loading the English (United States) writing system:" + @@ -323,7 +323,7 @@ public void InitializeFromXml_SingleBogusCharacter() "" + ""; - var validChars = ValidCharacters.Load(ws, RememberError); + var validChars = ValidCharacters.Load(ws, RememberError, FwDirectoryFinder.LegacyWordformingCharOverridesFile); VerifyDefaultWordFormingCharacters(validChars); Assert.AreEqual("Invalid ValidChars field while loading the English (United States) writing system. " + "The following characters are invalid:" + @@ -347,7 +347,7 @@ public void InitializeFromXml_SingleCompoundBogusCharacter() "" + ""; - var validChars = ValidCharacters.Load(ws, RememberError); + var validChars = ValidCharacters.Load(ws, RememberError, FwDirectoryFinder.LegacyWordformingCharOverridesFile); VerifyDefaultWordFormingCharacters(validChars); Assert.AreEqual("Invalid ValidChars field while loading the English (United States) writing system. " + "The following characters are invalid:" + @@ -371,7 +371,7 @@ public void InitializeFromXml_ValidAndBogusCharacters() "" + ""; - var validChars = ValidCharacters.Load(ws, RememberError); + var validChars = ValidCharacters.Load(ws, RememberError, FwDirectoryFinder.LegacyWordformingCharOverridesFile); ValidCharsWrapper validCharsW = new ValidCharsWrapper(validChars); Assert.AreEqual(2, validCharsW.WordFormingCharacters.Count); Assert.IsTrue(validCharsW.WordFormingCharacters.Contains("g")); @@ -401,7 +401,7 @@ public void InitializeFromXml_SameCharacterInWordFormingAndPunctuationXMLLists() "" + "'" + ""; - var validChars = ValidCharacters.Load(sXml, "Test WS", null, null); + var validChars = ValidCharacters.Load(sXml, "Test WS", null, null, FwDirectoryFinder.LegacyWordformingCharOverridesFile); ValidCharsWrapper validCharsW = new ValidCharsWrapper(validChars); Assert.AreEqual(1, validCharsW.WordFormingCharacters.Count); Assert.IsTrue(validCharsW.WordFormingCharacters.Contains("'")); @@ -422,7 +422,7 @@ public void InitializeFromXml_SameCharacterInWordFormingAndNumbericXMLLists() "1" + "" + ""; - var validChars = ValidCharacters.Load(sXml, "Test WS", null, null); + var validChars = ValidCharacters.Load(sXml, "Test WS", null, null, FwDirectoryFinder.LegacyWordformingCharOverridesFile); ValidCharsWrapper validCharsW = new ValidCharsWrapper(validChars); Assert.AreEqual(1, validCharsW.WordFormingCharacters.Count); Assert.IsTrue(validCharsW.WordFormingCharacters.Contains("1")); @@ -443,7 +443,7 @@ public void InitializeFromXml_SameCharacterInNumericAndPunctuationXMLLists() "1" + "1" + ""; - var validChars = ValidCharacters.Load(sXml, "Test WS", null, null); + var validChars = ValidCharacters.Load(sXml, "Test WS", null, null, FwDirectoryFinder.LegacyWordformingCharOverridesFile); ValidCharsWrapper validCharsW = new ValidCharsWrapper(validChars); Assert.AreEqual(0, validCharsW.WordFormingCharacters.Count); Assert.AreEqual(1, validCharsW.NumericCharacters.Count); @@ -464,7 +464,7 @@ public void InitializeFromXml_DuplicateCharacters() "4\uFFFC4" + "'\uFFFC'" + ""; - var validChars = ValidCharacters.Load(sXml, "Test WS", null, null); + var validChars = ValidCharacters.Load(sXml, "Test WS", null, null, FwDirectoryFinder.LegacyWordformingCharOverridesFile); ValidCharsWrapper validCharsW = new ValidCharsWrapper(validChars); Assert.AreEqual(1, validCharsW.WordFormingCharacters.Count); Assert.IsTrue(validCharsW.WordFormingCharacters.Contains("a")); @@ -482,7 +482,7 @@ public void InitializeFromXml_DuplicateCharacters() [Test] public void InitializeFromNullString() { - var validChars = ValidCharacters.Load(string.Empty, "Test WS", null, null); + var validChars = ValidCharacters.Load(string.Empty, "Test WS", null, null, FwDirectoryFinder.LegacyWordformingCharOverridesFile); ValidCharsWrapper validCharsW = new ValidCharsWrapper(validChars); Assert.AreEqual(0, validCharsW.WordFormingCharacters.Count); Assert.AreEqual(0, validCharsW.NumericCharacters.Count); @@ -500,7 +500,7 @@ public void InitializeFromNullString() [Test] public void AddCharacter_Duplicate() { - var validChars = ValidCharacters.Load(string.Empty, "Test WS", null, null); + var validChars = ValidCharacters.Load(string.Empty, "Test WS", null, null, FwDirectoryFinder.LegacyWordformingCharOverridesFile); ValidCharsWrapper validCharsW = new ValidCharsWrapper(validChars); validChars.AddCharacter("a"); validChars.AddCharacter("a"); @@ -528,7 +528,7 @@ public void AddCharacter_DuplicateOfOverriddenWordFormingChar() "" + "{" + ""; - var validChars = ValidCharacters.Load(sXml, "Test WS", null, null); + var validChars = ValidCharacters.Load(sXml, "Test WS", null, null, FwDirectoryFinder.LegacyWordformingCharOverridesFile); ValidCharsWrapper validCharsW = new ValidCharsWrapper(validChars); Assert.AreEqual(2, validCharsW.WordFormingCharacters.Count); Assert.AreEqual(0, validCharsW.NumericCharacters.Count); @@ -555,7 +555,7 @@ public void AddCharacter_DuplicateOfOverriddenWordFormingChar() [Test] public void AddCharacter_SuperscriptedToneNumber() { - var validChars = ValidCharacters.Load(string.Empty, "Test WS", null, null); + var validChars = ValidCharacters.Load(string.Empty, "Test WS", null, null, FwDirectoryFinder.LegacyWordformingCharOverridesFile); ValidCharsWrapper validCharsW = new ValidCharsWrapper(validChars); validChars.AddCharacter("\u00b9"); validChars.AddCharacter("\u2079"); @@ -574,7 +574,7 @@ public void AddCharacter_SuperscriptedToneNumber() [Test] public void GetNaturalCharType() { - var validChars = ValidCharacters.Load(string.Empty, "Test WS", null, null); + var validChars = ValidCharacters.Load(string.Empty, "Test WS", null, null, FwDirectoryFinder.LegacyWordformingCharOverridesFile); DummyCharPropEngine cpe = new DummyCharPropEngine(); ReflectionHelper.SetField(validChars, "m_cpe", cpe); Assert.AreEqual(ValidCharacterType.WordForming, @@ -601,7 +601,7 @@ public void IsWordFormingChar() "a\uFFFCb\uFFFCc\uFFFCd\uFFFCe\uFFFC#" + "" + "" + - "", "Test WS", null, null); + "", "Test WS", null, null, FwDirectoryFinder.LegacyWordformingCharOverridesFile); Assert.IsTrue(validChars.IsWordForming('#')); //Assert.IsTrue(validChars.IsWordForming("#")); } @@ -614,7 +614,7 @@ public void IsWordFormingChar() [Test] public void SortAfterAddSingles() { - var validChars = ValidCharacters.Load(string.Empty, "Test WS", null, null); + var validChars = ValidCharacters.Load(string.Empty, "Test WS", null, null, FwDirectoryFinder.LegacyWordformingCharOverridesFile); IWritingSystem ws = m_wsManager.Create("en"); validChars.InitSortComparer(ws); validChars.AddCharacter("z"); @@ -636,7 +636,7 @@ public void SortAfterAddSingles() [Test] public void SortAfterAddRange() { - var validChars = ValidCharacters.Load(string.Empty, "Test WS", null, null); + var validChars = ValidCharacters.Load(string.Empty, "Test WS", null, null, FwDirectoryFinder.LegacyWordformingCharOverridesFile); IWritingSystem ws = m_wsManager.Create("en"); validChars.InitSortComparer(ws); var list = new List(new[] { "z", "c", "t", "b", "8", "7", "6", "5" }); diff --git a/Src/FDO/FDOTests/WritingSystemServicesTests.cs b/Src/FDO/FDOTests/WritingSystemServicesTests.cs index 923922f17a..ca1be12016 100644 --- a/Src/FDO/FDOTests/WritingSystemServicesTests.cs +++ b/Src/FDO/FDOTests/WritingSystemServicesTests.cs @@ -1,14 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; using NUnit.Framework; using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.FDO.Infrastructure.Impl; -using SIL.FieldWorks.Test.TestUtils; namespace SIL.FieldWorks.FDO.FDOTests { @@ -49,7 +45,7 @@ public void UpdateWritingSystemListField_ReplacesNonDuplicateCode() public void FindOrCreateSomeWritingSystem_Converts_x_unk_To_qaa_x_unk() { IWritingSystem ws; - Assert.That(WritingSystemServices.FindOrCreateSomeWritingSystem(Cache, "x-unk", true, false, out ws), Is.False); + Assert.That(WritingSystemServices.FindOrCreateSomeWritingSystem(Cache, null, "x-unk", true, false, out ws), Is.False); Assert.That(ws.Id, Is.EqualTo("qaa-x-unk")); } @@ -62,7 +58,7 @@ public void FindOrCreateSomeWritingSystem_Converts_x_unk_To_qaa_x_unk() public void FindOrCreateSomeWritingSystem_Converts_Fr_Tech_30Oct_To_qaa_x_Fr_Tech_30Oct() { IWritingSystem ws; - Assert.That(WritingSystemServices.FindOrCreateSomeWritingSystem(Cache, "Fr-Tech 30Oct", true, false, out ws), Is.False); + Assert.That(WritingSystemServices.FindOrCreateSomeWritingSystem(Cache, null, "Fr-Tech 30Oct", true, false, out ws), Is.False); Assert.That(ws.Id, Is.EqualTo("qaa-x-Fr-Tech30Oc")); //8 characters is the maximum allowed for a part. } @@ -73,7 +69,7 @@ public void FindOrCreateSomeWritingSystem_Converts_Fr_Tech_30Oct_To_qaa_x_Fr_Tec public void FindOrCreateSomeWritingSystem_Converts_x_To_qaa_x_qaa() { IWritingSystem ws; - Assert.That(WritingSystemServices.FindOrCreateSomeWritingSystem(Cache, "x", true, false, out ws), Is.False); + Assert.That(WritingSystemServices.FindOrCreateSomeWritingSystem(Cache, null, "x", true, false, out ws), Is.False); Assert.That(ws.Id, Is.EqualTo("qaa-x-qaa")); } /// @@ -108,7 +104,7 @@ public void UpdateWritingSystemTag_MarksObjectsAsDirty() { var entry0 = Cache.ServiceLocator.GetInstance().Create(); IWritingSystem newWs; - var ws = WritingSystemServices.FindOrCreateWritingSystem(Cache, "en-NO", true, false, out newWs); + var ws = WritingSystemServices.FindOrCreateWritingSystem(Cache, null, "en-NO", true, false, out newWs); // A string property NOT using the WS we will change. entry0.ImportResidue = Cache.TsStrFactory.MakeString("hello", Cache.DefaultAnalWs); // A multilingual one using the WS. @@ -172,9 +168,9 @@ public void MergeWritingSystem_ConvertsMultiStrings() { var entry1 = Cache.ServiceLocator.GetInstance().Create(); IWritingSystem fromWs; - WritingSystemServices.FindOrCreateWritingSystem(Cache, "en-NO", true, false, out fromWs); + WritingSystemServices.FindOrCreateWritingSystem(Cache, null, "en-NO", true, false, out fromWs); IWritingSystem toWs; - WritingSystemServices.FindOrCreateWritingSystem(Cache, "en-SO", true, false, out toWs); + WritingSystemServices.FindOrCreateWritingSystem(Cache, null, "en-SO", true, false, out toWs); EnsureAnalysisWs(new [] {fromWs, toWs}); var sense1 = Cache.ServiceLocator.GetInstance().Create(); entry1.SensesOS.Add(sense1); @@ -209,9 +205,9 @@ void EnsureAnalysisWs(IWritingSystem[] wss) public void MergeWritingSystem_ConvertsStyleDefinition() { IWritingSystem fromWs; - WritingSystemServices.FindOrCreateWritingSystem(Cache, "en-NO", true, false, out fromWs); + WritingSystemServices.FindOrCreateWritingSystem(Cache, null, "en-NO", true, false, out fromWs); IWritingSystem toWs; - WritingSystemServices.FindOrCreateWritingSystem(Cache, "en-SO", true, false, out toWs); + WritingSystemServices.FindOrCreateWritingSystem(Cache, null, "en-SO", true, false, out toWs); EnsureAnalysisWs(new [] { fromWs, toWs }); var style1 = Cache.ServiceLocator.GetInstance().Create(); @@ -240,9 +236,9 @@ public void MergeWritingSystem_ConvertsStyleDefinition() public void MergeWritingSystemWithStyleDefnForToWs_DoesNotConvertStyleDefinition() { IWritingSystem fromWs; - WritingSystemServices.FindOrCreateWritingSystem(Cache, "en-NO", true, false, out fromWs); + WritingSystemServices.FindOrCreateWritingSystem(Cache, null, "en-NO", true, false, out fromWs); IWritingSystem toWs; - WritingSystemServices.FindOrCreateWritingSystem(Cache, "en-SO", true, false, out toWs); + WritingSystemServices.FindOrCreateWritingSystem(Cache, null, "en-SO", true, false, out toWs); EnsureAnalysisWs(new[] { fromWs, toWs }); var style1 = Cache.ServiceLocator.GetInstance().Create(); @@ -277,9 +273,9 @@ public void MergeWritingSystemWithStyleDefnForToWs_DoesNotConvertStyleDefinition public void MergeWritingSystem_ConvertsLiftResidue() { IWritingSystem fromWs; - WritingSystemServices.FindOrCreateWritingSystem(Cache, "en-NO", true, false, out fromWs); + WritingSystemServices.FindOrCreateWritingSystem(Cache, null, "en-NO", true, false, out fromWs); IWritingSystem toWs; - WritingSystemServices.FindOrCreateWritingSystem(Cache, "en-SO", true, false, out toWs); + WritingSystemServices.FindOrCreateWritingSystem(Cache, null, "en-SO", true, false, out toWs); EnsureAnalysisWs(new[] { fromWs, toWs }); var entry1 = Cache.ServiceLocator.GetInstance().Create(); @@ -306,7 +302,7 @@ public void CollatorSort_DoesNotThrow() Assert.DoesNotThrow(() => { IWritingSystem fromWs; - WritingSystemServices.FindOrCreateWritingSystem(Cache, "sen", false, true, out fromWs); + WritingSystemServices.FindOrCreateWritingSystem(Cache, null, "sen", false, true, out fromWs); Cache.LangProject.DefaultVernacularWritingSystem = fromWs; fromWs.Collator.GetSortKey("boom"); }); diff --git a/Src/FDO/FDOTests/XmlImportDataTests.cs b/Src/FDO/FDOTests/XmlImportDataTests.cs index ef6591b86d..2d060bf379 100644 --- a/Src/FDO/FDOTests/XmlImportDataTests.cs +++ b/Src/FDO/FDOTests/XmlImportDataTests.cs @@ -53,7 +53,7 @@ public void CreateTestCache() { m_now = DateTime.Now; m_cache = FdoCache.CreateCacheWithNewBlankLangProj( - new TestProjectId(FDOBackendProviderType.kMemoryOnly, "MemoryOnly.mem"), "en", "fr", "en", new DummyFdoUI()); + new TestProjectId(FDOBackendProviderType.kMemoryOnly, "MemoryOnly.mem"), "en", "fr", "en", new DummyFdoUI(), FwDirectoryFinder.FdoDirectories); IDataSetup dataSetup = m_cache.ServiceLocator.GetInstance(); dataSetup.LoadDomain(BackendBulkLoadDomain.All); if (m_cache.LangProject != null) @@ -499,7 +499,7 @@ public void ImportData2() public void ImportData3() { XmlImportData xid = new XmlImportData(m_cache); - string sFwSrcDir = DirectoryFinder.FwSourceDirectory; + string sFwSrcDir = FwDirectoryFinder.SourceDirectory; using (var rdr = new StringReader( "" + Environment.NewLine + "" + Environment.NewLine + @@ -1024,7 +1024,7 @@ private void CheckTheText(IText text) private void CheckFirstEntry(ILexEntry le, int wsEn, int wsAme) { - string sFwSrcDir = DirectoryFinder.FwSourceDirectory; + string sFwSrcDir = FwDirectoryFinder.SourceDirectory; Assert.AreEqual(1, le.LexemeFormOA.Form.StringCount); Assert.AreEqual("an", le.LexemeFormOA.Form.get_String(wsAme).Text); Assert.AreEqual("root", le.LexemeFormOA.MorphTypeRA.Name.get_String(wsEn).Text); diff --git a/Src/FDO/FDOTests/XmlListTests.cs b/Src/FDO/FDOTests/XmlListTests.cs index c3960de1a0..8b9b1f909b 100644 --- a/Src/FDO/FDOTests/XmlListTests.cs +++ b/Src/FDO/FDOTests/XmlListTests.cs @@ -17,7 +17,6 @@ using NUnit.Framework; using SIL.FieldWorks.FDO.Application.ApplicationServices; using SIL.FieldWorks.Test.TestUtils; -using SIL.Utils; using SIL.FieldWorks.Common.FwUtils; namespace SIL.FieldWorks.FDO.FDOTests @@ -599,7 +598,7 @@ public class XmlListTests : BaseTest public void CreateMockCache() { m_cache = FdoCache.CreateCacheWithNewBlankLangProj( - new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "es", "en", new DummyFdoUI()); + new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "es", "en", new DummyFdoUI(), FwDirectoryFinder.FdoDirectories); } /// diff --git a/Src/FDO/FDOTests/XmlTranslatedListsTests.cs b/Src/FDO/FDOTests/XmlTranslatedListsTests.cs index 64af184643..61edab82da 100644 --- a/Src/FDO/FDOTests/XmlTranslatedListsTests.cs +++ b/Src/FDO/FDOTests/XmlTranslatedListsTests.cs @@ -644,7 +644,7 @@ public class XmlTranslatedListsTests : BaseTest public void CreateMockCache() { m_cache = FdoCache.CreateCacheWithNewBlankLangProj( - new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "es", "en", new DummyFdoUI()); + new TestProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", "es", "en", new DummyFdoUI(), FwDirectoryFinder.FdoDirectories); var xl = new XmlList(); using (var reader = new StringReader(XmlListTests.s_ksPartsOfSpeechXml)) diff --git a/Src/FDO/FdoFactoryInterfaceAdditions.cs b/Src/FDO/FdoFactoryInterfaceAdditions.cs index 8f2c036bb3..c712edea9a 100644 --- a/Src/FDO/FdoFactoryInterfaceAdditions.cs +++ b/Src/FDO/FdoFactoryInterfaceAdditions.cs @@ -1080,6 +1080,6 @@ public partial interface IScrImportSetFactory /// /// Creates a new scripture import settings with the default paragraph characters style name. /// - IScrImportSet Create(string defaultParaCharsStyleName); + IScrImportSet Create(string defaultParaCharsStyleName, string stylesPath); } } \ No newline at end of file diff --git a/Src/FDO/FdoFileHelper.cs b/Src/FDO/FdoFileHelper.cs index 128385512e..8b6cb9f930 100644 --- a/Src/FDO/FdoFileHelper.cs +++ b/Src/FDO/FdoFileHelper.cs @@ -70,6 +70,9 @@ public static class FdoFileHelper /// Constant for locating the other repositories path of a project public const string OtherRepositories = @"OtherRepositories"; + /// The filename of the backup settings file + public const string kBackupSettingsFilename = "BackupSettings.xml"; + /// ------------------------------------------------------------------------------------ /// /// Gets the path to the configuration settings for the specified project. diff --git a/Src/FDO/FdoInterfaceAdditions.cs b/Src/FDO/FdoInterfaceAdditions.cs index 9bd1056acd..4418c075b1 100644 --- a/Src/FDO/FdoInterfaceAdditions.cs +++ b/Src/FDO/FdoInterfaceAdditions.cs @@ -5107,8 +5107,9 @@ bool HasDefaultFootnoteSettings /// /// type of import type to find. /// The default paragraph characters style name. + /// /// ------------------------------------------------------------------------------------ - IScrImportSet FindOrCreateDefaultImportSettings(TypeOfImport importType, string defaultParaCharsStyleName); + IScrImportSet FindOrCreateDefaultImportSettings(TypeOfImport importType, string defaultParaCharsStyleName, string stylesPath); /// ------------------------------------------------------------------------------------ /// diff --git a/Src/FDO/IFdoDirectories.cs b/Src/FDO/IFdoDirectories.cs new file mode 100644 index 0000000000..d341680f3f --- /dev/null +++ b/Src/FDO/IFdoDirectories.cs @@ -0,0 +1,18 @@ +namespace SIL.FieldWorks.FDO +{ + /// + /// This interface is used by FDO to retrieve directories that it needs. + /// + public interface IFdoDirectories + { + /// + /// Gets the projects directory. + /// + string ProjectsDirectory { get; } + + /// + /// Gets the template directory. + /// + string TemplateDirectory { get; } + } +} diff --git a/Src/FDO/IFdoUI.cs b/Src/FDO/IFdoUI.cs index 4e2e9b9bd6..ba07750df7 100644 --- a/Src/FDO/IFdoUI.cs +++ b/Src/FDO/IFdoUI.cs @@ -10,7 +10,6 @@ // --------------------------------------------------------------------------------------------- using System; using System.ComponentModel; -using Microsoft.Win32; namespace SIL.FieldWorks.FDO { @@ -76,10 +75,8 @@ public interface IFdoUI /// /// Reports duplicate guids to the user /// - /// The application key. - /// The email address. /// The error text. - void ReportDuplicateGuids(RegistryKey applicationKey, string emailAddress, string errorText); + void ReportDuplicateGuids(string errorText); /// /// Present a message to the user and allow the options to Retry or Cancel diff --git a/Src/FDO/IOC/FdoServiceLocatorFactory.cs b/Src/FDO/IOC/FdoServiceLocatorFactory.cs index 895b089139..c35590243a 100644 --- a/Src/FDO/IOC/FdoServiceLocatorFactory.cs +++ b/Src/FDO/IOC/FdoServiceLocatorFactory.cs @@ -16,7 +16,6 @@ using Microsoft.Practices.ServiceLocation; using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Application; using SIL.FieldWorks.FDO.Application.Impl; using SIL.FieldWorks.FDO.DomainImpl; @@ -40,17 +39,19 @@ internal sealed partial class FdoServiceLocatorFactory : IServiceLocatorBootstra { private readonly FDOBackendProviderType m_backendProviderType; private readonly IFdoUI m_ui; + private readonly IFdoDirectories m_dirs; /// /// Constructor /// /// Type of backend provider to create. - /// The user action implementation - /// ------------------------------------------------------------------------------------ - internal FdoServiceLocatorFactory(FDOBackendProviderType backendProviderType, IFdoUI ui) + /// The UI service. + /// The directories service. + internal FdoServiceLocatorFactory(FDOBackendProviderType backendProviderType, IFdoUI ui, IFdoDirectories dirs) { m_backendProviderType = backendProviderType; m_ui = ui; + m_dirs = dirs; } #region Implementation of IServiceLocatorBootstrapper @@ -238,7 +239,7 @@ public IServiceLocator CreateServiceLocator() registry .For() .LifecycleIs(new SingletonLifecycle()) - .Use(() => FwUtils.CreateWritingSystemManager()); + .Use(() => new PalasoWritingSystemManager {TemplateFolder = m_dirs.TemplateDirectory}); registry .For() .Use(c => (ILgWritingSystemFactory)c.GetInstance()); @@ -251,6 +252,10 @@ public IServiceLocator CreateServiceLocator() .For() .Use(m_ui); + registry + .For() + .Use(m_dirs); + // ================================================================================= // Don't add COM object to the registry. StructureMap does not properly release COM // objects when the container is disposed, it will crash when the container is diff --git a/Src/FDO/Infrastructure/Impl/ClientServerBackendProvider.cs b/Src/FDO/Infrastructure/Impl/ClientServerBackendProvider.cs index 1267033fcc..829a52944f 100644 --- a/Src/FDO/Infrastructure/Impl/ClientServerBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/ClientServerBackendProvider.cs @@ -23,7 +23,7 @@ protected ClientServerBackendProvider(FdoCache cache, ICmObjectSurrogateFactory surrogateFactory, IFwMetaDataCacheManagedInternal mdc, IDataMigrationManager dataMigrationManager, - IFdoUI ui) : base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager, ui) + IFdoUI ui, IFdoDirectories dirs) : base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager, ui, dirs) { } diff --git a/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs b/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs index 5396387978..a39e5758cf 100644 --- a/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs @@ -26,7 +26,6 @@ using Db4objects.Db4o.Linq; using FwRemoteDatabaseConnector; using SIL.CoreImpl; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.DomainServices.DataMigration; using SIL.Utils; @@ -88,14 +87,16 @@ internal class Db4oClientServerBackendProvider : ClientServerBackendProvider /// /// /// + /// public Db4oClientServerBackendProvider( FdoCache cache, IdentityMap identityMap, ICmObjectSurrogateFactory surrogateFactory, IFwMetaDataCacheManagedInternal mdc, IDataMigrationManager dataMigrationManager, - IFdoUI ui) - : base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager, ui) + IFdoUI ui, + IFdoDirectories dirs) + : base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager, ui, dirs) { } @@ -582,7 +583,7 @@ public override bool RenameDatabase(string sNewProjectName) if (!ProjectId.IsLocal) throw new InvalidOperationException("Renaming a database needs to be done on the local machine"); - string sNewProjectFolder = Path.Combine(DirectoryFinder.ProjectsDirectory, sNewProjectName); + string sNewProjectFolder = Path.Combine(m_dirs.ProjectsDirectory, sNewProjectName); if (FileUtils.NonEmptyDirectoryExists(sNewProjectFolder)) return false; @@ -604,7 +605,7 @@ public override bool RenameDatabase(string sNewProjectName) return false; } - string oldProjectFolder = Path.Combine(DirectoryFinder.ProjectsDirectory, ProjectId.Name); + string oldProjectFolder = Path.Combine(m_dirs.ProjectsDirectory, ProjectId.Name); string oldFile = Path.Combine(sNewProjectFolder, FdoFileHelper.GetDb4oDataFileName(ProjectId.Name)); string newFile = Path.Combine(sNewProjectFolder, FdoFileHelper.GetDb4oDataFileName(sNewProjectName)); diff --git a/Src/FDO/Infrastructure/Impl/Db4oServerInfo.cs b/Src/FDO/Infrastructure/Impl/Db4oServerInfo.cs index c396a7acf0..e300ea7009 100644 --- a/Src/FDO/Infrastructure/Impl/Db4oServerInfo.cs +++ b/Src/FDO/Infrastructure/Impl/Db4oServerInfo.cs @@ -27,7 +27,6 @@ using System.Security; using System.Threading; using Db4objects.Db4o; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.Infrastructure.Impl; using SIL.FieldWorks.FDO.DomainServices; @@ -40,8 +39,6 @@ namespace FwRemoteDatabaseConnector /// public class Db4oServerInfo : MarshalByRefObject { - private const string ksSharedProjectKey = "ProjectShared"; - /// /// Stores the filenames of all the db40 Servers /// @@ -82,10 +79,6 @@ protected struct RunningServerInfo /// public Db4oServerInfo() { - // We need FieldWorks here to get the correct registry key HKLM\Software\SIL\FieldWorks. - // The default without this would be HKLM\Software\SIL\SIL FieldWorks, - // which breaks FwRemoteDatabaseConnectorService.exe. - SIL.Utils.RegistryHelper.ProductName = "FieldWorks"; RemotingServer.ServerObject = this; } @@ -93,14 +86,16 @@ internal void PopulateServerList() { m_allServers = new List(); - if (!Directory.Exists(DirectoryFinder.ProjectsDirectory)) - throw new DirectoryNotFoundException(String.Format(Strings.ksWarningProjectFolderNotFoundOnServer, DirectoryFinder.ProjectsDirectory)); + string projectsDir = RemotingServer.Directories.ProjectsDirectory; + + if (!Directory.Exists(projectsDir)) + throw new DirectoryNotFoundException(String.Format(Strings.ksWarningProjectFolderNotFoundOnServer, projectsDir)); - string[] files = Directory.GetFiles(DirectoryFinder.ProjectsDirectory, "*" + FdoFileHelper.ksFwDataDb4oFileExtension); + string[] files = Directory.GetFiles(projectsDir, "*" + FdoFileHelper.ksFwDataDb4oFileExtension); m_allServers.AddRange(files); // search sub dirs - string[] dirs = Directory.GetDirectories(DirectoryFinder.ProjectsDirectory); + string[] dirs = Directory.GetDirectories(projectsDir); foreach (var dir in dirs) { files = Directory.GetFiles(dir, "*" + FdoFileHelper.ksFwDataDb4oFileExtension); @@ -173,7 +168,7 @@ public bool IsLocalHost(string hostname) public string[] ListServers() { // Only show Projects/Servers if Projects are shared. - if (!AreProjectsShared_Internal) + if (!RemotingServer.SharedProjectsGetter()) return Enumerable.Empty().ToArray(); if (m_allServers == null) @@ -201,7 +196,7 @@ public string[] ListRunningServers() /// ------------------------------------------------------------------------------------ public void CreateServerFile(string projectName) { - string projectDir = Path.Combine(DirectoryFinder.ProjectsDirectory, projectName); + string projectDir = Path.Combine(RemotingServer.Directories.ProjectsDirectory, projectName); string newFilename = Path.Combine(projectDir, FdoFileHelper.GetDb4oDataFileName(projectName)); // Ensure directory exists. @@ -364,7 +359,7 @@ public bool StopServer(string projectName) public bool AreProjectShared() { EnsureClientIsLocalHost(); - return AreProjectsShared_Internal; + return RemotingServer.SharedProjectsGetter(); } /// ------------------------------------------------------------------------------------ @@ -379,33 +374,33 @@ public bool AreProjectShared() public void ShareProjects(bool enableSharingOfProjects) { EnsureClientIsLocalHost(); - AreProjectsShared_Internal = enableSharingOfProjects; + RemotingServer.SharedProjectsSetter(enableSharingOfProjects); } - /// ------------------------------------------------------------------------------------ - /// - /// Gets a value indicating whether projects are shared. - /// - /// Internal method to facilitate testing. Tests can't use public setter - /// because that would actually do the conversion. Since this value is used only - /// temporarily during a test, there is no point in trying to set it on HKLM; - /// that only causes confusion if tests are sometimes run with admin privilege - /// and sometimes not. - /// ------------------------------------------------------------------------------------ - internal static bool AreProjectsShared_Internal - { - get - { - bool result; - var value = FwRegistryHelper.FieldWorksRegistryKey.GetValue(ksSharedProjectKey, "false"); - return (bool.TryParse((string)value, out result) && result); - } - set - { - FwRegistryHelper.FieldWorksRegistryKey.SetValue( - ksSharedProjectKey, value); - } - } + ///// ------------------------------------------------------------------------------------ + ///// + ///// Gets a value indicating whether projects are shared. + ///// + ///// Internal method to facilitate testing. Tests can't use public setter + ///// because that would actually do the conversion. Since this value is used only + ///// temporarily during a test, there is no point in trying to set it on HKLM; + ///// that only causes confusion if tests are sometimes run with admin privilege + ///// and sometimes not. + ///// ------------------------------------------------------------------------------------ + //internal static bool AreProjectsShared_Internal + //{ + // get + // { + // bool result; + // var value = FwRegistryHelper.FieldWorksRegistryKey.GetValue(ksSharedProjectKey, "false"); + // return (bool.TryParse((string)value, out result) && result); + // } + // set + // { + // FwRegistryHelper.FieldWorksRegistryKey.SetValue( + // ksSharedProjectKey, value); + // } + //} /// /// Allows querying all the connected clients for all projects. @@ -526,16 +521,35 @@ public static Db4oServerInfo ServerObject } /// + /// This delegate is used to retrieve the projects directory. + /// + internal static IFdoDirectories Directories { get; private set; } + + /// + /// Gets the shared projects getter. + /// + internal static Func SharedProjectsGetter { get; private set; } + + /// + /// Gets the shared projects setter. + /// + internal static Action SharedProjectsSetter { get; private set; } + + /// /// Start an instance of the .NET remoting server. /// [SuppressMessage("Gendarme.Rules.Portability", "MonoCompatibilityReviewRule", Justification="Added TODO-Linux")] - public static void Start() + public static void Start(string remotingTcpServerConfigFile, IFdoDirectories dirs, Func sharedProjectsGetter, Action sharedProjectsSetter) { // check if we are already running. if (ServerObject != null) return; + Directories = dirs; + SharedProjectsGetter = sharedProjectsGetter; + SharedProjectsSetter = sharedProjectsSetter; + if (ChannelServices.RegisteredChannels.Length > 0) { var tcpChannel = ChannelServices.GetChannel("tcp"); @@ -557,7 +571,7 @@ public static void Start() // TODO: currently running with no security // TODO-Linux: security support has not been implemented in Mono - RemotingConfiguration.Configure(DirectoryFinder.RemotingTcpServerConfigFile, false); + RemotingConfiguration.Configure(remotingTcpServerConfigFile, false); } /// diff --git a/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs b/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs index 63f2ebd15a..41b7171cf4 100644 --- a/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs @@ -17,7 +17,6 @@ using System.Threading; using SIL.CoreImpl; using SIL.CoreImpl.Properties; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.DomainServices.DataMigration; using SIL.Utils; @@ -44,19 +43,21 @@ internal abstract partial class FDOBackendProvider : IDataSetup, IDataReader, ID private readonly List m_loadDomainThreads = new List(); private readonly object m_syncRoot = new object(); protected volatile bool m_stopLoadDomain; + protected readonly IFdoDirectories m_dirs; /// /// /// protected FDOBackendProvider(FdoCache cache, IdentityMap identityMap, ICmObjectSurrogateFactory surrogateFactory, IFwMetaDataCacheManagedInternal mdc, IDataMigrationManager dataMigrationManager, - IFdoUI ui) + IFdoUI ui, IFdoDirectories dirs) { if (cache == null) throw new ArgumentNullException("cache"); if (identityMap == null) throw new ArgumentNullException("identityMap"); if (surrogateFactory == null) throw new ArgumentNullException("surrogateFactory"); if (dataMigrationManager == null) throw new ArgumentNullException("dataMigrationManager"); if (ui == null) throw new ArgumentNullException("ui"); + if (dirs == null) throw new ArgumentNullException("dirs"); m_cache = cache; m_cache.Disposing += OnCacheDisposing; @@ -65,6 +66,7 @@ protected FDOBackendProvider(FdoCache cache, IdentityMap identityMap, m_mdcInternal = mdc; m_dataMigrationManager = dataMigrationManager; m_ui = ui; + m_dirs = dirs; } @@ -400,7 +402,7 @@ private HashSet DoMigrationBasics(int currentDataStoreVers currentDataStoreVersion, dtos, (IFwMetaDataCacheManaged)m_mdcInternal, - ProjectId.ProjectFolder); + ProjectId.ProjectFolder, m_dirs); m_dataMigrationManager.PerformMigration(dtoRepository, ModelVersion, progressDlg); @@ -549,13 +551,12 @@ private void InitializeWritingSystemManager() if (UseMemoryWritingSystemManager || string.IsNullOrEmpty(ProjectId.SharedProjectFolder)) return; - var globalStore = new GlobalFileWritingSystemStore(DirectoryFinder.GlobalWritingSystemStoreDirectory); + var globalStore = new GlobalFileWritingSystemStore(); string storePath = Path.Combine(ProjectId.SharedProjectFolder, FdoFileHelper.ksWritingSystemsDir); - var wsManager = (PalasoWritingSystemManager)m_cache.ServiceLocator.WritingSystemManager; + var wsManager = (PalasoWritingSystemManager) m_cache.ServiceLocator.WritingSystemManager; wsManager.GlobalWritingSystemStore = globalStore; wsManager.LocalWritingSystemStore = new LocalFileWritingSystemStore(storePath, globalStore); wsManager.LocalWritingSystemStore.LocalKeyboardSettings = Settings.Default.LocalKeyboards; - wsManager.TemplateFolder = DirectoryFinder.TemplateDirectory; } #region IDataSetup implementation @@ -621,9 +622,9 @@ public void LoadDomain(BackendBulkLoadDomain bulkLoadDomain) ReconstituteObjectsFor(ScrTxtParaTags.kClassId); ReconstituteObjectsFor(CmTranslationTags.kClassId); ReconstituteObjectsFor(ScrFootnoteTags.kClassId); - ReconstituteObjectsFor(ChkTermTags.kClassId); - ReconstituteObjectsFor(ChkRefTags.kClassId); - ReconstituteObjectsFor(ChkRenderingTags.kClassId); + ReconstituteObjectsFor(ChkTermTags.kClassId); + ReconstituteObjectsFor(ChkRefTags.kClassId); + ReconstituteObjectsFor(ChkRenderingTags.kClassId); break; case BackendBulkLoadDomain.Text: lock (m_syncRoot) @@ -748,12 +749,6 @@ public void StartupExtantLanguageProject(IProjectIdentifier projectId, bool fBoo if (fBootstrapSystem) BootstrapExtantSystem(); } - catch (System.UnauthorizedAccessException e) - { - // Release any resources. - ShutdownInternal(); - throw; - } catch (Exception e) { // If anything unexpected goes wrong give BEP change to release any resources. @@ -813,8 +808,8 @@ public void InitializeFromSource(IProjectIdentifier projectId, InitializeWritingSystemManager(); // 3. Startup source BEP, but without instantiating any FDO objects (surrogates, are loaded). - using (var sourceCache = FdoCache.CreateCacheFromExistingData(sourceDataStore.ProjectId, - userWsIcuLocale, progressDlg, m_ui)) + using (FdoCache sourceCache = FdoCache.CreateCacheFromExistingData(sourceDataStore.ProjectId, + userWsIcuLocale, m_ui, m_cache.ServiceLocator.GetInstance(), progressDlg)) { // 4. Do the port. var sourceCacheServLoc = sourceCache.ServiceLocator; diff --git a/Src/FDO/Infrastructure/Impl/FdoRepositoryAdditions.cs b/Src/FDO/Infrastructure/Impl/FdoRepositoryAdditions.cs index 779d048416..adb1ae575c 100644 --- a/Src/FDO/Infrastructure/Impl/FdoRepositoryAdditions.cs +++ b/Src/FDO/Infrastructure/Impl/FdoRepositoryAdditions.cs @@ -22,7 +22,6 @@ using System.Linq; using System.Text; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainImpl; using SIL.FieldWorks.FDO.Validation; using SIL.Utils; diff --git a/Src/FDO/Infrastructure/Impl/MemoryOnlyBackendProvider.cs b/Src/FDO/Infrastructure/Impl/MemoryOnlyBackendProvider.cs index 26170d6bee..d78646341b 100644 --- a/Src/FDO/Infrastructure/Impl/MemoryOnlyBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/MemoryOnlyBackendProvider.cs @@ -24,8 +24,8 @@ internal sealed class MemoryOnlyBackendProvider : FDOBackendProvider /// Constructor. /// internal MemoryOnlyBackendProvider(FdoCache cache, IdentityMap identityMap, ICmObjectSurrogateFactory surrogateFactory, - IFwMetaDataCacheManagedInternal mdc, IDataMigrationManager dataMigrationManager, IFdoUI ui) - : base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager, ui) + IFwMetaDataCacheManagedInternal mdc, IDataMigrationManager dataMigrationManager, IFdoUI ui, IFdoDirectories dirs) + : base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager, ui, dirs) { } diff --git a/Src/FDO/Infrastructure/Impl/SimpleProjectId.cs b/Src/FDO/Infrastructure/Impl/SimpleProjectId.cs index 7dd72fbde4..5f2c9555f1 100644 --- a/Src/FDO/Infrastructure/Impl/SimpleProjectId.cs +++ b/Src/FDO/Infrastructure/Impl/SimpleProjectId.cs @@ -13,7 +13,6 @@ // --------------------------------------------------------------------------------------------- using System; -using SIL.FieldWorks.Common.FwUtils; namespace SIL.FieldWorks.FDO.Infrastructure.Impl { @@ -73,11 +72,12 @@ public string Handle /// ------------------------------------------------------------------------------------ /// /// Gets a token that uniquely identifies the project that can be used for a named pipe. + /// TODO: this will probably go away after we finish integrating FDO into Paratext /// /// ------------------------------------------------------------------------------------ public string PipeHandle { - get { return FwUtils.GeneratePipeHandle(Handle); } + get { throw new NotImplementedException(); } } /// ------------------------------------------------------------------------------------ diff --git a/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs b/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs index 82f03a9767..d62d94a582 100644 --- a/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs @@ -18,7 +18,6 @@ using SIL.CoreImpl; using SIL.FieldWorks.FDO.DomainServices.DataMigration; using SIL.Utils; -using SIL.FieldWorks.Common.FwUtils; namespace SIL.FieldWorks.FDO.Infrastructure.Impl { @@ -125,8 +124,8 @@ public void Combine(CommitWork work) /// internal XMLBackendProvider(FdoCache cache, IdentityMap identityMap, ICmObjectSurrogateFactory surrogateFactory, IFwMetaDataCacheManagedInternal mdc, - IDataMigrationManager dataMigrationManager, IFdoUI ui) : - base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager, ui) + IDataMigrationManager dataMigrationManager, IFdoUI ui, IFdoDirectories dirs) : + base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager, ui, dirs) { } @@ -305,7 +304,7 @@ internal virtual void ReportDuplicateGuidsIfTheyExist() sb.AppendLine(String.Format(Strings.ksDuplicateGuidsMsg2, guid)); sb.AppendLine(); } - m_cache.ServiceLocator.GetInstance().ReportDuplicateGuids(FwRegistryHelper.FieldWorksRegistryKey, "FLExErrors@sil.org", sb.ToString()); + m_cache.ServiceLocator.GetInstance().ReportDuplicateGuids(sb.ToString()); } } @@ -736,9 +735,9 @@ protected override void UpdateVersionNumber() /// ------------------------------------------------------------------------------------ public override bool RenameDatabase(string sNewProjectName) { - bool projectIsInDefaultLocation = DirectoryFinder.IsSubFolderOfProjectsDirectory(ProjectId.ProjectFolder); + bool projectIsInDefaultLocation = Path.GetDirectoryName(ProjectId.ProjectFolder) == m_dirs.ProjectsDirectory; string sNewProjectFolder = projectIsInDefaultLocation ? - Path.Combine(DirectoryFinder.ProjectsDirectory, sNewProjectName) : ProjectId.ProjectFolder; + Path.Combine(m_dirs.ProjectsDirectory, sNewProjectName) : ProjectId.ProjectFolder; if (FileUtils.NonEmptyDirectoryExists(sNewProjectFolder)) return false; // Destination directory already exists diff --git a/Src/FDO/FdoFileHelperRelativePaths.cs b/Src/FDO/LinkedFilesRelativePathHelper.cs similarity index 96% rename from Src/FDO/FdoFileHelperRelativePaths.cs rename to Src/FDO/LinkedFilesRelativePathHelper.cs index c164b8f88f..4d9441db97 100644 --- a/Src/FDO/FdoFileHelperRelativePaths.cs +++ b/Src/FDO/LinkedFilesRelativePathHelper.cs @@ -10,7 +10,7 @@ // -------------------------------------------------------------------------------------------- using System; using System.IO; -using SIL.FieldWorks.Common.FwUtils; +using SIL.CoreImpl; using SIL.Utils; namespace SIL.FieldWorks.FDO @@ -18,7 +18,7 @@ namespace SIL.FieldWorks.FDO /// /// This class is designed for converting between relative paths and full paths for the LinkedFiles of a FW project /// - public class FdoFileHelperRelativePaths + public static class LinkedFilesRelativePathHelper { /// Substitution string for a path that is under the LinkedFiles directory. public const string ksLFrelPath = "%lf%"; @@ -155,23 +155,23 @@ public static string GetRelativeLinkedFilesPath(string filePath, return FixPathSlashesIfNeeded(relativePath); } - /// /// Return the fullPath for a project's LinkedFiles based on the relative path that was persisted. /// If no match on a relativePath match is made then return the relativePath passed in assuming it /// is actually a full path. /// + /// /// /// /// - public static String GetLinkedFilesFullPathFromRelativePath(string relativePath, String projectPath) + public static String GetLinkedFilesFullPathFromRelativePath(string projectsPath, string relativePath, String projectPath) { String fullPath = null; fullPath = GetFullPathForRelativePath(relativePath, ksProjectRelPath, projectPath); if (String.IsNullOrEmpty(fullPath)) fullPath = GetFullPathForRelativePath(relativePath, ksProjectsRelPath, - DirectoryFinder.ProjectsDirectory); + projectsPath); if (String.IsNullOrEmpty(fullPath)) fullPath = GetFullPathForRelativePath(relativePath, ksCommonAppDataRelPath, DirectoryFinder.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)); @@ -201,11 +201,12 @@ private static String GetFullPathForRelativePath(String relativePath, String rel /// Get a relative path for the LinkedFilesPath which we will persist to be used when /// restoring a project. /// + /// /// /// /// /// - public static string GetLinkedFilesRelativePathFromFullPath(string linkedFilesFullPath, + public static string GetLinkedFilesRelativePathFromFullPath(string projectsPath, string linkedFilesFullPath, string projectPath, string projectName) { var linkedFilesPathLowercaseRoot = GetPathWithLowercaseRoot(linkedFilesFullPath); @@ -221,8 +222,7 @@ public static string GetLinkedFilesRelativePathFromFullPath(string linkedFilesFu // Even though the MyProj directory in both paths is the same directory. // It's important to catch this case and return a relative path. var projectFolderName = Path.GetFileName(projectPath); - var projectsPath = Path.GetDirectoryName(projectPath); - var allProjectsName = Path.GetFileName(projectsPath); + var allProjectsName = Path.GetFileName(Path.GetDirectoryName(projectPath)); var match = Path.Combine(allProjectsName, projectFolderName); int index = linkedFilesFullPath.IndexOf(match, StringComparison.InvariantCultureIgnoreCase); if (index >= 0) @@ -243,8 +243,7 @@ public static string GetLinkedFilesRelativePathFromFullPath(string linkedFilesFu // Case where user is presumably having a LinkedFiles folder shared among a number // of projects under the Projects folder. That would be a good reason to put it in // the projects folder common to all projects. - relativePath = GetRelativePathIfExists(ksProjectsRelPath, linkedFilesPathLowercaseRoot, - DirectoryFinder.ProjectsDirectory); + relativePath = GetRelativePathIfExists(ksProjectsRelPath, linkedFilesPathLowercaseRoot, projectsPath); if (!String.IsNullOrEmpty(relativePath)) return FixPathSlashesIfNeeded(relativePath); diff --git a/Src/Common/FwUtils/ProjectInfo.cs b/Src/FDO/ProjectInfo.cs similarity index 80% rename from Src/Common/FwUtils/ProjectInfo.cs rename to Src/FDO/ProjectInfo.cs index e805c56947..acf1b2367f 100644 --- a/Src/Common/FwUtils/ProjectInfo.cs +++ b/Src/FDO/ProjectInfo.cs @@ -16,7 +16,7 @@ using System.IO; using System.Linq; -namespace SIL.FieldWorks.Common.FwUtils +namespace SIL.FieldWorks.FDO { /// ---------------------------------------------------------------------------------------- /// @@ -60,26 +60,23 @@ public ProjectInfo(string databaseName) /// /// Set of ProjectInfo objects, representing the projects on server /// ------------------------------------------------------------------------------------ - public static List AllProjects + public static List GetAllProjects(string projectsDir) { - get + // Ensure that the folder actually contains a project data file. + List projectList = new List(); + string[] projectDirectories = Directory.GetDirectories(projectsDir); + foreach (var dir in projectDirectories) { - // Ensure that the folder actually contains a project data file. - List projectList = new List(); - string[] projectDirectories = Directory.GetDirectories(DirectoryFinder.ProjectsDirectory); - foreach (var dir in projectDirectories) - { - string basename = Path.GetFileName(dir); - if (File.Exists(Path.Combine(dir, basename + Resources.FwFileExtensions.ksFwDataXmlFileExtension)) || - File.Exists(Path.Combine(dir, basename + Resources.FwFileExtensions.ksFwDataDb4oFileExtension))) - { - projectList.Add(new ProjectInfo(basename)); - } + string basename = Path.GetFileName(dir); + if (File.Exists(Path.Combine(dir, basename + FdoFileHelper.ksFwDataXmlFileExtension)) || + File.Exists(Path.Combine(dir, basename + FdoFileHelper.ksFwDataDb4oFileExtension))) + { + projectList.Add(new ProjectInfo(basename)); } - //projectList.AddRange(projectDirectories.Select(sFolder => new ProjectInfo(Path.GetFileName(sFolder)))); - return projectList; } + //projectList.AddRange(projectDirectories.Select(sFolder => new ProjectInfo(Path.GetFileName(sFolder)))); + return projectList; } #endregion @@ -100,12 +97,13 @@ public override string ToString() /// Get the specified project info if it exists given the UI name (i.e., without path) /// on the local machine. /// + /// /// specified project name (without path) /// the project info for the specified name; otherwise null /// ------------------------------------------------------------------------------------ - public static ProjectInfo GetProjectInfoByName(string projectName) + public static ProjectInfo GetProjectInfoByName(string projectsDir, string projectName) { - return AllProjects.FirstOrDefault(info => ProjectsAreSame(projectName, info.DatabaseName)); + return GetAllProjects(projectsDir).FirstOrDefault(info => ProjectsAreSame(projectName, info.DatabaseName)); } /// ------------------------------------------------------------------------------------ diff --git a/Src/FDO/SilentFdoUI.cs b/Src/FDO/SilentFdoUI.cs index a7ff8bd5e0..cb973c4e07 100644 --- a/Src/FDO/SilentFdoUI.cs +++ b/Src/FDO/SilentFdoUI.cs @@ -10,7 +10,6 @@ // --------------------------------------------------------------------------------------------- using System; using System.ComponentModel; -using Microsoft.Win32; namespace SIL.FieldWorks.FDO { @@ -124,10 +123,8 @@ public void ReportException(Exception error, bool isLethal) /// /// Reports duplicate guids to the user /// - /// The application key. - /// The email address. /// The error text. - public void ReportDuplicateGuids(RegistryKey applicationKey, string emailAddress, string errorText) + public void ReportDuplicateGuids(string errorText) { // Informational only } diff --git a/Src/FDO/fdoCache.cs b/Src/FDO/fdoCache.cs index c593057196..54975ad849 100644 --- a/Src/FDO/fdoCache.cs +++ b/Src/FDO/fdoCache.cs @@ -24,7 +24,6 @@ using System.ComponentModel; using System.Xml.Linq; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Application.ApplicationServices; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.IOC; @@ -95,11 +94,12 @@ public sealed partial class FdoCache /// Identifies the new project to create. /// The ICU locale of the default user WS. /// + /// /// ------------------------------------------------------------------------------------ public static FdoCache CreateCacheWithNoLangProj(IProjectIdentifier projectId, - string userWsIcuLocale, IFdoUI ui) + string userWsIcuLocale, IFdoUI ui, IFdoDirectories dirs) { - FdoCache createdCache = CreateCacheInternal(projectId, ui); + FdoCache createdCache = CreateCacheInternal(projectId, ui, dirs); createdCache.FullyInitializedAndReadyToRock = true; return createdCache; } @@ -120,13 +120,14 @@ public static FdoCache CreateCacheWithNoLangProj(IProjectIdentifier projectId, /// The ICU locale of the default user writing /// system. /// + /// /// ------------------------------------------------------------------------------------ public static FdoCache CreateCacheWithNewBlankLangProj(IProjectIdentifier projectId, string analWsIcuLocale, string vernWsIcuLocale, string userWsIcuLocale, - IFdoUI ui) + IFdoUI ui, IFdoDirectories dirs) { - FdoCache createdCache = CreateCacheInternal(projectId, userWsIcuLocale, - dataSetup => dataSetup.CreateNewLanguageProject(projectId), ui); + FdoCache createdCache = CreateCacheInternal(projectId, userWsIcuLocale, ui, dirs, + dataSetup => dataSetup.CreateNewLanguageProject(projectId)); NonUndoableUnitOfWorkHelper.Do(createdCache.ActionHandlerAccessor, () => { createdCache.ServiceLocator.WritingSystems.DefaultAnalysisWritingSystem = @@ -144,15 +145,16 @@ public static FdoCache CreateCacheWithNewBlankLangProj(IProjectIdentifier projec /// /// Identifies the project to load. /// The ICU locale of the default user WS. - /// The progress dialog box /// + /// + /// The progress dialog box /// ------------------------------------------------------------------------------------ public static FdoCache CreateCacheFromExistingData(IProjectIdentifier projectId, - string userWsIcuLocale, IThreadedProgress progressDlg, IFdoUI ui) + string userWsIcuLocale, IFdoUI ui, IFdoDirectories dirs, IThreadedProgress progressDlg) { - return CreateCacheInternal(projectId, userWsIcuLocale, + return CreateCacheInternal(projectId, userWsIcuLocale, ui, dirs, dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg), - cache => cache.Initialize(userWsIcuLocale), ui); + cache => cache.Initialize(userWsIcuLocale)); } /// ------------------------------------------------------------------------------------ @@ -162,16 +164,17 @@ public static FdoCache CreateCacheFromExistingData(IProjectIdentifier projectId, /// /// /// - /// The progress dialog box /// + /// + /// The progress dialog box /// ------------------------------------------------------------------------------------ public static FdoCache CreateCacheFromLocalProjectFile(string projectPath, - string userWsIcuLocale, IThreadedProgress progressDlg, IFdoUI ui) + string userWsIcuLocale, IFdoUI ui, IFdoDirectories dirs, IThreadedProgress progressDlg) { var projectId = new SimpleProjectId(FDOBackendProviderType.kXML, projectPath); - return CreateCacheInternal(projectId, userWsIcuLocale, + return CreateCacheInternal(projectId, userWsIcuLocale, ui, dirs, dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg), - cache => cache.Initialize(userWsIcuLocale), ui); + cache => cache.Initialize(userWsIcuLocale)); } /// ------------------------------------------------------------------------------------ @@ -181,14 +184,15 @@ public static FdoCache CreateCacheFromLocalProjectFile(string projectPath, /// /// Identifies the project to create (i.e., the copy). /// The ICU locale of the default user WS. - /// The FdoCache to copy /// + /// + /// The FdoCache to copy /// ------------------------------------------------------------------------------------ public static FdoCache CreateCacheCopy(IProjectIdentifier projectId, - string userWsIcuLocale, FdoCache sourceCache, IFdoUI ui) + string userWsIcuLocale, IFdoUI ui, IFdoDirectories dirs, FdoCache sourceCache) { - return CreateCacheInternal(projectId, userWsIcuLocale, - dataSetup => dataSetup.InitializeFromSource(projectId, sourceCache), ui); + return CreateCacheInternal(projectId, userWsIcuLocale, ui, dirs, + dataSetup => dataSetup.InitializeFromSource(projectId, sourceCache)); } /// ------------------------------------------------------------------------------------ @@ -197,14 +201,15 @@ public static FdoCache CreateCacheCopy(IProjectIdentifier projectId, /// /// Identifies the project to create or load. /// + /// /// ------------------------------------------------------------------------------------ - private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, IFdoUI ui) + private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, IFdoUI ui, IFdoDirectories dirs) { FDOBackendProviderType providerType = projectId.Type; if (providerType == FDOBackendProviderType.kXMLWithMemoryOnlyWsMgr) providerType = FDOBackendProviderType.kXML; - var iocFactory = new FdoServiceLocatorFactory(providerType, ui); + var iocFactory = new FdoServiceLocatorFactory(providerType, ui, dirs); var servLoc = (IFdoServiceLocator)iocFactory.CreateServiceLocator(); var createdCache = servLoc.GetInstance(); createdCache.m_serviceLocator = servLoc; @@ -218,13 +223,14 @@ private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, IFdoUI /// /// Identifies the project to create or load. /// The ICU locale of the default user WS. - /// The data setup action to perform. /// + /// + /// The data setup action to perform. /// ------------------------------------------------------------------------------------ private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, - string userWsIcuLocale, Action doThe, IFdoUI ui) + string userWsIcuLocale, IFdoUI ui, IFdoDirectories dirs, Action doThe) { - return CreateCacheInternal(projectId, userWsIcuLocale, doThe, null, ui); + return CreateCacheInternal(projectId, userWsIcuLocale, ui, dirs, doThe, null); } /// ------------------------------------------------------------------------------------ @@ -233,19 +239,20 @@ private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, /// /// Identifies the project to create or load. /// The ICU locale of the default user WS. + /// + /// /// The data setup action to perform. /// The initialization step to perfrom (can be null). - /// /// The newly created cache /// ------------------------------------------------------------------------------------ private static FdoCache CreateCacheInternal(IProjectIdentifier projectId, - string userWsIcuLocale, Action doThe, - Action initialize, IFdoUI ui) + string userWsIcuLocale, IFdoUI ui, IFdoDirectories dirs, Action doThe, + Action initialize) { FDOBackendProviderType providerType = projectId.Type; bool useMemoryWsManager = (providerType == FDOBackendProviderType.kMemoryOnly || providerType == FDOBackendProviderType.kXMLWithMemoryOnlyWsMgr); - FdoCache createdCache = CreateCacheInternal(projectId, ui); + FdoCache createdCache = CreateCacheInternal(projectId, ui, dirs); // Init backend data provider var dataSetup = createdCache.ServiceLocator.GetInstance(); @@ -353,8 +360,8 @@ private static bool IsUpdatedWsInUse(StringBuilder updatedWssInUseBuilder) /// The progress dialog. /// One or more parameters, supplied in this order: /// 0. A string containing the name of the project (required); - /// 1. An ISynchronizeInvoke used for invoking actions on the main UI thread (required); - /// 2. An IFdoUI used for soliciting user feedback during deep FDO processing (required); + /// 1. An IFdoDirectories used to get needed directories (required); + /// 2. An ISynchronizeInvoke used for invoking actions on the main UI thread (required); /// 3. An IWritingSystem to be used as the default analylis writing system (default: English); /// 4. An IWritingSystem to be used as the default vernacular writing system (default: French); /// 5. A string with the ICU locale of the UI writing system (default: "en"). @@ -366,16 +373,16 @@ private static bool IsUpdatedWsInUse(StringBuilder updatedWssInUseBuilder) /// ------------------------------------------------------------------------------------ public static string CreateNewLangProj(IThreadedProgress progressDlg, params object[] parameters) { - if (parameters == null || parameters.Length < 3) - throw new ArgumentException("Parameters must include at least a project name, a SynchronizeInvoke object, and a FdoUserAction object"); - var projectName = (string)parameters[0]; + if (parameters == null || parameters.Length < 4) + throw new ArgumentException("Parameters must include at least a project directory, a project name, a template directory, and a SynchronizeInvoke object"); + var projectName = (string) parameters[0]; if (string.IsNullOrEmpty(projectName)) throw new ArgumentNullException("parameters", "Cannot be null or empty"); - var synchronizeInvoke = (ISynchronizeInvoke) parameters[1]; - var userAction = (IFdoUI) parameters[2]; - IWritingSystem analWrtSys = (parameters.Length > 3) ? (IWritingSystem)parameters[3] : null; - IWritingSystem vernWrtSys = (parameters.Length > 4) ? (IWritingSystem)parameters[4] : null; - var userIcuLocale = (parameters.Length > 5 && parameters[5] != null) ? (string)parameters[5] : "en"; + var dirs = (IFdoDirectories) parameters[1]; + var synchronizeInvoke = (ISynchronizeInvoke) parameters[2]; + IWritingSystem analWrtSys = (parameters.Length > 3) ? (IWritingSystem) parameters[3] : null; + IWritingSystem vernWrtSys = (parameters.Length > 4) ? (IWritingSystem) parameters[4] : null; + var userIcuLocale = (parameters.Length > 5 && parameters[5] != null) ? (string) parameters[5] : "en"; const int nMax = 10; if (progressDlg != null) { @@ -384,9 +391,7 @@ public static string CreateNewLangProj(IThreadedProgress progressDlg, params obj progressDlg.Message = Properties.Resources.kstidCreatingDB; } - var dbFileName = CreateNewDbFile(ref projectName); - Debug.Assert(DirectoryFinder.IsSubFolderOfProjectsDirectory(Path.GetDirectoryName(dbFileName)), - "new projects should always be created in the current projects directory"); + var dbFileName = CreateNewDbFile(dirs.ProjectsDirectory, dirs.TemplateDirectory, ref projectName); if (progressDlg != null) { @@ -395,8 +400,8 @@ public static string CreateNewLangProj(IThreadedProgress progressDlg, params obj } var projectId = new SimpleProjectId(FDOBackendProviderType.kXML, dbFileName); - using (var cache = CreateCacheInternal(projectId, userIcuLocale, - dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg), new SilentFdoUI(synchronizeInvoke))) + using (FdoCache cache = CreateCacheInternal(projectId, userIcuLocale, new SilentFdoUI(synchronizeInvoke), dirs, + dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg))) { if (progressDlg != null) { @@ -419,12 +424,12 @@ public static string CreateNewLangProj(IThreadedProgress progressDlg, params obj progressDlg.Step(0); var additionalAnalysisWss = (parameters.Length > 6 && parameters[6] != null) - ? (HashSet)parameters[6] + ? (HashSet) parameters[6] : new HashSet(); foreach (var additionalWs in additionalAnalysisWss) CreateAnalysisWritingSystem(cache, additionalWs, false); var additionalVernWss = (parameters.Length > 7 && parameters[7] != null) - ? (HashSet)parameters[7] + ? (HashSet) parameters[7] : new HashSet(); foreach (var additionalWs in additionalVernWss) CreateVernacularWritingSystem(cache, additionalWs, false); @@ -445,7 +450,7 @@ public static string CreateNewLangProj(IThreadedProgress progressDlg, params obj // Load the semantic domain list. // Enhance: allow user to choose among alternative semantic domain lists? - string sFile = Path.Combine(DirectoryFinder.TemplateDirectory, "SemDom.xml"); + string sFile = Path.Combine(dirs.TemplateDirectory, "SemDom.xml"); if (progressDlg != null) { progressDlg.Message = Properties.Resources.ksLoadingSemanticDomains; @@ -457,7 +462,7 @@ public static string CreateNewLangProj(IThreadedProgress progressDlg, params obj xlist.ImportList(cache.LangProject, "SemanticDomainList", sFile, progressDlg); // Load the intitial Part of Speech list. - sFile = Path.Combine(DirectoryFinder.TemplateDirectory, "POS.xml"); + sFile = Path.Combine(dirs.TemplateDirectory, "POS.xml"); if (progressDlg != null) { progressDlg.Message = Properties.Resources.ksLoadingPartsOfSpeech; @@ -470,17 +475,17 @@ public static string CreateNewLangProj(IThreadedProgress progressDlg, params obj // Make sure that the new project has all the writing systems actually used by the // default data. See FWR-1774. - AddMissingWritingSystems(Path.Combine(DirectoryFinder.TemplateDirectory, FdoFileHelper.GetXmlDataFileName("NewLangProj")), + AddMissingWritingSystems(Path.Combine(dirs.TemplateDirectory, FdoFileHelper.GetXmlDataFileName("NewLangProj")), cache.ServiceLocator.WritingSystemManager); - AddMissingWritingSystems(Path.Combine(DirectoryFinder.TemplateDirectory, "POS.xml"), + AddMissingWritingSystems(Path.Combine(dirs.TemplateDirectory, "POS.xml"), cache.ServiceLocator.WritingSystemManager); cache.ServiceLocator.WritingSystemManager.Save(); cache.ActionHandlerAccessor.BeginNonUndoableTask(); InitializeAnthroList(cache.LangProject, cache.WritingSystemFactory.GetWsFromStr(analWrtSys != null ? analWrtSys.IcuLocale : userIcuLocale), - (parameters.Length > 8) ? (string)parameters[8] : null); - ImportLocalizedLists(cache, progressDlg); + (parameters.Length > 8) ? (string) parameters[8] : null); + ImportLocalizedLists(cache, dirs.TemplateDirectory, progressDlg); cache.ActionHandlerAccessor.EndNonUndoableTask(); NonUndoableUnitOfWorkHelper.Do(cache.ServiceLocator.GetInstance(), () => @@ -509,7 +514,7 @@ public static string CreateNewLangProj(IThreadedProgress progressDlg, params obj cache.SaveAndForceNewestXmlForCmObjectWithoutUnitOfWork(null, cache.m_serviceLocator.ObjectRepository.AllInstances().ToList()); } } - return ClientServerServices.Current.Local.ConvertToDb4oBackendIfNeeded(progressDlg, dbFileName, userAction); + return ClientServerServices.Current.Local.ConvertToDb4oBackendIfNeeded(progressDlg, dbFileName); } /// @@ -569,11 +574,11 @@ private static void AddSubPossibilitiesToOverlay(ICmOverlay over, ICmPossibility /// Check for any localized lists files using pattern Templates\LocalizedLists-*.xml. /// If found, load each one into the project. /// - private static void ImportLocalizedLists(FdoCache cache, IThreadedProgress progress) + private static void ImportLocalizedLists(FdoCache cache, string templateDir, IThreadedProgress progress) { var filePrefix = XmlTranslatedLists.LocalizedListPrefix; var rgsAnthroFiles = new List(); - var rgsXmlFiles = Directory.GetFiles(DirectoryFinder.TemplateDirectory, filePrefix + "*.zip", SearchOption.TopDirectoryOnly); + var rgsXmlFiles = Directory.GetFiles(templateDir, filePrefix + "*.zip", SearchOption.TopDirectoryOnly); string sFile; for (var i = 0; i < rgsXmlFiles.Length; ++i) { @@ -676,19 +681,19 @@ private static void AddMissingWritingSystems(string fileName, /// Build the file name for the new project and copy the template file (NewLangProj.fwdata). /// /// ------------------------------------------------------------------------------------ - private static string CreateNewDbFile(ref string projectName) + private static string CreateNewDbFile(string projectsDir, string templateDir, ref string projectName) { projectName = MiscUtils.FilterForFileName(projectName, MiscUtils.FilenameFilterStrength.kFilterBackup); - if (ProjectInfo.GetProjectInfoByName(projectName) != null) + if (ProjectInfo.GetProjectInfoByName(projectsDir, projectName) != null) throw new ArgumentException("The specified project already exists.", "projectName"); - string dbDirName = Path.Combine(DirectoryFinder.ProjectsDirectory, projectName); + string dbDirName = Path.Combine(projectsDir, projectName); string dbFileName = Path.Combine(dbDirName, FdoFileHelper.GetXmlDataFileName(projectName)); try { Directory.CreateDirectory(dbDirName); CreateProjectSubfolders(dbDirName); // Make a copy of the template database that will become the new database - File.Copy(Path.Combine(DirectoryFinder.TemplateDirectory, + File.Copy(Path.Combine(templateDir, FdoFileHelper.GetXmlDataFileName("NewLangProj")), dbFileName, false); File.SetAttributes(dbFileName, FileAttributes.Normal); @@ -1088,6 +1093,7 @@ public int DefaultUserWs #endregion Public Properties #region Public methods + /// ----------------------------------------------------------------------------------- /// /// Change the name of the database represented by this connection. diff --git a/Src/FDOBrowser/FDOBrowserForm.cs b/Src/FDOBrowser/FDOBrowserForm.cs index deeb2e9e2e..3dcbabe8a8 100644 --- a/Src/FDOBrowser/FDOBrowserForm.cs +++ b/Src/FDOBrowser/FDOBrowserForm.cs @@ -377,14 +377,14 @@ protected override void OpenFile(string fileName) // Init backend data provider // TODO: Get the correct ICU local for the user writing system - var userAction = new FwFdoUI(this, this); + var ui = new FwFdoUI(this, this); if (isMemoryBEP) - m_cache = FdoCache.CreateCacheWithNewBlankLangProj(new BrowserProjectId(bepType, null), "en", "en", "en", userAction); + m_cache = FdoCache.CreateCacheWithNewBlankLangProj(new BrowserProjectId(bepType, null), "en", "en", "en", ui, FwDirectoryFinder.FdoDirectories); else { using (var progressDlg = new ProgressDialogWithTask(this)) { - m_cache = FdoCache.CreateCacheFromExistingData(new BrowserProjectId(bepType, fileName), "en", progressDlg, userAction); + m_cache = FdoCache.CreateCacheFromExistingData(new BrowserProjectId(bepType, fileName), "en", ui, FwDirectoryFinder.FdoDirectories, progressDlg); } } // var v = m_cache. @@ -2513,7 +2513,7 @@ public string GetHelpString(string sPropName) /// public string HelpFile { - get { return Path.Combine(DirectoryFinder.FWCodeDirectory, GetHelpString("UserHelpFile")); } + get { return Path.Combine(FwDirectoryFinder.CodeDirectory, GetHelpString("UserHelpFile")); } } #endregion diff --git a/Src/FDOBrowser/FDOClassList.cs b/Src/FDOBrowser/FDOClassList.cs index 7c1c05d8ab..4c1f7d8096 100644 --- a/Src/FDOBrowser/FDOClassList.cs +++ b/Src/FDOBrowser/FDOClassList.cs @@ -138,7 +138,7 @@ private static void LoadFDOClassNames() return; using (var threadHelper = new ThreadHelper()) - using (FdoCache cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", new SilentFdoUI(threadHelper))) + using (FdoCache cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", new SilentFdoUI(threadHelper), FwDirectoryFinder.FdoDirectories)) { IFwMetaDataCacheManaged mdc = (IFwMetaDataCacheManaged)cache.MainCacheAccessor.MetaDataCache; s_allFDOClassNames = new List(); diff --git a/Src/FDOBrowser/ModelWnd.cs b/Src/FDOBrowser/ModelWnd.cs index a8460719bd..4ad4cd5fe0 100644 --- a/Src/FDOBrowser/ModelWnd.cs +++ b/Src/FDOBrowser/ModelWnd.cs @@ -42,7 +42,7 @@ public ModelWnd() m_lvModel.Font = SystemFonts.MenuFont; // Add model browsing cache (no data, just model browsing). - m_cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", new SilentFdoUI(this)); + m_cache = FdoCache.CreateCacheWithNoLangProj(new BrowserProjectId(FDOBackendProviderType.kMemoryOnly, null), "en", new SilentFdoUI(this), FwDirectoryFinder.FdoDirectories); m_mdc = (IFwMetaDataCacheManaged)m_cache.MainCacheAccessor.MetaDataCache; PopulateModelTree(); diff --git a/Src/FXT/FxtDll/FxtDllTests/FxtTestBase.cs b/Src/FXT/FxtDll/FxtDllTests/FxtTestBase.cs index 28df8c0063..97b4309eef 100644 --- a/Src/FXT/FxtDll/FxtDllTests/FxtTestBase.cs +++ b/Src/FXT/FxtDll/FxtDllTests/FxtTestBase.cs @@ -86,7 +86,7 @@ public virtual void Init() { RegistryHelper.CompanyName = "SIL"; RegistryHelper.ProductName = "FieldWorks"; - m_sExpectedResultsPath = Path.Combine(DirectoryFinder.FwSourceDirectory, + m_sExpectedResultsPath = Path.Combine(FwDirectoryFinder.SourceDirectory, Path.Combine("FXT", Path.Combine("FxtDll", Path.Combine("FxtDllTests", "ExpectedResults")))); diff --git a/Src/FXT/FxtDll/FxtDllTests/SimpleTests.cs b/Src/FXT/FxtDll/FxtDllTests/SimpleTests.cs index 690dc65d40..dcac6af96c 100644 --- a/Src/FXT/FxtDll/FxtDllTests/SimpleTests.cs +++ b/Src/FXT/FxtDll/FxtDllTests/SimpleTests.cs @@ -36,7 +36,7 @@ public class QuickTests : FxtTestBase /// /// Location of simple test FXT files /// - protected string m_sFxtSimpleTestPath = Path.Combine(SIL.FieldWorks.Common.Utils.DirectoryFinder.FwSourceDirectory, + protected string m_sFxtSimpleTestPath = Path.Combine(SIL.FieldWorks.Common.Utils.DirectoryFinder.SourceDirectory, Path.Combine("FXT", Path.Combine("FxtDll", "FxtDllTests"))); /// ----------------------------------------------------------------------------------- diff --git a/Src/FXT/FxtDll/FxtDllTests/StandFormatExportTests.cs b/Src/FXT/FxtDll/FxtDllTests/StandFormatExportTests.cs index f30f99399e..01bf038320 100644 --- a/Src/FXT/FxtDll/FxtDllTests/StandFormatExportTests.cs +++ b/Src/FXT/FxtDll/FxtDllTests/StandFormatExportTests.cs @@ -28,19 +28,10 @@ public class StandardFormat : FxtTestBase /// protected string m_testDir; - /// ----------------------------------------------------------------------------------- - /// - /// Initializes a new instance of the class. - /// - /// ----------------------------------------------------------------------------------- - public StandardFormat() - { - } - public override void Init() { base.Init(); - m_testDir = Path.Combine(DirectoryFinder.FlexFolder, "Export Templates"); + m_testDir = Path.Combine(FwDirectoryFinder.FlexFolder, "Export Templates"); } [Test] diff --git a/Src/FdoUi/Dialogs/SummaryDialogForm.cs b/Src/FdoUi/Dialogs/SummaryDialogForm.cs index 2a5a0ca9d1..5742f232e8 100644 --- a/Src/FdoUi/Dialogs/SummaryDialogForm.cs +++ b/Src/FdoUi/Dialogs/SummaryDialogForm.cs @@ -144,7 +144,7 @@ private void Initialize(ITsString tssForm, IHelpTopicProvider helpProvider, stri { m_helpFileKey = helpFileKey; this.helpProvider = new HelpProvider(); - this.helpProvider.HelpNamespace = DirectoryFinder.FWCodeDirectory + m_helpProvider.GetHelpString("UserHelpFile"); + this.helpProvider.HelpNamespace = FwDirectoryFinder.CodeDirectory + m_helpProvider.GetHelpString("UserHelpFile"); this.helpProvider.SetHelpKeyword(this, m_helpProvider.GetHelpString(s_helpTopicKey)); this.helpProvider.SetHelpNavigator(this, HelpNavigator.Topic); } diff --git a/Src/FdoUi/FwFdoUI.cs b/Src/FdoUi/FwFdoUI.cs index 597a0c69be..567635ddcb 100644 --- a/Src/FdoUi/FwFdoUI.cs +++ b/Src/FdoUi/FwFdoUI.cs @@ -13,7 +13,7 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Windows.Forms; -using Microsoft.Win32; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FdoUi.Dialogs; using SIL.Utils; @@ -181,12 +181,10 @@ public void ReportException(Exception error, bool isLethal) /// /// Reports duplicate guids to the user /// - /// The application key. - /// The email address. /// The error text. - public void ReportDuplicateGuids(RegistryKey applicationKey, string emailAddress, string errorText) + public void ReportDuplicateGuids(string errorText) { - m_synchronizeInvoke.Invoke(() => ErrorReporter.ReportDuplicateGuids(applicationKey, emailAddress, null, errorText)); + m_synchronizeInvoke.Invoke(() => ErrorReporter.ReportDuplicateGuids(FwRegistryHelper.FieldWorksRegistryKey, "FLExErrors@sil.org", null, errorText)); } /// diff --git a/Src/FdoUi/LexEntryUi.cs b/Src/FdoUi/LexEntryUi.cs index bd807a350b..106c52a528 100644 --- a/Src/FdoUi/LexEntryUi.cs +++ b/Src/FdoUi/LexEntryUi.cs @@ -169,7 +169,7 @@ protected static Mediator EnsureValidMediator(Mediator mediator, } if (fRestoreStringTable || stOrig == null) { - string dir = Path.Combine(DirectoryFinder.FlexFolder, "Configuration"); + string dir = Path.Combine(FwDirectoryFinder.FlexFolder, "Configuration"); mediator.StringTbl = new StringTable(dir); } return mediator; @@ -461,7 +461,7 @@ private static void EnsureWindowConfiguration(Mediator mediator) XmlNode xnWindow = (XmlNode)mediator.PropertyTable.GetValue("WindowConfiguration"); if (xnWindow == null) { - string configFile = DirectoryFinder.GetFWCodeFile("Language Explorer/Configuration/Main.xml"); + string configFile = FwDirectoryFinder.GetCodeFile("Language Explorer/Configuration/Main.xml"); // This can be called from TE...in that case, we don't complain about missing include // files (true argument) but just trust that we put enough in the installer to make it work. XmlDocument configuration = XWindow.LoadConfigurationWithIncludes(configFile, true); @@ -596,7 +596,7 @@ public static void DisplayRelatedEntries(FdoCache cache, IVwSelection sel, IWin3 /// ------------------------------------------------------------------------------------ public static string FlexConfigFile { - get { return DirectoryFinder.GetFWCodeFile(@"Language Explorer/Configuration/Main.xml"); } + get { return FwDirectoryFinder.GetCodeFile(@"Language Explorer/Configuration/Main.xml"); } } /// ------------------------------------------------------------------------------------ diff --git a/Src/FwCoreDlgs/ArchiveWithRamp.cs b/Src/FwCoreDlgs/ArchiveWithRamp.cs index e1febf0b89..aa59f054e0 100644 --- a/Src/FwCoreDlgs/ArchiveWithRamp.cs +++ b/Src/FwCoreDlgs/ArchiveWithRamp.cs @@ -70,7 +70,7 @@ private void m_archive_Click(object sender, EventArgs e) private void get_Last_Backup() { - BackupFileRepository backups = new BackupFileRepository(); + BackupFileRepository backups = new BackupFileRepository(FwDirectoryFinder.DefaultBackupDirectory); var projName = backups.AvailableProjectNames.FirstOrDefault(s => s == m_cache.ProjectId.Name); if (!string.IsNullOrEmpty(projName)) diff --git a/Src/FwCoreDlgs/BackupRestore/BackupProjectDlg.cs b/Src/FwCoreDlgs/BackupRestore/BackupProjectDlg.cs index c600bfd3e5..804c422b9a 100644 --- a/Src/FwCoreDlgs/BackupRestore/BackupProjectDlg.cs +++ b/Src/FwCoreDlgs/BackupRestore/BackupProjectDlg.cs @@ -69,7 +69,7 @@ public BackupProjectDlg(FdoCache cache, string appAbbrev, m_supportingFiles.Enabled = false; } - DestinationFolder = DirectoryFinder.DefaultBackupDirectory; + DestinationFolder = FwDirectoryFinder.DefaultBackupDirectory; if (File.Exists(m_presenter.PersistanceFilePath)) { // If something bad happens when loading the previous dialog settings (probably just a @@ -108,7 +108,7 @@ private void m_browse_Click(object sender, EventArgs e) if (String.IsNullOrEmpty(DestinationFolder) || !Directory.Exists(DestinationFolder)) { - dlg.SelectedPath = DirectoryFinder.DefaultBackupDirectory; + dlg.SelectedPath = FwDirectoryFinder.DefaultBackupDirectory; } else { @@ -154,12 +154,12 @@ private void m_backUp_Click(object sender, EventArgs e) } } - if (!DestinationFolder.Equals(DirectoryFinder.DefaultBackupDirectory)) + if (!DestinationFolder.Equals(FwDirectoryFinder.DefaultBackupDirectory)) { using (var dlgChangeDefaultBackupLocation = new ChangeDefaultBackupDir(m_helpTopicProvider)) { if (dlgChangeDefaultBackupLocation.ShowDialog(this) == DialogResult.Yes) - DirectoryFinder.DefaultBackupDirectory = DestinationFolder; + FwDirectoryFinder.DefaultBackupDirectory = DestinationFolder; } } diff --git a/Src/FwCoreDlgs/BackupRestore/BackupProjectPresenter.cs b/Src/FwCoreDlgs/BackupRestore/BackupProjectPresenter.cs index 119b2ea89e..e738fe6e53 100644 --- a/Src/FwCoreDlgs/BackupRestore/BackupProjectPresenter.cs +++ b/Src/FwCoreDlgs/BackupRestore/BackupProjectPresenter.cs @@ -54,7 +54,7 @@ internal String PersistanceFilePath get { return Path.Combine(FdoFileHelper.GetBackupSettingsDir(m_cache.ProjectId.ProjectFolder), - DirectoryFinder.kBackupSettingsFilename); + FdoFileHelper.kBackupSettingsFilename); } } @@ -84,7 +84,7 @@ internal bool SupportingFilesFolderContainsFiles /// ------------------------------------------------------------------------------------ internal bool FileNameProblems(Form messageBoxOwner) { - BackupProjectSettings settings = new BackupProjectSettings(m_cache, m_backupProjectView); + BackupProjectSettings settings = new BackupProjectSettings(m_cache, m_backupProjectView, FwDirectoryFinder.DefaultBackupDirectory); settings.DestinationFolder = m_backupProjectView.DestinationFolder; if (settings.AdjustedComment.Trim() != settings.Comment.TrimEnd()) { @@ -119,7 +119,7 @@ internal bool FileNameProblems(Form messageBoxOwner) /// ------------------------------------------------------------------------------------ internal string BackupProject(IThreadedProgress progressDlg) { - BackupProjectSettings settings = new BackupProjectSettings(m_cache, m_backupProjectView); + BackupProjectSettings settings = new BackupProjectSettings(m_cache, m_backupProjectView, FwDirectoryFinder.DefaultBackupDirectory); settings.DestinationFolder = m_backupProjectView.DestinationFolder; settings.AppAbbrev = m_appAbbrev; diff --git a/Src/FwCoreDlgs/BackupRestore/RestoreProjectDlg.cs b/Src/FwCoreDlgs/BackupRestore/RestoreProjectDlg.cs index 620feae6aa..5c59125eb4 100644 --- a/Src/FwCoreDlgs/BackupRestore/RestoreProjectDlg.cs +++ b/Src/FwCoreDlgs/BackupRestore/RestoreProjectDlg.cs @@ -140,9 +140,9 @@ private RestoreProjectDlg(string appName, IHelpTopicProvider helpTopicProvider) m_lblBackupComment.Text = String.Empty; m_fmtUseOriginalName = m_rdoUseOriginalName.Text; m_rdoUseOriginalName.Text = String.Format(m_fmtUseOriginalName, String.Empty); - m_settings = new RestoreProjectSettings(); - m_txtOtherProjectName.KeyPress += new KeyPressEventHandler(m_txtOtherProjectName_KeyPress); - m_txtOtherProjectName.TextChanged += new EventHandler(m_txtOtherProjectName_TextChanged); + m_settings = new RestoreProjectSettings(FwDirectoryFinder.ProjectsDirectory); + m_txtOtherProjectName.KeyPress += m_txtOtherProjectName_KeyPress; + m_txtOtherProjectName.TextChanged += m_txtOtherProjectName_TextChanged; GetIllegalProjectNameChars(); } @@ -288,7 +288,7 @@ private void m_btnBrowse_Click(object sender, EventArgs e) { m_openFileDlg = new OpenFileDialogAdapter(); m_openFileDlg.CheckFileExists = true; - m_openFileDlg.InitialDirectory = DirectoryFinder.DefaultBackupDirectory; + m_openFileDlg.InitialDirectory = FwDirectoryFinder.DefaultBackupDirectory; m_openFileDlg.RestoreDirectory = true; m_openFileDlg.Title = FwCoreDlgs.ksFindBackupFileDialogTitle; m_openFileDlg.ValidateNames = true; diff --git a/Src/FwCoreDlgs/BackupRestore/RestoreProjectPresenter.cs b/Src/FwCoreDlgs/BackupRestore/RestoreProjectPresenter.cs index 6148c0e868..12a670330c 100644 --- a/Src/FwCoreDlgs/BackupRestore/RestoreProjectPresenter.cs +++ b/Src/FwCoreDlgs/BackupRestore/RestoreProjectPresenter.cs @@ -13,6 +13,7 @@ using System.Text; using System.Web.Configuration; using System.Windows.Forms; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices.BackupRestore; using System.Collections.Generic; using System.IO; @@ -56,7 +57,7 @@ public RestoreProjectPresenter(RestoreProjectDlg restoreProjectView) public RestoreProjectPresenter(RestoreProjectDlg restoreProjectView, string defaultProjectName) : this(restoreProjectView) { - m_backupFiles = new BackupFileRepository(); + m_backupFiles = new BackupFileRepository(FwDirectoryFinder.DefaultBackupDirectory); m_defaultProjectName = defaultProjectName; m_fEmptyProjectName = false; } diff --git a/Src/FwCoreDlgs/CharContextCtrl.cs b/Src/FwCoreDlgs/CharContextCtrl.cs index 32b63af53c..3ccba8c0c8 100644 --- a/Src/FwCoreDlgs/CharContextCtrl.cs +++ b/Src/FwCoreDlgs/CharContextCtrl.cs @@ -136,7 +136,7 @@ public void Initialize(FdoCache cache, IWritingSystemContainer wsContainer, TokenGrid = tokenGrid; if (FwUtils.IsOkToDisplayScriptureIfPresent) - m_scrChecksDllFile = DirectoryFinder.BasicEditorialChecksDll; + m_scrChecksDllFile = FwDirectoryFinder.BasicEditorialChecksDll; if (m_ws != null) { @@ -328,7 +328,7 @@ private ValidCharacters ValidCharacters // Get the writing system and valid characters list if (m_wsContainer.DefaultVernacularWritingSystem == null) return null; - return ValidCharacters.Load(m_wsContainer.DefaultVernacularWritingSystem, LoadException); + return ValidCharacters.Load(m_wsContainer.DefaultVernacularWritingSystem, LoadException, FwDirectoryFinder.LegacyWordformingCharOverridesFile); } } @@ -636,11 +636,12 @@ private void GetTokensSubStrings(string fileName) /// ------------------------------------------------------------------------------------ private List ReadTEScripture() { - var scrDataSource = new ScrChecksDataSource(m_cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), DirectoryFinder.TeStylesPath); + var scrDataSource = new ScrChecksDataSource(m_cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile, FwDirectoryFinder.TeStylesPath); scrDataSource.LoadException += scrDataSource_LoadException; - IScrCheckInventory scrCharInventoryBldr = CreateScrCharInventoryBldr(DirectoryFinder.BasicEditorialChecksDll, + IScrCheckInventory scrCharInventoryBldr = CreateScrCharInventoryBldr(FwDirectoryFinder.BasicEditorialChecksDll, scrDataSource, m_checkToRun == CheckType.Punctuation ? "SILUBS.ScriptureChecks.PunctuationCheck" : "SILUBS.ScriptureChecks.CharactersCheck"); diff --git a/Src/FwCoreDlgs/ChooseLangProjectDialog.cs b/Src/FwCoreDlgs/ChooseLangProjectDialog.cs index e36541f0a4..b4d94d289c 100644 --- a/Src/FwCoreDlgs/ChooseLangProjectDialog.cs +++ b/Src/FwCoreDlgs/ChooseLangProjectDialog.cs @@ -46,7 +46,6 @@ public partial class ChooseLangProjectDialog : Form private readonly Rectangle m_initialBounds = Rectangle.Empty; private readonly int m_initialSplitterPosition = -1; private ObtainedProjectType m_obtainedProjectType = ObtainedProjectType.None; - private readonly IFdoUI m_ui; #endregion #region LanguageProjectInfo class @@ -103,10 +102,9 @@ private ChooseLangProjectDialog() /// /// The initial client bounds of the dialog. /// The initial splitter position. - /// /// ------------------------------------------------------------------------------------ - public ChooseLangProjectDialog(Rectangle bounds, int splitterPosition, IFdoUI ui) - : this(null, false, ui) + public ChooseLangProjectDialog(Rectangle bounds, int splitterPosition) + : this(null, false) { m_initialBounds = bounds; m_initialSplitterPosition = splitterPosition; @@ -123,14 +121,12 @@ public ChooseLangProjectDialog(Rectangle bounds, int splitterPosition, IFdoUI ui /// If set to true the dialog will be /// used to assosiate a FieldWorks project with another application (e.g. Paratext). /// - /// /// ------------------------------------------------------------------------------------ public ChooseLangProjectDialog(IHelpTopicProvider helpTopicProvider, - bool openToAssosiateFwProject, IFdoUI ui) + bool openToAssosiateFwProject) : this() { m_helpTopicProvider = helpTopicProvider; - m_ui = ui; if (helpTopicProvider == null) m_btnHelp.Enabled = false; @@ -539,7 +535,7 @@ private void OkButtonClick(object sender, EventArgs e) private string HostsFileName { - get { return Path.Combine(DirectoryFinder.ProjectsDirectory, "HostsManuallyConnected.txt"); } + get { return Path.Combine(FwDirectoryFinder.ProjectsDirectory, "HostsManuallyConnected.txt"); } } private void AddHostButtonClick(object sender, EventArgs e) @@ -559,7 +555,7 @@ private void OpenFwDataProjectLinkClicked(object sender, LinkLabelLinkClickedEve { Hide(); dlg.CheckFileExists = true; - dlg.InitialDirectory = DirectoryFinder.ProjectsDirectory; + dlg.InitialDirectory = FwDirectoryFinder.ProjectsDirectory; dlg.RestoreDirectory = true; dlg.Title = FwCoreDlgs.ksChooseLangProjectDialogTitle; dlg.ValidateNames = true; @@ -573,7 +569,7 @@ private void OpenFwDataProjectLinkClicked(object sender, LinkLabelLinkClickedEve private void OpenBridgeProjectLinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { // ObtainProjectFromAnySource may return null, empty string, or the full pathname to an fwdata file. - Project = ObtainProjectMethod.ObtainProjectFromAnySource(this, m_helpTopicProvider, out m_obtainedProjectType, m_ui); + Project = ObtainProjectMethod.ObtainProjectFromAnySource(this, m_helpTopicProvider, out m_obtainedProjectType); Server = null; if (String.IsNullOrEmpty(Project)) return; // Don't close the Open project dialog yet (LT-13187) diff --git a/Src/FwCoreDlgs/FwCheckAnthroListDlg.cs b/Src/FwCoreDlgs/FwCheckAnthroListDlg.cs index 4a1037c75c..16d1ec9877 100644 --- a/Src/FwCoreDlgs/FwCheckAnthroListDlg.cs +++ b/Src/FwCoreDlgs/FwCheckAnthroListDlg.cs @@ -161,11 +161,11 @@ public static string PickAnthroList(Form parent, string description, IHelpTopicP { // Figure out what lists are available (in {FW}/Templates/*.xml). - var sFilePattern = Path.Combine(DirectoryFinder.TemplateDirectory, "*.xml"); + var sFilePattern = Path.Combine(FwDirectoryFinder.TemplateDirectory, "*.xml"); var fHaveOCM = false; var fHaveFRAME = false; var rgsAnthroFiles = new List(); - var rgsXmlFiles = Directory.GetFiles(DirectoryFinder.TemplateDirectory, "*.xml", SearchOption.TopDirectoryOnly); + var rgsXmlFiles = Directory.GetFiles(FwDirectoryFinder.TemplateDirectory, "*.xml", SearchOption.TopDirectoryOnly); string sFile; for (var i = 0; i < rgsXmlFiles.Length; ++i) { @@ -199,14 +199,14 @@ public static string PickAnthroList(Form parent, string description, IHelpTopicP case kralUserDef: break; case kralOCM: - sFile = Path.Combine(DirectoryFinder.TemplateDirectory, "OCM.xml"); + sFile = Path.Combine(FwDirectoryFinder.TemplateDirectory, "OCM.xml"); break; case kralFRAME: - sFile = Path.Combine(DirectoryFinder.TemplateDirectory, "OCM-Frame.xml"); + sFile = Path.Combine(FwDirectoryFinder.TemplateDirectory, "OCM-Frame.xml"); break; default: Debug.Assert(nChoice >= 0 && nChoice < rgsAnthroFiles.Count); - sFile = Path.Combine(DirectoryFinder.TemplateDirectory, rgsAnthroFiles[nChoice]); + sFile = Path.Combine(FwDirectoryFinder.TemplateDirectory, rgsAnthroFiles[nChoice]); break; } } diff --git a/Src/FwCoreDlgs/FwCoreDlgsTests/FwNewLangProjectTests.cs b/Src/FwCoreDlgs/FwCoreDlgsTests/FwNewLangProjectTests.cs index 89f880a0de..9777d9c655 100644 --- a/Src/FwCoreDlgs/FwCoreDlgsTests/FwNewLangProjectTests.cs +++ b/Src/FwCoreDlgs/FwCoreDlgsTests/FwNewLangProjectTests.cs @@ -20,7 +20,7 @@ using System.Linq; using System.Windows.Forms; using NUnit.Framework; - +using SIL.CoreImpl; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.Test.TestUtils; @@ -36,15 +36,6 @@ namespace SIL.FieldWorks.FwCoreDlgs /// ---------------------------------------------------------------------------------------- public class DummyFwNewLangProject : FwNewLangProject { - /// - /// Default parameterless constructor - /// - public DummyFwNewLangProject() : base(new DummyFdoUI()) - { - - } - - /// /// Tells tests whether or not the Non-Ascii project name warning dialog was activated. /// @@ -55,7 +46,7 @@ public void CreateNewLangProj() { CheckDisposed(); - CreateNewLangProjWithProgress(new DummyFdoUI()); + CreateNewLangProjWithProgress(); NonAsciiWarningWasActivated = false; SimulatedNonAsciiDialogResult = DialogResult.Cancel; } @@ -122,7 +113,7 @@ public class FwNewLangProjectTests: BaseTest public void CreateNewLangProject() { const string dbName = "Maileingwij2025"; - string storePath = FdoFileHelper.GetWritingSystemDir(Path.Combine(DirectoryFinder.ProjectsDirectory, dbName)); + string storePath = FdoFileHelper.GetWritingSystemDir(Path.Combine(FwDirectoryFinder.ProjectsDirectory, dbName)); string sharedStorePath = DirectoryFinder.GlobalWritingSystemStoreDirectory; using (var dlg = new DummyFwNewLangProject()) @@ -141,7 +132,7 @@ public void CreateNewLangProject() // despite of the name is DummyProgressDlg no real dialog (doesn't derive from Control), so // we don't need a 'using' cache = FdoCache.CreateCacheFromExistingData( - new TestProjectId(FDOBackendProviderType.kXML, DbFilename(dbName)), "en", new DummyProgressDlg(), new DummyFdoUI()); + new TestProjectId(FDOBackendProviderType.kXML, DbFilename(dbName)), "en", new DummyFdoUI(), FwDirectoryFinder.FdoDirectories, new DummyProgressDlg()); CheckInitialSetOfPartsOfSpeech(cache); Assert.AreEqual(1, cache.ServiceLocator.WritingSystems.AnalysisWritingSystems.Count); @@ -366,7 +357,7 @@ private void CheckInitialSetOfPartsOfSpeech(FdoCache cache) private static string DbDirectory(string dbName) { - return Path.Combine(DirectoryFinder.ProjectsDirectory, dbName); + return Path.Combine(FwDirectoryFinder.ProjectsDirectory, dbName); } private static string DbFilename(string dbName) diff --git a/Src/FwCoreDlgs/FwCoreDlgsTests/RestoreProjectPresenterTests.cs b/Src/FwCoreDlgs/FwCoreDlgsTests/RestoreProjectPresenterTests.cs index 9e821f3e7b..244266efca 100644 --- a/Src/FwCoreDlgs/FwCoreDlgsTests/RestoreProjectPresenterTests.cs +++ b/Src/FwCoreDlgs/FwCoreDlgsTests/RestoreProjectPresenterTests.cs @@ -95,7 +95,7 @@ public void VerifyStringForBackupPropertiesLabel() [Test] public void DefaultBackupFile_NoBackupFilesAvailable() { - m_fileOs.ExistingDirectories.Add(DirectoryFinder.DefaultBackupDirectory); + m_fileOs.ExistingDirectories.Add(FwDirectoryFinder.DefaultBackupDirectory); RestoreProjectPresenter presenter = new RestoreProjectPresenter(null, string.Empty); Assert.AreEqual(String.Empty, presenter.DefaultProjectName); } @@ -109,7 +109,7 @@ public void DefaultBackupFile_NoBackupFilesAvailable() [Test] public void DefaultBackupFile_BackupForCurrentProjectExists() { - BackupProjectSettings backupSettings = new BackupProjectSettings(Cache, null); + BackupProjectSettings backupSettings = new BackupProjectSettings(Cache, null, FwDirectoryFinder.DefaultBackupDirectory); string backupFileName1 = backupSettings.ZipFileName; m_fileOs.AddExistingFile(backupFileName1); // Force the second backup to appear to be older @@ -129,7 +129,7 @@ public void DefaultBackupFile_BackupForCurrentProjectExists() [Test] public void DefaultBackupFile_BackupsForOtherProjectsButNotCurrent() { - BackupProjectSettings backupSettings = new BackupProjectSettings(Cache, null); + BackupProjectSettings backupSettings = new BackupProjectSettings(Cache, null, FwDirectoryFinder.DefaultBackupDirectory); backupSettings.ProjectName = "AAA"; string backupFileName1 = backupSettings.ZipFileName; m_fileOs.AddExistingFile(backupFileName1); @@ -154,14 +154,14 @@ public void DefaultBackupFile_BackupsForOtherProjectsButNotCurrent() public void RestoreToName_GetSuggestedNewProjectName() { // Add three project files, one being a copy of another. - string proj1 = Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, "AAA"), "AAA.fwdata"); + string proj1 = Path.Combine(Path.Combine(FwDirectoryFinder.ProjectsDirectory, "AAA"), "AAA.fwdata"); m_fileOs.AddExistingFile(proj1); - string proj2 = Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, "BBB"), "BBB.fwdata"); + string proj2 = Path.Combine(Path.Combine(FwDirectoryFinder.ProjectsDirectory, "BBB"), "BBB.fwdata"); m_fileOs.AddExistingFile(proj2); - string proj3 = Path.Combine(Path.Combine(DirectoryFinder.ProjectsDirectory, "AAA-01"), "AAA-01.fwdata"); + string proj3 = Path.Combine(Path.Combine(FwDirectoryFinder.ProjectsDirectory, "AAA-01"), "AAA-01.fwdata"); m_fileOs.AddExistingFile(proj3); - BackupProjectSettings backupSettings = new BackupProjectSettings(Cache, null); + BackupProjectSettings backupSettings = new BackupProjectSettings(Cache, null, FwDirectoryFinder.DefaultBackupDirectory); backupSettings.ProjectName = "AAA"; string backupFileName1 = backupSettings.ZipFileName; m_fileOs.AddExistingFile(backupFileName1); diff --git a/Src/FwCoreDlgs/FwDeleteProjectDlg.cs b/Src/FwCoreDlgs/FwDeleteProjectDlg.cs index 6685accd83..b8e9883d2d 100644 --- a/Src/FwCoreDlgs/FwDeleteProjectDlg.cs +++ b/Src/FwCoreDlgs/FwDeleteProjectDlg.cs @@ -74,7 +74,7 @@ private static IEnumerable GetLocalProjects(ICollection pro { // ProjectInfo.AllProjects doesn't set the InUse flag, which is why we // pass a list of open projects to the dialog constructor. - List projectList = ProjectInfo.AllProjects; + List projectList = ProjectInfo.GetAllProjects(FwDirectoryFinder.ProjectsDirectory); foreach (ProjectInfo info in projectList.Where(info => projectsOpen.Contains(info.DatabaseName))) info.InUse = true; return projectList; @@ -272,7 +272,7 @@ private void m_btnDelete_Click(object sender, System.EventArgs e) itemsToDelete.Add(info); foreach (ProjectInfo info in itemsToDelete) { - string folder = Path.Combine(DirectoryFinder.ProjectsDirectory, info.DatabaseName); + string folder = Path.Combine(FwDirectoryFinder.ProjectsDirectory, info.DatabaseName); bool fExtraData = CheckForExtraData(info, folder); string msg; MessageBoxButtons buttons; diff --git a/Src/FwCoreDlgs/FwFindReplaceDlg.cs b/Src/FwCoreDlgs/FwFindReplaceDlg.cs index 131844209a..178b816ebc 100644 --- a/Src/FwCoreDlgs/FwFindReplaceDlg.cs +++ b/Src/FwCoreDlgs/FwFindReplaceDlg.cs @@ -311,7 +311,7 @@ public bool SetDialogValues(FdoCache cache, IVwPattern vwPattern, IVwRootSite ro if (m_helpTopicProvider != null) // Will be null when running tests { - helpProvider.HelpNamespace = DirectoryFinder.FWCodeDirectory + + helpProvider.HelpNamespace = FwDirectoryFinder.CodeDirectory + m_helpTopicProvider.GetHelpString("UserHelpFile"); } diff --git a/Src/FwCoreDlgs/FwHelpAbout.cs b/Src/FwCoreDlgs/FwHelpAbout.cs index 5a1c7c9f13..b949f420d3 100644 --- a/Src/FwCoreDlgs/FwHelpAbout.cs +++ b/Src/FwCoreDlgs/FwHelpAbout.cs @@ -16,6 +16,7 @@ using System.IO; using System.Reflection; using System.Windows.Forms; +using SIL.CoreImpl; using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; using System.Diagnostics; @@ -297,10 +298,10 @@ protected override void OnHandleCreated(EventArgs e) try { // Set the Application label to the name of the app - FwVersionInfoProvider viProvider = new FwVersionInfoProvider(ProductExecutableAssembly, true); + VersionInfoProvider viProvider = new VersionInfoProvider(ProductExecutableAssembly, true); lblName.Text = viProvider.ProductName; lblAppVersion.Text = viProvider.ApplicationVersion; - lblFwVersion.Text = viProvider.FieldWorksVersion; + lblFwVersion.Text = viProvider.MajorVersion; lblCopyright.Text = viProvider.CopyrightString + Environment.NewLine + viProvider.LicenseString + Environment.NewLine + viProvider.LicenseURL; // Set the title bar text diff --git a/Src/FwCoreDlgs/FwNewLangProject.cs b/Src/FwCoreDlgs/FwNewLangProject.cs index b1b48df3b7..0784a409a8 100644 --- a/Src/FwCoreDlgs/FwNewLangProject.cs +++ b/Src/FwCoreDlgs/FwNewLangProject.cs @@ -63,7 +63,6 @@ public class FwNewLangProject : Form, IFWDisposable private Label m_lblSpecifyWrtSys; private HelpProvider helpProvider1; private string m_dbFile; - private IFdoUI m_ui; #endregion #region Properties @@ -141,7 +140,7 @@ public ProjectInfo Project /// Constructs a new instance of the class. /// /// ----------------------------------------------------------------------------------- - private FwNewLangProject() + public FwNewLangProject() { Logger.WriteEvent("Opening New Language Project dialog"); // @@ -149,7 +148,7 @@ private FwNewLangProject() // InitializeComponent(); AccessibleName = GetType().Name; - m_wsManager = new PalasoWritingSystemManager(new GlobalFileWritingSystemStore(DirectoryFinder.GlobalWritingSystemStoreDirectory)); + m_wsManager = new PalasoWritingSystemManager(new GlobalFileWritingSystemStore()); #if __MonoCS__ FixLabelFont(m_lblTip); FixLabelFont(m_lblAnalysisWrtSys); @@ -173,16 +172,6 @@ private void FixLabelFont(Label lbl) } #endif - /// ----------------------------------------------------------------------------------- - /// - /// Constructs a new instance of the class. - /// - /// ----------------------------------------------------------------------------------- - public FwNewLangProject(IFdoUI ui) : this() - { - m_ui = ui; - } - /// /// Check to see if the object has been disposed. /// All public Properties and Methods should call this @@ -533,7 +522,7 @@ private void btnOK_Click(object sender, EventArgs e) // Project with this name already exists? try { - m_projInfo = ProjectInfo.GetProjectInfoByName(ProjectName); + m_projInfo = ProjectInfo.GetProjectInfoByName(FwDirectoryFinder.ProjectsDirectory, ProjectName); } catch (IOException ex) { @@ -567,7 +556,7 @@ private void btnOK_Click(object sender, EventArgs e) // // Create new project // - CreateNewLangProjWithProgress(m_ui); + CreateNewLangProjWithProgress(); } private string RemoveNonAsciiCharsFromProjectName() @@ -674,7 +663,7 @@ private void m_btnNewAnalWrtSys_Click(object sender, EventArgs e) /// Create a new language project showing a progress dialog. /// /// ------------------------------------------------------------------------------------ - protected void CreateNewLangProjWithProgress(IFdoUI ui) + protected void CreateNewLangProjWithProgress() { try { @@ -694,8 +683,9 @@ protected void CreateNewLangProjWithProgress(IFdoUI ui) using (var threadHelper = new ThreadHelper()) { + m_dbFile = (string)progressDlg.RunTask(DisplayUi, FdoCache.CreateNewLangProj, - ProjectName, threadHelper, ui, m_cbAnalWrtSys.SelectedItem, + ProjectName, FwDirectoryFinder.FdoDirectories, threadHelper, m_cbAnalWrtSys.SelectedItem, m_cbVernWrtSys.SelectedItem, ((PalasoWritingSystem)m_wsManager.UserWritingSystem).RFC5646, m_newAnalysisWss, m_newVernWss, anthroFile); @@ -807,7 +797,7 @@ public DialogResult DisplayDialog(Form f) public static bool CheckProjectDirectory(Form f, IHelpTopicProvider helpTopicProvider) { string warning = null; - string dataDirectory = DirectoryFinder.ProjectsDirectory; + string dataDirectory = FwDirectoryFinder.ProjectsDirectory; // Get the database directory attributes: var dir = new DirectoryInfo(dataDirectory); @@ -822,17 +812,17 @@ public static bool CheckProjectDirectory(Form f, IHelpTopicProvider helpTopicPro { if (dlg.ShowDialog(f) != DialogResult.OK) return false; // can't go on. - if (DirectoryFinder.ProjectsDirectoryLocalMachine == dlg.ProjectsFolder) + if (FwDirectoryFinder.ProjectsDirectoryLocalMachine == dlg.ProjectsFolder) { //Remove the user override since they reset to the default. - DirectoryFinder.ProjectsDirectory = null; + FwDirectoryFinder.ProjectsDirectory = null; } else { - DirectoryFinder.ProjectsDirectory = dlg.ProjectsFolder; + FwDirectoryFinder.ProjectsDirectory = dlg.ProjectsFolder; } } - dataDirectory = DirectoryFinder.ProjectsDirectory; + dataDirectory = FwDirectoryFinder.ProjectsDirectory; dir = new DirectoryInfo(dataDirectory); // loop on the offchance it didn't get created. } @@ -908,7 +898,7 @@ private void UpdateLanguageCombos() // Make sure our manager knows about any writing systems in the template folder. // In pathological cases where no projects have been installed these might not be in the global store. - foreach (var templateLangFile in Directory.GetFiles(DirectoryFinder.TemplateDirectory, @"*.ldml")) + foreach (var templateLangFile in Directory.GetFiles(FwDirectoryFinder.TemplateDirectory, @"*.ldml")) { var id = Path.GetFileNameWithoutExtension(templateLangFile); IWritingSystem dummy; diff --git a/Src/FwCoreDlgs/MoveOrCopyFilesDlg.cs b/Src/FwCoreDlgs/MoveOrCopyFilesDlg.cs index 4064e454a3..568f416b1a 100644 --- a/Src/FwCoreDlgs/MoveOrCopyFilesDlg.cs +++ b/Src/FwCoreDlgs/MoveOrCopyFilesDlg.cs @@ -207,7 +207,7 @@ private void SetupHelp(IHelpTopicProvider helpTopicProvider, string sHelpTopic) m_sHelpTopic = sHelpTopic; if (m_helpTopicProvider != null) { - this.m_helpProvider.HelpNamespace = Path.Combine(DirectoryFinder.FWCodeDirectory, + this.m_helpProvider.HelpNamespace = Path.Combine(FwDirectoryFinder.CodeDirectory, m_helpTopicProvider.GetHelpString("UserHelpFile")); this.m_helpProvider.SetHelpKeyword(this, m_helpTopicProvider.GetHelpString(m_sHelpTopic)); this.m_helpProvider.SetHelpNavigator(this, HelpNavigator.Topic); diff --git a/Src/FwCoreDlgs/PicturePropertiesDialog.cs b/Src/FwCoreDlgs/PicturePropertiesDialog.cs index f504ea807e..70f4abeff7 100644 --- a/Src/FwCoreDlgs/PicturePropertiesDialog.cs +++ b/Src/FwCoreDlgs/PicturePropertiesDialog.cs @@ -128,7 +128,7 @@ public PicturePropertiesDialog(FdoCache cache, ICmPicture initialPicture, if (m_helpTopicProvider != null) // Could be null during tests { helpProvider = new HelpProvider(); - helpProvider.HelpNamespace = DirectoryFinder.FWCodeDirectory + + helpProvider.HelpNamespace = FwDirectoryFinder.CodeDirectory + m_helpTopicProvider.GetHelpString("UserHelpFile"); helpProvider.SetHelpKeyword(this, m_helpTopicProvider.GetHelpString(s_helpTopic)); helpProvider.SetHelpNavigator(this, HelpNavigator.Topic); diff --git a/Src/FwCoreDlgs/ProjectLocationSharingDlg.cs b/Src/FwCoreDlgs/ProjectLocationSharingDlg.cs index 236a7db04e..9db3761df4 100644 --- a/Src/FwCoreDlgs/ProjectLocationSharingDlg.cs +++ b/Src/FwCoreDlgs/ProjectLocationSharingDlg.cs @@ -65,7 +65,7 @@ public ProjectLocationSharingDlg(IHelpTopicProvider helpTopicProvider, FdoCache { m_tbCurrentProjectPath.Text = cache.ProjectId.Path; } - m_tbProjectsFolder.Text = DirectoryFinder.ProjectsDirectory; + m_tbProjectsFolder.Text = FwDirectoryFinder.ProjectsDirectory; // We can only change the folder if sharing is INITIALLY turned off. m_tbProjectsFolder.Enabled = !m_cbShareMyProjects.Checked; m_btnBrowseProjectFolder.Enabled = !m_cbShareMyProjects.Checked; @@ -82,7 +82,7 @@ private void m_tbProjectsFolder_TextChanged(object sender, EventArgs e) if (Directory.Exists(m_tbProjectsFolder.Text)) { var newFolder = m_tbProjectsFolder.Text; - var oldFolder = DirectoryFinder.ProjectsDirectory; + var oldFolder = FwDirectoryFinder.ProjectsDirectory; if (!MiscUtils.IsUnix) { newFolder = newFolder.ToLowerInvariant(); @@ -225,7 +225,7 @@ private void m_tbProjectsFolder_TextChanged(object sender, EventArgs e) /// ------------------------------------------------------------------------------------ private void m_btnBrowseProjectFolder_Click(object sender, EventArgs e) { - string defaultPath = DirectoryFinder.ProjectsDirectory; + string defaultPath = FwDirectoryFinder.ProjectsDirectory; using (var fldrBrowse = new FolderBrowserDialogAdapter()) { @@ -287,14 +287,14 @@ private void m_cbShareMyProjects_CheckedChanged(object sender, EventArgs e) // If we just turned it on, and it was on to start with, changing the project directory is not allowed; // revert any changes that have been made to that. if (m_cbShareMyProjects.Checked && ClientServerServices.Current.Local.ShareMyProjects) - m_tbProjectsFolder.Text = DirectoryFinder.ProjectsDirectory; + m_tbProjectsFolder.Text = FwDirectoryFinder.ProjectsDirectory; // Sharing can only be turned on if these directories are the same, because of complications when the ProjectsDirectory // seen by FieldWorks is different from the one seen by the FwRemoteDatabaseConnectorService. - if (m_cbShareMyProjects.Checked && DirectoryFinder.ProjectsDirectory != DirectoryFinder.ProjectsDirectoryLocalMachine) + if (m_cbShareMyProjects.Checked && FwDirectoryFinder.ProjectsDirectory != FwDirectoryFinder.ProjectsDirectoryLocalMachine) { MessageBox.Show(this, - string.Format(FwCoreDlgs.ksCantShareDiffProjectFolders, DirectoryFinder.ProjectsDirectory, - DirectoryFinder.ProjectsDirectoryLocalMachine), + string.Format(FwCoreDlgs.ksCantShareDiffProjectFolders, FwDirectoryFinder.ProjectsDirectory, + FwDirectoryFinder.ProjectsDirectoryLocalMachine), FwCoreDlgs.ksCantShare); m_cbShareMyProjects.Checked = false; } diff --git a/Src/FwCoreDlgs/PunctuationDlg.cs b/Src/FwCoreDlgs/PunctuationDlg.cs index 38b7738b8b..a937c2bf36 100644 --- a/Src/FwCoreDlgs/PunctuationDlg.cs +++ b/Src/FwCoreDlgs/PunctuationDlg.cs @@ -96,7 +96,7 @@ public PunctuationDlg(FdoCache cache, IWritingSystemContainer wsContainer, if (string.IsNullOrEmpty(wsName)) throw new ArgumentException("Writing system name must not be null or empty.", "wsName"); - m_validChars = ValidCharacters.Load(m_ws, LoadException); + m_validChars = ValidCharacters.Load(m_ws, LoadException, FwDirectoryFinder.LegacyWordformingCharOverridesFile); m_matchedPairList = MatchedPairList.Load(m_ws.MatchedPairs, wsName); m_patternList = PuncPatternsList.Load(m_ws.PunctuationPatterns, wsName); m_chrPropEng = LgIcuCharPropEngineClass.Create(); @@ -861,7 +861,7 @@ private bool ValidateQuotationMarks(QuotationMarksList qmarks) private void UpdateValidCharactersList() { bool validCharsUpdated = false; - ValidCharacters validChars = ValidCharacters.Load(m_ws, LoadException); + ValidCharacters validChars = ValidCharacters.Load(m_ws, LoadException, FwDirectoryFinder.LegacyWordformingCharOverridesFile); if (validChars == null) return; @@ -1497,7 +1497,7 @@ public class QuotationLangList : List internal static string s_customName = Properties.Resources.kstidCustomQuotationMarksName; private static string s_file = - Path.Combine(DirectoryFinder.FWCodeDirectory, "QuotationLanguages.xml"); + Path.Combine(FwDirectoryFinder.CodeDirectory, "QuotationLanguages.xml"); private QuotationLang m_customItem; diff --git a/Src/FwCoreDlgs/RealSplashScreen.cs b/Src/FwCoreDlgs/RealSplashScreen.cs index 6f9cbea1d2..004cb794b4 100644 --- a/Src/FwCoreDlgs/RealSplashScreen.cs +++ b/Src/FwCoreDlgs/RealSplashScreen.cs @@ -17,6 +17,7 @@ using System.Reflection; using System.Threading; using System.Windows.Forms; +using SIL.CoreImpl; using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; using SIL.FieldWorks.Common.Controls; @@ -351,11 +352,11 @@ protected void InitControlLabels() // Set the Application label to the name of the app if (m_productExecutableAssembly != null) { - FwVersionInfoProvider viProvider = new FwVersionInfoProvider(m_productExecutableAssembly, m_fDisplaySILInfo); + VersionInfoProvider viProvider = new VersionInfoProvider(m_productExecutableAssembly, m_fDisplaySILInfo); lblProductName.Text = viProvider.ProductName; Text = lblProductName.Text; lblAppVersion.Text = viProvider.ApplicationVersion; - lblFwVersion.Text = viProvider.FieldWorksVersion; + lblFwVersion.Text = viProvider.MajorVersion; lblCopyright.Text = viProvider.CopyrightString + Environment.NewLine + viProvider.LicenseString; } } diff --git a/Src/FwCoreDlgs/UtilityDlg.cs b/Src/FwCoreDlgs/UtilityDlg.cs index 3b29065a3a..55818b5d04 100644 --- a/Src/FwCoreDlgs/UtilityDlg.cs +++ b/Src/FwCoreDlgs/UtilityDlg.cs @@ -58,7 +58,7 @@ public UtilityDlg(IHelpTopicProvider helpTopicProvider) m_helpTopicProvider = helpTopicProvider; helpProvider = new HelpProvider(); - helpProvider.HelpNamespace = DirectoryFinder.FWCodeDirectory + m_helpTopicProvider.GetHelpString("UserHelpFile"); + helpProvider.HelpNamespace = FwDirectoryFinder.CodeDirectory + m_helpTopicProvider.GetHelpString("UserHelpFile"); helpProvider.SetHelpKeyword(this, m_helpTopicProvider.GetHelpString(s_helpTopic)); helpProvider.SetHelpNavigator(this, HelpNavigator.Topic); @@ -194,7 +194,7 @@ public void SetDlgInfo(Mediator mediator, XmlNode configurationParameters) // this.Text = XmlUtils.GetLocalizedAttributeValue(mediator.StringTbl, configurationParameters, "title", "FieldWorks Project Utilities"); - string utilsPathname = Path.Combine(DirectoryFinder.FWCodeDirectory, + string utilsPathname = Path.Combine(FwDirectoryFinder.CodeDirectory, XmlUtils.GetManditoryAttributeValue(configurationParameters, "filename")); // Get the folder path: string utilsFolderName = Path.GetDirectoryName(utilsPathname); diff --git a/Src/FwCoreDlgs/ValidCharactersDlg.cs b/Src/FwCoreDlgs/ValidCharactersDlg.cs index 857e9d1003..4a34174bfa 100644 --- a/Src/FwCoreDlgs/ValidCharactersDlg.cs +++ b/Src/FwCoreDlgs/ValidCharactersDlg.cs @@ -24,7 +24,6 @@ using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; -using System.Windows.Forms.VisualStyles; using Palaso.WritingSystems; using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; @@ -77,7 +76,7 @@ protected internal class ValidCharGridsManager : IDisposable /// --------------------------------------------------------------------------------- /// - /// Constructs a new instance of the class. + /// Constructs a new instance of the class. /// /// --------------------------------------------------------------------------------- public ValidCharGridsManager() @@ -139,7 +138,7 @@ internal void Init(CharacterGrid gridWf, CharacterGrid gridOther, CharacterGrid m_gridWordForming = gridWf; m_gridNumbers = gridNum; m_gridOther = gridOther; - m_validChars = ValidCharacters.Load(ws, LoadException); + m_validChars = ValidCharacters.Load(ws, LoadException, FwDirectoryFinder.LegacyWordformingCharOverridesFile); RefreshCharacterGrids(ValidCharacterType.All); } @@ -674,7 +673,7 @@ internal void HandleRemoveClick(object sender, EventArgs e) #region Contructors /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// ------------------------------------------------------------------------------------ public ValidCharactersDlg() @@ -706,7 +705,7 @@ public ValidCharactersDlg() /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The cache. Can be null if called from New Project /// dialog. @@ -2020,7 +2019,7 @@ public class CharacterInventoryRow /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The character for this inventory row. /// ------------------------------------------------------------------------------------ diff --git a/Src/LexText/Discourse/ConstChartBody.cs b/Src/LexText/Discourse/ConstChartBody.cs index caf4e4095f..8761bb8994 100644 --- a/Src/LexText/Discourse/ConstChartBody.cs +++ b/Src/LexText/Discourse/ConstChartBody.cs @@ -617,7 +617,7 @@ internal ITsString SpaceString private void LoadFormatProps() { var doc = new XmlDocument(); - var path = Path.Combine(DirectoryFinder.FWCodeDirectory, @"Language Explorer/Configuration/ConstituentChartStyleInfo.xml"); + var path = Path.Combine(FwDirectoryFinder.CodeDirectory, @"Language Explorer/Configuration/ConstituentChartStyleInfo.xml"); if (!File.Exists(path)) return; doc.Load(path); diff --git a/Src/LexText/Discourse/Discourse.csproj b/Src/LexText/Discourse/Discourse.csproj index b565a5ebcf..bcc912ca49 100644 --- a/Src/LexText/Discourse/Discourse.csproj +++ b/Src/LexText/Discourse/Discourse.csproj @@ -1,221 +1,227 @@  - Debug - AnyCPU - 9.0.21022 - 2.0 - {28F1B78C-204A-41AF-8BDE-FECAD6559AAD} - Library - Properties - SIL.FieldWorks.Discourse - Discourse - - - 3.5 - v4.0 - - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - + Debug + AnyCPU + 9.0.21022 + 2.0 + {28F1B78C-204A-41AF-8BDE-FECAD6559AAD} + Library + Properties + SIL.FieldWorks.Discourse + Discourse + + + 3.5 + v4.0 + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + - true - full - false - 168,169,219,414,649,1635,1702,1701 - ..\..\..\Output\Debug\ - DEBUG;TRACE - prompt - 4 - - - true - AllRules.ruleset - x86 + true + full + false + 168,169,219,414,649,1635,1702,1701 + ..\..\..\Output\Debug\ + DEBUG;TRACE + prompt + 4 + + + true + AllRules.ruleset + x86 - pdbonly - true - 168,169,219,414,649,1635,1702,1701 - ..\..\..\Output\Release\ - TRACE - prompt - 4 - AllRules.ruleset - x86 + pdbonly + true + 168,169,219,414,649,1635,1702,1701 + ..\..\..\Output\Release\ + TRACE + prompt + 4 + AllRules.ruleset + x86 - - False - ..\..\..\Output\Debug\BasicUtils.dll - - - False - ..\..\..\Output\Debug\COMInterfaces.dll - - - False - ..\..\..\Output\Debug\CoreImpl.dll - - - False - ..\..\..\Output\Debug\FDO.dll - - - False - ..\..\..\Output\Debug\Framework.dll - - - False - ..\..\..\Output\Debug\FwControls.dll - - - False - ..\..\..\Output\Debug\FwResources.dll - - - False - ..\..\..\Output\Debug\FwUtils.dll - - - False - ..\..\..\Lib\debug\ICSharpCode.SharpZipLib.dll - - - False - ..\..\..\Output\Debug\ITextDll.dll - - - False - - - False - ..\..\..\Output\Debug\RootSite.dll - - - False - - - False - ..\..\..\Output\Debug\SimpleRootSite.dll - - - - - - - - - False - ..\..\..\Output\Debug\xCore.dll - - - False - ..\..\..\Output\Debug\xCoreInterfaces.dll - - - False - ..\..\..\Output\Debug\XMLUtils.dll - - - False - ..\..\..\Output\Debug\xWorks.dll - + + False + ..\..\..\Output\Debug\BasicUtils.dll + + + False + ..\..\..\Output\Debug\COMInterfaces.dll + + + False + ..\..\..\Output\Debug\CoreImpl.dll + + + False + ..\..\..\Output\Debug\FDO.dll + + + False + ..\..\..\Output\Debug\Framework.dll + + + False + ..\..\..\Output\Debug\FwControls.dll + + + False + ..\..\..\Output\Debug\FwResources.dll + + + False + ..\..\..\Output\Debug\FwUtils.dll + + + False + ..\..\..\Lib\debug\ICSharpCode.SharpZipLib.dll + + + False + ..\..\..\Output\Debug\ITextDll.dll + + + False + + + False + ..\..\..\Output\Debug\RootSite.dll + + + False + + + False + ..\..\..\Output\Debug\SimpleRootSite.dll + + + + + + + + + False + ..\..\..\Output\Debug\xCore.dll + + + False + ..\..\..\Output\Debug\xCoreInterfaces.dll + + + False + ..\..\..\Output\Debug\XMLUtils.dll + + + False + ..\..\..\Output\Debug\xWorks.dll + - - Properties\CommonAssemblyInfo.cs - - - Form - - - AdvancedMTDialog.cs - - - - - - Component - - - ConstituentChart.cs - - - Component - - - - - - - - - DiscourseStrings.resx - True - True - - - Form - - - SelectClausesDialog.cs - + + Properties\CommonAssemblyInfo.cs + + + Form + + + AdvancedMTDialog.cs + + + + UserControl + + + + UserControl + + + ConstituentChart.cs + + + Component + + + Form + + + + UserControl + + + + + + DiscourseStrings.resx + True + True + + + Form + + + SelectClausesDialog.cs + - - AdvancedMTDialog.cs - Designer - - - ConstChartBody.cs - Designer - - - ConstituentChart.cs - Designer - - - Designer - ResXFileCodeGenerator - DiscourseStrings.Designer.cs - - - SelectClausesDialog.cs - Designer - + + AdvancedMTDialog.cs + Designer + + + ConstChartBody.cs + Designer + + + ConstituentChart.cs + Designer + + + Designer + ResXFileCodeGenerator + DiscourseStrings.Designer.cs + + + SelectClausesDialog.cs + Designer + - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + --> - + + + + + + From a4d03edeb7df4688b788c73da20ddee94d2ef91e Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Thu, 19 Dec 2013 11:00:24 +0700 Subject: [PATCH 044/143] Combined FwKernel and Language COM DLLs Change-Id: I0fbc98c6ea11bc954a510c482554f9439026b40d --- Bld/_init.mak.lnx | 4 - Bld/_names.mak | 1 - Build/Linux.targets | 6 +- Build/Windows.targets | 3 +- Build/mkall.targets | 71 +-- Lib/linux/Common/FwKernelTlb.h | 4 +- Lib/linux/Common/FwKernelTlb.idl | 46 +- Lib/linux/Common/FwKernelTlb.tlb | Bin 95028 -> 95028 bytes Lib/linux/Common/ViewsTlb.h | 4 +- Lib/linux/Common/ViewsTlb.idl | 46 +- Lib/linux/Common/ViewsTlb.tlb | Bin 83976 -> 83976 bytes Lib/linux/Common/idhfiles.MD5 | 2 +- Src/Common/COMInterfaces/BuildInclude.targets | 4 +- Src/Generic/Generic.rc | 1 + Src/Kernel/FwKernel.mak | 23 +- Src/Kernel/FwKernel.rc | 383 ++++++++++++++- Src/Kernel/FwKernelPs.idl | 2 +- Src/Kernel/FwKernelTlb.idl | 2 +- Src/Kernel/Kernel.vcxproj | 173 ++++--- Src/Kernel/Kernel.vcxproj.filters | 252 ++++++---- Src/{Language => Kernel}/LangResource.h | 0 Src/{Language => Kernel}/Language.idh | 0 .../LgIcuCharPropEngine.cpp | 0 .../LgIcuCharPropEngine.h | 0 .../LgIcuCharPropertyInit.h | 0 Src/{Language => Kernel}/LgIcuWrappers.cpp | 0 Src/{Language => Kernel}/LgIcuWrappers.h | 0 Src/{Language => Kernel}/LgKeymanHandler.cpp | 0 Src/{Language => Kernel}/LgKeymanHandler.h | 0 Src/{Language => Kernel}/LgNumericEngine.cpp | 0 Src/{Language => Kernel}/LgNumericEngine.h | 0 Src/{Language => Kernel}/LgSimpleEngines.cpp | 0 Src/{Language => Kernel}/LgSimpleEngines.h | 0 .../LgUnicodeCollateInit.h | 0 .../LgUnicodeCollater.cpp | 0 Src/{Language => Kernel}/LgUnicodeCollater.h | 0 Src/{Language => Kernel}/LocaleIndex.cpp | 0 Src/{Language => Kernel}/LocaleIndex.h | 0 Src/Kernel/Main.h | 90 ++++ Src/Kernel/Makefile | 22 +- .../RegexMatcherWrapper.cpp | 0 .../RegexMatcherWrapper.h | 0 Src/{Language => Kernel}/Render.idh | 0 Src/{Language => Kernel}/RomRenderEngine.cpp | 0 Src/{Language => Kernel}/RomRenderEngine.h | 0 Src/{Language => Kernel}/RomRenderSegment.cpp | 0 Src/{Language => Kernel}/RomRenderSegment.h | 0 Src/Kernel/Test/Makefile | 21 +- .../Test/MockLgWritingSystem.h | 0 .../Test/MockLgWritingSystemFactory.h | 0 .../Test/RenderEngineTestBase.h | 6 +- Src/Kernel/Test/TestKernel.vcxproj | 114 +++-- Src/Kernel/Test/TestKernel.vcxproj.filters | 99 ++-- .../Test/TestLgCollatingEngine.h | 4 +- .../Test/TestLgIcuCharPropEngine.h | 4 +- .../Test/TestRegexMatcher.h | 4 +- .../Test/TestRomRenderEngine.h | 4 +- .../Test/TestUniscribeEngine.h | 4 +- Src/Kernel/Test/testFwKernel.cpp | 11 +- Src/Kernel/Test/testFwKernel.h | 8 + Src/Kernel/Test/testFwKernel.mak | 32 +- Src/{Language => Kernel}/UniscribeEngine.cpp | 0 Src/{Language => Kernel}/UniscribeEngine.h | 0 Src/{Language => Kernel}/UniscribeLinux.cpp | 0 Src/{Language => Kernel}/UniscribeLinux.h | 0 Src/{Language => Kernel}/UniscribeSegment.cpp | 0 Src/{Language => Kernel}/UniscribeSegment.h | 0 Src/Language/LangInstaller.idl | 48 -- Src/Language/Language.def | 8 - Src/Language/Language.mak | 135 ------ Src/Language/Language.rc | 444 ------------------ Src/Language/Language.vcxproj | 140 ------ Src/Language/LanguageExtra_GUIDs.cpp | 10 - Src/Language/LanguagePs.idl | 24 - Src/Language/LanguageTlb.idl | 34 -- Src/Language/Language_GUIDs.cpp | 71 --- Src/Language/Main.h | 200 -------- Src/Language/Makefile | 193 -------- Src/Language/Test/Makefile | 129 ----- Src/Language/Test/TestLanguage.vcxproj | 90 ---- .../Test/TestLanguage.vcxproj.filters | 52 -- Src/Language/Test/testLanguage.cpp | 54 --- Src/Language/Test/testLanguage.h | 53 --- Src/Language/Test/testLanguage.mak | 108 ----- Src/Language/dlldatax.c | 11 - Src/Language/mklg.bat | 12 - Src/views/Test/Makefile | 8 +- Src/views/Test/TestViews.vcxproj | 148 +++--- Src/views/Test/TestViews.vcxproj.filters | 197 ++++---- Src/views/Test/testViews.mak | 8 +- Src/views/Views.mak | 4 +- Src/views/views.vcxproj | 1 + Src/views/views.vcxproj.filters | 1 + 93 files changed, 1229 insertions(+), 2404 deletions(-) rename Src/{Language => Kernel}/LangResource.h (100%) rename Src/{Language => Kernel}/Language.idh (100%) rename Src/{Language => Kernel}/LgIcuCharPropEngine.cpp (100%) rename Src/{Language => Kernel}/LgIcuCharPropEngine.h (100%) rename Src/{Language => Kernel}/LgIcuCharPropertyInit.h (100%) rename Src/{Language => Kernel}/LgIcuWrappers.cpp (100%) rename Src/{Language => Kernel}/LgIcuWrappers.h (100%) rename Src/{Language => Kernel}/LgKeymanHandler.cpp (100%) rename Src/{Language => Kernel}/LgKeymanHandler.h (100%) rename Src/{Language => Kernel}/LgNumericEngine.cpp (100%) rename Src/{Language => Kernel}/LgNumericEngine.h (100%) rename Src/{Language => Kernel}/LgSimpleEngines.cpp (100%) rename Src/{Language => Kernel}/LgSimpleEngines.h (100%) rename Src/{Language => Kernel}/LgUnicodeCollateInit.h (100%) rename Src/{Language => Kernel}/LgUnicodeCollater.cpp (100%) rename Src/{Language => Kernel}/LgUnicodeCollater.h (100%) rename Src/{Language => Kernel}/LocaleIndex.cpp (100%) rename Src/{Language => Kernel}/LocaleIndex.h (100%) rename Src/{Language => Kernel}/RegexMatcherWrapper.cpp (100%) rename Src/{Language => Kernel}/RegexMatcherWrapper.h (100%) rename Src/{Language => Kernel}/Render.idh (100%) rename Src/{Language => Kernel}/RomRenderEngine.cpp (100%) rename Src/{Language => Kernel}/RomRenderEngine.h (100%) rename Src/{Language => Kernel}/RomRenderSegment.cpp (100%) rename Src/{Language => Kernel}/RomRenderSegment.h (100%) rename Src/{Language => Kernel}/Test/MockLgWritingSystem.h (100%) rename Src/{Language => Kernel}/Test/MockLgWritingSystemFactory.h (100%) rename Src/{Language => Kernel}/Test/RenderEngineTestBase.h (99%) rename Src/{Language => Kernel}/Test/TestLgCollatingEngine.h (98%) rename Src/{Language => Kernel}/Test/TestLgIcuCharPropEngine.h (99%) rename Src/{Language => Kernel}/Test/TestRegexMatcher.h (98%) rename Src/{Language => Kernel}/Test/TestRomRenderEngine.h (97%) rename Src/{Language => Kernel}/Test/TestUniscribeEngine.h (97%) rename Src/{Language => Kernel}/UniscribeEngine.cpp (100%) rename Src/{Language => Kernel}/UniscribeEngine.h (100%) rename Src/{Language => Kernel}/UniscribeLinux.cpp (100%) rename Src/{Language => Kernel}/UniscribeLinux.h (100%) rename Src/{Language => Kernel}/UniscribeSegment.cpp (100%) rename Src/{Language => Kernel}/UniscribeSegment.h (100%) delete mode 100644 Src/Language/LangInstaller.idl delete mode 100644 Src/Language/Language.def delete mode 100644 Src/Language/Language.mak delete mode 100644 Src/Language/Language.rc delete mode 100644 Src/Language/Language.vcxproj delete mode 100644 Src/Language/LanguageExtra_GUIDs.cpp delete mode 100644 Src/Language/LanguagePs.idl delete mode 100644 Src/Language/LanguageTlb.idl delete mode 100644 Src/Language/Language_GUIDs.cpp delete mode 100644 Src/Language/Main.h delete mode 100644 Src/Language/Makefile delete mode 100644 Src/Language/Test/Makefile delete mode 100644 Src/Language/Test/TestLanguage.vcxproj delete mode 100644 Src/Language/Test/TestLanguage.vcxproj.filters delete mode 100644 Src/Language/Test/testLanguage.cpp delete mode 100644 Src/Language/Test/testLanguage.h delete mode 100644 Src/Language/Test/testLanguage.mak delete mode 100644 Src/Language/dlldatax.c delete mode 100755 Src/Language/mklg.bat diff --git a/Bld/_init.mak.lnx b/Bld/_init.mak.lnx index e203117631..4adba00be8 100644 --- a/Bld/_init.mak.lnx +++ b/Bld/_init.mak.lnx @@ -62,24 +62,20 @@ include $(BUILD_ROOT)/Bld/_rule.mak.lnx DEBUGPROCS_OBJ = $(OBJ_DIR)/$(BUILD_CONFIG)/$(DEBUGPROCS_NAME) GENERIC_OBJ = $(OBJ_DIR)/$(BUILD_CONFIG)/$(GENERIC_NAME) KERNEL_OBJ = $(OBJ_DIR)/$(BUILD_CONFIG)/$(KERNEL_NAME) -LANGUAGE_OBJ= $(OBJ_DIR)/$(BUILD_CONFIG)/$(LANGUAGE_NAME) APPCORE_OBJ= $(OBJ_DIR)/$(BUILD_CONFIG)/$(APPCORE_NAME) TEXT_OBJ= $(OBJ_DIR)/$(BUILD_CONFIG)/$(TEXT_NAME) CELLAR_OBJ= $(OBJ_DIR)/$(BUILD_CONFIG)/$(CELLAR_NAME) GRENGINE_OBJ= $(OBJ_DIR)/$(BUILD_CONFIG)/$(GRENGINE_NAME) VIEWS_OBJ= $(OBJ_DIR)/$(BUILD_CONFIG)/$(VIEWS_NAME) -DBACCESS_OBJ= $(OBJ_DIR)/$(BUILD_CONFIG)/$(DBACCESS_NAME) DEBUGPROCS_SRC = $(SRC)/$(DEBUGPROCS_NAME) GENERIC_SRC = $(SRC)/$(GENERIC_NAME) KERNEL_SRC = $(SRC)/$(KERNEL_NAME) -LANGUAGE_SRC = $(SRC)/$(LANGUAGE_NAME) APPCORE_SRC = $(SRC)/$(APPCORE_NAME) TEXT_SRC = $(SRC)/$(TEXT_NAME) CELLAR_SRC = $(SRC)/$(CELLAR_NAME) GRENGINE_SRC = $(SRC)/Graphite/$(GRENGINE_NAME) VIEWS_SRC = $(SRC)/$(VIEWS_NAME) -DBACCESS_SRC = $(SRC)/$(DBACCESS_NAME) # Include user specific settings -include $(BUILD_ROOT)/Bld/_user.mak.lnx diff --git a/Bld/_names.mak b/Bld/_names.mak index 768ba7e8ac..29f296c3d0 100644 --- a/Bld/_names.mak +++ b/Bld/_names.mak @@ -7,7 +7,6 @@ KERNEL_NAME =Kernel GENERIC_NAME =Generic GRENGINE_NAME =GrEngine FDO_NAME =FDO -LANGUAGE_NAME =Language FWRESOURCES_NAME =FwResources TEXT_NAME =Text VIEWS_NAME =views diff --git a/Build/Linux.targets b/Build/Linux.targets index 568f025ffb..992e0b5a84 100644 --- a/Build/Linux.targets +++ b/Build/Linux.targets @@ -121,9 +121,8 @@ - - - + + @@ -161,7 +160,6 @@ - diff --git a/Build/Windows.targets b/Build/Windows.targets index 79acd1e5fb..9950cebe76 100644 --- a/Build/Windows.targets +++ b/Build/Windows.targets @@ -100,9 +100,8 @@ --> - + - diff --git a/Build/mkall.targets b/Build/mkall.targets index e1f9cb935a..40d2899b0c 100644 --- a/Build/mkall.targets +++ b/Build/mkall.targets @@ -14,13 +14,13 @@ - + - + @@ -30,10 +30,10 @@ - + @@ -77,7 +77,7 @@ BuildRoot="$(fwrt)" WorkingDirectory="$(fwrt)/Src/Generic/Test" ContinueOnError="true"/> - + - - - - - - - - - - - - - - - - - - - - - - - + - kY* delta 45 zcmdn;jCIR1)(y=^6bua%3{9;}4XsQ~6pRcEjk$ywvfK1GFFZ1N9RPb) B50C%= diff --git a/Lib/linux/Common/ViewsTlb.h b/Lib/linux/Common/ViewsTlb.h index a856b4b653..2af620100e 100644 --- a/Lib/linux/Common/ViewsTlb.h +++ b/Lib/linux/Common/ViewsTlb.h @@ -4,9 +4,9 @@ /* File created by MIDL compiler version 7.00.0555 */ -/* at Tue Sep 10 15:51:55 2013 +/* at Wed Dec 18 12:35:05 2013 */ -/* Compiler settings for C:\fwrepo\fw\Output\Common\ViewsTlb.idl: +/* Compiler settings for C:\develop\fwrepo\fw\Output\Common\ViewsTlb.idl: Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 7.00.0555 protocol : dce , ms_ext, c_ext, robust error checks: allocation ref bounds_check enum stub_data diff --git a/Lib/linux/Common/ViewsTlb.idl b/Lib/linux/Common/ViewsTlb.idl index bac77d9218..dcc705fc08 100644 --- a/Lib/linux/Common/ViewsTlb.idl +++ b/Lib/linux/Common/ViewsTlb.idl @@ -1,4 +1,4 @@ -#line 1 "C:\\fwrepo\\fw\\Src\\Views\\ViewsTlb.idl" +#line 1 "C:\\develop\\fwrepo\\fw\\Src\\Views\\ViewsTlb.idl" @@ -18,7 +18,7 @@ import "oaidl.idl"; import "ocidl.idl"; import "objidl.idl"; -#line 1 "C:\\fwrepo\\fw\\Src\\Generic\\common.idh" +#line 1 "C:\\develop\\fwrepo\\fw\\Src\\Generic\\common.idh" @@ -122,15 +122,15 @@ cpp_quote("// This is for code that uses a 64-bit integer for SilTime.") cpp_quote("typedef __int64 SilTime;") cpp_quote("#endif") cpp_quote("") -#line 21 "C:\\fwrepo\\fw\\Src\\Views\\ViewsTlb.idl" +#line 21 "C:\\develop\\fwrepo\\fw\\Src\\Views\\ViewsTlb.idl" cpp_quote("ATTACH_GUID_TO_CLASS(class,") cpp_quote("f6d10640-c00c-11d2-8078-0000c0fb81b5") cpp_quote(",") cpp_quote("Views") cpp_quote(");") [ uuid(f6d10640-c00c-11d2-8078-0000c0fb81b5), version(1.0), helpstring("Views 1.0 Type Library") ] library Views -#line 24 "C:\\fwrepo\\fw\\Src\\Views\\ViewsTlb.idl" +#line 24 "C:\\develop\\fwrepo\\fw\\Src\\Views\\ViewsTlb.idl" { importlib("FwKernelTlb.tlb"); - #line 1 "c:\\fwrepo\\fw\\src\\views\\Views.idh" + #line 1 "c:\\develop\\fwrepo\\fw\\src\\views\\Views.idh" @@ -1514,7 +1514,7 @@ cpp_quote("ATTACH_GUID_TO_CLASS(class,") cpp_quote("f6d10640-c00c-11d2-8078-0000 interface IVwCacheDa; interface IStructuredTextDataAccess; }; - #line 1385 "c:\\fwrepo\\fw\\src\\views\\Views.idh" + #line 1385 "c:\\develop\\fwrepo\\fw\\src\\views\\Views.idh" @@ -1728,7 +1728,7 @@ cpp_quote("ATTACH_GUID_TO_CLASS(class,") cpp_quote("f6d10640-c00c-11d2-8078-0000 -#line 1599 "c:\\fwrepo\\fw\\src\\views\\Views.idh" +#line 1599 "c:\\develop\\fwrepo\\fw\\src\\views\\Views.idh" @@ -2530,7 +2530,7 @@ cpp_quote("ATTACH_GUID_TO_CLASS(class,") cpp_quote("f6d10640-c00c-11d2-8078-0000 { interface IVwRootBox; }; -#line 2401 "c:\\fwrepo\\fw\\src\\views\\Views.idh" +#line 2401 "c:\\develop\\fwrepo\\fw\\src\\views\\Views.idh" @@ -4376,14 +4376,14 @@ cpp_quote("ATTACH_GUID_TO_CLASS(class,") cpp_quote("f6d10640-c00c-11d2-8078-0000 -#line 4247 "c:\\fwrepo\\fw\\src\\views\\Views.idh" +#line 4247 "c:\\develop\\fwrepo\\fw\\src\\views\\Views.idh" }; cpp_quote("ATTACH_GUID_TO_CLASS(class,") cpp_quote("CCE2A7ED-464C-4ec7-A0B0-E3C1F6B94C5A") cpp_quote(",") cpp_quote("VwStylesheet") cpp_quote(");") [ uuid(CCE2A7ED-464C-4ec7-A0B0-E3C1F6B94C5A) ] coclass VwStylesheet { interface IVwStylesheet; }; -#line 4254 "c:\\fwrepo\\fw\\src\\views\\Views.idh" +#line 4254 "c:\\develop\\fwrepo\\fw\\src\\views\\Views.idh" @@ -4460,7 +4460,7 @@ cpp_quote("ATTACH_GUID_TO_CLASS(class,") cpp_quote("f6d10640-c00c-11d2-8078-0000 { interface IVwPropertyStore; }; - #line 4331 "c:\\fwrepo\\fw\\src\\views\\Views.idh" + #line 4331 "c:\\develop\\fwrepo\\fw\\src\\views\\Views.idh" typedef [v1_enum] enum VwOverlayFlags @@ -4744,7 +4744,7 @@ cpp_quote("ATTACH_GUID_TO_CLASS(class,") cpp_quote("f6d10640-c00c-11d2-8078-0000 { interface IVwOverlay; }; - #line 4615 "c:\\fwrepo\\fw\\src\\views\\Views.idh" + #line 4615 "c:\\develop\\fwrepo\\fw\\src\\views\\Views.idh" @@ -4956,7 +4956,7 @@ cpp_quote("ATTACH_GUID_TO_CLASS(class,") cpp_quote("f6d10640-c00c-11d2-8078-0000 { interface IVwPrintContext; }; - #line 4827 "c:\\fwrepo\\fw\\src\\views\\Views.idh" + #line 4827 "c:\\develop\\fwrepo\\fw\\src\\views\\Views.idh" @@ -5267,7 +5267,7 @@ cpp_quote("ATTACH_GUID_TO_CLASS(class,") cpp_quote("f6d10640-c00c-11d2-8078-0000 { interface IVwPattern; }; - #line 5138 "c:\\fwrepo\\fw\\src\\views\\Views.idh" + #line 5138 "c:\\develop\\fwrepo\\fw\\src\\views\\Views.idh" @@ -5301,7 +5301,7 @@ cpp_quote("ATTACH_GUID_TO_CLASS(class,") cpp_quote("f6d10640-c00c-11d2-8078-0000 interface IVwTxtSrcInit2; interface IVwTextSource; }; - #line 5172 "c:\\fwrepo\\fw\\src\\views\\Views.idh" + #line 5172 "c:\\develop\\fwrepo\\fw\\src\\views\\Views.idh" @@ -5333,7 +5333,7 @@ cpp_quote("ATTACH_GUID_TO_CLASS(class,") cpp_quote("f6d10640-c00c-11d2-8078-0000 interface IVwTxtSrcInit; interface IVwTextSource; }; - #line 5204 "c:\\fwrepo\\fw\\src\\views\\Views.idh" + #line 5204 "c:\\develop\\fwrepo\\fw\\src\\views\\Views.idh" @@ -5375,7 +5375,7 @@ cpp_quote("ATTACH_GUID_TO_CLASS(class,") cpp_quote("f6d10640-c00c-11d2-8078-0000 { interface IVwSearchKiller; }; - #line 5246 "c:\\fwrepo\\fw\\src\\views\\Views.idh" + #line 5246 "c:\\develop\\fwrepo\\fw\\src\\views\\Views.idh" @@ -5455,7 +5455,7 @@ cpp_quote("ATTACH_GUID_TO_CLASS(class,") cpp_quote("f6d10640-c00c-11d2-8078-0000 { interface IVwDrawRootBuffered; }; - #line 5326 "c:\\fwrepo\\fw\\src\\views\\Views.idh" + #line 5326 "c:\\develop\\fwrepo\\fw\\src\\views\\Views.idh" @@ -5503,7 +5503,7 @@ cpp_quote("ATTACH_GUID_TO_CLASS(class,") cpp_quote("f6d10640-c00c-11d2-8078-0000 { interface IVwSynchronizer; }; - #line 5374 "c:\\fwrepo\\fw\\src\\views\\Views.idh" + #line 5374 "c:\\develop\\fwrepo\\fw\\src\\views\\Views.idh" @@ -5672,7 +5672,7 @@ cpp_quote("ATTACH_GUID_TO_CLASS(class,") cpp_quote("1CD09E06-6978-4969-A1FC-4627 { interface IVwLayoutStream; }; -#line 5543 "c:\\fwrepo\\fw\\src\\views\\Views.idh" +#line 5543 "c:\\develop\\fwrepo\\fw\\src\\views\\Views.idh" @@ -5785,7 +5785,7 @@ cpp_quote("GENERIC_DECLARE_SMART_INTERFACE_PTR(") cpp_quote("IVwLayoutManager") { interface IPictureFactory; }; -#line 5656 "c:\\fwrepo\\fw\\src\\views\\Views.idh" +#line 5656 "c:\\develop\\fwrepo\\fw\\src\\views\\Views.idh" @@ -6019,7 +6019,7 @@ cpp_quote("GENERIC_DECLARE_SMART_INTERFACE_PTR(") cpp_quote("IVwLayoutManager") { interface IVwWindow; }; - #line 5890 "c:\\fwrepo\\fw\\src\\views\\Views.idh" + #line 5890 "c:\\develop\\fwrepo\\fw\\src\\views\\Views.idh" typedef [v1_enum] enum VwMouseEvent @@ -6088,6 +6088,6 @@ cpp_quote("GENERIC_DECLARE_SMART_INTERFACE_PTR(") cpp_quote("IViewInputMgr") cpp HRESULT OnTextChange(); } -#line 29 "C:\\fwrepo\\fw\\Src\\Views\\ViewsTlb.idl" +#line 29 "C:\\develop\\fwrepo\\fw\\Src\\Views\\ViewsTlb.idl" }; diff --git a/Lib/linux/Common/ViewsTlb.tlb b/Lib/linux/Common/ViewsTlb.tlb index 0e8bd010126e4837e87674ca71e7a4d83aff6df5..ed237cfa57af386a55abc3d72e9f08bb418b2604 100644 GIT binary patch delta 45 zcmeB}z}hi^b%XFqx$x8!1((!h1w#u3LnA9=Q!4{g1tSAPV=iF^PLqwB4Od>D2LLj- B4N(99 delta 45 zcmeB}z}hi^b%XFqxscLSh2Ycz1w#V`LsKhLLn~8L1tSAPV=iHaoHqT - - + + diff --git a/Src/Generic/Generic.rc b/Src/Generic/Generic.rc index ca3c11cd9b..b496a1b6b5 100644 --- a/Src/Generic/Generic.rc +++ b/Src/Generic/Generic.rc @@ -1,4 +1,5 @@ // Resources used by generic code +#include "GenericResource.h" // TODO DevLeader(JohnT): move these out of AppCore; include this file everywhere it's needed. STRINGTABLE DISCARDABLE diff --git a/Src/Kernel/FwKernel.mak b/Src/Kernel/FwKernel.mak index bfbbceeaa6..fff387ca69 100644 --- a/Src/Kernel/FwKernel.mak +++ b/Src/Kernel/FwKernel.mak @@ -15,13 +15,10 @@ FWKERNEL_SRC=$(BUILD_ROOT)\src\Kernel GENERIC_SRC=$(BUILD_ROOT)\src\Generic APPCORE_SRC=$(BUILD_ROOT)\src\AppCore DEBUGPROCS_SRC=$(BUILD_ROOT)\src\DebugProcs - +CELLAR_SRC=$(BUILD_ROOT)\Src\Cellar # Set the USER_INCLUDE environment variable. -UI=$(FWKERNEL_SRC);$(GENERIC_SRC);$(APPCORE_SRC);$(DEBUGPROCS_SRC) - -LANGUAGE_SRC=$(BUILD_ROOT)\src\Language -UI=$(UI);$(LANGUAGE_SRC) +UI=$(FWKERNEL_SRC);$(GENERIC_SRC);$(APPCORE_SRC);$(DEBUGPROCS_SRC);$(CELLAR_SRC) !IF "$(USER_INCLUDE)"!="" USER_INCLUDE=$(UI);$(USER_INCLUDE) @@ -38,7 +35,7 @@ PATH=$(COM_OUT_DIR);$(PATH) RCFILE=FwKernel.rc DEFFILE=FwKernel.def -LINK_LIBS=Generic.lib xmlparse-utf16.lib $(LINK_LIBS) +LINK_LIBS=Generic.lib xmlparse-utf16.lib Usp10.lib $(LINK_LIBS) # === Object Lists === @@ -52,10 +49,21 @@ OBJ_FWKERNEL=\ $(INT_DIR)\autopch\TsMultiStr.obj\ $(INT_DIR)\usepch\TextProps1.obj\ $(INT_DIR)\autopch\ActionHandler.obj\ + $(INT_DIR)\genpch\RegexMatcherWrapper.obj\ + $(INT_DIR)\autopch\LgIcuWrappers.obj\ + $(INT_DIR)\autopch\UniscribeEngine.obj\ + $(INT_DIR)\autopch\UniscribeSegment.obj\ + $(INT_DIR)\autopch\RomRenderEngine.obj\ + $(INT_DIR)\autopch\RomRenderSegment.obj\ + $(INT_DIR)\autopch\LgSimpleEngines.obj\ + $(INT_DIR)\autopch\LgIcuCharPropEngine.obj\ + $(INT_DIR)\autopch\LgUnicodeCollater.obj\ + $(INT_DIR)\autopch\LgKeymanHandler.obj\ $(INT_DIR)\autopch\ModuleEntry.obj\ $(INT_DIR)\autopch\FwStyledText.obj\ $(INT_DIR)\autopch\WriteXml.obj\ $(INT_DIR)\autopch\DebugReport.obj\ + $(INT_DIR)\autopch\FwXml.obj\ $(INT_DIR)\autopch\dlldatax.obj\ @@ -83,6 +91,9 @@ ARG_SRCDIR=$(GENERIC_SRC) ARG_SRCDIR=$(APPCORE_SRC) !INCLUDE "$(BUILD_ROOT)\bld\_rule.mak" +ARG_SRCDIR=$(CELLAR_SRC) +!INCLUDE "$(BUILD_ROOT)\bld\_rule.mak" + # === Custom Rules === diff --git a/Src/Kernel/FwKernel.rc b/Src/Kernel/FwKernel.rc index 9fdd256f2a..579daef901 100644 --- a/Src/Kernel/FwKernel.rc +++ b/Src/Kernel/FwKernel.rc @@ -13,11 +13,10 @@ Description: -------------------------------------------------------------------------------*//*:End Ignore*/ 1 TYPELIB FwKernelTlb.tlb - -#include "GenericResource.h" #if WIN32 #include "winresrc.h" #endif +#include "LangResource.h" #include "Generic.rc" @@ -63,3 +62,383 @@ BEGIN VALUE "Translation", 0x409, 1200 END END + +STRINGTABLE DISCARDABLE +BEGIN + kstidBufferTooSmall "The buffer passed to this method was too small to hold the result." + kstidFracNumVal "Can't report a fractional numeric value" + kstidNoNumeric "Unicode does not define a numeric value for this character" + kstidInvalidUnicode "Found an invalid Unicode character or sequence" + kstidICUCharName "The ICU code retrieving the Unicode character name found an error." + kstidICUDecomp "The ICU code finding the Unicode decomposition encountered an error." + kstidICUNormalize "The ICU code normalizing the text found an error." + kstidICUCase "The ICU function for changing the case found an error." + kstidICUBrkInit "The ICU function to initialize the BreakIterator returned an error." + kstidICUBrkRange "The line break asked for was out of range of the given text." + kstidLangDefaultCollation "DefaultCollation" + kstidUserWs "en" // unless and until someone translates all our resources and + // fixes up the resulting problems in the code. + kstidKeymanInitFailedCaption "Keyman initialization failed" + kstidKeymanInitUnexpectedFailMsg "Unexpected Keyman failure" + kstidKeymanNotRegisteredMsg "No known version of Keyman is registered." + kstidKeymanRootNotRegisteredMsg "Keyman program is not registered correctly." + kstidKeymanDllLoadFailureMsg "Failed to load Keyman32.dll" +END + +STRINGTABLE DISCARDABLE +BEGIN + kstidLangDefXmlMsg001 "Missing CharDef code attribute value.\n" + kstidLangDefXmlMsg002 "Missing CharDef data attribute value.\n" + kstidLangDefXmlMsg003 "Invalid CharDef code attribute value: ""%<0>s"".\n" + kstidLangDefXmlMsg004 "Missing Font file attribute value.\n" + kstidLangDefXmlMsg005 "Missing LgWritingSystem definition!?\n" + kstidLangDefXmlMsg006 "Unbalanced object stack!?\n" + kstidLangDefXmlMsg007 "Unbalanced property value stack!?\n" + kstidLangDefXmlMsg008 "Cannot put multiple objects in an atomic property.\n" + kstidLangDefXmlMsg009 "Cannot open language definition file ""%<0>s""!?\n" + kstidLangDefXmlMsg010 "Error accessing language definition file ""%<0>s""!?\n" + kstidLangDefXmlMsg011 "XML parser detected an XML syntax error!\n" + kstidLangDefXmlMsg012 "Error detected while parsing XML file!\n" + kstidLangDefXmlMsg013 "Missing EncodingConverter install attribute value.\n" +END + +STRINGTABLE DISCARDABLE +BEGIN + kstidLangDefXmlMsg014 "Problem while opening project" + kstidLangDefXmlMsg015 "The %<0>s writing system could not be installed, possibly due to insufficient user privileges.%nThis may affect sorting, special character definitions, and other aspects of the writing system.%n" +END + +// Message strings for the XML import/export process. These are shared with the Language DLL. + +STRINGTABLE DISCARDABLE +BEGIN + kstidXmlUserWs "en" +END + +STRINGTABLE DISCARDABLE +BEGIN + kstidXmlInfoMsg001 " %<0>d %<1>s processed, %<2>d successful, %<3>d attempted\n" + kstidParameter "Parameter" + kstidParameters "Parameters" + kstidXmlInfoMsg002 "%<0>d custom %<1>s have been added to the database schema.\n" + kstidField "field" + kstidFields "fields" + kstidXmlInfoMsg003 "First pass of reading the XML file took %<0>d %<1>s.\n" + kstidXmlInfoMsg007 "Creating %<0>d objects after the first pass took %<1>d %<2>s.\n" + kstidXmlInfoMsg009 "Second pass of reading the XML file took %d %s.\n" + kstidXmlInfoMsg004 "Storing data after the second pass took %<0>d %<1>s.\n" + kstidXmlInfoMsg006 "Loading the XML file into the database took %<0>d %<1>s.\n" + kstidSecond "second" + kstidSeconds "seconds" + kstidXmlInfoMsg005 "Storing the data into the database took %<0>d SQL %<1>s.\n" + kstidCommand "command" + kstidCommands "commands" + kstidXmlInfoMsg008 "Creating %<0>d empty structured text paragraphs.\n" + kstidXmlInfoMsg010 "d""> does not match the database version (%<1>d).\n" + kstidXmlInfoMsg011 "No version number given with .\n" + + kstidXmlErrorMsg001 "<%<0>s> elements cannot be nested inside either or !\n" + kstidXmlErrorMsg002 "<%<0>s> is improperly nested!\n" + kstidXmlErrorMsg003 "<%<0>s> must be nested inside <%<1>s> or an object attribute element!\n" + kstidXmlErrorMsg004 "<%<0>s> must be nested inside <%<1>s>...s>!\n" + kstidXmlErrorMsg005 "<%<0>s> must be nested inside an object attribute element!\n" + kstidXmlErrorMsg006 "<%<0>s> must be nested inside an object element!\n" + kstidXmlErrorMsg007 "<%<0>s> not recognized nested within either or !\n" + kstidXmlErrorMsg008 " must be a toplevel element inside !?\n" + kstidXmlErrorMsg009 " must be a toplevel element inside !?\n" + kstidXmlErrorMsg010 "<%<0>s> must be the outermost XML element!?\n" + kstidXmlErrorMsg011 "Cannot convert ""%<0>s"" into a Language Writing system code.\n" + kstidXmlErrorMsg012 "Cannot create GUID for object identifier!\n" + kstidXmlErrorMsg013 "Cannot get buffer from the XML parser [pass 1]! (Out of memory?)\n" + kstidXmlErrorMsg014 "Cannot get buffer from the XML parser [pass 2]! (Out of memory?)\n" + kstidXmlErrorMsg015 "Cannot have some ord attribute values missing and some present!\n" + kstidXmlErrorMsg016 "Cannot read the CmObject table in the database!\n" + kstidXmlErrorMsg017 "Invalid list root id '%<0>s' in custom field definition [%<1>S]??\n" + kstidXmlErrorMsg018 "ERROR %<0>s executing SQL command:\n %<1>s\n" + kstidXmlErrorMsg019 "ERROR %<0>s executing SQL function on line %<1>d of %<2>s:\n %<3>s\n" + kstidXmlErrorMsg020 "ERROR creating %<0>S (%<1>d, %<2>g)\n" + kstidXmlErrorMsg021 "ERROR in SetMultiBigStr$ %<0>d,%<1>d,%<2>d,'...',0x...\n" + kstidXmlErrorMsg022 "ERROR in SetMultiBigTxt$ %<0>d,%<1>d,%<2>d,'...'\n" + kstidXmlErrorMsg023 "ERROR in SetMultiStr$ %<0>d,%<1>d,%<2>d,'...',0x...\n" + kstidXmlErrorMsg024 "ERROR in SetMultiTxt$ %<0>d,%<1>d,%<2>d,'...'\n" + kstidXmlErrorMsg025 "ERROR in UPDATE [%<0>S] SET [%<1>S]=? WHERE [Id]=%<2>d\n" + kstidXmlErrorMsg026 "ERROR in UPDATE [%<0>S] SET [%<1>S]=?,%<2>S_Fmt=? WHERE [Id]=%<3>d\n" + kstidXmlErrorMsg027 "ERROR with INSERT %<0>S_%<1>S (Src, Dst) VALUES (%<2>d, %<3>d)\n" + kstidXmlErrorMsg028 "ERROR with INSERT %<0>S_%<1>S (Src, Dst, Ord) VALUES (%<2>d, %<3>d, %<4>d)\n" + kstidXmlErrorMsg029 "ERROR with UPDATE [%<0>S] SET [%<1>S]=%<2>d WHERE [Id]=%<3>d\n" + kstidXmlErrorMsg030 "ERROR! BUG! Invalid field data type storing data?? (%<0>d)\n" + kstidXmlErrorMsg031 "Empty <%<0>s> element?\n" +// kstidXmlErrorMsg032 "Empty element? (cbtext = 0)\n" + kstidXmlErrorMsg033 "Empty element?\n" +// kstidXmlErrorMsg034 "Empty element? (cbtext = 0)\n" + kstidXmlErrorMsg035 "Empty MultiString element? (cbtext = 0)\n" + kstidXmlErrorMsg036 "Empty String element? (cbtext = 0)\n" + kstidXmlErrorMsg037 "Error detected while parsing XML file [pass 1]!\n" + kstidXmlErrorMsg038 "Error detected while parsing XML file [pass 2]!\n" + kstidXmlErrorMsg039 "Found a with identical properties to preceding : these have been merged.\n" + kstidXmlErrorMsg040 "INTERNAL DATA CORRUPTION: unable to get class for field!\n" + kstidXmlErrorMsg041 "INTERNAL XML ELEMENT STACK CORRUPTED!?\n" + kstidXmlErrorMsg042 "Ignoring s=""%<1>s""> in the absence of a %<2>s attribute.\n" +// kstidXmlErrorMsg043 "Ignoring s""> in the absence of a offset attribute.\n" + kstidXmlErrorMsg044 "Ignoring s""> in the absence of a ws attribute.\n" + kstidXmlErrorMsg045 "Ignoring s""> in the absence of a wsBase attribute.\n" + kstidXmlErrorMsg046 "Improperly nested <%<0>s name=""%<1>s""> element!\n" + kstidXmlErrorMsg047 "Improperly nested <%<0>s> element!\n" + kstidXmlErrorMsg048 "Invalid Boolean value for the %<0>S field of a %<1>S object: ""%<2>s"".\n" + kstidXmlErrorMsg049 "Invalid GUID value in s=""%<1>s""> element!\n" + kstidXmlErrorMsg050 "Invalid GenDate value for the %<0>S field of a %<1>S object: ""%<2>s"".\n" + kstidXmlErrorMsg051 "Invalid Integer value for the %<0>S field of a %<1>S object: ""%<2>s"".\n" + kstidXmlErrorMsg052 "Invalid Numeric value for the %<0>S field of a %<1>S object: ""%<2>s"".\n" + kstidXmlErrorMsg053 "Invalid XML Element: unknown class ""%<0>s""\n" + kstidXmlErrorMsg054 "Invalid XML Element: unknown field ""%<0>s""\n" + kstidXmlErrorMsg055 "Invalid bin attribute in Float element: ""%<0>s"".\n" + kstidXmlErrorMsg056 "Invalid character data found between runs: """ + kstidXmlErrorMsg057 "Invalid class attribute for CustomField element: %<0>s\n" + kstidXmlErrorMsg058 "Invalid writing system in s"">!\n" + kstidXmlErrorMsg059 "Invalid writing system in s"">!\n" + kstidXmlErrorMsg060 "Invalid field type containing <%<0>s> element: %<1>d.\n" + kstidXmlErrorMsg061 "Invalid ord attribute in Link element: ""%<0>s"".\n" + kstidXmlErrorMsg062 "Invalid ord attribute value: ""%<0>s""\n" + kstidXmlErrorMsg063 "Invalid target attribute for CustomField element: %<0>s\n" + kstidXmlErrorMsg064 "Invalid type attribute for CustomField element: %<0>s\n" + kstidXmlErrorMsg065 "Invalid Float value for the %<0>S field of a %<1>S object: ""%<2>s"".\n" + kstidXmlErrorMsg066 "Invalid value in s=""%<1>s"">: need on, off or invert\n" + kstidXmlErrorMsg067 "Invalid value in s=""%<1>s"">.\n" + kstidXmlErrorMsg068 "Invalid value in s=""%<1>s"">.\n" +// kstidXmlErrorMsg069 "Invalid value in s"">: need on, off or invert\n" +// kstidXmlErrorMsg070 "Invalid value in s"">.\n" +// kstidXmlErrorMsg071 "Invalid value in s"">.\n" + kstidXmlErrorMsg072 "Invalid value in s"">: need off, super, or sub\n" + kstidXmlErrorMsg073 "Invalid value in s"">: need chars or picture\n" + kstidXmlErrorMsg074 "Invalid value in s"">: need none, single, double, dotted, dashed, or strikethrough\n" + kstidXmlErrorMsg075 "Invalid Guid value for the %<0>S field of a %<1>S object: ""%<2>s"".\n" + kstidXmlErrorMsg076 "Invalid Time value for the %<0>S field of a %<1>S object: ""%<2>s"".\n" + kstidXmlErrorMsg077 "Missing Link target: ""%<0>s""\n" + kstidXmlErrorMsg078 "Missing both bin and val attributes in Float element.\n" + + kstidXmlErrorMsg079 "Missing %<0>s attribute for %<1>s element.\n" + + kstidXmlErrorMsg080 "Missing writing system for element!\n" + kstidXmlErrorMsg081 "Missing writing system for element!\n" +// THE NEXT SEVERAL ITEMS SHOULD BE REPLACED BY THE NEW kstidXmlErrorMsg079 SOMETIME. + kstidXmlErrorMsg089 "Missing val attribute in GenDate element.\n" + kstidXmlErrorMsg090 "Missing val attribute in Guid element.\n" + kstidXmlErrorMsg091 "Missing val attribute in Integer element.\n" + kstidXmlErrorMsg092 "Missing val attribute in Numeric element.\n" + kstidXmlErrorMsg093 "Missing val attribute in Time element.\n" + kstidXmlErrorMsg094 "Out of memory after first pass through XML file!\n" + kstidXmlErrorMsg095 "Out of memory before parsing anything!\n" + kstidXmlErrorMsg096 "Out of memory!\n" + kstidXmlErrorMsg097 "Repeated object GUID\n" + kstidXmlErrorMsg098 "Repeated object ID\n" + kstidXmlErrorMsg099 "SQL_PARAM_DIAG_UNAVAILABLE INFO creating %<0>S (%<1>d, %<2>g, %<3>d, %<4>d, %<5>d)\n" + kstidXmlErrorMsg100 "SQL_PARAM_ERROR creating %<0>S (%<1>d, %<2>g, %<3>d, %<4>d, %<5>d)\n" + kstidXmlErrorMsg101 "SQL_PARAM_UNUSED creating %<0>S (%<1>d, %<2>g, %<3>d, %<4>d, %<5>d)\n" + kstidXmlErrorMsg102 "The database is not empty!\n" + kstidXmlErrorMsg103 "UNAVAIL INFO in SetMultiBigStr$ %<0>d,%<1>d,%<2>d,'...',0x...\n" + kstidXmlErrorMsg104 "UNAVAIL INFO in SetMultiBigTxt$ %<0>d,%<1>d,%<2>d,'...'\n" + kstidXmlErrorMsg105 "UNAVAIL INFO in SetMultiStr$ %<0>d,%<1>d,%<2>d,'...',0x...\n" + kstidXmlErrorMsg106 "UNAVAIL INFO in SetMultiTxt$ %<0>d,%<1>d,%<2>d,'...'\n" + kstidXmlErrorMsg107 "UNAVAIL INFO in UPDATE [%<0>S] SET [%<1>S]=? WHERE [Id]=%<2>d\n" + kstidXmlErrorMsg108 "UNAVAIL INFO in UPDATE [%<0>S] SET [%<1>S]=?,%<2>S_Fmt=? WHERE [Id]=%<3>d\n" + kstidXmlErrorMsg109 "UNAVAILABLE INFO creating %<0>S (%<1>d, %<2>g)\n" + kstidXmlErrorMsg110 "UNAVAILABLE INFO for INSERT %<0>S_%<1>S (Src, Dst) VALUES (%<2>d, %<3>d)\n" + kstidXmlErrorMsg111 "UNAVAILABLE INFO for INSERT (Src, Dst, Ord) %<0>S_%<1>S VALUES (%<2>d, %<3>d, %<4>d)\n" + kstidXmlErrorMsg112 "UNAVAILABLE INFO for UPDATE [%<0>S] SET [%<1>S]=%<2>d WHERE [Id]=%<3>d\n" + kstidXmlErrorMsg113 "UNUSED creating %<0>S (%<1>d, %<2>g)\n" + kstidXmlErrorMsg114 "UNUSED data INSERT %<0>S_%<1>S (Src, Dst) VALUES (%<2>d, %<3>d)\n" + kstidXmlErrorMsg115 "UNUSED data INSERT %<0>S_%<1>S (Src, Dst, Ord) VALUES (%<2>d, %<3>d, %<4>d)\n" + kstidXmlErrorMsg116 "UNUSED data UPDATE [%<0>S] SET [%<1>S]=%<2>d WHERE [Id]=%<3>d\n" + kstidXmlErrorMsg117 "UNUSED in SetMultiBigStr$ %<0>d,%<1>d,%<2>d,'...',0x...\n" + kstidXmlErrorMsg118 "UNUSED in SetMultiBigTxt$ %<0>d,%<1>d,%<2>d,'...'\n" + kstidXmlErrorMsg119 "UNUSED in SetMultiStr$ %<0>d,%<1>d,%<2>d,'...',0x...\n" + kstidXmlErrorMsg120 "UNUSED in SetMultiTxt$ %<0>d,%<1>d,%<2>d,'...'\n" + kstidXmlErrorMsg121 "UNUSED in UPDATE [%<0>S] SET [%<1>S]=? WHERE [Id]=%<2>d\n" + kstidXmlErrorMsg122 "UNUSED in UPDATE [%<0>S] SET [%<1>S]=?,%<2>S_Fmt=? WHERE [Id]=%<3>d\n" + kstidXmlErrorMsg123 "Unbalanced XML element stack!?\n" + kstidXmlErrorMsg124 "Unbalanced element stack!?\n" + kstidXmlErrorMsg125 "Unbalanced object id stack!?\n" + kstidXmlErrorMsg126 "Unbalanced property name stack!?\n" + kstidXmlErrorMsg127 "Unknown XML end tag: ""%<0>s""\n" + kstidXmlErrorMsg128 "Unknown XML start tag: ""%<0>s""\n" + kstidXmlErrorMsg129 "WARNING: GUID-based id strings do not all begin with the same letter!\n" + kstidXmlErrorMsg130 "WARNING: You've got to be kidding: string property length > 1 gigabyte!!!\n" + kstidXmlErrorMsg131 "WARNING: the ownership hierarchy is not properly nested!\n" + kstidXmlErrorMsg132 "Warning: String does not have a writing system!\n" + kstidXmlErrorMsg133 "Warning: ignoring extra character at the end of %<0>s data.\n" + kstidXmlErrorMsg134 "Wrong field type for Link element: %<0>d\n" + kstidXmlErrorMsg135 "XML parser detected an XML syntax error [pass 1]!\n" + kstidXmlErrorMsg136 "XML parser detected an XML syntax error [pass 2]!\n" + kstidXmlErrorMsg137 "<%<0>s> not recognized nested within !\n" + kstidXmlErrorMsg138 "<%<0>s> not recognized nested within !\n" + kstidXmlErrorMsg139 "Invalid value in <%<0>s bold=""%<1>s"">: need on, off or invert\n" + kstidXmlErrorMsg140 "Ignoring <%<0>s fontsizeUnit=""%<1>s""> in the absence of a fontsize attribute.\n" + kstidXmlErrorMsg141 "Invalid value in <%<0>s fontsize=""%<1>s"">.\n" + kstidXmlErrorMsg142 "Invalid value in <%<0>s fontsizeUnit=""%<1>s"">.\n" + kstidXmlErrorMsg143 "Invalid value in <%<0>s align=""%<1>s"">: need leading, left, center, right, trailing, or justify\n" + kstidXmlErrorMsg144 "Ignoring <%<0>s ows=""%<1>s""> in the absence of a ws attribute.\n" + kstidXmlErrorMsg145 "Ignoring <%<0>s owsBase=""%<1>s""> in the absence of a wsBase attribute.\n" + kstidXmlErrorMsg146 "Invalid value in <%<0>s italic=""%<1>s"">: need on, off or invert\n" + kstidXmlErrorMsg147 "Invalid value in <%<0>s lineHeight=""%<1>s"">.\n" + kstidXmlErrorMsg148 "Invalid value in <%<0>s lineHeightUnit=""%<1>s"">.\n" + kstidXmlErrorMsg149 "Ignoring <%<0>s lineHeightUnit=""%<1>s""> in the absence of a lineHeight attribute.\n" + kstidXmlErrorMsg150 "Invalid value in <%<0>s offset=""%<1>s"">.\n" + kstidXmlErrorMsg151 "Invalid value in <%<0>s offsetUnit=""%<1>s"">.\n" + kstidXmlErrorMsg152 "Ignoring <%<0>s offsetUnit=""%<1>s""> in the absence of a offset attribute.\n" + kstidXmlErrorMsg153 "Invalid value in <%<0>s superscript=""%<1>s"">: need off, super, or sub.\n" + kstidXmlErrorMsg154 "Invalid value in <%<0>s underline=""%<1>s"">: need none, single, double, dotted, dashed, or strikethrough.\n" +// kstidXmlErrorMsg155 "Ignoring an empty .\n" + kstidXmlErrorMsg156 "Warning: Invalid GUID-based id string for importing object.\n" + kstidXmlErrorMsg157 "Warning: Invalid writing system in s"" .../>.\n" + kstidXmlErrorMsg158 "Warning: Invalid field for implicit target in a Link element: %<0>S.\n" + kstidXmlErrorMsg159 "Warning: Implicit MoInflAffixSlot target in a Link element is missing the name attribute.\n" + kstidXmlErrorMsg160 "Warning: Implicit %<0>s target in a Link element cannot access the PartOfSpeech list.\n" + kstidXmlErrorMsg161 "Warning: Implicit %<0>s target in Link element cannot find/create a needed PartOfSpeech.\n" + kstidXmlErrorMsg162 "Warning: Implicit %<0>s target in Link element is missing one or more required attributes.\n" + kstidXmlErrorMsg163 "Warning: Implicit ReversalIndexEntry target in a Link element is missing the form attribute.\n" + kstidXmlErrorMsg164 "Warning: Implicit ReversalIndexEntry target in a Link element cannot find/create the ReversalIndex.\n" + kstidXmlErrorMsg165 "Warning: Implicit ReversalIndexEntry target in a Link element has an invalid form attribute.\n" + kstidXmlErrorMsg166 "Error obtaining LexDb id from the database!?\n" + kstidXmlErrorMsg167 "Info: Implicit %<0>s target in a Link element has abbr attribute ""%<1>S"" which matches a Name value.\n" + kstidXmlErrorMsg168 "Info: Implicit %<0>s target in a Link element has name attribute ""%<1>S"" which matches an Abbreviation value.\n" + kstidXmlErrorMsg169 "Implicit MoInflAffixSlot target in a Link element has neither the nameOwner nor the abbrOwner attribute.\n" + kstidXmlErrorMsg170 "Implicit %<0>s target in a Link element is missing the sense or entry attribute.\n" + kstidXmlErrorMsg171 "Implicit %<0>s target in a Link element is missing the name or abbr attribute.\n" + kstidXmlErrorMsg172 "Invalid class for implicit target in Link element: %<0>S.\n" + kstidXmlErrorMsg173 "Warning: Invalid writing system in s"" .../>.\n" + kstidXmlErrorMsg174 "Warning: empty ws attribute found: substituting analysis writing system.\n" + kstidXmlErrorMsg175 "Invalid value in <%<0>s spellcheck=""%<1>s"">: need normal, doNotCheck, or forceCheck.\n" + + kstidXmlDebugMsg001 "DEBUG: External Link target: db=""%<0>s"", target=""%<1>s""\n" + kstidXmlDebugMsg002 "DEBUG: Repeated run properties found: ibProp = %<0>d, Top()->ibProp = %<1>d\n" + kstidXmlDebugMsg003 "ERROR CAUGHT on line %<0>d of %<1>s: %<2>s\n" + kstidXmlDebugMsg004 "SUCCESSFULLY CREATED %<0>S (%<1>d, %<2>g, %<3>d, %<4>d, %<5>d)\n" + kstidXmlDebugMsg005 "UNKNOWN ERROR CAUGHT on line %<0>d of %<1>s\n" + kstidXmlDebugMsg006 "m_vetiOpen[%<0>d].m_elty = %<1>s, m_icls = %<2>d\n" + kstidXmlDebugMsg007 "rpi[%<0>d] = %<1>d, %<2>d, 0x" + kstidXmlDebugMsg008 "run[%<0>d]: ichMin = %<1>d, ibProp = %<2>d; distinct = %<3>d, fMerge = %<4>s\n" +END + +STRINGTABLE DISCARDABLE +BEGIN + kstidXmlInfoMsg101 "Info: Creating new inflection class with ws=""%<0>S"", abbr=""%<1>s"", and name=""%<2>s"".\n" + kstidXmlInfoMsg102 "Info: Creating new inflectional affix slot with ws=""%<0>S"" and name=""%<1>s"", for POS with abbr=""%<2>s"" and name=""%<3>s"".\n" + kstidXmlInfoMsg103 "Info: Creating new object with ws=""%<0>S"", abbr=""%<1>s"", and name=""%<2>s"" in the %<3>S list.\n" + kstidXmlInfoMsg104 "Warning: The %<0>S list is not supposed to be extensible!\n" + kstidXmlInfoMsg105 "Info: Creating ReversalIndex for the %<0>S (""%<1>S"") language.\n" + kstidXmlInfoMsg106 "Info: Creating ReversalIndexEntry ""%<0>S"" (""%<1>S"") for the %<2>S (""%<3>S"") language.\n" + kstidXmlInfoMsg107 "%<0>s [repeated %<1>d more times in the XML file]\n" + kstidXmlInfoMsg108 "Warning: Truncating string from %<0>d characters to %<1>d characters for the %<2>S field of a %<3>S object.\n" +END + +STRINGTABLE DISCARDABLE +BEGIN + kstidXmlInfoMsg201 "%<0>u custom field %<1>s written.\n" + kstidDefinition "definition" + kstidDefinitions "definitions" + kstidXmlInfoMsg202 "Dumping the XML file from the database took %<0>d %<1>s.\n" + kstidXmlInfoMsg203 "Loading %<0>u %<1>s of Object Ownership Hierarchy data took %<2>d %<3>s.\n" + kstidRow "row" + kstidRows "rows" + kstidXmlInfoMsg206 "Loading %<0>u %<1>s of ""Binary"" data took %<2>d %<3>s.\n" + kstidXmlInfoMsg207 "Loading %<0>u %<1>s of ""Image"" data took %<2>d %<3>s.\n" + kstidXmlInfoMsg210 "Loading %<0>u %<1>s of ""MultiString"" data took %<2>d %<3>s.\n" + kstidXmlInfoMsg211 "Loading %<0>u %<1>s of ""MultiUnicode"" data took %<2>d %<3>s.\n" + kstidXmlInfoMsg212 "Loading %<0>u %<1>s of ""ReferenceAtom"" data took %<2>d %<3>s.\n" + kstidXmlInfoMsg213 "Loading %<0>u %<1>s of ""ReferenceCollection/Sequence"" data took %<2>d %<3>s.\n" + kstidXmlInfoMsg214 "Loading %<0>u %<1>s of ""String"" data took %<2>d %<3>s.\n" + kstidXmlInfoMsg215 "Loading %<0>u %<1>s of ""Unicode"" data took %<2>d %<3>s.\n" + kstidXmlInfoMsg216 "Loading %<0>u %<1>s of basic attribute data took %<2>d %<3>s.\n" + kstidXmlInfoMsg217 "Loading the data from the database took %<0>d SQL %<1>s.\n" + kstidXmlInfoMsg218 "Rebuilding the object hierarchy table took %<0>d %<1>s.\n" + kstidXmlInfoMsg219 "SQL[%<0>d]: %<1>s\n" + kstidXmlInfoMsg220 "Writing the XML file took %<0>d %<1>s.\n" + kstidXmlInfoMsg221 " Reading %<0>d additional characters of string data.\n" + kstidXmlInfoMsg222 " Reading %<0>d additional bytes of format data.\n" + kstidXmlInfoMsg224 "Owner of object %<0>d does not have a name in the default analysis language.\n" + kstidXmlInfoMsg225 "Owner of object %<0>d does not have an abbreviation in the default analysis language.\n" + + kstidXmlErrorMsg201 " %<0>s - %<1>s\n" + kstidXmlErrorMsg202 "BUG/FEATURE - cannot handle Run scalar property code ""%<0>s""\n" + kstidXmlErrorMsg203 "ERROR %<0>s executing SQL command:\n %<1>s\n" + kstidXmlErrorMsg204 "ERROR %<0>s executing SQL function on line %<1>d of %<2>s:\n %<3>s\n" + kstidXmlErrorMsg205 "ERROR - invalid Run scalar property length (%<0>d)\n" + kstidXmlErrorMsg206 "ERROR - invalid Run string property length\n" + kstidXmlErrorMsg207 "ERROR - invalid binary format data for a string: %<0>d run%<1>s, %<2>d byte%<3>s." + kstidRun "run" + kstidRuns "runs" + kstidByte "byte" + kstidBytes "bytes" + kstidXmlErrorMsg208 "ERROR - invalid binary format data for a string: %<0>d run%<1>s." + kstidXmlErrorMsg209 "ERROR - invalid binary format data for a string: only %<0>d byte%<1>s." + kstidXmlErrorMsg210 "ERROR - invalid binary format data for a string: run %<0>d does not start after\nrun %<1>d (min %<2>d <= min %<3>d).\n" + kstidXmlErrorMsg211 "ERROR - invalid binary format data for a string: run %<0>d has invalid internal\noffset (%<1>d)." + kstidXmlErrorMsg212 "ERROR - invalid binary format data for a string: run %<0>d starts after end of\nstring (length = %<1>d <= min = %<2>d)." + kstidXmlErrorMsg213 "ERROR - invalid binary format data for a string: run %<0>d starts before the\nstring (min = %<1>d)." + kstidXmlErrorMsg214 "ERROR - invalid embedded object type in Run string property (%<0>d)\n" + kstidXmlErrorMsg215 "ERROR - invalid writing system of Run string property length\n" + kstidXmlErrorMsg216 "ERROR - invalid internal writing system of Run scalar property code\n" + kstidXmlErrorMsg217 "ERROR - invalid internal writing system of Run string property code\n" + kstidXmlErrorMsg218 "ERROR - unknown Run scalar property code (%<0>d)\n" + kstidXmlErrorMsg219 "ERROR - unknown Run string property code (%<0>d)\n" + kstidXmlErrorMsg220 "ERROR [%<0>d]: Constructed Query overflowed its buffer!\n""%<1>s""\n" + kstidXmlErrorMsg221 "WARNING - invalid binary format data for a string: 0 runs, %<0>d byte%<1>s." + kstidXmlErrorDecoding "ERROR decoding the properties: check the log file for details." + kstidXmlErrorMsg222 "WARNING: no writing system" + kstidXmlErrorMsg223 "Cannot get version number from the database!?\n" + kstidXmlErrorMsg224 "Corrupted database: missing %<0>S object (hobj = %<1>d) for %<2>S (hobj = %<3>d)\n" + kstidXmlErrorMsg225 "Corrupted database: missing integer property for %<1>S style.%n" + kstidXmlErrorMsg226 "Corrupted database: missing %<0>d integer properties for %<1>S style.%n" + kstidXmlErrorMsg227 "Corrupted database: missing integer property in paragraph's style.%n" + kstidXmlErrorMsg228 "Corrupted database: missing %<0>d integer properties in paragraph's style.%n" + kstidXmlErrorMsg229 "Corrupted database: missing string property for %<1>S style.%n" + kstidXmlErrorMsg230 "Corrupted database: missing %<0>d string properties for %<1>S style.%n" + kstidXmlErrorMsg231 "Corrupted database: missing string property in paragraph's style.%n" + kstidXmlErrorMsg232 "Corrupted database: missing %<0>d string properties in paragraph's style.%n" + kstidUNKNOWN "UNKNOWN" +END + +STRINGTABLE DISCARDABLE +BEGIN + kstidXmlErrorMsg301 "Invalid hvoOwner passed to ImportXmlObject method: %<0>d\n" + kstidXmlErrorMsg302 "Unknown clid (%<0>d) retrieved for hvoOwner: SOMETHING IS VERY WRONG!\n" + kstidXmlErrorMsg303 "Unknown flid passed to ImportXmlObject method: %<0>d\n" + kstidXmlErrorMsg304 "Invalid flid passed to ImportXmlObject method: flid = %<0>d, but class = %<1>d\n" + kstidXmlErrorMsg305 "Empty database: THIS SHOULD NEVER HAPPEN!\n" + kstidXmlErrorMsg306 "<%<0>s> must be nested inside <%<1>s>...s>!\n" + kstidXmlErrorMsg307 "DEBUG: Unknown flid for list: %<0>d\n" + kstidXmlInfoMsg223 "Info: Creating new writing system for code ""%<0>s"".\n" + kstidXmlErrorMsg308 "Warning: Picture file ""%<0>s"" does not exist.\n" + kstidXmlErrorMsg309 "Warning: Cannot copy picture file ""%<0>s"" to ""%<1>s"".\n" + kstidXmlErrorMsg310 "DEBUG: Unknown flid for folders: %<0>d" + kstidXmlErrorMsg311 "ERROR - Invalid start tag <%<0>s> for XML file: expected <%<1>s>.\n" + kstidXmlErrorMsg312 "Warning: Media file ""%<0>s"" does not exist.\n" + kstidXmlErrorMsg313 "Warning: Cannot copy media file ""%<0>s"" to ""%<1>s"".\n" + kstidXmlErrorMsg314 "ERROR - Cannot create directory ""%<0>s"".\n" + + kstidXmlErrorMsg315 "Invalid %<0>s attribute value for %<1>s element: not GUID based.\n" + kstidXmlErrorMsg316 "Invalid %<0>s attribute value for %<1>s element: bad GUID value.\n" + kstidXmlErrorMsg317 "Object id being merged (%<0>g) should not appear in the updated list.\n" + kstidXmlErrorMsg318 "Object id being deleted (%<0>g) should not appear in the updated list.\n" + kstidXmlErrorMsg319 "A list update XML file must begin with a field tag, not a class tag!\n" + kstidXmlErrorMsg320 "ERROR in ""%s"" [param=%d].\n" + kstidXmlErrorMsg321 "UNUSED in ""%s"" [param=%d].\n" + kstidXmlErrorMsg322 "UNAVAIL INFO in ""%s"" [param=%d].\n" + kstidXmlErrorMsg323 "Warning: Storing only the first %<0>d of %<1>d characters for this string: ""%<2>s"".\n" + + kstidXmlInfoMsg301 "Initializing from the database before reading the XML file took %<0>d %<1>s.\n" + kstidXmlInfoMsg302 "Processing the update information took %<0>d %<1>s.\n" + kstidXmlInfoMsg303 "Creating new objects took %<0>d %<1>s.\n" + kstidXmlInfoMsg304 "Updating owners and sequence positions took %<0>d %<1>s.\n" + kstidXmlInfoMsg305 "Fixing links to merged or deleted list items took %<0>d %<1>s.\n" + kstidXmlInfoMsg306 "Deleting obsolete database objects took %<0>d %<1>s.\n" + kstidXmlInfoMsg307 "Removing possibly obsolete data from list items took %<0>d %<1>s.\n" + kstidXmlInfoMsg308 "Collecting obsolete database objects to delete took %<0>d %<1>s.\n" + kstidXmlInfoMsg309 "Need to delete %<0>d obsolete database %<1>s.\n" + kstidObject "object" + kstidObjects "objects" + kstidXmlInfoMsg310 "(Special initializing for update alone took %<0>d %<1>s.)\n" + kstidXmlInfoMsg311 "Info: Creating %<0>s Pair Lexical Reference Type with name=""%<1>S"" and abbr=""%<2>S"".\n" + kstidSense "Sense" + kstidEntry "Entry" +END diff --git a/Src/Kernel/FwKernelPs.idl b/Src/Kernel/FwKernelPs.idl index f0bb5e2275..49705d7e40 100644 --- a/Src/Kernel/FwKernelPs.idl +++ b/Src/Kernel/FwKernelPs.idl @@ -19,5 +19,5 @@ import "ocidl.idl"; #include "FwKernel.idh" #include "TextServ.idh" -#include "Render.idh" // for Language DLL +#include "Render.idh" #include "Language.idh" diff --git a/Src/Kernel/FwKernelTlb.idl b/Src/Kernel/FwKernelTlb.idl index 61cc491509..3bb395a138 100644 --- a/Src/Kernel/FwKernelTlb.idl +++ b/Src/Kernel/FwKernelTlb.idl @@ -20,6 +20,6 @@ DeclareLibrary(FwKernelLib, 1.0, "FieldWorks Kernel", F1EF76E0-BE04-11d3-8D9A-00 { #include "FwKernel.idh" #include "TextServ.idh" - #include "Render.idh" // Language DLL stuff + #include "Render.idh" #include "Language.idh" }; diff --git a/Src/Kernel/Kernel.vcxproj b/Src/Kernel/Kernel.vcxproj index 1a1e884302..9ebb3ac2e1 100644 --- a/Src/Kernel/Kernel.vcxproj +++ b/Src/Kernel/Kernel.vcxproj @@ -1,105 +1,138 @@  - - Debug - Win32 - - - Release - Win32 - + + Debug + Win32 + + + Release + Win32 + - FwKernel - {6396B488-4D34-48B2-8639-EEB90707405B} - FwKernel - - - - MakeFileProj + FwKernel + {6396B488-4D34-48B2-8639-EEB90707405B} + FwKernel + + + + + + + MakeFileProj - Makefile + Makefile - Makefile + Makefile - - + + - - + + - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)\..\..\Output\Debug\ - $(ProjectDir)\..\..\obj\Debug\ - ..\..\bin\mkfwk - ..\..\bin\mkfwk cc - - FwKernel.dll - DEBUG;$(NMakePreprocessorDefinitions) - $(NMakeIncludeSearchPath) - $(NMakeForcedIncludes) - $(NMakeAssemblySearchPath) - $(NMakeForcedUsingAssemblies) - Release\ - Release\ - ..\..\bin\mkfwk r - ..\..\bin\mkfwk r cc - - Kernel.exe - $(NMakePreprocessorDefinitions) - $(NMakeIncludeSearchPath) - $(NMakeForcedIncludes) - $(NMakeAssemblySearchPath) - $(NMakeForcedUsingAssemblies) + <_ProjectFileVersion>10.0.30319.1 + $(ProjectDir)\..\..\Output\Debug\ + $(ProjectDir)\..\..\obj\Debug\ + ..\..\bin\mkfwk + ..\..\bin\mkfwk cc + + FwKernel.dll + DEBUG;$(NMakePreprocessorDefinitions) + $(NMakeIncludeSearchPath) + $(NMakeForcedIncludes) + $(NMakeAssemblySearchPath) + $(NMakeForcedUsingAssemblies) + Release\ + Release\ + ..\..\bin\mkfwk r + ..\..\bin\mkfwk r cc + + Kernel.exe + $(NMakePreprocessorDefinitions) + $(NMakeIncludeSearchPath) + $(NMakeForcedIncludes) + $(NMakeAssemblySearchPath) + $(NMakeForcedUsingAssemblies) - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + - - + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/Src/Kernel/Kernel.vcxproj.filters b/Src/Kernel/Kernel.vcxproj.filters index 1d547bc21a..8fcd642314 100644 --- a/Src/Kernel/Kernel.vcxproj.filters +++ b/Src/Kernel/Kernel.vcxproj.filters @@ -1,99 +1,183 @@  - - {398036a2-f52a-482d-9525-33c8406a59a6} - cpp;c;cxx;def;odl;idl;hpj;bat;asm - - - {7bf8133d-ca9d-4250-a953-2eb94f681dd8} - h;hpp;hxx;hm;inl;inc - - - {81fdee2e-c415-401f-80ec-58de44941b8a} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe - + + {398036a2-f52a-482d-9525-33c8406a59a6} + cpp;c;cxx;def;odl;idl;hpj;bat;asm + + + {7bf8133d-ca9d-4250-a953-2eb94f681dd8} + h;hpp;hxx;hm;inl;inc + + + {81fdee2e-c415-401f-80ec-58de44941b8a} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + - - Source Files - - - - + + Source Files + + + + + + + - - Source Files - - - Source Files - + + Source Files + + + Source Files + - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + - - Resource Files - + + Resource Files + \ No newline at end of file diff --git a/Src/Language/LangResource.h b/Src/Kernel/LangResource.h similarity index 100% rename from Src/Language/LangResource.h rename to Src/Kernel/LangResource.h diff --git a/Src/Language/Language.idh b/Src/Kernel/Language.idh similarity index 100% rename from Src/Language/Language.idh rename to Src/Kernel/Language.idh diff --git a/Src/Language/LgIcuCharPropEngine.cpp b/Src/Kernel/LgIcuCharPropEngine.cpp similarity index 100% rename from Src/Language/LgIcuCharPropEngine.cpp rename to Src/Kernel/LgIcuCharPropEngine.cpp diff --git a/Src/Language/LgIcuCharPropEngine.h b/Src/Kernel/LgIcuCharPropEngine.h similarity index 100% rename from Src/Language/LgIcuCharPropEngine.h rename to Src/Kernel/LgIcuCharPropEngine.h diff --git a/Src/Language/LgIcuCharPropertyInit.h b/Src/Kernel/LgIcuCharPropertyInit.h similarity index 100% rename from Src/Language/LgIcuCharPropertyInit.h rename to Src/Kernel/LgIcuCharPropertyInit.h diff --git a/Src/Language/LgIcuWrappers.cpp b/Src/Kernel/LgIcuWrappers.cpp similarity index 100% rename from Src/Language/LgIcuWrappers.cpp rename to Src/Kernel/LgIcuWrappers.cpp diff --git a/Src/Language/LgIcuWrappers.h b/Src/Kernel/LgIcuWrappers.h similarity index 100% rename from Src/Language/LgIcuWrappers.h rename to Src/Kernel/LgIcuWrappers.h diff --git a/Src/Language/LgKeymanHandler.cpp b/Src/Kernel/LgKeymanHandler.cpp similarity index 100% rename from Src/Language/LgKeymanHandler.cpp rename to Src/Kernel/LgKeymanHandler.cpp diff --git a/Src/Language/LgKeymanHandler.h b/Src/Kernel/LgKeymanHandler.h similarity index 100% rename from Src/Language/LgKeymanHandler.h rename to Src/Kernel/LgKeymanHandler.h diff --git a/Src/Language/LgNumericEngine.cpp b/Src/Kernel/LgNumericEngine.cpp similarity index 100% rename from Src/Language/LgNumericEngine.cpp rename to Src/Kernel/LgNumericEngine.cpp diff --git a/Src/Language/LgNumericEngine.h b/Src/Kernel/LgNumericEngine.h similarity index 100% rename from Src/Language/LgNumericEngine.h rename to Src/Kernel/LgNumericEngine.h diff --git a/Src/Language/LgSimpleEngines.cpp b/Src/Kernel/LgSimpleEngines.cpp similarity index 100% rename from Src/Language/LgSimpleEngines.cpp rename to Src/Kernel/LgSimpleEngines.cpp diff --git a/Src/Language/LgSimpleEngines.h b/Src/Kernel/LgSimpleEngines.h similarity index 100% rename from Src/Language/LgSimpleEngines.h rename to Src/Kernel/LgSimpleEngines.h diff --git a/Src/Language/LgUnicodeCollateInit.h b/Src/Kernel/LgUnicodeCollateInit.h similarity index 100% rename from Src/Language/LgUnicodeCollateInit.h rename to Src/Kernel/LgUnicodeCollateInit.h diff --git a/Src/Language/LgUnicodeCollater.cpp b/Src/Kernel/LgUnicodeCollater.cpp similarity index 100% rename from Src/Language/LgUnicodeCollater.cpp rename to Src/Kernel/LgUnicodeCollater.cpp diff --git a/Src/Language/LgUnicodeCollater.h b/Src/Kernel/LgUnicodeCollater.h similarity index 100% rename from Src/Language/LgUnicodeCollater.h rename to Src/Kernel/LgUnicodeCollater.h diff --git a/Src/Language/LocaleIndex.cpp b/Src/Kernel/LocaleIndex.cpp similarity index 100% rename from Src/Language/LocaleIndex.cpp rename to Src/Kernel/LocaleIndex.cpp diff --git a/Src/Language/LocaleIndex.h b/Src/Kernel/LocaleIndex.h similarity index 100% rename from Src/Language/LocaleIndex.h rename to Src/Kernel/LocaleIndex.h diff --git a/Src/Kernel/Main.h b/Src/Kernel/Main.h index c3d4ac519a..5236ac9755 100644 --- a/Src/Kernel/Main.h +++ b/Src/Kernel/Main.h @@ -21,6 +21,10 @@ Last reviewed: //#define kwsLim 0xfffffff9 #include "CellarConstants.h" +#if WIN32 +#include +#endif + using std::min; using std::max; @@ -32,6 +36,68 @@ using std::max; /*********************************************************************************************** Implementations. ***********************************************************************************************/ +#include "LangResource.h" +using namespace fwutil; // Rect and Point classes +// these are a gray area, including aspects of both model and engine +// Todo JohnT: These structs are part of an obsolete approach to overriding character properties. +// Get rid of them and whatever uses them. (Taken from OldLgWritingSystem file.) +/*---------------------------------------------------------------------------------------------- + The CharacterPropertyObject stores all of the data that we allow to be overriden for a + single character (right now, pretty much everything except the Unicode 1.0 name). +----------------------------------------------------------------------------------------------*/ +struct CharacterPropertyObject +{ + UChar32 uch32CodePoint; + StrUni stuCharName; + LgGeneralCharCategory ccGenCategory; + unsigned int nCombiningClass : 8; + LgBidiCategory bicBidiCategory; + LgDecompMapTag dtDecompMapTag; + Vector vuch32Decomp; + unsigned int nDecDigit : 4; + unsigned int nDigit : 4; + int nNumericValue; //numerator stored in the top 16 bits, denominator in the bottom 16 + bool fMirrored : 1; + StrUni stuISOComment; + UChar32 uch32Uppercase; + UChar32 uch32Lowercase; + UChar32 uch32Titlecase; + LgLBP lbpLineBreak; + + void Clear() + { + uch32CodePoint = 0; + stuCharName.Clear(); + ccGenCategory = kccLu; //0 + nCombiningClass = 0; + bicBidiCategory = kbicL; //0 + dtDecompMapTag = kdtNoTag; //0 + vuch32Decomp.Clear(); + nDecDigit = 0; + nDigit = 0; + nNumericValue = 0; + fMirrored = false; + stuISOComment.Clear(); + uch32Uppercase = 0; + uch32Lowercase = 0; + uch32Titlecase = 0; + lbpLineBreak = klbpAI; //0 + } +}; //hungarian cpo +struct CharPropRange +{ + UChar32 iMin; + UChar32 iLim; + Vector vRange; +}; //hungarian cpr +struct OverriddenCharProps +{ + UChar32 iMin; + UChar32 iLim; + Vector * pvcprOverride1; + Vector * pvcpoOverride2; +}; //hungarian ocp + #include "KernelGlobals.h" #include "TsString.h" #include "TsTextProps.h" @@ -40,7 +106,31 @@ using std::max; #include "TextServ.h" #include "TsMultiStr.h" #include "ActionHandler.h" +// Engines +#include "LgIcuCharPropEngine.h" +#include "LgUnicodeCollater.h" +class RomRenderEngine; +DEFINE_COM_PTR(RomRenderEngine); +class UniscribeEngine; +DEFINE_COM_PTR(UniscribeEngine); +#include "RomRenderSegment.h" +#include "RomRenderEngine.h" +#include "LgSimpleEngines.h" +#include "LgNumericEngine.h" +#if !WIN32 +#include "UniscribeLinux.h" +#endif +#include "UniscribeSegment.h" +#include "UniscribeEngine.h" +#include "RegexMatcherWrapper.h" + +// Other tools #include "FwStyledText.h" +#include "StringToNumHelpers.h" +#include "WriteXml.h" // From AppCore. +#include "xmlparse.h" +#include "LgKeymanHandler.h" +#include "LgIcuWrappers.h" #if WIN32 // for parsing XML files; in this DLL, we want the parser to work with wide characters, diff --git a/Src/Kernel/Makefile b/Src/Kernel/Makefile index 6a56c24353..5277ad2e39 100644 --- a/Src/Kernel/Makefile +++ b/Src/Kernel/Makefile @@ -23,11 +23,9 @@ else OPTIMIZATIONS = -O3 endif -CELLAR_SRC = $(SRC)/Cellar -DBSERVICES_SRC = $(SRC)/DbServices +PACKAGES = glib-2.0 gtk+-2.0 glibmm-2.4 gtkmm-2.4 cairomm-1.0 pangomm-1.4 INCLUDES := -I$(KERNEL_SRC) -I$(CELLAR_SRC) -I$(GENERIC_SRC) -I$(APPCORE_SRC) $(DEBUG_INCLUDES) -INCLUDES := $(INCLUDES) -I$(LANGUAGE_SRC) -I$(DBACCESS_SRC) -I$(DBSERVICES_SRC) INCLUDES := $(shell icu-config --cppflags) \ $(INCLUDES) \ @@ -36,12 +34,14 @@ INCLUDES := $(shell icu-config --cppflags) \ -I$(WIN32MORE_INC) \ -I$(COM_INC) \ -I$(WIN32BASE_INC) \ + $(shell pkg-config --cflags $(PACKAGES)) \ LDLIBS := $(LDLIBS) \ -L$(WIN32MORE_LIB) -lWin32More \ -L$(COM_LIB) -lcom \ -L$(WIN32BASE_LIB) -lWin32Base \ + $(shell pkg-config --libs $(PACKAGES)) \ $(shell icu-config --ldflags) \ -luuid -lexpat @@ -71,12 +71,24 @@ OBJ_FWKERNEL = \ $(INT_DIR)/TextServ.o \ $(INT_DIR)/ActionHandler.o \ $(INT_DIR)/DebugReport.o \ + $(INT_DIR)/LgIcuWrappers.o \ + $(INT_DIR)/LgSimpleEngines.o \ + $(INT_DIR)/LgIcuCharPropEngine.o \ + $(INT_DIR)/LgUnicodeCollater.o \ + $(INT_DIR)/LgKeymanHandler.o \ + $(INT_DIR)/LocaleIndex.o \ + $(INT_DIR)/UniscribeLinux.o \ + $(INT_DIR)/UniscribeSegment.o \ + $(INT_DIR)/UniscribeEngine.o \ + $(INT_DIR)/RomRenderEngine.o \ + $(INT_DIR)/RomRenderSegment.o \ OBJ_OTHER = \ $(GENERIC_OBJ)/ModuleEntry.o \ $(GENERIC_OBJ)/TextProps1.o \ $(APPCORE_OBJ)/FwStyledText.o \ $(APPCORE_OBJ)/WriteXml.o \ + $(CELLAR_OBJ)/FwXml.o \ # === Targets === @@ -115,6 +127,10 @@ $(APPCORE_OBJ)/FwStyledText.o $(APPCORE_OBJ)/WriteXml.o: @$(MAKE) -C $(APPCORE_SRC) $@ -q || \ $(MAKE) -C $(APPCORE_SRC) $@ +$(CELLAR_OBJ)/FwXml.o: + @$(MAKE) -C $(CELLAR_SRC) $@ -q || \ + $(MAKE) -C $(CELLAR_SRC) $@ + $(GENERIC_OBJ)/main.o: @$(MAKE) -C $(GENERIC_SRC) -q $@ || \ $(MAKE) -C $(GENERIC_SRC) $@ diff --git a/Src/Language/RegexMatcherWrapper.cpp b/Src/Kernel/RegexMatcherWrapper.cpp similarity index 100% rename from Src/Language/RegexMatcherWrapper.cpp rename to Src/Kernel/RegexMatcherWrapper.cpp diff --git a/Src/Language/RegexMatcherWrapper.h b/Src/Kernel/RegexMatcherWrapper.h similarity index 100% rename from Src/Language/RegexMatcherWrapper.h rename to Src/Kernel/RegexMatcherWrapper.h diff --git a/Src/Language/Render.idh b/Src/Kernel/Render.idh similarity index 100% rename from Src/Language/Render.idh rename to Src/Kernel/Render.idh diff --git a/Src/Language/RomRenderEngine.cpp b/Src/Kernel/RomRenderEngine.cpp similarity index 100% rename from Src/Language/RomRenderEngine.cpp rename to Src/Kernel/RomRenderEngine.cpp diff --git a/Src/Language/RomRenderEngine.h b/Src/Kernel/RomRenderEngine.h similarity index 100% rename from Src/Language/RomRenderEngine.h rename to Src/Kernel/RomRenderEngine.h diff --git a/Src/Language/RomRenderSegment.cpp b/Src/Kernel/RomRenderSegment.cpp similarity index 100% rename from Src/Language/RomRenderSegment.cpp rename to Src/Kernel/RomRenderSegment.cpp diff --git a/Src/Language/RomRenderSegment.h b/Src/Kernel/RomRenderSegment.h similarity index 100% rename from Src/Language/RomRenderSegment.h rename to Src/Kernel/RomRenderSegment.h diff --git a/Src/Kernel/Test/Makefile b/Src/Kernel/Test/Makefile index 9fd67ddc10..49b53d383b 100644 --- a/Src/Kernel/Test/Makefile +++ b/Src/Kernel/Test/Makefile @@ -26,8 +26,6 @@ endif PACKAGES = gdk-2.0 gtkmm-2.4 gdkmm-2.4 cairomm-1.0 pangomm-1.4 -LANGUAGETEST_SRC = $(LANGUAGE_SRC)/Test - INCLUDES := -I$(KERNEL_SRC) -I$(KERNEL_SRC)/Test -I$(CELLAR_SRC) \ -I$(GENERIC_SRC) -I$(APPCORE_SRC) -I$(DEBUGPROCS_SRC) \ @@ -40,7 +38,6 @@ INCLUDES := \ -I$(WIN32MORE_INC) \ -I$(COM_INC) \ -I$(WIN32BASE_INC) \ - -I$(LANGUAGETEST_SRC) \ $(shell pkg-config --cflags $(PACKAGES)) \ LDLIBS := \ @@ -77,8 +74,16 @@ FWKERNEL_OBJ := \ $(KERNEL_OBJ)/TextServ.o \ $(KERNEL_OBJ)/TsMultiStr.o \ $(KERNEL_OBJ)/ActionHandler.o \ + $(KERNEL_OBJ)/LgUnicodeCollater.o \ + $(KERNEL_OBJ)/RomRenderEngine.o \ + $(KERNEL_OBJ)/RomRenderSegment.o \ + $(KERNEL_OBJ)/LgSimpleEngines.o \ + $(KERNEL_OBJ)/LgIcuCharPropEngine.o \ + $(KERNEL_OBJ)/LgKeymanHandler.o \ + $(KERNEL_OBJ)/LocaleIndex.o \ $(GENERIC_OBJ)/ModuleEntry.o \ $(GENERIC_OBJ)/TextProps1.o \ + $(CELLAR_OBJ)/FwXml.o \ #Run make in the directory of each library $(LINK_LIBS) $(FWKERNEL_OBJ):: @@ -108,12 +113,16 @@ COLLECT=$(BUILD_ROOT)/Bin/CollectUnit++Tests.sh Kernel $(INT_DIR)/Collection.cpp: testFwKernel.h \ - $(LANGUAGETEST_SRC)/MockLgWritingSystemFactory.h\ - $(LANGUAGETEST_SRC)/MockLgWritingSystem.h\ TestUndoStack.h \ TestTsStrBldr.h \ TestTsString.h \ TestTsPropsBldr.h \ - TestTsTextProps.h + TestTsTextProps.h \ + MockLgWritingSystemFactory.h \ + MockLgWritingSystem.h \ + TestLgCollatingEngine.h \ + TestLgIcuCharPropEngine.h \ + TestRomRenderEngine.h \ + RenderEngineTestBase.h @echo Collecting tests for testFwKernel $(COLLECT) $^ $@ diff --git a/Src/Language/Test/MockLgWritingSystem.h b/Src/Kernel/Test/MockLgWritingSystem.h similarity index 100% rename from Src/Language/Test/MockLgWritingSystem.h rename to Src/Kernel/Test/MockLgWritingSystem.h diff --git a/Src/Language/Test/MockLgWritingSystemFactory.h b/Src/Kernel/Test/MockLgWritingSystemFactory.h similarity index 100% rename from Src/Language/Test/MockLgWritingSystemFactory.h rename to Src/Kernel/Test/MockLgWritingSystemFactory.h diff --git a/Src/Language/Test/RenderEngineTestBase.h b/Src/Kernel/Test/RenderEngineTestBase.h similarity index 99% rename from Src/Language/Test/RenderEngineTestBase.h rename to Src/Kernel/Test/RenderEngineTestBase.h index f6c6e31837..e9691e5ddc 100644 --- a/Src/Language/Test/RenderEngineTestBase.h +++ b/Src/Kernel/Test/RenderEngineTestBase.h @@ -15,16 +15,16 @@ Last reviewed: #pragma once -#include "testLanguage.h" +#include "testFwKernel.h" #ifndef WIN32 // on Linux - symbols for for methods of Vector - This include adds them into testLanguage #include "Vector_i.cpp" #endif -namespace TestLanguage +namespace TestFwKernel { // For error reporting: - static DummyFactory g_fact(_T("SIL.TestLanguage.TxtSrc")); + static DummyFactory g_fact(_T("SIL.TestFwKernel.TxtSrc")); /******************************************************************************************* Mock object class for TestUniscribeEngine::testBreakPointing(). diff --git a/Src/Kernel/Test/TestKernel.vcxproj b/Src/Kernel/Test/TestKernel.vcxproj index ac1404878e..8c60edafff 100644 --- a/Src/Kernel/Test/TestKernel.vcxproj +++ b/Src/Kernel/Test/TestKernel.vcxproj @@ -1,82 +1,94 @@  - - Debug - Win32 - - - Release - Win32 - + + Debug + Win32 + + + Release + Win32 + - {4869A8EB-1013-47FB-8FED-53FC532F9125} - - - - MakeFileProj + {4869A8EB-1013-47FB-8FED-53FC532F9125} + + + + + + + MakeFileProj - Makefile + Makefile - Makefile + Makefile - - + + - - + + - <_ProjectFileVersion>10.0.30319.1 - Debug\ - Debug\ - ..\..\..\bin\mkfwk-tst.bat DONTRUN - ..\..\..\bin\mkfwk-tst.bat DONTRUN cc - ..\..\..\bin\mkfwk-tst.bat DONTRUN ec - ..\..\..\output\debug\testFwKernel.exe - $(NMakePreprocessorDefinitions) - $(NMakeIncludeSearchPath) - $(NMakeForcedIncludes) - $(NMakeAssemblySearchPath) - $(NMakeForcedUsingAssemblies) - Release\ - Release\ - - - - Test.exe - $(NMakePreprocessorDefinitions) - $(NMakeIncludeSearchPath) - $(NMakeForcedIncludes) - $(NMakeAssemblySearchPath) - $(NMakeForcedUsingAssemblies) + <_ProjectFileVersion>10.0.30319.1 + Debug\ + Debug\ + ..\..\..\bin\mkfwk-tst.bat DONTRUN + ..\..\..\bin\mkfwk-tst.bat DONTRUN cc + ..\..\..\bin\mkfwk-tst.bat DONTRUN ec + ..\..\..\output\debug\testFwKernel.exe + $(NMakePreprocessorDefinitions) + $(NMakeIncludeSearchPath) + $(NMakeForcedIncludes) + $(NMakeAssemblySearchPath) + $(NMakeForcedUsingAssemblies) + Release\ + Release\ + + + + Test.exe + $(NMakePreprocessorDefinitions) + $(NMakeIncludeSearchPath) + $(NMakeForcedIncludes) + $(NMakeAssemblySearchPath) + $(NMakeForcedUsingAssemblies) - - + + - - - - - - + + + + + + + + + + + + + + - + + diff --git a/Src/Kernel/Test/TestKernel.vcxproj.filters b/Src/Kernel/Test/TestKernel.vcxproj.filters index 5cfbc64637..03352c3d2d 100644 --- a/Src/Kernel/Test/TestKernel.vcxproj.filters +++ b/Src/Kernel/Test/TestKernel.vcxproj.filters @@ -1,48 +1,73 @@  - - {5623374b-c87b-4ab3-8249-2e420565a567} - cpp;c;cxx;def;odl;idl;hpj;bat;asm - - - {fb936a20-a6fe-4029-878f-768c6cba0d0a} - h;hpp;hxx;hm;inl;inc - - - {70ed67c2-a166-44ac-9670-273d82fe0b04} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe - + + {5623374b-c87b-4ab3-8249-2e420565a567} + cpp;c;cxx;def;odl;idl;hpj;bat;asm + + + {fb936a20-a6fe-4029-878f-768c6cba0d0a} + h;hpp;hxx;hm;inl;inc + + + {70ed67c2-a166-44ac-9670-273d82fe0b04} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + - - Source Files - - - Source Files - + + Source Files + + + Source Files + - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + - + + \ No newline at end of file diff --git a/Src/Language/Test/TestLgCollatingEngine.h b/Src/Kernel/Test/TestLgCollatingEngine.h similarity index 98% rename from Src/Language/Test/TestLgCollatingEngine.h rename to Src/Kernel/Test/TestLgCollatingEngine.h index 5929425000..a974a19340 100644 --- a/Src/Language/Test/TestLgCollatingEngine.h +++ b/Src/Kernel/Test/TestLgCollatingEngine.h @@ -15,9 +15,9 @@ Last reviewed: #pragma once -#include "testLanguage.h" +#include "testFwKernel.h" -namespace TestLanguage +namespace TestFwKernel { /******************************************************************************************* Tests for LgCollatingEngine diff --git a/Src/Language/Test/TestLgIcuCharPropEngine.h b/Src/Kernel/Test/TestLgIcuCharPropEngine.h similarity index 99% rename from Src/Language/Test/TestLgIcuCharPropEngine.h rename to Src/Kernel/Test/TestLgIcuCharPropEngine.h index 31ea4fda8e..2452194f14 100644 --- a/Src/Language/Test/TestLgIcuCharPropEngine.h +++ b/Src/Kernel/Test/TestLgIcuCharPropEngine.h @@ -15,9 +15,9 @@ Last reviewed: #pragma once -#include "testLanguage.h" +#include "testFwKernel.h" -namespace TestLanguage +namespace TestFwKernel { /******************************************************************************************* Tests for LgCharacterPropertyEngine (ICU based implementation) diff --git a/Src/Language/Test/TestRegexMatcher.h b/Src/Kernel/Test/TestRegexMatcher.h similarity index 98% rename from Src/Language/Test/TestRegexMatcher.h rename to Src/Kernel/Test/TestRegexMatcher.h index a25d9769aa..b663f8f9a7 100644 --- a/Src/Language/Test/TestRegexMatcher.h +++ b/Src/Kernel/Test/TestRegexMatcher.h @@ -15,9 +15,9 @@ Last reviewed: #pragma once -#include "testLanguage.h" +#include "testFwKernel.h" -namespace TestLanguage +namespace TestFwKernel { /******************************************************************************************* Tests for LgCharacterPropertyEngine (ICU based implementation) diff --git a/Src/Language/Test/TestRomRenderEngine.h b/Src/Kernel/Test/TestRomRenderEngine.h similarity index 97% rename from Src/Language/Test/TestRomRenderEngine.h rename to Src/Kernel/Test/TestRomRenderEngine.h index 570845e155..a26af9501d 100644 --- a/Src/Language/Test/TestRomRenderEngine.h +++ b/Src/Kernel/Test/TestRomRenderEngine.h @@ -15,10 +15,10 @@ Last reviewed: #pragma once -#include "testLanguage.h" +#include "testFwKernel.h" #include "RenderEngineTestBase.h" -namespace TestLanguage +namespace TestFwKernel { /******************************************************************************************* Tests for RomRenderEngine diff --git a/Src/Language/Test/TestUniscribeEngine.h b/Src/Kernel/Test/TestUniscribeEngine.h similarity index 97% rename from Src/Language/Test/TestUniscribeEngine.h rename to Src/Kernel/Test/TestUniscribeEngine.h index 331661f174..ce1d7de314 100644 --- a/Src/Language/Test/TestUniscribeEngine.h +++ b/Src/Kernel/Test/TestUniscribeEngine.h @@ -15,10 +15,10 @@ Last reviewed: #pragma once -#include "testLanguage.h" +#include "testFwKernel.h" #include "RenderEngineTestBase.h" -namespace TestLanguage +namespace TestFwKernel { /******************************************************************************************* Tests for TestUniscribeEngine diff --git a/Src/Kernel/Test/testFwKernel.cpp b/Src/Kernel/Test/testFwKernel.cpp index 5ee40762bd..9cd55556c0 100644 --- a/Src/Kernel/Test/testFwKernel.cpp +++ b/Src/Kernel/Test/testFwKernel.cpp @@ -22,7 +22,7 @@ namespace unitpp #ifdef WIN32 ModuleEntry::DllMain(0, DLL_PROCESS_ATTACH); #endif - CoInitialize(NULL); + CheckHr(::OleInitialize(NULL)); RedirectRegistry(); StrUtil::InitIcuDataDir(); } @@ -31,6 +31,13 @@ namespace unitpp #ifdef WIN32 ModuleEntry::DllMain(0, DLL_PROCESS_DETACH); #endif - CoUninitialize(); + ::OleUninitialize(); } } + +namespace TestFwKernel +{ + int g_wsEng = 0; + int g_wsTest = 0; + int g_wsTest2 = 0; +} diff --git a/Src/Kernel/Test/testFwKernel.h b/Src/Kernel/Test/testFwKernel.h index 38ac2157fa..9debfec628 100644 --- a/Src/Kernel/Test/testFwKernel.h +++ b/Src/Kernel/Test/testFwKernel.h @@ -32,6 +32,14 @@ namespace TestFwKernel static const StrUni g_pszTest2(L"TESTING"); static const int g_cchTest2 = 7; + const StrUni kszEng(L"en"); + const StrUni kszTest(L"test"); + const StrUni kszTest2(L"tst2"); + + extern int g_wsEng; + extern int g_wsTest; + extern int g_wsTest2; + enum { // Arbitrary values chosen more or less at random... diff --git a/Src/Kernel/Test/testFwKernel.mak b/Src/Kernel/Test/testFwKernel.mak index 027d702232..486f09b800 100644 --- a/Src/Kernel/Test/testFwKernel.mak +++ b/Src/Kernel/Test/testFwKernel.mak @@ -17,10 +17,10 @@ FWKERNELTEST_SRC=$(BUILD_ROOT)\Src\Kernel\Test GENERIC_SRC=$(BUILD_ROOT)\Src\Generic APPCORE_SRC=$(BUILD_ROOT)\Src\AppCore DEBUGPROCS_SRC=$(BUILD_ROOT)\src\DebugProcs -LANGUAGETEST_SRC=$(BUILD_ROOT)\Src\Language\Test +CELLAR_SRC=$(BUILD_ROOT)\Src\Cellar # Set the USER_INCLUDE environment variable. -UI=$(UNITPP_INC);$(FWKERNELTEST_SRC);$(FWKERNEL_SRC);$(GENERIC_SRC);$(APPCORE_SRC);$(DEBUGPROCS_SRC);$(LANGUAGETEST_SRC) +UI=$(UNITPP_INC);$(FWKERNELTEST_SRC);$(FWKERNEL_SRC);$(GENERIC_SRC);$(APPCORE_SRC);$(DEBUGPROCS_SRC);$(CELLAR_SRC) !IF "$(USER_INCLUDE)"!="" USER_INCLUDE=$(UI);$(USER_INCLUDE) @@ -34,9 +34,11 @@ USER_INCLUDE=$(UI) PATH=$(COM_OUT_DIR);$(PATH) +RCFILE=FwKernel.rc + LINK_OPTS=$(LINK_OPTS:/subsystem:windows=/subsystem:console) /LIBPATH:"$(BUILD_ROOT)\Lib\$(BUILD_CONFIG)" CPPUNIT_LIBS=unit++.lib -LINK_LIBS=$(CPPUNIT_LIBS) Generic.lib xmlparse.lib $(LINK_LIBS) +LINK_LIBS=$(CPPUNIT_LIBS) Generic.lib xmlparse.lib Usp10.lib $(LINK_LIBS) # === Object Lists === @@ -53,8 +55,17 @@ OBJ_KERNELTESTSUITE=\ $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\FwKernel\autopch\TsMultiStr.obj\ $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\FwKernel\usepch\TextProps1.obj\ $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\FwKernel\autopch\ActionHandler.obj\ + $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\FwKernel\autopch\UniscribeEngine.obj\ + $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\FwKernel\autopch\UniscribeSegment.obj\ + $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\FwKernel\autopch\RomRenderEngine.obj\ + $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\FwKernel\autopch\RomRenderSegment.obj\ + $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\FwKernel\autopch\LgSimpleEngines.obj\ + $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\FwKernel\autopch\LgIcuCharPropEngine.obj\ + $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\FwKernel\autopch\LgUnicodeCollater.obj\ + $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\FwKernel\autopch\LgKeymanHandler.obj\ $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\FwKernel\autopch\FwStyledText.obj\ $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\FwKernel\autopch\WriteXml.obj\ + $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\FwKernel\autopch\FwXml.obj\ OBJ_ALL=$(OBJ_KERNELTESTSUITE) @@ -80,12 +91,21 @@ COLLECT=$(BUILD_ROOT)\Bin\CollectUnit++Tests.cmd Kernel $(INT_DIR)\genpch\Collection.obj: $(FWKERNELTEST_SRC)\Collection.cpp $(FWKERNELTEST_SRC)\Collection.cpp: $(FWKERNELTEST_SRC)\testFwKernel.h\ - $(LANGUAGETEST_SRC)\MockLgWritingSystemFactory.h\ - $(LANGUAGETEST_SRC)\MockLgWritingSystem.h\ $(FWKERNELTEST_SRC)\TestUndoStack.h\ $(FWKERNELTEST_SRC)\TestTsStrBldr.h\ $(FWKERNELTEST_SRC)\TestTsString.h\ $(FWKERNELTEST_SRC)\TestTsPropsBldr.h\ - $(FWKERNELTEST_SRC)\TestTsTextProps.h + $(FWKERNELTEST_SRC)\TestTsTextProps.h\ + $(FWKERNELTEST_SRC)\MockLgWritingSystemFactory.h\ + $(FWKERNELTEST_SRC)\MockLgWritingSystem.h\ + $(FWKERNELTEST_SRC)\TestRegexMatcher.h\ + $(FWKERNELTEST_SRC)\TestLgCollatingEngine.h\ + $(FWKERNELTEST_SRC)\TestLgIcuCharPropEngine.h\ + $(FWKERNELTEST_SRC)\TestUniscribeEngine.h\ + $(FWKERNELTEST_SRC)\TestRomRenderEngine.h\ + $(FWKERNELTEST_SRC)\RenderEngineTestBase.h $(DISPLAY) Collecting tests for $(BUILD_PRODUCT).$(BUILD_EXTENSION) $(COLLECT) $** $(FWKERNELTEST_SRC)\Collection.cpp + +$(INT_DIR)\FwKernel.res: $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\FwKernel\FwKernel.res + copy $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\FwKernel\FwKernel.res $(INT_DIR)\FwKernel.res >nul \ No newline at end of file diff --git a/Src/Language/UniscribeEngine.cpp b/Src/Kernel/UniscribeEngine.cpp similarity index 100% rename from Src/Language/UniscribeEngine.cpp rename to Src/Kernel/UniscribeEngine.cpp diff --git a/Src/Language/UniscribeEngine.h b/Src/Kernel/UniscribeEngine.h similarity index 100% rename from Src/Language/UniscribeEngine.h rename to Src/Kernel/UniscribeEngine.h diff --git a/Src/Language/UniscribeLinux.cpp b/Src/Kernel/UniscribeLinux.cpp similarity index 100% rename from Src/Language/UniscribeLinux.cpp rename to Src/Kernel/UniscribeLinux.cpp diff --git a/Src/Language/UniscribeLinux.h b/Src/Kernel/UniscribeLinux.h similarity index 100% rename from Src/Language/UniscribeLinux.h rename to Src/Kernel/UniscribeLinux.h diff --git a/Src/Language/UniscribeSegment.cpp b/Src/Kernel/UniscribeSegment.cpp similarity index 100% rename from Src/Language/UniscribeSegment.cpp rename to Src/Kernel/UniscribeSegment.cpp diff --git a/Src/Language/UniscribeSegment.h b/Src/Kernel/UniscribeSegment.h similarity index 100% rename from Src/Language/UniscribeSegment.h rename to Src/Kernel/UniscribeSegment.h diff --git a/Src/Language/LangInstaller.idl b/Src/Language/LangInstaller.idl deleted file mode 100644 index 7f34f6c633..0000000000 --- a/Src/Language/LangInstaller.idl +++ /dev/null @@ -1,48 +0,0 @@ -import "oaidl.idl"; -import "ocidl.idl"; - -#include "common.idh" // DeclareInterface and similar - -// This idl file was written based upon LangInstaller.cs definition of the interface. -// Its is used by linux as linux can't use #import on a tlb -// This idl file could be run through idlimp and replace the C# definition of the interface. - -DeclareLibrary(LangInstaller, 1.0, "InstallLang", C13F5F35-1FD2-4388-B905-394D18D28EFB) -{ - DeclareInterface(LangInstaller, Unknown, EB5B7CFA-6EC8-4641-97D2-5FE338FF5434) - { - HRESULT Install( - [in] BSTR locale, - [in] VARIANT_BOOL fNewLang, - [in] VARIANT_BOOL fAddPUA, - [out, retval] VARIANT_BOOL *pfSuccess); - - HRESULT AddPUAChars( - [in] BSTR locale, - [out, retval] VARIANT_BOOL *pfSuccess); - - HRESULT Uninstall( - [in] BSTR locale, - [out, retval] VARIANT_BOOL *pfSuccess); - - HRESULT ShowCustomLocales( - [out, retval] VARIANT_BOOL *pfSuccess); - - HRESULT ShowCustomLanguages( - [out, retval] VARIANT_BOOL *pfSuccess); - - HRESULT RestoreOriginalSettings( - [in] VARIANT_BOOL fNewLang, - [out, retval] VARIANT_BOOL *pfSuccess); - - HRESULT get_ErrorCode( - [out, retval] long *pErrorCode); - - HRESULT Cleanup(); - }; - - DeclareCoClass(LangInstaller, 5EDF610A-F38F-4034-8714-76B95FDF70EC) - { - interface ILangInstaller; - }; -} diff --git a/Src/Language/Language.def b/Src/Language/Language.def deleted file mode 100644 index 9f0c9e51ba..0000000000 --- a/Src/Language/Language.def +++ /dev/null @@ -1,8 +0,0 @@ -LIBRARY Language - -EXPORTS - DllGetClassObject PRIVATE - DllRegisterServer PRIVATE - DllUnregisterServer PRIVATE - DllCanUnloadNow PRIVATE - DllInstall PRIVATE diff --git a/Src/Language/Language.mak b/Src/Language/Language.mak deleted file mode 100644 index 0e382e62f2..0000000000 --- a/Src/Language/Language.mak +++ /dev/null @@ -1,135 +0,0 @@ -# Input -# ===== -# BUILD_ROOT: d:\FieldWorks -# BUILD_TYPE: d, r, p -# BUILD_CONFIG: Debug, Release, Profile -# - -BUILD_PRODUCT=Language -BUILD_EXTENSION=dll -BUILD_REGSVR=1 - -# LANG_XML=$(BUILD_ROOT)\src\Services\language\XML - -DEFS=$(DEFS) /DGR_FW /D_MERGE_PROXYSTUB /I"$(COM_OUT_DIR)" /I"$(COM_OUT_DIR_RAW)" - -LANG_SRC=$(BUILD_ROOT)\Src\Language -GENERIC_SRC=$(BUILD_ROOT)\Src\Generic -APPCORE_SRC=$(BUILD_ROOT)\Src\AppCore -TEXT_SRC=$(BUILD_ROOT)\Src\Text -CELLAR_SRC=$(BUILD_ROOT)\Src\Cellar -GRUTIL_LIB=$(BUILD_ROOT)\Src\Graphite\lib -TTFUTIL_LIB=$(BUILD_ROOT)\Src\Graphite\TtfUtil -VIEWS_LIB=$(BUILD_ROOT)\Src\Views\lib -GRFW_SRC=$(BUILD_ROOT)\Src\Graphite\FwOnly -# FWUTILS_SRC=$(BUILD_ROOT)\src\FWUtils - -# Set the USER_INCLUDE environment variable. Make sure Lang is first, as we want -# to get the Main.h from there, not any of the others (e.g., in Views) -UI=$(LANG_SRC);$(GENERIC_SRC);$(APPCORE_SRC);$(TEXT_SRC);$(CELLAR_SRC) - -KERNEL_SRC=$(BUILD_ROOT)\src\Kernel -UI=$(UI);$(KERNEL_SRC) - - -!IF "$(USER_INCLUDE)"!="" -USER_INCLUDE=$(UI);$(USER_INCLUDE);$(GRUTIL_LIB);$(TTFUTIL_LIB);$(VIEWS_LIB);$(GRFW_SRC) -!ELSE -USER_INCLUDE=$(UI);$(GRUTIL_LIB);$(TTFUTIL_LIB);$(VIEWS_LIB);$(GRFW_SRC) -!ENDIF - -# XML_INC=$(CELLAR_XML);$(LANG_XML) - -!INCLUDE "$(BUILD_ROOT)\bld\_init.mak" - -!INCLUDE "$(BUILD_ROOT)\bld\_rule.mak" - -PATH=$(COM_OUT_DIR);$(PATH) - -RCFILE=Language.rc -DEFFILE=Language.def -# add Usp10.lib for Uniscribe. -!IF "$(BUILD_TYPE)"=="d" || "$(BUILD_TYPE)"=="b" -LINK_LIBS=Generic.lib Usp10.lib xmlparse.lib $(LINK_LIBS) -!ELSE -LINK_LIBS=Generic.lib Usp10.lib xmlparse.lib $(LINK_LIBS) -!ENDIF - -# === Object Lists === - -OBJ_LANG=\ - $(INT_DIR)\genpch\RegexMatcherWrapper.obj\ - $(INT_DIR)\autopch\LgIcuWrappers.obj\ - $(INT_DIR)\autopch\UniscribeEngine.obj\ - $(INT_DIR)\autopch\UniscribeSegment.obj\ - $(INT_DIR)\autopch\RomRenderEngine.obj\ - $(INT_DIR)\autopch\RomRenderSegment.obj\ - $(INT_DIR)\autopch\LgSimpleEngines.obj\ - $(INT_DIR)\autopch\LgIcuCharPropEngine.obj\ - $(INT_DIR)\autopch\LgUnicodeCollater.obj\ - $(INT_DIR)\autopch\LgKeymanHandler.obj\ - $(INT_DIR)\autopch\ModuleEntry.obj\ - $(INT_DIR)\autopch\FwStyledText.obj\ - $(INT_DIR)\autopch\WriteXml.obj\ - $(INT_DIR)\usepch\TextProps1.obj\ - $(INT_DIR)\autopch\FwXml.obj\ - $(INT_DIR)\autopch\dlldatax.obj\ - - -OBJ_GRUTIL=\ -## $(INT_DIR)\autopch\TtfUtil.obj\ - $(INT_DIR)\autopch\GrUtil.obj\ - - -IDL_MAIN=$(COM_OUT_DIR)\LanguageTlb.idl - -PS_MAIN=LanguagePs - -OBJ_ALL= $(OBJ_LANG) $(OBJ_GRUTIL) - -OBJECTS_IDH=$(COM_INT_DIR)\Objects.idh - -# ? OBJECTS_H=$(COM_INT_DIR)\Objects.h - -# === Targets === -!INCLUDE "$(BUILD_ROOT)\bld\_targ.mak" - - -# === Rules === -PCHNAME=main - -ARG_SRCDIR=$(CELLAR_XML) -!INCLUDE "$(BUILD_ROOT)\bld\_rule.mak" - -ARG_SRCDIR=$(LANG_XML) -!INCLUDE "$(BUILD_ROOT)\bld\_rule.mak" - -ARG_SRCDIR=$(LANG_SRC) -!INCLUDE "$(BUILD_ROOT)\bld\_rule.mak" - -ARG_SRCDIR=$(CELLAR_SRC) -!INCLUDE "$(BUILD_ROOT)\bld\_rule.mak" - -ARG_SRCDIR=$(GENERIC_SRC) -!INCLUDE "$(BUILD_ROOT)\bld\_rule.mak" - -ARG_SRCDIR=$(APPCORE_SRC) -!INCLUDE "$(BUILD_ROOT)\bld\_rule.mak" - -ARG_SRCDIR=$(FWUTILS_SRC) -!INCLUDE "$(BUILD_ROOT)\bld\_rule.mak" - -ARG_SRCDIR=$(GRUTIL_LIB) -!INCLUDE "$(BUILD_ROOT)\bld\_rule.mak" - -## ARG_SRCDIR=$(TTFUTIL_LIB) -## !INCLUDE "$(BUILD_ROOT)\bld\_rule.mak" - -# === Custom Rules === -$(OBJ_ALL): $(OBJECTS_H) - -$(COM_OUT_DIR)\LanguageTlb.tlb: $(COM_OUT_DIR)\LanguageTlb.idl - -$(COM_OUT_DIR)\LanguageTlb.idl: $(LANG_SRC)\Render.idh - -# === Custom Targets === diff --git a/Src/Language/Language.rc b/Src/Language/Language.rc deleted file mode 100644 index 658d8ca01a..0000000000 --- a/Src/Language/Language.rc +++ /dev/null @@ -1,444 +0,0 @@ -/*--------------------------------------------------------------------*//*:Ignore this sentence. -Copyright (C) 1999, 2004 SIL International. All rights reserved. - -Distributable under the terms of either the Common Public License or the -GNU Lesser General Public License, as specified in the LICENSING.txt file. - -File: Language.rc -Responsibility: -Last reviewed: Not yet. - -Description: - --------------------------------------------------------------------------------*//*:End Ignore*/ -1 TYPELIB LanguageTlb.tlb -#if WIN32 -#include "winresrc.h" -#endif -#include "LangResource.h" - -///////////////////////////////////////////////////////////////////////////// -// -// Version: bldinc.h holds the current version number and it is created by executing -// bin\mkverrsc.exe from within the bin\mk*.bat file. The major and minor version -// numbers are hard-coded in mk*.bat. -#if WIN32 -#include "..\..\Output\Common\bldinc.h" -#endif -VS_VERSION_INFO VERSIONINFO -// NOTE: These defines are in bldinc.h. - FILEVERSION MAJOR_VERSION,MINOR_VERSION,SUITE_REVISION,NUMBER_OF_DAYS - PRODUCTVERSION MAJOR_VERSION,MINOR_VERSION,SUITE_REVISION,NUMBER_OF_DAYS - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE VFT_DLL - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "Comments", "\0" - VALUE "CompanyName", "SIL\0" - VALUE "FileDescription", "Fieldworks Language support\0" - VALUE "FileVersion", STR_PRODUCT // Uses FILEVERSION. - VALUE "InternalName", "Language\0" - VALUE "LegalCopyright", COPYRIGHT - VALUE "LegalTrademarks", "\0" - VALUE "OriginalFilename", "Language.dll\0" - VALUE "PrivateBuild", "\0" - VALUE "ProductName", "FieldWorks\0" - VALUE "ProductVersion", FWSUITE_VERSION - VALUE "SpecialBuild", "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -STRINGTABLE DISCARDABLE -BEGIN - kstidBufferTooSmall "The buffer passed to this method was too small to hold the result." - kstidFracNumVal "Can't report a fractional numeric value" - kstidNoNumeric "Unicode does not define a numeric value for this character" - kstidInvalidUnicode "Found an invalid Unicode character or sequence" - kstidICUCharName "The ICU code retrieving the Unicode character name found an error." - kstidICUDecomp "The ICU code finding the Unicode decomposition encountered an error." - kstidICUNormalize "The ICU code normalizing the text found an error." - kstidICUCase "The ICU function for changing the case found an error." - kstidICUBrkInit "The ICU function to initialize the BreakIterator returned an error." - kstidICUBrkRange "The line break asked for was out of range of the given text." - kstidLangDefaultCollation "DefaultCollation" - kstidUserWs "en" // unless and until someone translates all our resources and - // fixes up the resulting problems in the code. - kstidKeymanInitFailedCaption "Keyman initialization failed" - kstidKeymanInitUnexpectedFailMsg "Unexpected Keyman failure" - kstidKeymanNotRegisteredMsg "No known version of Keyman is registered." - kstidKeymanRootNotRegisteredMsg "Keyman program is not registered correctly." - kstidKeymanDllLoadFailureMsg "Failed to load Keyman32.dll" -END - -STRINGTABLE DISCARDABLE -BEGIN - kstidLangDefXmlMsg001 "Missing CharDef code attribute value.\n" - kstidLangDefXmlMsg002 "Missing CharDef data attribute value.\n" - kstidLangDefXmlMsg003 "Invalid CharDef code attribute value: ""%<0>s"".\n" - kstidLangDefXmlMsg004 "Missing Font file attribute value.\n" - kstidLangDefXmlMsg005 "Missing LgWritingSystem definition!?\n" - kstidLangDefXmlMsg006 "Unbalanced object stack!?\n" - kstidLangDefXmlMsg007 "Unbalanced property value stack!?\n" - kstidLangDefXmlMsg008 "Cannot put multiple objects in an atomic property.\n" - kstidLangDefXmlMsg009 "Cannot open language definition file ""%<0>s""!?\n" - kstidLangDefXmlMsg010 "Error accessing language definition file ""%<0>s""!?\n" - kstidLangDefXmlMsg011 "XML parser detected an XML syntax error!\n" - kstidLangDefXmlMsg012 "Error detected while parsing XML file!\n" - kstidLangDefXmlMsg013 "Missing EncodingConverter install attribute value.\n" -END - -STRINGTABLE DISCARDABLE -BEGIN - kstidLangDefXmlMsg014 "Problem while opening project" - kstidLangDefXmlMsg015 "The %<0>s writing system could not be installed, possibly due to insufficient user privileges.%nThis may affect sorting, special character definitions, and other aspects of the writing system.%n" -END - -// Message strings for the XML import/export process. These are shared with the Language DLL. - -STRINGTABLE DISCARDABLE -BEGIN - kstidXmlUserWs "en" -END - -STRINGTABLE DISCARDABLE -BEGIN - kstidXmlInfoMsg001 " %<0>d %<1>s processed, %<2>d successful, %<3>d attempted\n" - kstidParameter "Parameter" - kstidParameters "Parameters" - kstidXmlInfoMsg002 "%<0>d custom %<1>s have been added to the database schema.\n" - kstidField "field" - kstidFields "fields" - kstidXmlInfoMsg003 "First pass of reading the XML file took %<0>d %<1>s.\n" - kstidXmlInfoMsg007 "Creating %<0>d objects after the first pass took %<1>d %<2>s.\n" - kstidXmlInfoMsg009 "Second pass of reading the XML file took %d %s.\n" - kstidXmlInfoMsg004 "Storing data after the second pass took %<0>d %<1>s.\n" - kstidXmlInfoMsg006 "Loading the XML file into the database took %<0>d %<1>s.\n" - kstidSecond "second" - kstidSeconds "seconds" - kstidXmlInfoMsg005 "Storing the data into the database took %<0>d SQL %<1>s.\n" - kstidCommand "command" - kstidCommands "commands" - kstidXmlInfoMsg008 "Creating %<0>d empty structured text paragraphs.\n" - kstidXmlInfoMsg010 "d""> does not match the database version (%<1>d).\n" - kstidXmlInfoMsg011 "No version number given with .\n" - - kstidXmlErrorMsg001 "<%<0>s> elements cannot be nested inside either or !\n" - kstidXmlErrorMsg002 "<%<0>s> is improperly nested!\n" - kstidXmlErrorMsg003 "<%<0>s> must be nested inside <%<1>s> or an object attribute element!\n" - kstidXmlErrorMsg004 "<%<0>s> must be nested inside <%<1>s>...s>!\n" - kstidXmlErrorMsg005 "<%<0>s> must be nested inside an object attribute element!\n" - kstidXmlErrorMsg006 "<%<0>s> must be nested inside an object element!\n" - kstidXmlErrorMsg007 "<%<0>s> not recognized nested within either or !\n" - kstidXmlErrorMsg008 " must be a toplevel element inside !?\n" - kstidXmlErrorMsg009 " must be a toplevel element inside !?\n" - kstidXmlErrorMsg010 "<%<0>s> must be the outermost XML element!?\n" - kstidXmlErrorMsg011 "Cannot convert ""%<0>s"" into a Language Writing system code.\n" - kstidXmlErrorMsg012 "Cannot create GUID for object identifier!\n" - kstidXmlErrorMsg013 "Cannot get buffer from the XML parser [pass 1]! (Out of memory?)\n" - kstidXmlErrorMsg014 "Cannot get buffer from the XML parser [pass 2]! (Out of memory?)\n" - kstidXmlErrorMsg015 "Cannot have some ord attribute values missing and some present!\n" - kstidXmlErrorMsg016 "Cannot read the CmObject table in the database!\n" - kstidXmlErrorMsg017 "Invalid list root id '%<0>s' in custom field definition [%<1>S]??\n" - kstidXmlErrorMsg018 "ERROR %<0>s executing SQL command:\n %<1>s\n" - kstidXmlErrorMsg019 "ERROR %<0>s executing SQL function on line %<1>d of %<2>s:\n %<3>s\n" - kstidXmlErrorMsg020 "ERROR creating %<0>S (%<1>d, %<2>g)\n" - kstidXmlErrorMsg021 "ERROR in SetMultiBigStr$ %<0>d,%<1>d,%<2>d,'...',0x...\n" - kstidXmlErrorMsg022 "ERROR in SetMultiBigTxt$ %<0>d,%<1>d,%<2>d,'...'\n" - kstidXmlErrorMsg023 "ERROR in SetMultiStr$ %<0>d,%<1>d,%<2>d,'...',0x...\n" - kstidXmlErrorMsg024 "ERROR in SetMultiTxt$ %<0>d,%<1>d,%<2>d,'...'\n" - kstidXmlErrorMsg025 "ERROR in UPDATE [%<0>S] SET [%<1>S]=? WHERE [Id]=%<2>d\n" - kstidXmlErrorMsg026 "ERROR in UPDATE [%<0>S] SET [%<1>S]=?,%<2>S_Fmt=? WHERE [Id]=%<3>d\n" - kstidXmlErrorMsg027 "ERROR with INSERT %<0>S_%<1>S (Src, Dst) VALUES (%<2>d, %<3>d)\n" - kstidXmlErrorMsg028 "ERROR with INSERT %<0>S_%<1>S (Src, Dst, Ord) VALUES (%<2>d, %<3>d, %<4>d)\n" - kstidXmlErrorMsg029 "ERROR with UPDATE [%<0>S] SET [%<1>S]=%<2>d WHERE [Id]=%<3>d\n" - kstidXmlErrorMsg030 "ERROR! BUG! Invalid field data type storing data?? (%<0>d)\n" - kstidXmlErrorMsg031 "Empty <%<0>s> element?\n" -// kstidXmlErrorMsg032 "Empty element? (cbtext = 0)\n" - kstidXmlErrorMsg033 "Empty element?\n" -// kstidXmlErrorMsg034 "Empty element? (cbtext = 0)\n" - kstidXmlErrorMsg035 "Empty MultiString element? (cbtext = 0)\n" - kstidXmlErrorMsg036 "Empty String element? (cbtext = 0)\n" - kstidXmlErrorMsg037 "Error detected while parsing XML file [pass 1]!\n" - kstidXmlErrorMsg038 "Error detected while parsing XML file [pass 2]!\n" - kstidXmlErrorMsg039 "Found a with identical properties to preceding : these have been merged.\n" - kstidXmlErrorMsg040 "INTERNAL DATA CORRUPTION: unable to get class for field!\n" - kstidXmlErrorMsg041 "INTERNAL XML ELEMENT STACK CORRUPTED!?\n" - kstidXmlErrorMsg042 "Ignoring s=""%<1>s""> in the absence of a %<2>s attribute.\n" -// kstidXmlErrorMsg043 "Ignoring s""> in the absence of a offset attribute.\n" - kstidXmlErrorMsg044 "Ignoring s""> in the absence of a ws attribute.\n" - kstidXmlErrorMsg045 "Ignoring s""> in the absence of a wsBase attribute.\n" - kstidXmlErrorMsg046 "Improperly nested <%<0>s name=""%<1>s""> element!\n" - kstidXmlErrorMsg047 "Improperly nested <%<0>s> element!\n" - kstidXmlErrorMsg048 "Invalid Boolean value for the %<0>S field of a %<1>S object: ""%<2>s"".\n" - kstidXmlErrorMsg049 "Invalid GUID value in s=""%<1>s""> element!\n" - kstidXmlErrorMsg050 "Invalid GenDate value for the %<0>S field of a %<1>S object: ""%<2>s"".\n" - kstidXmlErrorMsg051 "Invalid Integer value for the %<0>S field of a %<1>S object: ""%<2>s"".\n" - kstidXmlErrorMsg052 "Invalid Numeric value for the %<0>S field of a %<1>S object: ""%<2>s"".\n" - kstidXmlErrorMsg053 "Invalid XML Element: unknown class ""%<0>s""\n" - kstidXmlErrorMsg054 "Invalid XML Element: unknown field ""%<0>s""\n" - kstidXmlErrorMsg055 "Invalid bin attribute in Float element: ""%<0>s"".\n" - kstidXmlErrorMsg056 "Invalid character data found between runs: """ - kstidXmlErrorMsg057 "Invalid class attribute for CustomField element: %<0>s\n" - kstidXmlErrorMsg058 "Invalid writing system in s"">!\n" - kstidXmlErrorMsg059 "Invalid writing system in s"">!\n" - kstidXmlErrorMsg060 "Invalid field type containing <%<0>s> element: %<1>d.\n" - kstidXmlErrorMsg061 "Invalid ord attribute in Link element: ""%<0>s"".\n" - kstidXmlErrorMsg062 "Invalid ord attribute value: ""%<0>s""\n" - kstidXmlErrorMsg063 "Invalid target attribute for CustomField element: %<0>s\n" - kstidXmlErrorMsg064 "Invalid type attribute for CustomField element: %<0>s\n" - kstidXmlErrorMsg065 "Invalid Float value for the %<0>S field of a %<1>S object: ""%<2>s"".\n" - kstidXmlErrorMsg066 "Invalid value in s=""%<1>s"">: need on, off or invert\n" - kstidXmlErrorMsg067 "Invalid value in s=""%<1>s"">.\n" - kstidXmlErrorMsg068 "Invalid value in s=""%<1>s"">.\n" -// kstidXmlErrorMsg069 "Invalid value in s"">: need on, off or invert\n" -// kstidXmlErrorMsg070 "Invalid value in s"">.\n" -// kstidXmlErrorMsg071 "Invalid value in s"">.\n" - kstidXmlErrorMsg072 "Invalid value in s"">: need off, super, or sub\n" - kstidXmlErrorMsg073 "Invalid value in s"">: need chars or picture\n" - kstidXmlErrorMsg074 "Invalid value in s"">: need none, single, double, dotted, dashed, or strikethrough\n" - kstidXmlErrorMsg075 "Invalid Guid value for the %<0>S field of a %<1>S object: ""%<2>s"".\n" - kstidXmlErrorMsg076 "Invalid Time value for the %<0>S field of a %<1>S object: ""%<2>s"".\n" - kstidXmlErrorMsg077 "Missing Link target: ""%<0>s""\n" - kstidXmlErrorMsg078 "Missing both bin and val attributes in Float element.\n" - - kstidXmlErrorMsg079 "Missing %<0>s attribute for %<1>s element.\n" - - kstidXmlErrorMsg080 "Missing writing system for element!\n" - kstidXmlErrorMsg081 "Missing writing system for element!\n" -// THE NEXT SEVERAL ITEMS SHOULD BE REPLACED BY THE NEW kstidXmlErrorMsg079 SOMETIME. - kstidXmlErrorMsg089 "Missing val attribute in GenDate element.\n" - kstidXmlErrorMsg090 "Missing val attribute in Guid element.\n" - kstidXmlErrorMsg091 "Missing val attribute in Integer element.\n" - kstidXmlErrorMsg092 "Missing val attribute in Numeric element.\n" - kstidXmlErrorMsg093 "Missing val attribute in Time element.\n" - kstidXmlErrorMsg094 "Out of memory after first pass through XML file!\n" - kstidXmlErrorMsg095 "Out of memory before parsing anything!\n" - kstidXmlErrorMsg096 "Out of memory!\n" - kstidXmlErrorMsg097 "Repeated object GUID\n" - kstidXmlErrorMsg098 "Repeated object ID\n" - kstidXmlErrorMsg099 "SQL_PARAM_DIAG_UNAVAILABLE INFO creating %<0>S (%<1>d, %<2>g, %<3>d, %<4>d, %<5>d)\n" - kstidXmlErrorMsg100 "SQL_PARAM_ERROR creating %<0>S (%<1>d, %<2>g, %<3>d, %<4>d, %<5>d)\n" - kstidXmlErrorMsg101 "SQL_PARAM_UNUSED creating %<0>S (%<1>d, %<2>g, %<3>d, %<4>d, %<5>d)\n" - kstidXmlErrorMsg102 "The database is not empty!\n" - kstidXmlErrorMsg103 "UNAVAIL INFO in SetMultiBigStr$ %<0>d,%<1>d,%<2>d,'...',0x...\n" - kstidXmlErrorMsg104 "UNAVAIL INFO in SetMultiBigTxt$ %<0>d,%<1>d,%<2>d,'...'\n" - kstidXmlErrorMsg105 "UNAVAIL INFO in SetMultiStr$ %<0>d,%<1>d,%<2>d,'...',0x...\n" - kstidXmlErrorMsg106 "UNAVAIL INFO in SetMultiTxt$ %<0>d,%<1>d,%<2>d,'...'\n" - kstidXmlErrorMsg107 "UNAVAIL INFO in UPDATE [%<0>S] SET [%<1>S]=? WHERE [Id]=%<2>d\n" - kstidXmlErrorMsg108 "UNAVAIL INFO in UPDATE [%<0>S] SET [%<1>S]=?,%<2>S_Fmt=? WHERE [Id]=%<3>d\n" - kstidXmlErrorMsg109 "UNAVAILABLE INFO creating %<0>S (%<1>d, %<2>g)\n" - kstidXmlErrorMsg110 "UNAVAILABLE INFO for INSERT %<0>S_%<1>S (Src, Dst) VALUES (%<2>d, %<3>d)\n" - kstidXmlErrorMsg111 "UNAVAILABLE INFO for INSERT (Src, Dst, Ord) %<0>S_%<1>S VALUES (%<2>d, %<3>d, %<4>d)\n" - kstidXmlErrorMsg112 "UNAVAILABLE INFO for UPDATE [%<0>S] SET [%<1>S]=%<2>d WHERE [Id]=%<3>d\n" - kstidXmlErrorMsg113 "UNUSED creating %<0>S (%<1>d, %<2>g)\n" - kstidXmlErrorMsg114 "UNUSED data INSERT %<0>S_%<1>S (Src, Dst) VALUES (%<2>d, %<3>d)\n" - kstidXmlErrorMsg115 "UNUSED data INSERT %<0>S_%<1>S (Src, Dst, Ord) VALUES (%<2>d, %<3>d, %<4>d)\n" - kstidXmlErrorMsg116 "UNUSED data UPDATE [%<0>S] SET [%<1>S]=%<2>d WHERE [Id]=%<3>d\n" - kstidXmlErrorMsg117 "UNUSED in SetMultiBigStr$ %<0>d,%<1>d,%<2>d,'...',0x...\n" - kstidXmlErrorMsg118 "UNUSED in SetMultiBigTxt$ %<0>d,%<1>d,%<2>d,'...'\n" - kstidXmlErrorMsg119 "UNUSED in SetMultiStr$ %<0>d,%<1>d,%<2>d,'...',0x...\n" - kstidXmlErrorMsg120 "UNUSED in SetMultiTxt$ %<0>d,%<1>d,%<2>d,'...'\n" - kstidXmlErrorMsg121 "UNUSED in UPDATE [%<0>S] SET [%<1>S]=? WHERE [Id]=%<2>d\n" - kstidXmlErrorMsg122 "UNUSED in UPDATE [%<0>S] SET [%<1>S]=?,%<2>S_Fmt=? WHERE [Id]=%<3>d\n" - kstidXmlErrorMsg123 "Unbalanced XML element stack!?\n" - kstidXmlErrorMsg124 "Unbalanced element stack!?\n" - kstidXmlErrorMsg125 "Unbalanced object id stack!?\n" - kstidXmlErrorMsg126 "Unbalanced property name stack!?\n" - kstidXmlErrorMsg127 "Unknown XML end tag: ""%<0>s""\n" - kstidXmlErrorMsg128 "Unknown XML start tag: ""%<0>s""\n" - kstidXmlErrorMsg129 "WARNING: GUID-based id strings do not all begin with the same letter!\n" - kstidXmlErrorMsg130 "WARNING: You've got to be kidding: string property length > 1 gigabyte!!!\n" - kstidXmlErrorMsg131 "WARNING: the ownership hierarchy is not properly nested!\n" - kstidXmlErrorMsg132 "Warning: String does not have a writing system!\n" - kstidXmlErrorMsg133 "Warning: ignoring extra character at the end of %<0>s data.\n" - kstidXmlErrorMsg134 "Wrong field type for Link element: %<0>d\n" - kstidXmlErrorMsg135 "XML parser detected an XML syntax error [pass 1]!\n" - kstidXmlErrorMsg136 "XML parser detected an XML syntax error [pass 2]!\n" - kstidXmlErrorMsg137 "<%<0>s> not recognized nested within !\n" - kstidXmlErrorMsg138 "<%<0>s> not recognized nested within !\n" - kstidXmlErrorMsg139 "Invalid value in <%<0>s bold=""%<1>s"">: need on, off or invert\n" - kstidXmlErrorMsg140 "Ignoring <%<0>s fontsizeUnit=""%<1>s""> in the absence of a fontsize attribute.\n" - kstidXmlErrorMsg141 "Invalid value in <%<0>s fontsize=""%<1>s"">.\n" - kstidXmlErrorMsg142 "Invalid value in <%<0>s fontsizeUnit=""%<1>s"">.\n" - kstidXmlErrorMsg143 "Invalid value in <%<0>s align=""%<1>s"">: need leading, left, center, right, trailing, or justify\n" - kstidXmlErrorMsg144 "Ignoring <%<0>s ows=""%<1>s""> in the absence of a ws attribute.\n" - kstidXmlErrorMsg145 "Ignoring <%<0>s owsBase=""%<1>s""> in the absence of a wsBase attribute.\n" - kstidXmlErrorMsg146 "Invalid value in <%<0>s italic=""%<1>s"">: need on, off or invert\n" - kstidXmlErrorMsg147 "Invalid value in <%<0>s lineHeight=""%<1>s"">.\n" - kstidXmlErrorMsg148 "Invalid value in <%<0>s lineHeightUnit=""%<1>s"">.\n" - kstidXmlErrorMsg149 "Ignoring <%<0>s lineHeightUnit=""%<1>s""> in the absence of a lineHeight attribute.\n" - kstidXmlErrorMsg150 "Invalid value in <%<0>s offset=""%<1>s"">.\n" - kstidXmlErrorMsg151 "Invalid value in <%<0>s offsetUnit=""%<1>s"">.\n" - kstidXmlErrorMsg152 "Ignoring <%<0>s offsetUnit=""%<1>s""> in the absence of a offset attribute.\n" - kstidXmlErrorMsg153 "Invalid value in <%<0>s superscript=""%<1>s"">: need off, super, or sub.\n" - kstidXmlErrorMsg154 "Invalid value in <%<0>s underline=""%<1>s"">: need none, single, double, dotted, dashed, or strikethrough.\n" -// kstidXmlErrorMsg155 "Ignoring an empty .\n" - kstidXmlErrorMsg156 "Warning: Invalid GUID-based id string for importing object.\n" - kstidXmlErrorMsg157 "Warning: Invalid writing system in s"" .../>.\n" - kstidXmlErrorMsg158 "Warning: Invalid field for implicit target in a Link element: %<0>S.\n" - kstidXmlErrorMsg159 "Warning: Implicit MoInflAffixSlot target in a Link element is missing the name attribute.\n" - kstidXmlErrorMsg160 "Warning: Implicit %<0>s target in a Link element cannot access the PartOfSpeech list.\n" - kstidXmlErrorMsg161 "Warning: Implicit %<0>s target in Link element cannot find/create a needed PartOfSpeech.\n" - kstidXmlErrorMsg162 "Warning: Implicit %<0>s target in Link element is missing one or more required attributes.\n" - kstidXmlErrorMsg163 "Warning: Implicit ReversalIndexEntry target in a Link element is missing the form attribute.\n" - kstidXmlErrorMsg164 "Warning: Implicit ReversalIndexEntry target in a Link element cannot find/create the ReversalIndex.\n" - kstidXmlErrorMsg165 "Warning: Implicit ReversalIndexEntry target in a Link element has an invalid form attribute.\n" - kstidXmlErrorMsg166 "Error obtaining LexDb id from the database!?\n" - kstidXmlErrorMsg167 "Info: Implicit %<0>s target in a Link element has abbr attribute ""%<1>S"" which matches a Name value.\n" - kstidXmlErrorMsg168 "Info: Implicit %<0>s target in a Link element has name attribute ""%<1>S"" which matches an Abbreviation value.\n" - kstidXmlErrorMsg169 "Implicit MoInflAffixSlot target in a Link element has neither the nameOwner nor the abbrOwner attribute.\n" - kstidXmlErrorMsg170 "Implicit %<0>s target in a Link element is missing the sense or entry attribute.\n" - kstidXmlErrorMsg171 "Implicit %<0>s target in a Link element is missing the name or abbr attribute.\n" - kstidXmlErrorMsg172 "Invalid class for implicit target in Link element: %<0>S.\n" - kstidXmlErrorMsg173 "Warning: Invalid writing system in s"" .../>.\n" - kstidXmlErrorMsg174 "Warning: empty ws attribute found: substituting analysis writing system.\n" - kstidXmlErrorMsg175 "Invalid value in <%<0>s spellcheck=""%<1>s"">: need normal, doNotCheck, or forceCheck.\n" - - kstidXmlDebugMsg001 "DEBUG: External Link target: db=""%<0>s"", target=""%<1>s""\n" - kstidXmlDebugMsg002 "DEBUG: Repeated run properties found: ibProp = %<0>d, Top()->ibProp = %<1>d\n" - kstidXmlDebugMsg003 "ERROR CAUGHT on line %<0>d of %<1>s: %<2>s\n" - kstidXmlDebugMsg004 "SUCCESSFULLY CREATED %<0>S (%<1>d, %<2>g, %<3>d, %<4>d, %<5>d)\n" - kstidXmlDebugMsg005 "UNKNOWN ERROR CAUGHT on line %<0>d of %<1>s\n" - kstidXmlDebugMsg006 "m_vetiOpen[%<0>d].m_elty = %<1>s, m_icls = %<2>d\n" - kstidXmlDebugMsg007 "rpi[%<0>d] = %<1>d, %<2>d, 0x" - kstidXmlDebugMsg008 "run[%<0>d]: ichMin = %<1>d, ibProp = %<2>d; distinct = %<3>d, fMerge = %<4>s\n" -END - -STRINGTABLE DISCARDABLE -BEGIN - kstidXmlInfoMsg101 "Info: Creating new inflection class with ws=""%<0>S"", abbr=""%<1>s"", and name=""%<2>s"".\n" - kstidXmlInfoMsg102 "Info: Creating new inflectional affix slot with ws=""%<0>S"" and name=""%<1>s"", for POS with abbr=""%<2>s"" and name=""%<3>s"".\n" - kstidXmlInfoMsg103 "Info: Creating new object with ws=""%<0>S"", abbr=""%<1>s"", and name=""%<2>s"" in the %<3>S list.\n" - kstidXmlInfoMsg104 "Warning: The %<0>S list is not supposed to be extensible!\n" - kstidXmlInfoMsg105 "Info: Creating ReversalIndex for the %<0>S (""%<1>S"") language.\n" - kstidXmlInfoMsg106 "Info: Creating ReversalIndexEntry ""%<0>S"" (""%<1>S"") for the %<2>S (""%<3>S"") language.\n" - kstidXmlInfoMsg107 "%<0>s [repeated %<1>d more times in the XML file]\n" - kstidXmlInfoMsg108 "Warning: Truncating string from %<0>d characters to %<1>d characters for the %<2>S field of a %<3>S object.\n" -END - -STRINGTABLE DISCARDABLE -BEGIN - kstidXmlInfoMsg201 "%<0>u custom field %<1>s written.\n" - kstidDefinition "definition" - kstidDefinitions "definitions" - kstidXmlInfoMsg202 "Dumping the XML file from the database took %<0>d %<1>s.\n" - kstidXmlInfoMsg203 "Loading %<0>u %<1>s of Object Ownership Hierarchy data took %<2>d %<3>s.\n" - kstidRow "row" - kstidRows "rows" - kstidXmlInfoMsg206 "Loading %<0>u %<1>s of ""Binary"" data took %<2>d %<3>s.\n" - kstidXmlInfoMsg207 "Loading %<0>u %<1>s of ""Image"" data took %<2>d %<3>s.\n" - kstidXmlInfoMsg210 "Loading %<0>u %<1>s of ""MultiString"" data took %<2>d %<3>s.\n" - kstidXmlInfoMsg211 "Loading %<0>u %<1>s of ""MultiUnicode"" data took %<2>d %<3>s.\n" - kstidXmlInfoMsg212 "Loading %<0>u %<1>s of ""ReferenceAtom"" data took %<2>d %<3>s.\n" - kstidXmlInfoMsg213 "Loading %<0>u %<1>s of ""ReferenceCollection/Sequence"" data took %<2>d %<3>s.\n" - kstidXmlInfoMsg214 "Loading %<0>u %<1>s of ""String"" data took %<2>d %<3>s.\n" - kstidXmlInfoMsg215 "Loading %<0>u %<1>s of ""Unicode"" data took %<2>d %<3>s.\n" - kstidXmlInfoMsg216 "Loading %<0>u %<1>s of basic attribute data took %<2>d %<3>s.\n" - kstidXmlInfoMsg217 "Loading the data from the database took %<0>d SQL %<1>s.\n" - kstidXmlInfoMsg218 "Rebuilding the object hierarchy table took %<0>d %<1>s.\n" - kstidXmlInfoMsg219 "SQL[%<0>d]: %<1>s\n" - kstidXmlInfoMsg220 "Writing the XML file took %<0>d %<1>s.\n" - kstidXmlInfoMsg221 " Reading %<0>d additional characters of string data.\n" - kstidXmlInfoMsg222 " Reading %<0>d additional bytes of format data.\n" - kstidXmlInfoMsg224 "Owner of object %<0>d does not have a name in the default analysis language.\n" - kstidXmlInfoMsg225 "Owner of object %<0>d does not have an abbreviation in the default analysis language.\n" - - kstidXmlErrorMsg201 " %<0>s - %<1>s\n" - kstidXmlErrorMsg202 "BUG/FEATURE - cannot handle Run scalar property code ""%<0>s""\n" - kstidXmlErrorMsg203 "ERROR %<0>s executing SQL command:\n %<1>s\n" - kstidXmlErrorMsg204 "ERROR %<0>s executing SQL function on line %<1>d of %<2>s:\n %<3>s\n" - kstidXmlErrorMsg205 "ERROR - invalid Run scalar property length (%<0>d)\n" - kstidXmlErrorMsg206 "ERROR - invalid Run string property length\n" - kstidXmlErrorMsg207 "ERROR - invalid binary format data for a string: %<0>d run%<1>s, %<2>d byte%<3>s." - kstidRun "run" - kstidRuns "runs" - kstidByte "byte" - kstidBytes "bytes" - kstidXmlErrorMsg208 "ERROR - invalid binary format data for a string: %<0>d run%<1>s." - kstidXmlErrorMsg209 "ERROR - invalid binary format data for a string: only %<0>d byte%<1>s." - kstidXmlErrorMsg210 "ERROR - invalid binary format data for a string: run %<0>d does not start after\nrun %<1>d (min %<2>d <= min %<3>d).\n" - kstidXmlErrorMsg211 "ERROR - invalid binary format data for a string: run %<0>d has invalid internal\noffset (%<1>d)." - kstidXmlErrorMsg212 "ERROR - invalid binary format data for a string: run %<0>d starts after end of\nstring (length = %<1>d <= min = %<2>d)." - kstidXmlErrorMsg213 "ERROR - invalid binary format data for a string: run %<0>d starts before the\nstring (min = %<1>d)." - kstidXmlErrorMsg214 "ERROR - invalid embedded object type in Run string property (%<0>d)\n" - kstidXmlErrorMsg215 "ERROR - invalid writing system of Run string property length\n" - kstidXmlErrorMsg216 "ERROR - invalid internal writing system of Run scalar property code\n" - kstidXmlErrorMsg217 "ERROR - invalid internal writing system of Run string property code\n" - kstidXmlErrorMsg218 "ERROR - unknown Run scalar property code (%<0>d)\n" - kstidXmlErrorMsg219 "ERROR - unknown Run string property code (%<0>d)\n" - kstidXmlErrorMsg220 "ERROR [%<0>d]: Constructed Query overflowed its buffer!\n""%<1>s""\n" - kstidXmlErrorMsg221 "WARNING - invalid binary format data for a string: 0 runs, %<0>d byte%<1>s." - kstidXmlErrorDecoding "ERROR decoding the properties: check the log file for details." - kstidXmlErrorMsg222 "WARNING: no writing system" - kstidXmlErrorMsg223 "Cannot get version number from the database!?\n" - kstidXmlErrorMsg224 "Corrupted database: missing %<0>S object (hobj = %<1>d) for %<2>S (hobj = %<3>d)\n" - kstidXmlErrorMsg225 "Corrupted database: missing integer property for %<1>S style.%n" - kstidXmlErrorMsg226 "Corrupted database: missing %<0>d integer properties for %<1>S style.%n" - kstidXmlErrorMsg227 "Corrupted database: missing integer property in paragraph's style.%n" - kstidXmlErrorMsg228 "Corrupted database: missing %<0>d integer properties in paragraph's style.%n" - kstidXmlErrorMsg229 "Corrupted database: missing string property for %<1>S style.%n" - kstidXmlErrorMsg230 "Corrupted database: missing %<0>d string properties for %<1>S style.%n" - kstidXmlErrorMsg231 "Corrupted database: missing string property in paragraph's style.%n" - kstidXmlErrorMsg232 "Corrupted database: missing %<0>d string properties in paragraph's style.%n" - kstidUNKNOWN "UNKNOWN" -END - -STRINGTABLE DISCARDABLE -BEGIN - kstidXmlErrorMsg301 "Invalid hvoOwner passed to ImportXmlObject method: %<0>d\n" - kstidXmlErrorMsg302 "Unknown clid (%<0>d) retrieved for hvoOwner: SOMETHING IS VERY WRONG!\n" - kstidXmlErrorMsg303 "Unknown flid passed to ImportXmlObject method: %<0>d\n" - kstidXmlErrorMsg304 "Invalid flid passed to ImportXmlObject method: flid = %<0>d, but class = %<1>d\n" - kstidXmlErrorMsg305 "Empty database: THIS SHOULD NEVER HAPPEN!\n" - kstidXmlErrorMsg306 "<%<0>s> must be nested inside <%<1>s>...s>!\n" - kstidXmlErrorMsg307 "DEBUG: Unknown flid for list: %<0>d\n" - kstidXmlInfoMsg223 "Info: Creating new writing system for code ""%<0>s"".\n" - kstidXmlErrorMsg308 "Warning: Picture file ""%<0>s"" does not exist.\n" - kstidXmlErrorMsg309 "Warning: Cannot copy picture file ""%<0>s"" to ""%<1>s"".\n" - kstidXmlErrorMsg310 "DEBUG: Unknown flid for folders: %<0>d" - kstidXmlErrorMsg311 "ERROR - Invalid start tag <%<0>s> for XML file: expected <%<1>s>.\n" - kstidXmlErrorMsg312 "Warning: Media file ""%<0>s"" does not exist.\n" - kstidXmlErrorMsg313 "Warning: Cannot copy media file ""%<0>s"" to ""%<1>s"".\n" - kstidXmlErrorMsg314 "ERROR - Cannot create directory ""%<0>s"".\n" - - kstidXmlErrorMsg315 "Invalid %<0>s attribute value for %<1>s element: not GUID based.\n" - kstidXmlErrorMsg316 "Invalid %<0>s attribute value for %<1>s element: bad GUID value.\n" - kstidXmlErrorMsg317 "Object id being merged (%<0>g) should not appear in the updated list.\n" - kstidXmlErrorMsg318 "Object id being deleted (%<0>g) should not appear in the updated list.\n" - kstidXmlErrorMsg319 "A list update XML file must begin with a field tag, not a class tag!\n" - kstidXmlErrorMsg320 "ERROR in ""%s"" [param=%d].\n" - kstidXmlErrorMsg321 "UNUSED in ""%s"" [param=%d].\n" - kstidXmlErrorMsg322 "UNAVAIL INFO in ""%s"" [param=%d].\n" - kstidXmlErrorMsg323 "Warning: Storing only the first %<0>d of %<1>d characters for this string: ""%<2>s"".\n" - - kstidXmlInfoMsg301 "Initializing from the database before reading the XML file took %<0>d %<1>s.\n" - kstidXmlInfoMsg302 "Processing the update information took %<0>d %<1>s.\n" - kstidXmlInfoMsg303 "Creating new objects took %<0>d %<1>s.\n" - kstidXmlInfoMsg304 "Updating owners and sequence positions took %<0>d %<1>s.\n" - kstidXmlInfoMsg305 "Fixing links to merged or deleted list items took %<0>d %<1>s.\n" - kstidXmlInfoMsg306 "Deleting obsolete database objects took %<0>d %<1>s.\n" - kstidXmlInfoMsg307 "Removing possibly obsolete data from list items took %<0>d %<1>s.\n" - kstidXmlInfoMsg308 "Collecting obsolete database objects to delete took %<0>d %<1>s.\n" - kstidXmlInfoMsg309 "Need to delete %<0>d obsolete database %<1>s.\n" - kstidObject "object" - kstidObjects "objects" - kstidXmlInfoMsg310 "(Special initializing for update alone took %<0>d %<1>s.)\n" - kstidXmlInfoMsg311 "Info: Creating %<0>s Pair Lexical Reference Type with name=""%<1>S"" and abbr=""%<2>S"".\n" - kstidSense "Sense" - kstidEntry "Entry" -END diff --git a/Src/Language/Language.vcxproj b/Src/Language/Language.vcxproj deleted file mode 100644 index 847e71362b..0000000000 --- a/Src/Language/Language.vcxproj +++ /dev/null @@ -1,140 +0,0 @@ - - - - - Bounds - Win32 - - - Debug - Win32 - - - Release - Win32 - - - - {C3B9238A-A4F5-48CE-BBCE-313A77D8DABC} - Language - - - - - - - MakeFileProj - - - - Makefile - false - - - Makefile - false - - - Makefile - false - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - .\Release\ - .\Release\ - ..\..\bin\mklg.bat r - ..\..\bin\mklg.bat r cc - - ..\..\output\release\language.dll - $(NMakePreprocessorDefinitions) - $(NMakeIncludeSearchPath) - $(NMakeForcedIncludes) - $(NMakeAssemblySearchPath) - $(NMakeForcedUsingAssemblies) - .\Bounds\ - .\Bounds\ - ..\..\bin\mklg.bat b - ..\..\bin\mklg.bat b cc - - ..\..\output\Bounds\language.dll - $(NMakePreprocessorDefinitions) - $(NMakeIncludeSearchPath) - $(NMakeForcedIncludes) - $(NMakeAssemblySearchPath) - $(NMakeForcedUsingAssemblies) - .\Debug\ - .\Debug\ - ..\..\bin\mklg.bat - ..\..\bin\mklg.bat cc - - ..\..\output\debug\language.dll - $(NMakePreprocessorDefinitions) - ..\..\Output\Common\Raw;..\..\Output\Common;..\Kernel;..\Generic;.;$(NMakeIncludeSearchPath) - $(NMakeForcedIncludes) - $(NMakeAssemblySearchPath) - $(NMakeForcedUsingAssemblies) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Src/Language/LanguageExtra_GUIDs.cpp b/Src/Language/LanguageExtra_GUIDs.cpp deleted file mode 100644 index b113448168..0000000000 --- a/Src/Language/LanguageExtra_GUIDs.cpp +++ /dev/null @@ -1,10 +0,0 @@ -/* - * This (handmade) file contains GUIDs that are not defined in IDL - * - * Neil Mayhew - 2011-06-07 - */ - -#include - -DEFINE_UUIDOF(UniscribeSegment,0x61299C3B,0x54D6,0x4c46,0xAC,0xE5,0x72,0xB9,0x12,0x8F,0x20,0x48); -DEFINE_UUIDOF(RomRenderSegment,0xA124E0C1,0xDD4B,0x11d2,0x80,0x78,0x00,0x00,0xC0,0xFB,0x81,0xB5); diff --git a/Src/Language/LanguagePs.idl b/Src/Language/LanguagePs.idl deleted file mode 100644 index a66351ed04..0000000000 --- a/Src/Language/LanguagePs.idl +++ /dev/null @@ -1,24 +0,0 @@ -/*--------------------------------------------------------------------*//*:Ignore this sentence. -Copyright (C) 1999, 2001 SIL International. All rights reserved. - -Distributable under the terms of either the Common Public License or the -GNU Lesser General Public License, as specified in the LICENSING.txt file. - -File: LanguagePs.idl -Responsibility: John Thomson -Last reviewed: - - Defines Language Services Interfaces for proxy / stub generation. --------------------------------------------------------------------------------*//*:End Ignore*/ -import "oaidl.idl"; -import "ocidl.idl"; -//import "FwKernelPs.idl"; - -#include "Common.idh" - -#define NO_COCLASSES - -#include "FwKernel.idh" -#include "TextServ.idh" -#include "Render.idh" -#include "Language.idh" diff --git a/Src/Language/LanguageTlb.idl b/Src/Language/LanguageTlb.idl deleted file mode 100644 index 757136875c..0000000000 --- a/Src/Language/LanguageTlb.idl +++ /dev/null @@ -1,34 +0,0 @@ -/*--------------------------------------------------------------------*//*:Ignore this sentence. -Copyright (C) 1999, 2001 SIL International. All rights reserved. - -Distributable under the terms of either the Common Public License or the -GNU Lesser General Public License, as specified in the LICENSING.txt file. - -File: LanguageTlb.idl -Responsibility: John Thomson -Last reviewed: Not yet. (previous main contents, now language.idh, reviewed mid June 99) - -Description: - Interface descriptions for the Language server. See Language.idh for a fuller description. --------------------------------------------------------------------------------*//*:End Ignore*/ - -/*********************************************************************************************** - Include files -***********************************************************************************************/ -import "oaidl.idl"; -import "ocidl.idl"; -import "objidl.idl"; - -#include "common.idh" // DeclareInterface and similar - -DeclareLibrary(LanguageLib, 1.0, "Language 1.0 Type Library", - b80ee180-c0f1-11d2-8078-0000c0fb81b5) -{ - interface IOleDbEncap; - - #include "FwKernel.idh" - #include "TextServ.idh" - - #include "Render.idh" - #include "Language.idh" -}; diff --git a/Src/Language/Language_GUIDs.cpp b/Src/Language/Language_GUIDs.cpp deleted file mode 100644 index 3678dc48b2..0000000000 --- a/Src/Language/Language_GUIDs.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// Automatically generated from LanguageTlb.h by ExtractIIDs task -#include "LanguageTlb.h" - -DEFINE_UUIDOF(ITsString, 0x295B2E11, 0xB149, 0x49C5, 0x9B, 0xE9, 0x9F, 0x46, 0x18, 0x56, 0x09, 0xAA); -DEFINE_UUIDOF(IUndoGrouper, 0xC38348D3, 0x392C, 0x4e02, 0xBD, 0x50, 0xA0, 0x1D, 0xC4, 0x18, 0x9E, 0x1D); -DEFINE_UUIDOF(IFwMetaDataCache, 0xEDBB1DED, 0x7065, 0x4b56, 0xA2, 0x62, 0x74, 0x64, 0x53, 0x83, 0x54, 0x51); -DEFINE_UUIDOF(IUndoAction, 0xB831F535, 0x0D5F, 0x42c8, 0xBF, 0x9F, 0x7F, 0x5E, 0xCA, 0x2C, 0x46, 0x57); -DEFINE_UUIDOF(IActionHandler, 0x0F8EA3BE, 0xC982, 0x40f8, 0xB6, 0x74, 0x25, 0xB8, 0x48, 0x2E, 0xB2, 0x22); -DEFINE_UUIDOF(ActionHandler, 0x6A46D810, 0x7F14, 0x4151, 0x80, 0xF5, 0x0B, 0x13, 0xFF, 0xC1, 0xF9, 0x17); -DEFINE_UUIDOF(IDebugReportSink, 0xDD9CE7AD, 0x6ECC, 0x4e0c, 0xBB, 0xFC, 0x1D, 0xC5, 0x2E, 0x05, 0x33, 0x54); -DEFINE_UUIDOF(IDebugReport, 0x3D6A0880, 0xD17D, 0x4e4a, 0x9D, 0xE9, 0x86, 0x1A, 0x85, 0xCA, 0x40, 0x46); -DEFINE_UUIDOF(DebugReport, 0x24636FD1, 0xDB8D, 0x4b2c, 0xB4, 0xC0, 0x44, 0xC2, 0x59, 0x2C, 0xA4, 0x82); -DEFINE_UUIDOF(IComDisposable, 0xCA9AAF91, 0x4C34, 0x4c6a, 0x8E, 0x07, 0x97, 0xC1, 0xA7, 0xB3, 0x48, 0x6A); -DEFINE_UUIDOF(ITsTextProps, 0x4FA0B99A, 0x5A56, 0x41A4, 0xBE, 0x8B, 0xB8, 0x9B, 0xC6, 0x22, 0x51, 0xA5); -DEFINE_UUIDOF(ITsStrFactory, 0xC10EA417, 0x8317, 0x4048, 0xAC, 0x90, 0x10, 0x3F, 0x8B, 0xDF, 0xB3, 0x25); -DEFINE_UUIDOF(ITsPropsFactory, 0x8DCE56A6, 0xCFF1, 0x4402, 0x95, 0xFE, 0x2B, 0x57, 0x49, 0x12, 0xB5, 0x4E); -DEFINE_UUIDOF(ITsStrBldr, 0xF1EF76E6, 0xBE04, 0x11d3, 0x8D, 0x9A, 0x00, 0x50, 0x04, 0xDE, 0xFE, 0xC4); -DEFINE_UUIDOF(ITsIncStrBldr, 0xF1EF76E7, 0xBE04, 0x11d3, 0x8D, 0x9A, 0x00, 0x50, 0x04, 0xDE, 0xFE, 0xC4); -DEFINE_UUIDOF(ITsPropsBldr, 0xF1EF76E8, 0xBE04, 0x11d3, 0x8D, 0x9A, 0x00, 0x50, 0x04, 0xDE, 0xFE, 0xC4); -DEFINE_UUIDOF(ITsMultiString, 0xDD409520, 0xC212, 0x11d3, 0x9B, 0xB7, 0x00, 0x40, 0x05, 0x41, 0xF9, 0xE9); -DEFINE_UUIDOF(ILgWritingSystemFactory, 0x22376578, 0xBFEB, 0x4c46, 0x8D, 0x72, 0xC9, 0x15, 0x48, 0x90, 0xDD, 0x16); -DEFINE_UUIDOF(TsStrFactory, 0xF1EF76E9, 0xBE04, 0x11d3, 0x8D, 0x9A, 0x00, 0x50, 0x04, 0xDE, 0xFE, 0xC4); -DEFINE_UUIDOF(TsPropsFactory, 0xF1EF76EA, 0xBE04, 0x11d3, 0x8D, 0x9A, 0x00, 0x50, 0x04, 0xDE, 0xFE, 0xC4); -DEFINE_UUIDOF(TsStrBldr, 0xF1EF76EB, 0xBE04, 0x11d3, 0x8D, 0x9A, 0x00, 0x50, 0x04, 0xDE, 0xFE, 0xC4); -DEFINE_UUIDOF(TsIncStrBldr, 0xF1EF76EC, 0xBE04, 0x11d3, 0x8D, 0x9A, 0x00, 0x50, 0x04, 0xDE, 0xFE, 0xC4); -DEFINE_UUIDOF(TsPropsBldr, 0xF1EF76ED, 0xBE04, 0x11d3, 0x8D, 0x9A, 0x00, 0x50, 0x04, 0xDE, 0xFE, 0xC4); -DEFINE_UUIDOF(TsMultiString, 0x7A1B89C0, 0xC2D6, 0x11d3, 0x9B, 0xB7, 0x00, 0x40, 0x05, 0x41, 0xF9, 0xE9); -DEFINE_UUIDOF(IVwGraphics, 0xF7233278, 0xEA87, 0x4FC9, 0x83, 0xE2, 0xCB, 0x7C, 0xC4, 0x5D, 0xEB, 0xE7); -DEFINE_UUIDOF(IJustifyingRenderer, 0x1141174B, 0x923F, 0x4C43, 0xBA, 0x43, 0x8A, 0x32, 0x6B, 0x76, 0xA3, 0xF2); -DEFINE_UUIDOF(ISimpleInit, 0x6433D19E, 0x2DA2, 0x4041, 0xB2, 0x02, 0xDB, 0x11, 0x8E, 0xE1, 0x69, 0x4D); -DEFINE_UUIDOF(IVwGraphicsWin32, 0xC955E295, 0xA259, 0x47D4, 0x81, 0x58, 0x4C, 0x7A, 0x35, 0x39, 0xD3, 0x5E); -DEFINE_UUIDOF(VwGraphicsWin32, 0xD888DB98, 0x83A9, 0x4592, 0xAA, 0xD2, 0xF1, 0x8F, 0x6F, 0x74, 0xAB, 0x87); -DEFINE_UUIDOF(IVwTextSource, 0x6C0465AC, 0x17C5, 0x4C9C, 0x8A, 0xF3, 0x62, 0x22, 0x1F, 0x2F, 0x77, 0x07); -DEFINE_UUIDOF(IVwJustifier, 0x22D5E030, 0x5239, 0x4924, 0xBF, 0x1B, 0x6B, 0x4F, 0x2C, 0xBB, 0xAB, 0xA5); -DEFINE_UUIDOF(VwJustifier, 0xD3E3ADB7, 0x94CB, 0x443B, 0xBB, 0x8F, 0x82, 0xA0, 0x3B, 0xF8, 0x50, 0xF3); -DEFINE_UUIDOF(ILgSegment, 0x3818E245, 0x6A0B, 0x45A7, 0xA5, 0xD6, 0x52, 0x69, 0x49, 0x31, 0x27, 0x9E); -DEFINE_UUIDOF(IRenderEngine, 0x7F4B8F79, 0x2A40, 0x408C, 0x94, 0x4B, 0x84, 0x8B, 0x14, 0xD6, 0x5D, 0x23); -DEFINE_UUIDOF(RomRenderEngine, 0x6EACAB83, 0x6BDC, 0x49CA, 0x8F, 0x66, 0x8C, 0x11, 0x6D, 0x3E, 0xEB, 0xD8); -DEFINE_UUIDOF(UniscribeEngine, 0x1287735C, 0x3CAD, 0x41CD, 0x98, 0x6C, 0x39, 0xD7, 0xC0, 0xDF, 0x03, 0x14); -DEFINE_UUIDOF(FwGrEngine, 0xF39F9433, 0xF05A, 0x4A19, 0x8D, 0x1E, 0x3C, 0x55, 0xDD, 0x60, 0x76, 0x33); -DEFINE_UUIDOF(IRenderingFeatures, 0x75AFE861, 0x3C17, 0x4F16, 0x85, 0x1F, 0xA3, 0x6F, 0x5F, 0xFA, 0xBC, 0xC6); -DEFINE_UUIDOF(FwGraphiteProcess, 0xB56AEFB9, 0x96B4, 0x4415, 0x84, 0x15, 0x64, 0xCB, 0xF3, 0x82, 0x67, 0x04); -DEFINE_UUIDOF(ILgCharacterPropertyEngine, 0x890C5B18, 0x6E95, 0x438E, 0x8A, 0xDE, 0xA4, 0xFF, 0xAD, 0xDF, 0x06, 0x84); -DEFINE_UUIDOF(ILgStringConverter, 0x8BE2C911, 0x6A81, 0x48B5, 0xA2, 0x7F, 0xB8, 0xCE, 0x63, 0x98, 0x30, 0x82); -DEFINE_UUIDOF(ILgTokenizer, 0x577C6DA1, 0xCFC1, 0x4AFB, 0x82, 0xB2, 0xAF, 0x81, 0x8E, 0xC2, 0xFE, 0x9F); -DEFINE_UUIDOF(ILgSpellCheckFactory, 0x9F9298F5, 0xFD41, 0x44B0, 0x83, 0xBA, 0xBE, 0xD9, 0xF5, 0x6C, 0xF9, 0x74); -DEFINE_UUIDOF(ILgSpellChecker, 0xE3661AF5, 0x26C6, 0x4907, 0x92, 0x43, 0x61, 0x0D, 0xAD, 0x84, 0xD9, 0xD4); -DEFINE_UUIDOF(ILgCollatingEngine, 0xD27A3D8C, 0xD3FE, 0x4E25, 0x90, 0x97, 0x8F, 0x4A, 0x1F, 0xB3, 0x03, 0x61); -DEFINE_UUIDOF(ILgSearchEngine, 0x09FCA8D5, 0x5BF6, 0x4BFF, 0xA3, 0x17, 0xE0, 0x12, 0x64, 0x10, 0xD7, 0x9A); -DEFINE_UUIDOF(ILgWritingSystem, 0x9F74A170, 0xE8BB, 0x466d, 0x88, 0x48, 0x5F, 0xDB, 0x28, 0xAC, 0x5A, 0xF8); -DEFINE_UUIDOF(ILgIcuCharPropEngine, 0xE8689492, 0x7622, 0x427b, 0x85, 0x18, 0x63, 0x39, 0x29, 0x4F, 0xD2, 0x27); -DEFINE_UUIDOF(ILgNumericEngine, 0xCBBF35E1, 0xCE39, 0x4EEC, 0xAE, 0xBD, 0x5B, 0x4A, 0xAA, 0xA5, 0x2B, 0x6C); -DEFINE_UUIDOF(ILgKeymanHandler, 0x3F42144B, 0x509F, 0x4def, 0x8D, 0xD3, 0x6D, 0x8D, 0x26, 0x67, 0x70, 0x01); -DEFINE_UUIDOF(ILgIcuConverterEnumerator, 0x8E6D558E, 0x8755, 0x4EA1, 0x9F, 0xF6, 0x03, 0x9D, 0x37, 0x53, 0x12, 0xE9); -DEFINE_UUIDOF(ILgIcuTransliteratorEnumerator, 0x50F2492C, 0x6C46, 0x48BA, 0x8B, 0x7F, 0x5F, 0x04, 0x15, 0x3A, 0xB2, 0xCC); -DEFINE_UUIDOF(ILgIcuLocaleEnumerator, 0x08F649D0, 0xD8AB, 0x447B, 0xAA, 0xB6, 0x21, 0xF8, 0x5C, 0xFA, 0x74, 0x3C); -DEFINE_UUIDOF(ILgIcuResourceBundle, 0xC243C72A, 0x0D15, 0x44D9, 0xAB, 0xCB, 0xA6, 0xE8, 0x75, 0xA7, 0x65, 0x9A); -DEFINE_UUIDOF(IRegexMatcher, 0x6C62CCF0, 0x4EE1, 0x493C, 0x80, 0x92, 0x31, 0x9B, 0x6C, 0xFB, 0xEE, 0xBC); -DEFINE_UUIDOF(RegexMatcherWrapper, 0x13D5C6D3, 0x39D9, 0x4BDA, 0xA3, 0xF8, 0xA5, 0xCA, 0xF6, 0xA6, 0x94, 0x0A); -DEFINE_UUIDOF(LgSystemCollater, 0xE361F805, 0xC902, 0x4306, 0xA5, 0xD8, 0xF7, 0x80, 0x2B, 0x0E, 0x73, 0x65); -DEFINE_UUIDOF(LgUnicodeCollater, 0x0D9900D2, 0x1693, 0x481F, 0xAA, 0x70, 0x7E, 0xA6, 0x4F, 0x26, 0x4E, 0xC4); -DEFINE_UUIDOF(LgIcuCharPropEngine, 0x30D75676, 0xA10F, 0x48FE, 0x96, 0x27, 0xEB, 0xF4, 0x06, 0x1E, 0xA4, 0x9D); -DEFINE_UUIDOF(LgCPWordTokenizer, 0x7CE7CE94, 0xAC47, 0x42A5, 0x82, 0x3F, 0x2F, 0x8E, 0xF5, 0x1A, 0x90, 0x07); -DEFINE_UUIDOF(LgWfiSpellChecker, 0x818445E2, 0x0282, 0x4688, 0x8B, 0xB7, 0x14, 0x7F, 0xAA, 0xCF, 0xF7, 0x3A); -DEFINE_UUIDOF(LgMSWordSpellChecker, 0x5CF96DA5, 0x299E, 0x4FC5, 0xA9, 0x90, 0x2D, 0x2F, 0xCE, 0xE7, 0x83, 0x4D); -DEFINE_UUIDOF(LgNumericEngine, 0xFF22A7AB, 0x223E, 0x4D04, 0xB6, 0x48, 0x0A, 0xE4, 0x05, 0x88, 0x26, 0x1D); -DEFINE_UUIDOF(LgKeymanHandler, 0x69ACA99C, 0xF852, 0x4C2C, 0x9B, 0x5F, 0xFF, 0x83, 0x23, 0x8A, 0x17, 0xA5); -DEFINE_UUIDOF(LgIcuConverterEnumerator, 0x9E729461, 0xF80D, 0x4796, 0xBA, 0x17, 0x08, 0x6B, 0xC6, 0x19, 0x07, 0xF1); -DEFINE_UUIDOF(LgIcuTransliteratorEnumerator, 0x3F1FD0A4, 0xB2B1, 0x4589, 0xBC, 0x82, 0x9C, 0xEF, 0x5B, 0xA8, 0x4F, 0x4E); -DEFINE_UUIDOF(LgIcuResourceBundle, 0x0DD7FC1A, 0xAB97, 0x4A39, 0x88, 0x2C, 0x26, 0x97, 0x60, 0xD8, 0x66, 0x19); -DEFINE_UUIDOF(LgIcuLocaleEnumerator, 0xE426656C, 0x64F7, 0x480E, 0x92, 0xF4, 0xD4, 0x1A, 0x7B, 0xFF, 0xD0, 0x66); diff --git a/Src/Language/Main.h b/Src/Language/Main.h deleted file mode 100644 index ac4503d8c7..0000000000 --- a/Src/Language/Main.h +++ /dev/null @@ -1,200 +0,0 @@ -/*--------------------------------------------------------------------*//*:Ignore this sentence. -Copyright (C) 1999, 2001 SIL International. All rights reserved. - -Distributable under the terms of either the Common Public License or the -GNU Lesser General Public License, as specified in the LICENSING.txt file. - -File: Main.h -Responsibility: -Last reviewed: - - Main header file for the Language component. --------------------------------------------------------------------------------*//*:End Ignore*/ -#if _MSC_VER -#pragma once -#endif -#ifndef LANGUAGE_H -#define LANGUAGE_H 1 - -// If ICU_LINEBREAKING is defined, we use the ICU functions for linebreaking. -// If this is undefined, then we go to JohnT's previous version which doesn't -// use ICU functions. -#ifndef ICU_LINEBREAKING -#define ICU_LINEBREAKING -#endif /*ICU_LINEBREAKING*/ - -#define NO_EXCEPTIONS 1 -#include "common.h" // Most of generic. -#if WIN32 -#include -#endif - -#if !WIN32 -#include -#include "BasicTypes.h" -#include -#endif - -using std::min; -using std::max; - -//:>********************************************************************************** -//:> Interfaces. -//:>********************************************************************************** -#include "FwKernelTlb.h" -#include "CellarConstants.h" -// Special interface mainly used for Graphite engine not defined in an IDH. -#include "../Graphite/GrEngine/ITraceControl.h" -#ifndef ITraceControlPtr // for portability I don't think this header defines this. - DEFINE_COM_PTR(ITraceControl); -#endif - -//:>********************************************************************************** -//:> Implementations. -//:>********************************************************************************** - -// Forward declarations for unit test friends. -namespace TestLanguage -{ - class TestLgWritingSystem; - class TestLgWritingSystemFactory; - extern void CreateTestWritingSystemFactory(ILgWritingSystemFactory ** ppwsf); - extern HRESULT CreateTestWritingSystem(ILgWritingSystemFactory * pwsf, int ws, - const OLECHAR * pszWs); -}; - -#include "LangResource.h" - -// For interfacing with Graphite engines: -namespace gr { -typedef unsigned char utf8; -typedef wchar_t utf16; -typedef unsigned long int utf32; -#define UtfType LgUtfForm -} -// defined in TtSfnt_en.h - but this avoids including all of TtfUtil in the Language.dll -#define tag_Silf 0x666c6953 -#include "GrResult.h" -#include "GrUtil.h" -#include "ITextSource.h" -#include "IGrJustifier.h" -#include "FwGr.h" - -using namespace fwutil; // Rect and Point classes - -// Conceptual model of an writing system -#ifdef LANG_MODEL -#include "LgSpec.h" -#include "LgCharOverride.h" -#include "LgCharPropSpec.h" -#include "LgCharSpec.h" -#include "LgCollaterSpec.h" -#include "LgComponent.h" -#include "LgConverterSpec.h" -#include "LgConvertStringSpec.h" -#include "LgExternalSpecComponent.h" -#include "LgLineBreakSpec.h" -#include "LgLineBreakSpaceSpec.h" -#include "LgOwnedSpecComponent.h" -#include "LgNumericConverterSpec.h" -#include "LgRenderSpec.h" -#include "LgRomanRendererSpec.h" -#include "LgSpellCheckSpec.h" -#include "LgSysCollaterSpec.h" -#include "LgTokenizerSpec.h" -#include "LgUnicodeCollaterSpec.h" -#include "LgUserClassSpec.h" -#include "LgWfiCheckerSpec.h" -#include "LgWinRendSpec.h" -#include "LgWordBreakSpaceSpec.h" -#endif // LANG_MODEL - -// these are a gray area, including aspects of both model and engine -// Todo JohnT: These structs are part of an obsolete approach to overriding character properties. -// Get rid of them and whatever uses them. (Taken from OldLgWritingSystem file.) -/*---------------------------------------------------------------------------------------------- - The CharacterPropertyObject stores all of the data that we allow to be overriden for a - single character (right now, pretty much everything except the Unicode 1.0 name). -----------------------------------------------------------------------------------------------*/ -struct CharacterPropertyObject -{ - UChar32 uch32CodePoint; - StrUni stuCharName; - LgGeneralCharCategory ccGenCategory; - unsigned int nCombiningClass : 8; - LgBidiCategory bicBidiCategory; - LgDecompMapTag dtDecompMapTag; - Vector vuch32Decomp; - unsigned int nDecDigit : 4; - unsigned int nDigit : 4; - int nNumericValue; //numerator stored in the top 16 bits, denominator in the bottom 16 - bool fMirrored : 1; - StrUni stuISOComment; - UChar32 uch32Uppercase; - UChar32 uch32Lowercase; - UChar32 uch32Titlecase; - LgLBP lbpLineBreak; - - void Clear() - { - uch32CodePoint = 0; - stuCharName.Clear(); - ccGenCategory = kccLu; //0 - nCombiningClass = 0; - bicBidiCategory = kbicL; //0 - dtDecompMapTag = kdtNoTag; //0 - vuch32Decomp.Clear(); - nDecDigit = 0; - nDigit = 0; - nNumericValue = 0; - fMirrored = false; - stuISOComment.Clear(); - uch32Uppercase = 0; - uch32Lowercase = 0; - uch32Titlecase = 0; - lbpLineBreak = klbpAI; //0 - } -}; //hungarian cpo - -struct CharPropRange -{ - UChar32 iMin; - UChar32 iLim; - Vector vRange; -}; //hungarian cpr -struct OverriddenCharProps -{ - UChar32 iMin; - UChar32 iLim; - Vector * pvcprOverride1; - Vector * pvcpoOverride2; -}; //hungarian ocp - -// Engines -#include "LgIcuCharPropEngine.h" -#include "LgUnicodeCollater.h" -class RomRenderEngine; -DEFINE_COM_PTR(RomRenderEngine); -class UniscribeEngine; -DEFINE_COM_PTR(UniscribeEngine); -#include "RomRenderSegment.h" -#include "RomRenderEngine.h" -#include "LgSimpleEngines.h" -#include "LgNumericEngine.h" -#if !WIN32 -#include "UniscribeLinux.h" -#endif -#include "UniscribeSegment.h" -#include "UniscribeEngine.h" - -// Other tools -#include "FwStyledText.h" -#include "StringToNumHelpers.h" -#include "WriteXml.h" // From AppCore. -#include "xmlparse.h" -#include "LgKeymanHandler.h" -#include "LgIcuWrappers.h" - -#include "RegexMatcherWrapper.h" - -#endif //!LANGUAGE_H diff --git a/Src/Language/Makefile b/Src/Language/Makefile deleted file mode 100644 index 884adfa561..0000000000 --- a/Src/Language/Makefile +++ /dev/null @@ -1,193 +0,0 @@ - -# $Id: Makefile 2650 2009-12-15 14:15:18Z beilharz $ -# -# Makefile for FW Language directory -# -# Neil Mayhew - 2007-03-15 -# -# Adapted from Language.mak - - -BUILD_ROOT = ../.. -include $(BUILD_ROOT)/Bld/_names.mak -BUILD_PRODUCT = $(LANGUAGE_NAME) -include $(BUILD_ROOT)/Bld/_init.mak.lnx - -DEFINES := $(DEFINES) -DGR_FW -DSUPPRESS_FW_EXCEPTION_HANDLING -DWIN32_KEY_VALUES=1 - -ifeq ($(BUILD_CONFIG),Debug) - DEBUG_LIBS = $(OUT_DIR)/libDebugProcs.a - DEFINES := $(DEFINES) -D_DEBUG - OPTIMIZATIONS = -O0 -else - OPTIMIZATIONS = -O3 -endif - -CELLAR_SRC = $(SRC)/Cellar -GRAPHITE_SRC = $(SRC)/Graphite -GRFW_SRC = $(GRAPHITE_SRC)/FwOnly -GRUTIL_LIB = $(GRAPHITE_SRC)/lib -TTFUTIL_LIB = $(GRAPHITE_SRC)/TtfUtil -VIEWS_LIB = $(SRC)/views/lib - -PACKAGES = glib-2.0 gtk+-2.0 glibmm-2.4 gtkmm-2.4 cairomm-1.0 pangomm-1.4 - -# Make sure Lang is first, as we want to get the Main.h from there, -# not any of the others (e.g., in Views) -INCLUDES := -I$(LANGUAGE_SRC) -I$(GENERIC_SRC) -I$(APPCORE_SRC) -I$(TEXT_SRC) -INCLUDES := $(INCLUDES) -I$(KERNEL_SRC) -I$(CELLAR_SRC) -I$(DBACCESS_SRC) -INCLUDES := $(INCLUDES) -I$(GRUTIL_LIB) -I$(TTFUTIL_LIB) -I$(VIEWS_SRC) -I$(VIEWS_LIB) -I$(GRFW_SRC) -INCLUDES := $(shell icu-config --cppflags) \ - $(INCLUDES) \ - -I$(FWINCLUDE) \ - -I$(COM_OUT_DIR) \ - -I$(WIN32MORE_INC) \ - -I$(COM_INC) \ - -I$(WIN32BASE_INC) \ - $(shell pkg-config --cflags $(PACKAGES)) \ - - -LDLIBS = \ - -L$(FWINCLUDE) \ - $(DEBUG_LIBS) \ - -L$(WIN32MORE_LIB) -lWin32More \ - -L$(COM_LIB) -lcom \ - -L$(WIN32BASE_LIB) -lWin32Base \ - $(shell pkg-config --libs $(PACKAGES)) \ - $(shell icu-config --ldflags) \ - -luuid -lexpat - -CPPFLAGS = $(DEFINES) $(INCLUDES) -MMD -CXXFLAGS = -g $(OPTIMIZATIONS) -fPIC -fvisibility=hidden -Werror -Waddress -Warray-bounds -Wmissing-field-initializers -Wclobbered -Wreturn-type -fstack-protector-all -Wshadow -rdynamic - -ARFLAGS = -crs - -# XML_INC = $(CELLAR_XML) -I$(LANG_XML) - -#PATH = $(COM_OUT_DIR);$(PATH) - -RCFILE = Language.rc -DEFFILE = Language.def - -LINK_LIBS := \ - $(DEBUG_LIBS) \ - $(OUT_DIR)/libGeneric.a \ - $(COM_OUT_DIR)/libFwKernelTlb.a \ - $(COM_OUT_DIR)/libGraphiteTlb.a \ - $(COM_OUT_DIR)/libViewsTlb.a \ - -# === Object Lists === - -OBJ_LANGSERV = - -OBJ_LANG = \ - $(INT_DIR)/LgIcuWrappers.o \ - $(INT_DIR)/LgSimpleEngines.o \ - $(INT_DIR)/LgIcuCharPropEngine.o \ - $(INT_DIR)/LgUnicodeCollater.o \ - $(INT_DIR)/LgKeymanHandler.o \ - $(INT_DIR)/LocaleIndex.o \ - $(INT_DIR)/FwXml.o \ - $(INT_DIR)/WriteXml.o \ - $(INT_DIR)/FwStyledText.o \ - $(INT_DIR)/UniscribeLinux.o \ - $(INT_DIR)/UniscribeSegment.o \ - $(INT_DIR)/UniscribeEngine.o \ - $(INT_DIR)/RomRenderEngine.o \ - $(INT_DIR)/RomRenderSegment.o \ - - -OBJ_OTHER = \ - $(INT_DIR)/ModuleEntry.o \ - $(INT_DIR)/TextProps1.o \ - -OBJ_LIB = \ - $(INT_DIR)/Language_GUIDs.o \ - $(INT_DIR)/LanguageExtra_GUIDs.o - -#OBJ_GRUTIL = \ -# $(GRUTIL_LIB)/GrUtil.o \ -# $(TTFUTIL_LIB)/TtfUtil.o \ - -# XMO_ALL = $(XMO_LANGSERV) -# -# IDL_MAIN = $(COM_OUT_DIR)/LanguageTlb.idl -# -# PS_MAIN = LanguagePs -# -# OBJECTS_IDH = $(COM_INT_DIR)/Objects.idh -# -# ? OBJECTS_H = $(COM_INT_DIR)/Objects.h - -OBJ_ALL = $(OBJ_LANG) $(OBJ_LANGSERV) $(OBJ_OTHER) $(OBJ_GRUTIL) - -# === Targets === - -all: $(OUT_DIR)/libLanguage.so $(COM_OUT_DIR)/libLanguageTlb.a ComponentsMap link_check - -$(OUT_DIR)/libLanguage.so: $(OBJ_ALL) $(LINK_LIBS) $(COM_OUT_DIR)/libLanguageTlb.a -ifeq "$(GCC46)" "1" - $(LINK.cc) -shared -o $@ -Wl,-whole-archive $(COM_OUT_DIR)/libLanguageTlb.a -Wl,-no-whole-archive $(OBJ_ALL) $(LINK_LIBS) $(LDLIBS) -else - $(LINK.cc) -shared -o $@ $^ $(LDLIBS) -endif - -$(COM_OUT_DIR)/libLanguageTlb.a: $(OBJ_LIB) - $(AR) $(ARFLAGS) $@ $^ - -link_check: $(INT_DIR)/libLanguage - -$(INT_DIR)/libLanguage: $(OBJ_ALL) $(GENERIC_OBJ)/main.o $(LINK_LIBS) $(COM_OUT_DIR)/libLanguageTlb.a - $(LINK.cc) -o $@ -Wl,-whole-archive $(COM_OUT_DIR)/libLanguageTlb.a -Wl,-no-whole-archive $(GENERIC_OBJ)/main.o $(OBJ_ALL) $(LINK_LIBS) $(LDLIBS) - -ComponentsMap: $(OUT_DIR)/libLanguage.so - (export PATH=$(PATH):$(COM_DIR)/build$(ARCH)/bin && cd $(OUT_DIR) && generate-map.sh libLanguage.so > libLanguage.compmap) - -# === Rules === - -PCHNAME = $(INT_DIR)/Main.h.gch - -$(OBJ_LANG) $(OBJ_LANGSERV): $(PCHNAME) - -# ensure object dependies are built. - -$(INT_DIR)/%.o: $(APPCORE_SRC)/%.cpp - $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(TARGET_ARCH) \ - -c $< -o $@ -MMD -MF $(@:%.o=%.d) - -$(INT_DIR)/%.o: $(CELLAR_SRC)/%.cpp - $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(TARGET_ARCH) \ - -c $< -o $@ -MMD -MF $(@:%.o=%.d) - -$(INT_DIR)/%.o: $(GENERIC_SRC)/%.cpp - $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(TARGET_ARCH) \ - -c $< -o $@ -MMD -MF $(@:%.o=%.d) - -$(OUT_DIR)/libDebugProcs.a: - @$(MAKE) -C $(SRC)/DebugProcs $@ -q || \ - $(MAKE) -C $(SRC)/DebugProcs $@ - -$(OUT_DIR)/libGeneric.a: - @$(MAKE) -C $(SRC)/Generic $@ -q || \ - $(MAKE) -C $(SRC)/Generic $@ - -$(COM_OUT_DIR)/libFwKernelTlb.a: - @$(MAKE) -C $(SRC)/Kernel $@ -q || \ - $(MAKE) -C $(SRC)/Kernel $@ - -$(COM_OUT_DIR)/libGraphiteTlb.a: - @$(MAKE) -C $(GRENGINE_SRC) all -q || \ - $(MAKE) -C $(GRENGINE_SRC) all - -$(COM_OUT_DIR)/libViewsTlb.a: - @$(MAKE) -C $(SRC)/views/ $@ -q || \ - $(MAKE) -C $(SRC)/views/ $@ - -%.h.gch: %.h - $(COMPILE.cc) -o $@ $< - --include $(OBJ_ALL:%.o=%.d) --include $(PCHNAME:%.gch=%.d) - -clean: - $(RM) $(OUT_DIR)/libLanguage.so $(COM_OUT_DIR)/libLanguageTlb.a $(INT_DIR)/libLanguage $(INT_DIR)/*.[od] $(INT_DIR)/*.gch diff --git a/Src/Language/Test/Makefile b/Src/Language/Test/Makefile deleted file mode 100644 index 91201898c6..0000000000 --- a/Src/Language/Test/Makefile +++ /dev/null @@ -1,129 +0,0 @@ - -# $Id: Makefile 1119 2008-04-10 23:23:04Z mccarthy $ -# -# Makefile for FW Kernel directory -# -# Brent McCarthy - 2007-06-22 -# -# Adapted from testLanguage.mak - -BUILD_ROOT = ../../.. -include $(BUILD_ROOT)/Bld/_names.mak -BUILD_PRODUCT = $(LANGUAGE_NAME)Test -include $(BUILD_ROOT)/Bld/_init.mak.lnx - -UNIT = $(FWINCLUDE)/unit++ -LIB_UNIT = $(BUILD_ROOT)/Lib/src/unit++/build$(ARCH) - -GRAPHITE_SRC = $(SRC)/Graphite -GR_LIB_SRC = $(GRAPHITE_SRC)/lib -GR_LIB_OBJ = $(OBJ_DIR)/$(BUILD_CONFIG)/Graphite/lib -GRAPHITE_FW = $(GRAPHITE_SRC)/FwOnly -VIEWS_LIB = $(VIEWS_SRC)/lib - -DEFINES := -DGR_FW -DVIEWSDLL -DSUPPRESS_FW_EXCEPTION_HANDLING -PACKAGES = gdk-2.0 gtkmm-2.4 cairomm-1.0 pangomm-1.4 - -ifeq ($(BUILD_CONFIG),Debug) - DEFINES := $(DEFINES) -D_DEBUG - OPTIMIZATIONS = -O0 -else - OPTIMIZATIONS = -O3 -endif - -# Make sure Lang is first, as we want to get the Main.h from there, -# not any of the others (e.g., in Views) -INCLUDES := -I$(LANGUAGE_SRC) -I$(LANGUAGE_SRC)/Test -I$(KERNEL_SRC) -I$(CELLAR_SRC) \ - -I$(GENERIC_SRC) -I$(APPCORE_SRC) - -INCLUDES := $(INCLUDES) -I$(GRENGINE_SRC) -I$(GR_LIB_SRC) -I$(GRAPHITE_FW) -I$(VIEWS_SRC) -I$(VIEWS_LIB) -INCLUDES := \ - $(shell icu-config --cppflags) \ - $(INCLUDES) \ - -I$(FWINCLUDE) \ - -I$(UNIT) -I$(LIB_UNIT) \ - -I$(COM_OUT_DIR) \ - -I$(WIN32MORE_INC) \ - -I$(COM_INC) \ - -I$(WIN32BASE_INC) \ - $(shell pkg-config --cflags $(PACKAGES)) \ - -#` -L$(FWKERNEL_SRC) -lFwKernel - -LDLIBS = \ - -L$(WIN32MORE_LIB) -lWin32More \ - -L$(COM_LIB) -lcom \ - -L$(WIN32BASE_LIB) -lWin32Base \ - -L$(OUT_DIR) -lDebugProcs \ - -L$(LIB_UNIT) -lunit++ \ - $(shell pkg-config --libs $(PACKAGES)) \ - $(shell icu-config --ldflags) \ - -luuid -lexpat - - -CPPFLAGS = $(DEFINES) $(INCLUDES) -MMD -CXXFLAGS = -g $(OPTIMIZATIONS) -fvisibility=hidden -Werror - -RCFILE = $(LANGUAGE_SRC)/FwLanguage.rc -DEFFILE = $(LANGUAGE_SRC)/FwLanguage.def -LINK_LIBS := \ - $(OUT_DIR)/libGeneric.a \ - $(OUT_DIR)/libAppCore.a \ - $(OUT_DIR)/libDebugProcs.a \ - $(COM_OUT_DIR)/libGraphiteTlb.a \ - $(COM_OUT_DIR)/libViewsTlb.a \ - $(COM_OUT_DIR)/libLanguageTlb.a - -all: $(OUT_DIR)/testLanguage - -FWLANG_OBJ := \ - $(LANGUAGE_OBJ)/LgUnicodeCollater.o \ - $(LANGUAGE_OBJ)/RomRenderEngine.o \ - $(LANGUAGE_OBJ)/RomRenderSegment.o \ - $(LANGUAGE_OBJ)/LgSimpleEngines.o \ - $(LANGUAGE_OBJ)/LgIcuCharPropEngine.o \ - $(LANGUAGE_OBJ)/LgKeymanHandler.o \ - $(LANGUAGE_OBJ)/LocaleIndex.o \ - $(GENERIC_OBJ)/TextProps1.o \ - $(GR_LIB_OBJ)/GrUtil.o \ - $(LANGUAGE_OBJ)/FwXml.o \ - $(GENERIC_OBJ)/ModuleEntry.o \ - -#Run make in the directory of each library -$(LINK_LIBS) $(FWLANG_OBJ):: - @$(MAKE) -C $(@D) $(@F) -q || \ - $(MAKE) -C $(@D) $(@F) - -$(OUT_DIR)/testLanguage: $(INT_DIR)/testLanguage.o $(INT_DIR)/Collection.o $(FWLANG_OBJ) $(LINK_LIBS) -ifeq "$(GCC46)" "1" - $(LINK.cc) -o $@ -Wl,-whole-archive $(LINK_LIBS) -Wl,-no-whole-archive $(INT_DIR)/testLanguage.o $(INT_DIR)/Collection.o $(FWLANG_OBJ) $(LDLIBS) -else - $(LINK.cc) -o $@ $^ $(LDLIBS) -endif - -clean: - $(RM) $(OUT_DIR)/testLanguage $(INT_DIR)/*.[od] $(INT_DIR)/Collection.cpp *.[od] *.gch - -%.i: %.cpp - $(COMPILE.cc) -E -o $@ $< - -# environ needs to be source before running this. -check: all - cd $(OUT_DIR) && ./testLanguage - - -COLLECT=$(BUILD_ROOT)/Bin/CollectUnit++Tests.sh Language - -$(INT_DIR)/Collection.cpp: testLanguage.h \ - MockLgWritingSystemFactory.h \ - MockLgWritingSystem.h \ - TestLgCollatingEngine.h \ - TestLgIcuCharPropEngine.h \ - TestRomRenderEngine.h \ - RenderEngineTestBase.h - @echo Collecting tests for testLanguage - $(COLLECT) $^ $@ - -# TestLgWritingSystemFactoryBuilder.h \ -# RenderEngineTestBase.h \ -# TestUniscribeEngine.h\ diff --git a/Src/Language/Test/TestLanguage.vcxproj b/Src/Language/Test/TestLanguage.vcxproj deleted file mode 100644 index 7c54622b6c..0000000000 --- a/Src/Language/Test/TestLanguage.vcxproj +++ /dev/null @@ -1,90 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {CFCBEA18-3091-45FC-9407-C8C1303D2363} - TestLanguage - - - - - - - MakeFileProj - - - - Makefile - - - Makefile - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - Debug\ - Debug\ - ..\..\..\Bin\mklg-tst.bat DONTRUN - ..\..\..\Bin\mklg-tst.bat DONTRUN cc - ..\..\..\Bin\mklg-tst.bat DONTRUN ec - ..\..\..\Output\debug\TestLanguage.exe - $(NMakePreprocessorDefinitions) - $(NMakeIncludeSearchPath) - $(NMakeForcedIncludes) - $(NMakeAssemblySearchPath) - $(NMakeForcedUsingAssemblies) - Release\ - Release\ - ..\..\..\Bin\mklg-tst.bat DONTRUN r - ..\..\..\Bin\mklg-tst.bat DONTRUN r cc - ..\..\..\Bin\mklg-tst.bat DONTRUN r ec - ..\..\..\Output\release\TestLanguage.exe -v - $(NMakePreprocessorDefinitions) - $(NMakeIncludeSearchPath) - $(NMakeForcedIncludes) - $(NMakeAssemblySearchPath) - $(NMakeForcedUsingAssemblies) - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Src/Language/Test/TestLanguage.vcxproj.filters b/Src/Language/Test/TestLanguage.vcxproj.filters deleted file mode 100644 index 6643abcf5b..0000000000 --- a/Src/Language/Test/TestLanguage.vcxproj.filters +++ /dev/null @@ -1,52 +0,0 @@ - - - - - {e615eb4d-2caf-43c9-9a0b-24c68c96b443} - cpp;c;cxx;def;odl;idl;hpj;bat;asm - - - {8fe76bbf-550f-4779-886d-3c82abebf37b} - h;hpp;hxx;hm;inl;inc - - - {000be4d4-f7ee-4fd8-8823-24080bca4cc3} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe - - - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - - - \ No newline at end of file diff --git a/Src/Language/Test/testLanguage.cpp b/Src/Language/Test/testLanguage.cpp deleted file mode 100644 index ca77479d8a..0000000000 --- a/Src/Language/Test/testLanguage.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/*--------------------------------------------------------------------*//*:Ignore this sentence. -Copyright (C) 2003 SIL International. All rights reserved. - -Distributable under the terms of either the Common Public License or the -GNU Lesser General Public License, as specified in the LICENSING.txt file. - -File: testLanguage.cpp -Responsibility: -Last reviewed: - - Global initialization/cleanup for unit testing the Language DLL classes. --------------------------------------------------------------------------------*//*:End Ignore*/ -#include "testLanguage.h" -#include "RedirectHKCU.h" - -#ifndef WIN32 -#include -#include -#endif - -namespace unitpp -{ - void GlobalSetup(bool verbose) - { -#ifdef WIN32 - ModuleEntry::DllMain(0, DLL_PROCESS_ATTACH); -#endif - CheckHr(::OleInitialize(NULL)); - RedirectRegistry(); - StrUtil::InitIcuDataDir(); // needed for the normalize routines (ICU) - } - void GlobalTeardown() - { -#ifdef WIN32 - ModuleEntry::DllMain(0, DLL_PROCESS_DETACH); -#endif - ::OleUninitialize(); - } -} - -namespace TestLanguage -{ - int g_wsEng = 0; - int g_wsTest = 0; - int g_wsTest2 = 0; -} - -#include "Vector_i.cpp" -template class Vector; - -// Local Variables: -// mode:C++ -// compile-command:"cmd.exe /e:4096 /c c:\\FW\\Bin\\mklg-tst.bat DONTRUN" -// End: (These 4 lines are useful to Steve McConnel.) diff --git a/Src/Language/Test/testLanguage.h b/Src/Language/Test/testLanguage.h deleted file mode 100644 index 393ee3c4b0..0000000000 --- a/Src/Language/Test/testLanguage.h +++ /dev/null @@ -1,53 +0,0 @@ -/*--------------------------------------------------------------------*//*:Ignore this sentence. -Copyright (C) 2003 SIL International. All rights reserved. - -Distributable under the terms of either the Common Public License or the -GNU Lesser General Public License, as specified in the LICENSING.txt file. - -File: testLanguage.h -Responsibility: -Last reviewed: - - Global header for unit testing the Language DLL classes. --------------------------------------------------------------------------------*//*:End Ignore*/ -#ifndef TESTLANGUAGE_H_INCLUDED -#define TESTLANGUAGE_H_INCLUDED - -#pragma once -#include "Main.h" -#include - -#if !WIN32 -// Stream insertion operators for FW string types -namespace std -{ - inline std::ostream& operator << (std::ostream& stream, const OLECHAR* text) - { - return stream << StrAnsi(text).Chars(); - } - - inline std::ostream& operator << (std::ostream& stream, const StrUni& text) - { - return stream << text.Chars(); - } -} -#endif //!WIN32 - -namespace TestLanguage -{ - const StrUni kszEng(L"en"); - const StrUni kszTest(L"test"); - const StrUni kszTest2(L"tst2"); - - extern int g_wsEng; - extern int g_wsTest; - extern int g_wsTest2; -} - - -// Local Variables: -// mode:C++ -// compile-command:"cmd.exe /e:4096 /c c:\\FW\\Bin\\mklg-tst.bat DONTRUN" -// End: (These 4 lines are useful to Steve McConnel.) - -#endif /*TESTLANGUAGE_H_INCLUDED*/ diff --git a/Src/Language/Test/testLanguage.mak b/Src/Language/Test/testLanguage.mak deleted file mode 100644 index 149b253285..0000000000 --- a/Src/Language/Test/testLanguage.mak +++ /dev/null @@ -1,108 +0,0 @@ -# Input -# ===== -# BUILD_ROOT: d:\FieldWorks -# BUILD_TYPE: d, r, p -# BUILD_CONFIG: Debug, Release, Profile -# - -BUILD_PRODUCT=testLanguage -BUILD_EXTENSION=exe -BUILD_REGSVR=0 - -DEFS=$(DEFS) /DGR_FW - -!INCLUDE "$(BUILD_ROOT)\bld\_init.mak" - -UNITPP_INC=$(BUILD_ROOT)\Include\unit++ -LANGUAGE_SRC=$(BUILD_ROOT)\Src\Language -LANGUAGETEST_SRC=$(BUILD_ROOT)\Src\Language\Test -GENERIC_SRC=$(BUILD_ROOT)\Src\Generic -APPCORE_SRC=$(BUILD_ROOT)\Src\AppCore -CELLAR_SRC=$(BUILD_ROOT)\Src\Cellar -GRUTIL_LIB=$(BUILD_ROOT)\Src\Graphite\lib -GRFW_SRC=$(BUILD_ROOT)\Src\Graphite\FwOnly -VIEWS_LIB=$(BUILD_ROOT)\Src\Views\lib - -# Set the USER_INCLUDE environment variable. -UI=$(UNITPP_INC);$(LANGUAGETEST_SRC);$(LANGUAGE_SRC);$(GENERIC_SRC);$(APPCORE_SRC);$(CELLAR_SRC) - -!IF "$(USER_INCLUDE)"!="" -USER_INCLUDE=$(UI);$(USER_INCLUDE);$(GRUTIL_LIB);$(VIEWS_LIB);$(GRFW_SRC) -!ELSE -USER_INCLUDE=$(UI);$(GRUTIL_LIB);$(VIEWS_LIB);$(GRFW_SRC) -!ENDIF - -!INCLUDE "$(BUILD_ROOT)\bld\_init.mak" - -!INCLUDE "$(BUILD_ROOT)\bld\_rule.mak" - -PATH=$(COM_OUT_DIR);$(PATH) - -RCFILE=Language.rc - -LINK_OPTS=$(LINK_OPTS:/subsystem:windows=/subsystem:console) /LIBPATH:"$(BUILD_ROOT)\Lib\$(BUILD_CONFIG)" -CPPUNIT_LIBS=unit++.lib -LINK_LIBS=$(CPPUNIT_LIBS) Generic.lib Usp10.lib xmlparse.lib $(LINK_LIBS) - -# === Object Lists === - -OBJ_LANGUAGETESTSUITE=\ - $(INT_DIR)\genpch\testLanguage.obj\ - $(INT_DIR)\genpch\Collection.obj\ - $(INT_DIR)\ModuleEntry.obj\ - $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\Language\autopch\UniscribeEngine.obj\ - $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\Language\autopch\UniscribeSegment.obj\ - $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\Language\autopch\RomRenderEngine.obj\ - $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\Language\autopch\RomRenderSegment.obj\ - $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\Language\autopch\LgSimpleEngines.obj\ - $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\Language\autopch\LgIcuCharPropEngine.obj\ - $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\Language\autopch\LgUnicodeCollater.obj\ - $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\Language\autopch\LgKeymanHandler.obj\ - $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\Language\autopch\FwStyledText.obj\ - $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\Language\autopch\WriteXml.obj\ - $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\Language\usepch\TextProps1.obj\ - $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\Language\autopch\FwXml.obj\ - -OBJ_GRUTIL=\ - $(INT_DIR)\autopch\GrUtil.obj\ - -OBJ_ALL=$(OBJ_LANGUAGETESTSUITE) $(OBJ_GRUTIL) $(OBJ_CELLAR) - -# === Targets === -!INCLUDE "$(BUILD_ROOT)\bld\_targ.mak" - -# === Rules === -PCHNAME=testLanguage - -ARG_SRCDIR=$(LANGUAGETEST_SRC) -!INCLUDE "$(BUILD_ROOT)\bld\_rule.mak" - -ARG_SRCDIR=$(GRUTIL_LIB) -!INCLUDE "$(BUILD_ROOT)\bld\_rule.mak" - -ARG_SRCDIR=$(GENERIC_SRC) -!INCLUDE "$(BUILD_ROOT)\bld\_rule.mak" - -# === Custom Rules === - - -# === Custom Targets === - -COLLECT=$(BUILD_ROOT)\Bin\CollectUnit++Tests.cmd Language - -$(INT_DIR)\genpch\Collection.obj: $(LANGUAGETEST_SRC)\Collection.cpp - -$(LANGUAGETEST_SRC)\Collection.cpp: $(LANGUAGETEST_SRC)\testLanguage.h\ - $(LANGUAGETEST_SRC)\MockLgWritingSystemFactory.h\ - $(LANGUAGETEST_SRC)\MockLgWritingSystem.h\ - $(LANGUAGETEST_SRC)\TestRegexMatcher.h\ - $(LANGUAGETEST_SRC)\TestLgCollatingEngine.h\ - $(LANGUAGETEST_SRC)\TestLgIcuCharPropEngine.h\ - $(LANGUAGETEST_SRC)\TestUniscribeEngine.h\ - $(LANGUAGETEST_SRC)\TestRomRenderEngine.h\ - $(LANGUAGETEST_SRC)\RenderEngineTestBase.h - $(DISPLAY) Collecting tests for $(BUILD_PRODUCT).$(BUILD_EXTENSION) - $(COLLECT) $** $(LANGUAGETEST_SRC)\Collection.cpp - -$(INT_DIR)\Language.res: $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\Language\Language.res - copy $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\Language\Language.res $(INT_DIR)\Language.res >nul diff --git a/Src/Language/dlldatax.c b/Src/Language/dlldatax.c deleted file mode 100644 index 296fe27b8c..0000000000 --- a/Src/Language/dlldatax.c +++ /dev/null @@ -1,11 +0,0 @@ -// wrapper for dlldata.c - -#ifdef _MERGE_PROXYSTUB // merge proxy stub DLL - -#include "proxystub.c" // in Generic - -#include "LanguagePs_d.c" // dlldata.c -#include "LanguagePs_p.c" -#include "LanguagePs_i.c" - -#endif //_MERGE_PROXYSTUB diff --git a/Src/Language/mklg.bat b/Src/Language/mklg.bat deleted file mode 100755 index 90efce1231..0000000000 --- a/Src/Language/mklg.bat +++ /dev/null @@ -1,12 +0,0 @@ -@if "%_echo%"=="" echo off - -rem ***** Set BUILD_ROOT to the root of the FieldWorks project. ***** -%0\..\..\..\..\bin\here.exe ".." "set BUILD_ROOT=" > foo.bat -call foo.bat -del foo.bat - -set BUILD_MAKEFILE=%BUILD_ROOT%\Src\Services\Language\Language.mak - -call %BUILD_ROOT%\bld\_mkcore.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 - -set BUILD_MAKEFILE= diff --git a/Src/views/Test/Makefile b/Src/views/Test/Makefile index ae6d89d49e..d82fb0048c 100644 --- a/Src/views/Test/Makefile +++ b/Src/views/Test/Makefile @@ -18,7 +18,7 @@ VIEWS_LIB = $(VIEWS_OBJ)/lib GRENG = $(SRC)/Graphite/lib GRFW = $(SRC)/Graphite/FwOnly -LANGUAGETEST_SRC = $(LANGUAGE_SRC)/Test +KERNELTEST_SRC = $(KERNEL_SRC)/Test DEFINES := -DGR_FW -DVIEWSDLL -DSUPPRESS_FW_EXCEPTION_HANDLING \ -D_VW_GRAPHICS_DEBUG -DVIEWSTEST -DWIN32_KEY_VALUES=1 @@ -34,7 +34,7 @@ PACKAGES = glib-2.0 gtk+-2.0 glibmm-2.4 gtkmm-2.4 gdkmm-2.4 cairomm-1.0 pangomm- INCLUDES := -I$(VIEWS_SRC) -I$(VIEWS_SRC)/lib -I$(VIEWS_SRC)/Test \ -I$(GENERIC_SRC) -I$(APPCORE_SRC) -I$(CELLAR_SRC) -I$(KERNEL_SRC) \ - -I$(LANGUAGE_SRC) -I$(GRENG) -I$(GRFW) -I$(DBACCESS_SRC) -I$(LANGUAGETEST_SRC)\ + -I$(GRENG) -I$(GRFW) -I$(KERNELTEST_SRC)\ INCLUDES := \ $(shell icu-config --cppflags) \ @@ -132,8 +132,8 @@ $(INT_DIR)/Collection.cpp: \ DummyBaseVc.h \ DummyRootsite.h \ testViews.h \ - $(LANGUAGETEST_SRC)/MockLgWritingSystemFactory.h \ - $(LANGUAGETEST_SRC)/MockLgWritingSystem.h \ + $(KERNELTEST_SRC)/MockLgWritingSystemFactory.h \ + $(KERNELTEST_SRC)/MockLgWritingSystem.h \ TestNotifier.h \ TestLayoutPage.h \ TestVwTxtSrc.h \ diff --git a/Src/views/Test/TestViews.vcxproj b/Src/views/Test/TestViews.vcxproj index 76b1e0e3b8..17bf9b8bbe 100644 --- a/Src/views/Test/TestViews.vcxproj +++ b/Src/views/Test/TestViews.vcxproj @@ -1,105 +1,109 @@  - - Debug - Win32 - - - Release - Win32 - + + Debug + Win32 + + + Release + Win32 + - {1D4CC42D-BC16-4EC3-A89B-173798828F56} - TestViews - - - - MakeFileProj + {1D4CC42D-BC16-4EC3-A89B-173798828F56} + TestViews + + + + + + + MakeFileProj - Makefile + Makefile - Makefile + Makefile - - + + - - + + - <_ProjectFileVersion>10.0.30319.1 - $(ProjectDir)\..\..\..\Output\Debug\ - $(ProjectDir)\..\..\..\Obj\Debug\ - ..\..\..\bin\mkvw-tst.bat DONTRUN - ..\..\..\bin\mkvw-tst.bat DONTRUN cc - ..\..\..\bin\mkvw-tst.bat DONTRUN ec - ..\..\..\output\debug\TestViews.exe - $(NMakePreprocessorDefinitions) - $(ProjectDir)..\..\..\Src\views;$(ProjectDir)..\..\Views;$(ProjectDir)..\..\Views\Lib;$(ProjectDir)..\..\Kernel;$(ProjectDir)..\..\Generic;$(ProjectDir)..\..\..\Lib\src\unit++;$(ProjectDir)..\..\..\Output\Common;$(ProjectDir)..\..\..\Output\Common\Raw;$(NMakeIncludeSearchPath) - $(NMakeForcedIncludes) - $(NMakeAssemblySearchPath) - $(NMakeForcedUsingAssemblies) - Release\ - Release\ - - - - TestViews.exe - $(NMakePreprocessorDefinitions) - $(NMakeIncludeSearchPath) - $(NMakeForcedIncludes) - $(NMakeAssemblySearchPath) - $(NMakeForcedUsingAssemblies) + <_ProjectFileVersion>10.0.30319.1 + $(ProjectDir)\..\..\..\Output\Debug\ + $(ProjectDir)\..\..\..\Obj\Debug\ + ..\..\..\bin\mkvw-tst.bat DONTRUN + ..\..\..\bin\mkvw-tst.bat DONTRUN cc + ..\..\..\bin\mkvw-tst.bat DONTRUN ec + ..\..\..\output\debug\TestViews.exe + $(NMakePreprocessorDefinitions) + $(ProjectDir)..\..\..\Src\views;$(ProjectDir)..\..\Views;$(ProjectDir)..\..\Views\Lib;$(ProjectDir)..\..\Kernel;$(ProjectDir)..\..\Generic;$(ProjectDir)..\..\..\Lib\src\unit++;$(ProjectDir)..\..\..\Output\Common;$(ProjectDir)..\..\..\Output\Common\Raw;$(NMakeIncludeSearchPath) + $(NMakeForcedIncludes) + $(NMakeAssemblySearchPath) + $(NMakeForcedUsingAssemblies) + Release\ + Release\ + + + + TestViews.exe + $(NMakePreprocessorDefinitions) + $(NMakeIncludeSearchPath) + $(NMakeForcedIncludes) + $(NMakeAssemblySearchPath) + $(NMakeForcedUsingAssemblies) - - + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + - + diff --git a/Src/views/Test/TestViews.vcxproj.filters b/Src/views/Test/TestViews.vcxproj.filters index 1017c08ce7..a558ffb299 100644 --- a/Src/views/Test/TestViews.vcxproj.filters +++ b/Src/views/Test/TestViews.vcxproj.filters @@ -1,112 +1,111 @@  - - {9399cd57-6823-4458-8784-b31b77cd37a0} - cpp;c;cxx;def;odl;idl;hpj;bat;asm - - - {6e1ad6cb-9ba0-41fd-a86b-8027cd265ce0} - h;hpp;hxx;hm;inl;inc - - - {f2bcfdfd-c6ac-4119-b53c-d64ad4edbe5a} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe - + + {9399cd57-6823-4458-8784-b31b77cd37a0} + cpp;c;cxx;def;odl;idl;hpj;bat;asm + + + {6e1ad6cb-9ba0-41fd-a86b-8027cd265ce0} + h;hpp;hxx;hm;inl;inc + + + {f2bcfdfd-c6ac-4119-b53c-d64ad4edbe5a} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + - - Source Files - - - Source Files - + + Source Files + + + Source Files + - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + - - Resource Files - - - Resource Files - + + Resource Files + + + - - Resource Files - + + Resource Files + \ No newline at end of file diff --git a/Src/views/Test/testViews.mak b/Src/views/Test/testViews.mak index 63aec9c94d..a913080f40 100644 --- a/Src/views/Test/testViews.mak +++ b/Src/views/Test/testViews.mak @@ -19,10 +19,10 @@ GENERIC_SRC=$(BUILD_ROOT)\Src\Generic APPCORE_SRC=$(BUILD_ROOT)\Src\AppCore GRENG_LIB_SRC=$(BUILD_ROOT)\Src\Graphite\lib GRFW_SRC=$(BUILD_ROOT)\Src\Graphite\FwOnly -LANGUAGETEST_SRC=$(BUILD_ROOT)\Src\Language\Test +FWKERNELTEST_SRC=$(BUILD_ROOT)\Src\Kernel\Test # Set the USER_INCLUDE environment variable. -UI=$(UNITPP_INC);$(VIEWSTEST_SRC);$(VIEWS_SRC);$(VIEWS_LIB_SRC);$(GENERIC_SRC);$(APPCORE_SRC);$(GRENG_LIB_SRC);$(GRFW_SRC);$(LANGUAGETEST_SRC) +UI=$(UNITPP_INC);$(VIEWSTEST_SRC);$(VIEWS_SRC);$(VIEWS_LIB_SRC);$(GENERIC_SRC);$(APPCORE_SRC);$(GRENG_LIB_SRC);$(GRFW_SRC);$(FWKERNELTEST_SRC) !IF "$(USER_INCLUDE)"!="" USER_INCLUDE=$(UI);$(USER_INCLUDE) @@ -108,8 +108,8 @@ $(INT_DIR)\genpch\Collection.obj: $(VIEWSTEST_SRC)\Collection.cpp $(VIEWSTEST_SRC)\Collection.cpp: $(VIEWSTEST_SRC)\DummyBaseVc.h $(VIEWSTEST_SRC)\DummyRootsite.h\ $(VIEWSTEST_SRC)\testViews.h\ - $(LANGUAGETEST_SRC)\MockLgWritingSystemFactory.h\ - $(LANGUAGETEST_SRC)\MockLgWritingSystem.h\ + $(FWKERNELTEST_SRC)\MockLgWritingSystemFactory.h\ + $(FWKERNELTEST_SRC)\MockLgWritingSystem.h\ $(VIEWSTEST_SRC)\TestNotifier.h\ $(VIEWSTEST_SRC)\TestLayoutPage.h\ $(VIEWSTEST_SRC)\TestVirtualHandlers.h\ diff --git a/Src/views/Views.mak b/Src/views/Views.mak index 50c822e86d..6fc542c1d9 100644 --- a/Src/views/Views.mak +++ b/Src/views/Views.mak @@ -117,8 +117,8 @@ ARG_SRCDIR=$(AFCORE_SRC) #$(OBJ_ALL): $(TLB_ALL) # because of importlib statements, must build lower TLB's before higher. -$(COM_OUT_DIR)\LanguageTlb.tlb: $(COM_OUT_DIR)\LanguageTlb.idl +$(COM_OUT_DIR)\FwKernelTlb.tlb: $(COM_OUT_DIR)\FwKernelTlb.idl -$(COM_OUT_DIR)\ViewsTlb.tlb: $(COM_OUT_DIR)\LanguageTlb.tlb +$(COM_OUT_DIR)\ViewsTlb.tlb: $(COM_OUT_DIR)\FwKernelTlb.tlb # === Custom Targets === diff --git a/Src/views/views.vcxproj b/Src/views/views.vcxproj index 2c669ca996..8c356f348c 100644 --- a/Src/views/views.vcxproj +++ b/Src/views/views.vcxproj @@ -161,6 +161,7 @@ + diff --git a/Src/views/views.vcxproj.filters b/Src/views/views.vcxproj.filters index 25577e3aed..64db5fb5e1 100644 --- a/Src/views/views.vcxproj.filters +++ b/Src/views/views.vcxproj.filters @@ -123,6 +123,7 @@ + From 34d7daabe08b73158d9e08bfeec9ec6b8ae61b97 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Thu, 19 Dec 2013 12:04:12 +0700 Subject: [PATCH 045/143] fixed Makefile that broke from changes in previous revision Change-Id: Ib0a93c33da166f552c148078668fc67b71d13089 --- Src/AppCore/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Src/AppCore/Makefile b/Src/AppCore/Makefile index 6857f943e6..065ee818f0 100644 --- a/Src/AppCore/Makefile +++ b/Src/AppCore/Makefile @@ -27,7 +27,7 @@ endif # not any of the others (e.g., in Views) INCLUDES := -I$(AFLIB_SRC) -I$(GENERIC_SRC) -I$(APPCORE_SRC) -I$(TEXT_SRC) -I$(DEBUGPROCS_SRC) -INCLUDES := $(INCLUDES) -I$(KERNEL_SRC) -I$(DBACCESS_SRC) +INCLUDES := $(INCLUDES) -I$(KERNEL_SRC) INCLUDES := $(INCLUDES) \ -I$(FWINCLUDE) \ From 72833497ddd2d0800e67402d27a453af1c2b681f Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Thu, 19 Dec 2013 12:45:44 +0700 Subject: [PATCH 046/143] fixed building of FwXml.cpp in Kernel Makefile Change-Id: Ia479da60cfab40c83abcfae4d498f48d12f27706 --- Src/Kernel/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Src/Kernel/Makefile b/Src/Kernel/Makefile index 5277ad2e39..b1c9db8479 100644 --- a/Src/Kernel/Makefile +++ b/Src/Kernel/Makefile @@ -82,13 +82,13 @@ OBJ_FWKERNEL = \ $(INT_DIR)/UniscribeEngine.o \ $(INT_DIR)/RomRenderEngine.o \ $(INT_DIR)/RomRenderSegment.o \ + $(INT_DIR)/FwXml.o \ OBJ_OTHER = \ $(GENERIC_OBJ)/ModuleEntry.o \ $(GENERIC_OBJ)/TextProps1.o \ $(APPCORE_OBJ)/FwStyledText.o \ $(APPCORE_OBJ)/WriteXml.o \ - $(CELLAR_OBJ)/FwXml.o \ # === Targets === @@ -127,9 +127,9 @@ $(APPCORE_OBJ)/FwStyledText.o $(APPCORE_OBJ)/WriteXml.o: @$(MAKE) -C $(APPCORE_SRC) $@ -q || \ $(MAKE) -C $(APPCORE_SRC) $@ -$(CELLAR_OBJ)/FwXml.o: - @$(MAKE) -C $(CELLAR_SRC) $@ -q || \ - $(MAKE) -C $(CELLAR_SRC) $@ +$(INT_DIR)/%.o: $(CELLAR_SRC)/%.cpp + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(TARGET_ARCH) \ + -c $< -o $@ -MMD -MF $(@:%.o=%.d) $(GENERIC_OBJ)/main.o: @$(MAKE) -C $(GENERIC_SRC) -q $@ || \ From 529bb19e9a30cc8199a24ae1e0a84b714ca8e7e0 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 20 Dec 2013 17:12:07 +0700 Subject: [PATCH 047/143] fixed build for FwKernel on Linux Change-Id: Iaaa6773ea6ed47934ca44f0e14d9559b0297f6b6 --- Src/Kernel/FwKernelExtra_GUIDs.cpp | 2 ++ Src/Kernel/Test/Makefile | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Src/Kernel/FwKernelExtra_GUIDs.cpp b/Src/Kernel/FwKernelExtra_GUIDs.cpp index 2c87e34616..ad94a71ea7 100644 --- a/Src/Kernel/FwKernelExtra_GUIDs.cpp +++ b/Src/Kernel/FwKernelExtra_GUIDs.cpp @@ -11,3 +11,5 @@ DEFINE_UUIDOF(ITsStringRaw,0x2AC0CB90,0xB14B,0x11d2,0xB8,0x1D,0x00,0x40,0x05,0x41,0xF9,0xDA); DEFINE_UUIDOF(ITsTextPropsRaw,0x31BDA5F0,0xD286,0x11d3,0x9B,0xBC,0x00,0x40,0x05,0x41,0xF9,0xE9); +DEFINE_UUIDOF(UniscribeSegment,0x61299C3B,0x54D6,0x4c46,0xAC,0xE5,0x72,0xB9,0x12,0x8F,0x20,0x48); +DEFINE_UUIDOF(RomRenderSegment,0xA124E0C1,0xDD4B,0x11d2,0x80,0x78,0x00,0x00,0xC0,0xFB,0x81,0xB5); \ No newline at end of file diff --git a/Src/Kernel/Test/Makefile b/Src/Kernel/Test/Makefile index 49b53d383b..0678956dde 100644 --- a/Src/Kernel/Test/Makefile +++ b/Src/Kernel/Test/Makefile @@ -83,7 +83,7 @@ FWKERNEL_OBJ := \ $(KERNEL_OBJ)/LocaleIndex.o \ $(GENERIC_OBJ)/ModuleEntry.o \ $(GENERIC_OBJ)/TextProps1.o \ - $(CELLAR_OBJ)/FwXml.o \ + $(KERNEL_OBJ)/FwXml.o \ #Run make in the directory of each library $(LINK_LIBS) $(FWKERNEL_OBJ):: From 4471c2732e1356b92a0e7e47dab91058d74ee002 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Tue, 7 Jan 2014 13:23:44 +0700 Subject: [PATCH 048/143] updated ManifestHelper so that a manifest file can be specified Change-Id: I3e8fd1976ef8b0c0b484715d181583fff0f42a45 --- .../FwControls/ProgressDialogWithTask.cs | 3 +- .../CreateComObjectsFromManifestAttribute.cs | 2 +- Src/Utilities/BasicUtils/ManifestHelper.cs | 34 +++++++------------ 3 files changed, 15 insertions(+), 24 deletions(-) diff --git a/Src/Common/Controls/FwControls/ProgressDialogWithTask.cs b/Src/Common/Controls/FwControls/ProgressDialogWithTask.cs index 4d693a1e01..5a9e4df5a3 100644 --- a/Src/Common/Controls/FwControls/ProgressDialogWithTask.cs +++ b/Src/Common/Controls/FwControls/ProgressDialogWithTask.cs @@ -712,7 +712,8 @@ private void RunBackgroundTask(object sender, DoWorkEventArgs e) Thread.CurrentThread.Name = "Background thread"; if (MiscUtils.RunningTests) - ManifestHelper.CreateActivationContext(); + ManifestHelper.CreateActivationContext("FieldWorks.Tests.manifest"); + m_Exception = null; m_RetValue = null; diff --git a/Src/Utilities/BasicUtils/BasicUtilsTests/Attributes/CreateComObjectsFromManifestAttribute.cs b/Src/Utilities/BasicUtils/BasicUtilsTests/Attributes/CreateComObjectsFromManifestAttribute.cs index 9230578830..de181eda22 100644 --- a/Src/Utilities/BasicUtils/BasicUtilsTests/Attributes/CreateComObjectsFromManifestAttribute.cs +++ b/Src/Utilities/BasicUtils/BasicUtilsTests/Attributes/CreateComObjectsFromManifestAttribute.cs @@ -36,7 +36,7 @@ public override void BeforeTest(TestDetails testDetails) base.BeforeTest(testDetails); #if !__MonoCS__ - ManifestHelper.CreateActivationContext(); + ManifestHelper.CreateActivationContext("FieldWorks.Tests.manifest"); #endif } diff --git a/Src/Utilities/BasicUtils/ManifestHelper.cs b/Src/Utilities/BasicUtils/ManifestHelper.cs index 5979dbb437..77cadeb389 100644 --- a/Src/Utilities/BasicUtils/ManifestHelper.cs +++ b/Src/Utilities/BasicUtils/ManifestHelper.cs @@ -12,6 +12,7 @@ using System.ComponentModel; using System.Diagnostics; using System.IO; +using System.Reflection; using System.Runtime.InteropServices; using System.Security; @@ -108,43 +109,32 @@ private void Dispose(bool fDisposing) #endregion /// - /// Gets (and creates) the activation context + /// Creates and activates an activation context on the current thread /// - private IntPtr ActivationContext + public void CreateContext(string manifestFile) { - get + if (m_Cookie == IntPtr.Zero) { if (m_ActivationContext == IntPtr.Zero) { - // Specifying a full path to the Tests.manifest file like this allows our unit tests to work even with a + // Specifying a full path to the manifest file like this allows our unit tests to work even with a // test runner like Resharper 8 which does not set the current directory to the one containing the DLLs. // Note that we have to use CodeBase here because NUnit runs the tests from a shadow copy directory // that doesn't contain the manifest file. - var uri = new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase); - var location = Path.GetDirectoryName(uri.AbsolutePath); + var uri = new Uri(Assembly.GetExecutingAssembly().CodeBase); + string location = Path.GetDirectoryName(uri.AbsolutePath); var context = new ActCtx { cbSize = Marshal.SizeOf(typeof(ActCtx)), - lpSource = Path.Combine(location, "FieldWorks.Tests.manifest") + lpSource = Path.Combine(location, manifestFile) }; - var handle = CreateActCtx(ref context); + IntPtr handle = CreateActCtx(ref context); if (handle == (IntPtr)(-1)) throw new Win32Exception(Marshal.GetLastWin32Error(), "Error creating activation context"); m_ActivationContext = handle; } - return m_ActivationContext; - } - } - - /// - /// Creates and activates an activation context on the current thread - /// - public void CreateContext() - { - if (m_Cookie == IntPtr.Zero) - { - if (!ActivateActCtx(ActivationContext, out m_Cookie)) + if (!ActivateActCtx(m_ActivationContext, out m_Cookie)) throw new Win32Exception(Marshal.GetLastWin32Error(), "Error activating context"); } m_Count++; @@ -173,10 +163,10 @@ public void DestroyContext() /// /// Creates and activates an activation context on the current thread /// - public static void CreateActivationContext() + public static void CreateActivationContext(string manifestFile) { #if !__MonoCS__ - SingletonsContainer.Get().CreateContext(); + SingletonsContainer.Get().CreateContext(manifestFile); #endif } From adf042ac3590b333f36b45c0e90cfaf999989b22 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Mon, 13 Jan 2014 15:35:32 +0700 Subject: [PATCH 049/143] fixed bug where segments were not updated when analyses were removed Change-Id: I5f12fe8b77c38835c6a69eb90f30e939142ed1b4 --- .../RootSiteTests/RootSiteTests.csproj | 2 +- .../SimpleRootSite/SimpleRootSite.csproj | 2 +- .../SimpleRootSiteTests.csproj | 4 ++-- .../Impl/FdoIFwMetaDataCache.cs | 24 +++++++++++++++---- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/Src/Common/RootSite/RootSiteTests/RootSiteTests.csproj b/Src/Common/RootSite/RootSiteTests/RootSiteTests.csproj index b772e82e25..588b27945c 100644 --- a/Src/Common/RootSite/RootSiteTests/RootSiteTests.csproj +++ b/Src/Common/RootSite/RootSiteTests/RootSiteTests.csproj @@ -83,7 +83,7 @@ true 4096 false - 168,169,219,414,649,1635,1702,1701 + 168,169,219,414,649,1635,1702,1701,1591,1685 true false false diff --git a/Src/Common/SimpleRootSite/SimpleRootSite.csproj b/Src/Common/SimpleRootSite/SimpleRootSite.csproj index 6daa81ea4b..37625354be 100644 --- a/Src/Common/SimpleRootSite/SimpleRootSite.csproj +++ b/Src/Common/SimpleRootSite/SimpleRootSite.csproj @@ -90,7 +90,7 @@ true 4096 false - 168,169,219,414,649,1635,1702,1701 + 168,169,219,414,649,1635,1702,1701,1685 true false false diff --git a/Src/Common/SimpleRootSite/SimpleRootSiteTests/SimpleRootSiteTests.csproj b/Src/Common/SimpleRootSite/SimpleRootSiteTests/SimpleRootSiteTests.csproj index 61cbfa5570..dcd573b1ab 100644 --- a/Src/Common/SimpleRootSite/SimpleRootSiteTests/SimpleRootSiteTests.csproj +++ b/Src/Common/SimpleRootSite/SimpleRootSiteTests/SimpleRootSiteTests.csproj @@ -84,7 +84,7 @@ false 4096 false - 168,169,219,414,649,1635,1702,1701 + 168,169,219,414,649,1635,1702,1701,1685 true false false @@ -249,4 +249,4 @@ - + \ No newline at end of file diff --git a/Src/FDO/Infrastructure/Impl/FdoIFwMetaDataCache.cs b/Src/FDO/Infrastructure/Impl/FdoIFwMetaDataCache.cs index 5ba77d00e6..aef3e55886 100644 --- a/Src/FDO/Infrastructure/Impl/FdoIFwMetaDataCache.cs +++ b/Src/FDO/Infrastructure/Impl/FdoIFwMetaDataCache.cs @@ -67,6 +67,7 @@ internal sealed class FdoMetaDataCache : IFwMetaDataCacheManaged, IFwMetaDataCac private readonly Dictionary m_nameToFlid = new Dictionary(); private readonly Dictionary m_clidToNextCustomFlid = new Dictionary(); private readonly HashSet m_customFields = new HashSet(); + private readonly HashSet m_analysisClids = new HashSet(); #endregion Data Members for IFwMetaDataCache Support @@ -121,9 +122,10 @@ private void InitializeMetaDataCache(IEnumerable cmObjectTypes) continue; // ScrFootnote does not have the 'ModelClassAttribute'. //throw new InvalidOperationException("CmObjects must use 'ModelClassAttribute'."); + int clid = ((ModelClassAttribute)classAttrs[0]).Clsid; // Add its class information. AddClass(fdoType.Name, - ((ModelClassAttribute)classAttrs[0]).Clsid, + clid, fdoType.Name == "CmObject" ? "CmObject" : fdoType.BaseType.Name, fdoType.IsAbstract); #else @@ -154,6 +156,8 @@ private void InitializeMetaDataCache(IEnumerable cmObjectTypes) fdoType.IsAbstract); #endif + if (fdoType.GetInterface("IAnalysis") != null) + m_analysisClids.Add(clid); // Cache properties. // Regular foreach loop is faster. //PropertyInfo[] pis = fdoType.GetProperties(); @@ -216,11 +220,21 @@ private void InitializeMetaDataCache(IEnumerable cmObjectTypes) private void ConnectMetaFieldRec(MetaFieldRec mfr) { - int clid; - if (mfr.m_sig == null || !m_nameToClid.TryGetValue(mfr.m_sig, out clid)) return; + if (mfr.m_sig == null) + return; - SetDestClass(mfr, clid); - mfr.m_sig = null; + int clid; + if (m_nameToClid.TryGetValue(mfr.m_sig, out clid)) + { + SetDestClass(mfr, clid); + mfr.m_sig = null; + } + else if (mfr.m_sig == "IAnalyses") + { + foreach (int analysisClid in m_analysisClids) + m_metaClassRecords[analysisClid].m_incomingFields.Add(mfr); + mfr.m_sig = null; + } } private void SetDestClass(MetaFieldRec mfr, int clid) From 5bf79525cf9f231c98f9685da02eb3a3ec79ac1a Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Fri, 17 Jan 2014 15:28:19 +0700 Subject: [PATCH 050/143] Remove obsolete LexicalProvider code Change-Id: Ie1133a17d950feffaf8cf250b7754d21c18ce6bb --- Src/Common/FieldWorks/FieldWorks.cs | 5 - Src/Common/FieldWorks/FieldWorks.csproj | 4 - .../LexicalProvider/ILexicalProvider.cs | 327 ---------- .../LexicalProvider/LexicalProviderImpl.cs | 601 ------------------ .../LexicalProvider/LexicalProviderManager.cs | 191 ------ .../LexicalProvider/LexicalServiceProvider.cs | 102 --- Src/FdoUi/LexEntryUi.cs | 64 -- 7 files changed, 1294 deletions(-) delete mode 100644 Src/Common/FieldWorks/LexicalProvider/ILexicalProvider.cs delete mode 100644 Src/Common/FieldWorks/LexicalProvider/LexicalProviderImpl.cs delete mode 100644 Src/Common/FieldWorks/LexicalProvider/LexicalProviderManager.cs delete mode 100644 Src/Common/FieldWorks/LexicalProvider/LexicalServiceProvider.cs diff --git a/Src/Common/FieldWorks/FieldWorks.cs b/Src/Common/FieldWorks/FieldWorks.cs index 6a8b739b69..b2abe9148e 100644 --- a/Src/Common/FieldWorks/FieldWorks.cs +++ b/Src/Common/FieldWorks/FieldWorks.cs @@ -48,7 +48,6 @@ using SIL.FieldWorks.FwCoreDlgs.BackupRestore; using SIL.FieldWorks.PaObjects; using SIL.FieldWorks.Resources; -using SIL.FieldWorks.LexicalProvider; using SIL.Utils; using SIL.Utils.FileDialog; using XCore; @@ -345,9 +344,6 @@ static int Main(string[] rgArgs) else if (!LaunchApplicationFromCommandLine(appArgs)) return 0; // Didn't launch, but probably not a serious error - // Create a listener for this project for applications using FLEx as a LexicalProvider. - LexicalProviderManager.StartLexicalServiceProvider(s_projectId, s_cache); - #if __MonoCS__ UglyHackForXkbIndicator(); #endif @@ -3563,7 +3559,6 @@ private static RemoteRequest CreateRequestor(int port, string requestType) private static void StaticDispose() { s_appServerMode = false; // Make sure the cache can be cleaned up - LexicalProviderManager.StaticDispose(); // Must be done before disposing the cache if (s_serviceChannel != null) { ChannelServices.UnregisterChannel(s_serviceChannel); diff --git a/Src/Common/FieldWorks/FieldWorks.csproj b/Src/Common/FieldWorks/FieldWorks.csproj index 65ae5049c2..3b6196f7b2 100644 --- a/Src/Common/FieldWorks/FieldWorks.csproj +++ b/Src/Common/FieldWorks/FieldWorks.csproj @@ -200,9 +200,6 @@ - - - Form @@ -221,7 +218,6 @@ - diff --git a/Src/Common/FieldWorks/LexicalProvider/ILexicalProvider.cs b/Src/Common/FieldWorks/LexicalProvider/ILexicalProvider.cs deleted file mode 100644 index 0d5e281fa6..0000000000 --- a/Src/Common/FieldWorks/LexicalProvider/ILexicalProvider.cs +++ /dev/null @@ -1,327 +0,0 @@ -// --------------------------------------------------------------------------------------------- -#region // Copyright (c) 2011, SIL International. All Rights Reserved. -// -// Copyright (c) 2011, SIL International. All Rights Reserved. -// -// Distributable under the terms of either the Common Public License or the -// GNU Lesser General Public License, as specified in the LICENSING.txt file. -// -#endregion -// -// File: ILexicalProvider.cs -// Responsibility: FW Team -// -// -// -// --------------------------------------------------------------------------------------------- -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; -using System.ServiceModel; - -namespace SIL.FieldWorks.LexicalProvider -{ - #region ILexicalServiceProvider interface - /// ---------------------------------------------------------------------------------------- - /// - /// Provides a service contract for getting a lexical provider from an application. - /// WARNING: Paratext contains its own identical definition of these interfaces. - /// Any change must be coordinated (both in corresponding source files and in terms - /// of product release schedules. - /// - /// ---------------------------------------------------------------------------------------- - [ServiceContract] - public interface ILexicalServiceProvider - { - /// ------------------------------------------------------------------------------------ - /// - /// Gets the location for the provider for the specified project and - /// provider type. If the providerType is not supported, return null for the Uri. - /// - /// ------------------------------------------------------------------------------------ - [OperationContract] - Uri GetProviderLocation(string projhandle, string providerType); - - /// ------------------------------------------------------------------------------------ - /// - /// Gets the version of the specified provider that the server supports. If the - /// providerType is not supported, return 0 for the version. - /// - /// ------------------------------------------------------------------------------------ - [OperationContract] - int GetSupportedVersion(string providerType); - - /// ------------------------------------------------------------------------------------ - /// - /// Unlike a normal ping method that gets a response, we just use this ping method - /// to determine if the service provider is actually valid since no exception is - /// thrown until a method is called. - /// - /// ------------------------------------------------------------------------------------ - [OperationContract] - void Ping(); - } - #endregion - - #region ILexicalProvider interface - /// ---------------------------------------------------------------------------------------- - /// - /// Provides a service contract for accessing lexical data from other applications. - /// - /// ---------------------------------------------------------------------------------------- - [ServiceContract] - public interface ILexicalProvider - { - /// ------------------------------------------------------------------------------------ - /// - /// Displays the specified entry using the application with the lexical data. - /// - /// ------------------------------------------------------------------------------------ - [OperationContract] - void ShowEntry(string entry, EntryType entryType); - - /// ------------------------------------------------------------------------------------ - /// - /// Displays the related words using the application with the lexical data. - /// - /// ------------------------------------------------------------------------------------ - [OperationContract] - void ShowRelatedWords(string entry, EntryType entryType); - - /// ------------------------------------------------------------------------------------ - /// - /// Gets all lexemes in the Lexicon - /// - /// ------------------------------------------------------------------------------------ - [OperationContract] - IEnumerable Lexemes(); - - /// - /// Looks up an lexeme in the lexicon - /// - [OperationContract] - LexicalEntry GetLexeme(LexemeType type, string lexicalForm, int homograph); - - /// - /// Adds the lexeme to the lexicon. - /// - /// if matching lexeme is already in lexicon - [OperationContract] - void AddLexeme(LexicalEntry lexeme); - - /// - /// Adds a new sense to the lexeme with the specified information - /// - [OperationContract] - LexSense AddSenseToEntry(LexemeType type, string lexicalForm, int homograph); - - /// - /// Adds a new gloss to the sense with the specified information - /// - [OperationContract] - LexGloss AddGlossToSense(LexemeType type, string lexicalForm, int homograph, string senseId, string language, string text); - - /// - /// Removes the gloss with the specified language form the sense with the specified information - /// - [OperationContract] - void RemoveGloss(LexemeType type, string lexicalForm, int homograph, string senseId, string language); - - /// ------------------------------------------------------------------------------------ - /// - /// Forces a save of lexicon - /// - /// ------------------------------------------------------------------------------------ - [OperationContract] - void Save(); - - /// ------------------------------------------------------------------------------------ - /// - /// This must be called before entries are changed to ensure that - /// it is saved to disk. Since the lexicon is a complex structure - /// and other features depend on knowing when it is changed, - /// all work done with the lexicon is marked with a begin and - /// end change. - /// - /// ------------------------------------------------------------------------------------ - [OperationContract] - void BeginChange(); - - /// ------------------------------------------------------------------------------------ - /// - /// This must be called after entries are changed to ensure that - /// other features dependent on the lexicon are made aware of the - /// change. - /// - /// ------------------------------------------------------------------------------------ - [OperationContract] - void EndChange(); - } - #endregion - - #region EntryType enumeration - /// ---------------------------------------------------------------------------------------- - /// - /// Types of lexical entries that can be requested by a client of a LexicalProvider - /// - /// ---------------------------------------------------------------------------------------- - public enum EntryType - { - /// entry represents a word - Word - } - #endregion - - #region LexemeType enumeration - /// ---------------------------------------------------------------------------------------- - /// - /// All known lexeme types - /// - /// ---------------------------------------------------------------------------------------- - public enum LexemeType - { - /// - Phrase, - /// - Word, - /// - Lemma, - /// - Stem, - /// - Prefix, - /// - Suffix - }; - #endregion - - #region LexicalEntry class - /// ---------------------------------------------------------------------------------------- - /// - /// Data contract used by WCF for holding information about a Lexeme - /// - /// ---------------------------------------------------------------------------------------- - [DataContract(Namespace = "LexicalData")] - public sealed class LexicalEntry - { - /// ------------------------------------------------------------------------------------ - /// - /// Initializes a new instance of the class. - /// - /// ------------------------------------------------------------------------------------ - public LexicalEntry(LexemeType type, string form, int homograph) - { - Type = type; - LexicalForm = form; - Homograph = homograph; - Senses = new List(); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets or sets the type. - /// - /// ------------------------------------------------------------------------------------ - [DataMember] - public LexemeType Type { get; private set; } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets or sets the lexical form. - /// - /// ------------------------------------------------------------------------------------ - [DataMember] - public string LexicalForm { get; private set; } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets or sets the homograph. - /// - /// ------------------------------------------------------------------------------------ - [DataMember] - public int Homograph { get; private set; } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets or sets the senses. - /// - /// ------------------------------------------------------------------------------------ - [DataMember] - public IList Senses { get; set; } - } - #endregion - - #region LexSense class - /// ---------------------------------------------------------------------------------------- - /// - /// Data contract used by WCF for holding information about a Sense - /// - /// ---------------------------------------------------------------------------------------- - [DataContract(Namespace = "LexicalData")] - public sealed class LexSense - { - /// ------------------------------------------------------------------------------------ - /// - /// Initializes a new instance of the class. - /// - /// ------------------------------------------------------------------------------------ - public LexSense(string id) - { - Id = id; - Glosses = new List(); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets or sets the id. - /// - /// ------------------------------------------------------------------------------------ - [DataMember] - public string Id { get; private set; } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets or sets the glosses. - /// - /// ------------------------------------------------------------------------------------ - [DataMember] - public IList Glosses { get; set; } - } - #endregion - - #region LexGloss class - /// - /// Data contract used by WCF for holding information about a Gloss - /// - [DataContract(Namespace = "LexicalData")] - public sealed class LexGloss - { - /// ------------------------------------------------------------------------------------ - /// - /// Initializes a new instance of the class. - /// - /// ------------------------------------------------------------------------------------ - public LexGloss(string language, string text) - { - Language = language; - Text = text; - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets or sets the language. - /// - /// ------------------------------------------------------------------------------------ - [DataMember] - public string Language { get; private set; } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets or sets the text. - /// - /// ------------------------------------------------------------------------------------ - [DataMember] - public string Text { get; private set; } - } - #endregion -} diff --git a/Src/Common/FieldWorks/LexicalProvider/LexicalProviderImpl.cs b/Src/Common/FieldWorks/LexicalProvider/LexicalProviderImpl.cs deleted file mode 100644 index f4c0d35d2f..0000000000 --- a/Src/Common/FieldWorks/LexicalProvider/LexicalProviderImpl.cs +++ /dev/null @@ -1,601 +0,0 @@ -// --------------------------------------------------------------------------------------------- -#region // Copyright (c) 2011, SIL International. All Rights Reserved. -// -// Copyright (c) 2011, SIL International. All Rights Reserved. -// -// Distributable under the terms of either the Common Public License or the -// GNU Lesser General Public License, as specified in the LICENSING.txt file. -// -#endregion -// -// File: LexicalProviderImpl.cs -// Responsibility: FW Team -// -// -// -// --------------------------------------------------------------------------------------------- -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.ServiceModel; -using SIL.FieldWorks.Common.COMInterfaces; -using SIL.CoreImpl; -using SIL.FieldWorks.FDO; -using SIL.FieldWorks.FDO.DomainServices; -using SIL.FieldWorks.FDO.Infrastructure; -using SIL.FieldWorks.FdoUi; -using SIL.FieldWorks.Common.FwUtils; -using SIL.Utils; -using XCore; - -namespace SIL.FieldWorks.LexicalProvider -{ - /// ---------------------------------------------------------------------------------------- - /// - /// This class implements the ILexicalProvider - /// - /// ---------------------------------------------------------------------------------------- - [ServiceBehavior(IncludeExceptionDetailInFaults = true, - InstanceContextMode = InstanceContextMode.Single, - MaxItemsInObjectGraph = 2147483647)] - [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", - Justification="m_cache is a reference")] - public sealed class LexicalProviderImpl : ILexicalProvider - { - private const string kAnalysisPrefix = "Analysis:"; - private readonly FdoCache m_cache; - - /// ------------------------------------------------------------------------------------ - /// - /// Initializes a new instance of the class for the - /// specified cache. - /// - /// ------------------------------------------------------------------------------------ - public LexicalProviderImpl(FdoCache cache) - { - m_cache = cache; - } - - #region ILexicalProvider Members - /// ------------------------------------------------------------------------------------ - /// - /// Displays the specified entry using the application with the lexical data. - /// - /// ------------------------------------------------------------------------------------ - public void ShowEntry(string entry, EntryType entryType) - { - LexicalProviderManager.ResetLexicalProviderTimer(); - Logger.WriteEvent("Showing entry from external application for the " + entryType + " " + entry); - - if (entryType != EntryType.Word) - throw new ArgumentException("Unknown entry type specified."); - - // An asynchronous call is necessary because the WCF server (FieldWorks) will not - // respond until this method returns. This also allows methods that show dialogs on the - // WCF server to not be OneWay. (Otherwise, time-out exceptions occur.) - FieldWorks.ThreadHelper.InvokeAsync(() => - { - ITsString tss = TsStringUtils.MakeTss(entry, FieldWorks.Cache.DefaultVernWs); - Mediator mediator = new Mediator(); - mediator.HelpTopicProvider = FieldWorks.GetHelpTopicProvider(FwUtils.ksFlexAbbrev); - mediator.FeedbackInfoProvider = FieldWorks.GetOrCreateFlexApp(); - mediator.PropertyTable.SetProperty("App", FieldWorks.GetOrCreateFlexApp()); - - LexEntryUi.DisplayEntry(FieldWorks.Cache, mediator, mediator.HelpTopicProvider, - "UserHelpFile", tss, null); - }); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Displays the related words to the specified entry using the application with the - /// lexical data. - /// - /// ------------------------------------------------------------------------------------ - public void ShowRelatedWords(string entry, EntryType entryType) - { - LexicalProviderManager.ResetLexicalProviderTimer(); - Logger.WriteEvent("Showing related word from external application for the " + entryType + " " + entry); - - if (entryType != EntryType.Word) - throw new ArgumentException("Unknown entry type specified."); - - // An asynchronous call is necessary because the WCF server (FieldWorks) will not - // respond until this method returns. This also allows methods that show dialogs on the - // WCF server to not be OneWay. (Otherwise, time-out exceptions occur.) - FieldWorks.ThreadHelper.InvokeAsync(() => - { - ITsString tss = TsStringUtils.MakeTss(entry, FieldWorks.Cache.DefaultVernWs); - Mediator mediator = new Mediator(); - mediator.HelpTopicProvider = FieldWorks.GetHelpTopicProvider(FwUtils.ksFlexAbbrev); - mediator.FeedbackInfoProvider = FieldWorks.GetOrCreateFlexApp(); - mediator.PropertyTable.SetProperty("App", FieldWorks.GetOrCreateFlexApp()); - - LexEntryUi.DisplayRelatedEntries(FieldWorks.Cache, mediator, mediator.HelpTopicProvider, - "UserHelpFile", tss); - }); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets all lexemes in the Lexicon - /// - /// ------------------------------------------------------------------------------------ - public IEnumerable Lexemes() - { - LexicalProviderManager.ResetLexicalProviderTimer(); - - List entries = new List(); - // Get all of the lexical entries in the database - foreach (ILexEntry dbEntry in m_cache.ServiceLocator.GetInstance().AllInstances()) - { - IMoMorphType morphType = dbEntry.PrimaryMorphType; - if (morphType != null) - entries.Add(CreateEntryFromDbEntry(GetLexemeTypeForMorphType(morphType), dbEntry)); - } - - // Get all the wordforms in the database - foreach (IWfiWordform wordform in m_cache.ServiceLocator.GetInstance().AllInstances()) - entries.Add(CreateEntryFromDbWordform(wordform)); - - return entries; - } - - /// ------------------------------------------------------------------------------------ - /// - /// Looks up an lexeme - /// - /// ------------------------------------------------------------------------------------ - public LexicalEntry GetLexeme(LexemeType type, string lexicalForm, int homograph) - { - LexicalProviderManager.ResetLexicalProviderTimer(); - - switch (type) - { - case LexemeType.Word: - IWfiWordform wf = GetDbWordform(lexicalForm); - return (wf != null) ? CreateEntryFromDbWordform(wf) : null; - default: - ILexEntry dbEntry = GetDbLexeme(type, lexicalForm, homograph); - return (dbEntry != null) ? CreateEntryFromDbEntry(type, dbEntry) : null; - } - } - - /// ------------------------------------------------------------------------------------ - /// - /// Adds the lexeme to the lexicon. - /// - /// if matching lexeme is already in lexicon - /// ------------------------------------------------------------------------------------ - public void AddLexeme(LexicalEntry lexeme) - { - LexicalProviderManager.ResetLexicalProviderTimer(); - Logger.WriteEvent("Adding new lexeme from an external application: " + lexeme.LexicalForm); - - NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, () => - { - string sForm = lexeme.LexicalForm; - switch(lexeme.Type) - { - case LexemeType.Word: - ITsString tss = TsStringUtils.MakeTss(lexeme.LexicalForm, m_cache.DefaultVernWs); - m_cache.ServiceLocator.GetInstance().Create(tss); - break; - default: - { - SandboxGenericMSA msa = new SandboxGenericMSA(); - msa.MsaType = (lexeme.Type == LexemeType.Stem) ? MsaType.kStem : MsaType.kUnclassified; - - IMoMorphType morphType = GetMorphTypeForLexemeType(lexeme.Type); - ITsString tssForm = TsStringUtils.MakeTss(sForm, m_cache.DefaultVernWs); - m_cache.ServiceLocator.GetInstance().Create(morphType, tssForm, null, msa); - break; - } - } - }); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Adds a new sense to the lexeme with the specified information - /// - /// ------------------------------------------------------------------------------------ - public LexSense AddSenseToEntry(LexemeType type, string lexicalForm, int homograph) - { - LexicalProviderManager.ResetLexicalProviderTimer(); - Logger.WriteEvent("Adding new sense to lexeme '" + lexicalForm + "' from an external application"); - - return NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, () => - { - string guid = string.Empty; - switch (type) - { - case LexemeType.Word: - { - IWfiWordform dbWordform = GetDbWordform(lexicalForm); - if (dbWordform == null) - throw new ArgumentException("Entry in the lexicon not found for the specified information"); - - // For wordforms, our "senses" could be new meanings of an analysis for the word - // or it could be a brand new analysis. Because we have no idea what the user actually - // wanted, we just assume the worst (they want to create a new analysis for the word - // with a new meaning). - IWfiAnalysis dbAnalysis = m_cache.ServiceLocator.GetInstance().Create(); - dbWordform.AnalysesOC.Add(dbAnalysis); - guid = kAnalysisPrefix + dbAnalysis.Guid; - break; - } - default: - { - ILexEntry dbEntry = GetDbLexeme(type, lexicalForm, homograph); - if (dbEntry == null) - throw new ArgumentException("Entry in the lexicon not found for the specified information"); - - if (dbEntry.SensesOS.Count == 1 && dbEntry.SensesOS[0].Gloss.StringCount == 0) - { - // An empty sense exists (probably was created during a call to AddLexeme) - guid = dbEntry.SensesOS[0].Guid.ToString(); - break; - } - - ILexSense newSense = m_cache.ServiceLocator.GetInstance().Create( - dbEntry, new SandboxGenericMSA(), null); - guid = newSense.Guid.ToString(); - break; - } - } - return new LexSense(guid); - }); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Adds a new gloss to the sense with the specified information - /// - /// ------------------------------------------------------------------------------------ - public LexGloss AddGlossToSense(LexemeType type, string lexicalForm, int homograph, - string senseId, string language, string text) - { - LexicalProviderManager.ResetLexicalProviderTimer(); - Logger.WriteEvent("Adding new gloss to lexeme '" + lexicalForm + "' from an external application"); - - return NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, () => - { - IMultiUnicode dbGlosses; - if (senseId.StartsWith(kAnalysisPrefix)) - { - // The "sense" is actually an analysis for a wordform and our new - // gloss is a new meaning for that analysis. - Guid analysisGuid = new Guid(senseId.Substring(kAnalysisPrefix.Length)); - IWfiAnalysis dbAnalysis = m_cache.ServiceLocator.GetInstance().GetObject(analysisGuid); - IWfiGloss dbGloss = dbAnalysis.MeaningsOC.FirstOrDefault(); - if (dbGloss == null) - { - dbGloss = m_cache.ServiceLocator.GetInstance().Create(); - dbAnalysis.MeaningsOC.Add(dbGloss); - } - dbGlosses = dbGloss.Form; - dbAnalysis.ApprovalStatusIcon = 1; // Assume the analysis from the external application is user approved - } - else - { - Guid senseGuid = new Guid(senseId); - ILexSense dbSense = m_cache.ServiceLocator.GetInstance().GetObject(senseGuid); - dbGlosses = dbSense.Gloss; - } - - // Add the new gloss to the list of glosses for the sense - ILgWritingSystem writingSystem = m_cache.WritingSystemFactory.get_Engine(language); - dbGlosses.set_String(writingSystem.Handle, TsStringUtils.MakeTss(text, writingSystem.Handle)); - - return new LexGloss(language, text); - }); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Removes the gloss with the specified language form the sense with the specified information - /// - /// ------------------------------------------------------------------------------------ - public void RemoveGloss(LexemeType type, string lexicalForm, int homograph, - string senseId, string language) - { - LexicalProviderManager.ResetLexicalProviderTimer(); - Logger.WriteEvent("Removing gloss from lexeme '" + lexicalForm + "' from an external application"); - - NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, () => - { - IMultiUnicode dbGlosses; - Guid guid; - if (senseId.StartsWith(kAnalysisPrefix)) - { - // The "sense" is actually an analysis for a wordform and the gloss - // we want to delete is a meaning for that analysis. - guid = new Guid(senseId.Substring(kAnalysisPrefix.Length)); - IWfiAnalysis dbAnalysis = m_cache.ServiceLocator.GetInstance().GetObject(guid); - IWfiGloss dbGloss = dbAnalysis.MeaningsOC.First(); - dbGlosses = dbGloss.Form; - } - else - { - guid = new Guid(senseId); - ILexSense dbSense = m_cache.ServiceLocator.GetInstance().GetObject(guid); - dbGlosses = dbSense.Gloss; - } - // Remove the gloss from the list of glosses for the sense - int wsId = m_cache.WritingSystemFactory.GetWsFromStr(language); - dbGlosses.set_String(wsId, (ITsString)null); - - // Delete the sense if there are no more glosses for it - if (dbGlosses.StringCount == 0) - RemoveSense(senseId, guid); - }); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Forces a save of lexicon - /// - /// ------------------------------------------------------------------------------------ - public void Save() - { - LexicalProviderManager.ResetLexicalProviderTimer(); - - // ENHANCE: We could do a save on the cache here. It doesn't seem really important - // since the cache will be saved automatically with 10 seconds of inactivity anyways. - } - - /// ------------------------------------------------------------------------------------ - /// - /// This must be called before entries are changed to ensure that - /// it is saved to disk. Since the lexicon is a complex structure - /// and other features depend on knowing when it is changed, - /// all work done with the lexicon is marked with a begin and - /// end change. - /// - /// ------------------------------------------------------------------------------------ - public void BeginChange() - { - LexicalProviderManager.ResetLexicalProviderTimer(); - - // Ideally, we would like to be able to begin an undo task here and then end it in - // EndChange(). However, because there is no guarantee that EndChange() will ever - // get called (and to keep the data in a consistant state), we need to wrap - // each individual change in it's own undo task. - } - - /// ------------------------------------------------------------------------------------ - /// - /// This must be called after entries are changed to ensure that - /// other features dependent on the lexicon are made aware of the - /// change. - /// - /// ------------------------------------------------------------------------------------ - public void EndChange() - { - LexicalProviderManager.ResetLexicalProviderTimer(); - } - #endregion - - #region Private helper methods - /// ------------------------------------------------------------------------------------ - /// - /// Gets the DB LexEntry for the specified type and form (homograph currently ignored) or - /// null if none could be found. - /// - /// ------------------------------------------------------------------------------------ - private ILexEntry GetDbLexeme(LexemeType type, string lexicalForm, int homograph) - { - if (type == LexemeType.Word) - throw new ArgumentException("LexEntry can not be found for the Lexeme type specified"); - - // ENHANCE: We may have to do something with the homograph number eventually, but - // currently there is no correlation between the homograph number in the DB and - // the homograph number passed from the external application. - return m_cache.ServiceLocator.GetInstance().GetHomographs(lexicalForm).FirstOrDefault( - dbEntry => LexemeTypeAndMorphTypeMatch(type, dbEntry.PrimaryMorphType)); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets the DB Wordform for the form or null if none could be found. - /// - /// ------------------------------------------------------------------------------------ - private IWfiWordform GetDbWordform(string lexicalForm) - { - IWfiWordform wf; - m_cache.ServiceLocator.GetInstance().TryGetObject( - TsStringUtils.MakeTss(lexicalForm, m_cache.DefaultVernWs), true, out wf); - return wf; - } - - /// ------------------------------------------------------------------------------------ - /// - /// Creates a new LexicalEntry from the specified lexical entry in the DB - /// - /// ------------------------------------------------------------------------------------ - private LexicalEntry CreateEntryFromDbEntry(LexemeType type, ILexEntry dbEntry) - { - if (type == LexemeType.Word) - throw new ArgumentException("Lexeme type specified can not be created from a LexEntry"); - - // A homograph number of zero in the DB means there is only one entry for the wordform. - // However, the interface requires there be an entry with a homograph of one even if - // there is only one entry. - LexicalEntry entry = new LexicalEntry(type, dbEntry.HomographForm, - dbEntry.HomographNumber > 0 ? dbEntry.HomographNumber : 1); - - // Add the senses to the interface (non-DB) entry - foreach (ILexSense dbSense in dbEntry.SensesOS) - { - LexSense sense = new LexSense(dbSense.Guid.ToString()); - AddDbGlossesToSense(sense, dbSense.Gloss); - entry.Senses.Add(sense); // Add the sense to the list of senses - } - return entry; - } - - /// ------------------------------------------------------------------------------------ - /// - /// Creates a new LexicalEntry from the specified word form in the DB - /// - /// ------------------------------------------------------------------------------------ - private LexicalEntry CreateEntryFromDbWordform(IWfiWordform wordform) - { - const int homograph = 1; - LexicalEntry entry = new LexicalEntry(LexemeType.Word, wordform.Form.VernacularDefaultWritingSystem.Text, homograph); - foreach (IWfiAnalysis dbAnalysis in wordform.AnalysesOC) - { - // Since our "sense" is really an analysis for a wordform, assume that any meanings - // for that analysis are glosses for the same "sense". - LexSense sense = new LexSense(kAnalysisPrefix + dbAnalysis.Guid.ToString()); - foreach (IWfiGloss gloss in dbAnalysis.MeaningsOC) - AddDbGlossesToSense(sense, gloss.Form); - entry.Senses.Add(sense); - } - return entry; - } - - /// ------------------------------------------------------------------------------------ - /// - /// Adds the glosses in all available writing systems to the specified sense. - /// - /// ------------------------------------------------------------------------------------ - private void AddDbGlossesToSense(LexSense sense, IMultiUnicode glosses) - { - for (int i = 0; i < glosses.StringCount; i++) - { - int ws; - ITsString tssGloss = glosses.GetStringFromIndex(i, out ws); - string icuLocale = m_cache.WritingSystemFactory.GetStrFromWs(ws); - sense.Glosses.Add(new LexGloss(icuLocale, tssGloss.Text)); - } - } - - /// ------------------------------------------------------------------------------------ - /// - /// Removes the sense with the specified ID and guid from the DB. - /// - /// ------------------------------------------------------------------------------------ - private void RemoveSense(string senseId, Guid guid) - { - if (senseId.StartsWith(kAnalysisPrefix)) - { - IWfiAnalysis dbAnalysis = m_cache.ServiceLocator.GetInstance().GetObject(guid); - IWfiWordform dbWordform = (IWfiWordform)dbAnalysis.Owner; - dbWordform.AnalysesOC.Remove(dbAnalysis); - } - else - { - ILexSense dbSense = m_cache.ServiceLocator.GetInstance().GetObject(guid); - ILexEntry dbEntry = (ILexEntry)dbSense.Owner; - - // Make sure we keep at least one sense around. This seems to be required. - if (dbEntry.SensesOS.Count > 1) - dbEntry.SensesOS.Remove(dbSense); - } - } - #endregion - - #region LexemeType and MorphType matching methods - /// ------------------------------------------------------------------------------------ - /// - /// Determines if the specified lexeme type matches the specified morph type - /// - /// ------------------------------------------------------------------------------------ - private static bool LexemeTypeAndMorphTypeMatch(LexemeType type, IMoMorphType morphType) - { - if (type == LexemeType.Word || type == LexemeType.Lemma) - throw new ArgumentException("Morph type can never be of the specified lexeme type"); - - switch (type) - { - case LexemeType.Prefix: return morphType.IsPrefixishType; - case LexemeType.Suffix: return morphType.IsSuffixishType; - case LexemeType.Stem: return morphType.IsStemType && - morphType.Guid != MoMorphTypeTags.kguidMorphPhrase && - morphType.Guid != MoMorphTypeTags.kguidMorphDiscontiguousPhrase; - case LexemeType.Phrase: - return morphType.Guid == MoMorphTypeTags.kguidMorphPhrase || - morphType.Guid == MoMorphTypeTags.kguidMorphDiscontiguousPhrase; - } - return false; - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets the morph type for the specified lexeme type. - /// - /// ------------------------------------------------------------------------------------ - private IMoMorphType GetMorphTypeForLexemeType(LexemeType type) - { - if (type == LexemeType.Word || type == LexemeType.Lemma) - throw new ArgumentException("Morph type can never be of the specified lexeme type"); - - IMoMorphTypeRepository repo = m_cache.ServiceLocator.GetInstance(); - switch (type) - { - case LexemeType.Prefix: return repo.GetObject(MoMorphTypeTags.kguidMorphPrefix); - case LexemeType.Suffix: return repo.GetObject(MoMorphTypeTags.kguidMorphSuffix); - case LexemeType.Phrase: return repo.GetObject(MoMorphTypeTags.kguidMorphPhrase); - case LexemeType.Stem: return repo.GetObject(MoMorphTypeTags.kguidMorphStem); - } - return null; - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets the lexeme type that most closely represents the specified morph type. - /// - /// This method attempts to do it's best to get the correct lexeme type. - /// However, the FW database contains many more morph types then can be represented with - /// the few lexeme types. This creates some ambiguous mappings which are commented - /// inside this method body. - /// ------------------------------------------------------------------------------------ - private LexemeType GetLexemeTypeForMorphType(IMoMorphType type) - { - switch (type.Guid.ToString()) - { - case MoMorphTypeTags.kMorphCircumfix: - case MoMorphTypeTags.kMorphInfix: - case MoMorphTypeTags.kMorphInfixingInterfix: - case MoMorphTypeTags.kMorphSimulfix: - case MoMorphTypeTags.kMorphSuprafix: - case MoMorphTypeTags.kMorphClitic: - case MoMorphTypeTags.kMorphProclitic: - // These don't map neatly to a lexeme type, so we just return prefix - return LexemeType.Prefix; - - case MoMorphTypeTags.kMorphEnclitic: - // This one also isn't a great match, but there is no better choice - return LexemeType.Suffix; - - case MoMorphTypeTags.kMorphPrefix: - case MoMorphTypeTags.kMorphPrefixingInterfix: - return LexemeType.Prefix; - - case MoMorphTypeTags.kMorphSuffix: - case MoMorphTypeTags.kMorphSuffixingInterfix: - return LexemeType.Suffix; - - case MoMorphTypeTags.kMorphPhrase: - case MoMorphTypeTags.kMorphDiscontiguousPhrase: - return LexemeType.Phrase; - - case MoMorphTypeTags.kMorphStem: - case MoMorphTypeTags.kMorphRoot: - case MoMorphTypeTags.kMorphBoundRoot: - case MoMorphTypeTags.kMorphBoundStem: - case MoMorphTypeTags.kMorphParticle: - return LexemeType.Stem; - } - - // Shouldn't ever get here, but since we don't know what type it is just return - // a random default and hope for the best. - return LexemeType.Stem; - } - #endregion - } -} diff --git a/Src/Common/FieldWorks/LexicalProvider/LexicalProviderManager.cs b/Src/Common/FieldWorks/LexicalProvider/LexicalProviderManager.cs deleted file mode 100644 index 08b27a30c6..0000000000 --- a/Src/Common/FieldWorks/LexicalProvider/LexicalProviderManager.cs +++ /dev/null @@ -1,191 +0,0 @@ -// --------------------------------------------------------------------------------------------- -#region // Copyright (c) 2011, SIL International. All Rights Reserved. -// -// Copyright (c) 2011, SIL International. All Rights Reserved. -// -// Distributable under the terms of either the Common Public License or the -// GNU Lesser General Public License, as specified in the LICENSING.txt file. -// -#endregion -// -// File: LexicalProviderManager.cs -// Responsibility: FW Team -// --------------------------------------------------------------------------------------------- -using System; -using System.Collections.Generic; -using System.IO; -using System.Diagnostics.CodeAnalysis; -using System.ServiceModel; -using System.Threading; -using System.Windows.Forms; -using SIL.FieldWorks.Common.FwUtils; -using SIL.FieldWorks.FDO; -using SIL.Utils; -using Timer = System.Threading.Timer; - -namespace SIL.FieldWorks.LexicalProvider -{ - - /// ---------------------------------------------------------------------------------------- - /// - /// Manages FieldWorks's lexical service provider for access by external applications. - /// - /// ---------------------------------------------------------------------------------------- - internal static class LexicalProviderManager - { - private const int kInactivityTimeout = 1800000; // 30 minutes in msec - - private static Timer s_lexicalProviderTimer; - private static readonly Dictionary s_runningProviders = new Dictionary(); - - private static string PtCommunicationProbTitle = "Paratext Communication Problem"; - private static string PtCommunicationProb = - "The project you are opening will not communicate with Paratext because a project with the same name is " + - "already open. If you want to use Paratext with this project, make a change in this project" + - " (so that it will start first), close both projects, then restart Flex."; - - // The different URL prefixes that are required for Windows named pipes and Linux basic http binding. - #if __MonoCS__ - // Just in case port 40001 is in use for something else on a particular system, we allow the user to configure both - // programs to use a different port. - internal static string UrlPrefix = "http://127.0.0.1:" + (Environment.GetEnvironmentVariable("LEXICAL_PROVIDER_PORT") ?? "40001") + "/"; - #else - internal const string UrlPrefix = "net.pipe://localhost/"; - #endif - - // Mono requires the pipe handle to use slashes instead of colons. - // We could put this conditional code somewhere in the routines that generate the pipe handles, - // but it seemed cleaner to keep all the conditional code for different kinds of pipe more-or-less in one place. - internal static string FixPipeHandle(string pipeHandle) - { - #if __MonoCS__ - return pipeHandle.Replace (":", "/"); - #else - return pipeHandle; - #endif - } - - /// ------------------------------------------------------------------------------------ - /// - /// Creates a LexicalServiceProvider listener for the specified project. - /// - /// ------------------------------------------------------------------------------------ - internal static void StartLexicalServiceProvider(ProjectId projectId, FdoCache cache) - { - if (projectId == null) - throw new InvalidOperationException("Project identity must be known before creating the lexical provider listener"); - var url = UrlPrefix + FixPipeHandle(projectId.PipeHandle); - StartProvider(new Uri(url), - new LexicalServiceProvider(cache), typeof(ILexicalServiceProvider)); - - s_lexicalProviderTimer = new Timer(s_timeSinceLexicalProviderUsed_Tick, null, - kInactivityTimeout, Timeout.Infinite); - Logger.WriteEvent("Started listening for lexical service provider requests."); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Starts the provider. - /// - /// The provider location. - /// The provider. - /// Type of the provider. - /// ------------------------------------------------------------------------------------ - [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", - Justification="See review comment")] - [SuppressMessage("Gendarme.Rules.Portability", "MonoCompatibilityReviewRule", - Justification="See TODO-Linux comment")] - internal static void StartProvider(Uri providerLocation, object provider, Type providerType) - { - if (s_runningProviders.ContainsKey(providerType)) - return; - - string sNamedPipe = providerLocation.ToString(); - // REVIEW: we don't dispose ServiceHost. It might be better to add it to the - // SingletonsContainer - ServiceHost providerHost = null; - try - { - providerHost = new ServiceHost(provider); - // Named pipes are better for Windows...don't tie up a dedicated port and perform better. - // However, Mono does not yet support them, so on Mono we use a different binding. - // Note that any attempt to unify these will require parallel changes in Paratext - // and some sort of coordinated release of the new versions. -#if __MonoCS__ - BasicHttpBinding binding = new BasicHttpBinding(); -#else - NetNamedPipeBinding binding = new NetNamedPipeBinding(); - binding.Security.Mode = NetNamedPipeSecurityMode.None; -#endif - binding.MaxBufferSize *= 4; - binding.MaxReceivedMessageSize *= 4; - binding.MaxBufferPoolSize *= 2; - binding.ReaderQuotas.MaxBytesPerRead *= 4; - binding.ReaderQuotas.MaxArrayLength *= 4; - binding.ReaderQuotas.MaxDepth *= 4; - binding.ReaderQuotas.MaxNameTableCharCount *= 4; - binding.ReaderQuotas.MaxStringContentLength *= 4; - - providerHost.AddServiceEndpoint(providerType, binding, sNamedPipe); - providerHost.Open(); - } - catch (Exception e) - { - Logger.WriteError(e); - providerHost = null; - var paratextInstalled = FwRegistryHelper.Paratext7orLaterInstalled(); - if (paratextInstalled) - { - MessageBox.Show(PtCommunicationProb, PtCommunicationProbTitle, - MessageBoxButtons.OK, MessageBoxIcon.Information); - } - return; - } - Logger.WriteEvent("Started provider " + providerLocation + " for type " + providerType + "."); - s_runningProviders.Add(providerType, providerHost); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Resets the lexical provider timer. - /// - /// ------------------------------------------------------------------------------------ - internal static void ResetLexicalProviderTimer() - { - s_lexicalProviderTimer.Change(kInactivityTimeout, Timeout.Infinite); - FieldWorks.InAppServerMode = true; - } - - /// ------------------------------------------------------------------------------------ - /// - /// Releases unmanaged and - optionally - managed resources - /// - /// ------------------------------------------------------------------------------------ - internal static void StaticDispose() - { - Logger.WriteEvent("Closing service hosts"); - - if (s_lexicalProviderTimer != null) - s_lexicalProviderTimer.Dispose(); - s_lexicalProviderTimer = null; - - foreach (ServiceHost host in s_runningProviders.Values) - host.Close(); - s_runningProviders.Clear(); - FieldWorks.InAppServerMode = false; // Make sure FW can shut down - } - - /// ------------------------------------------------------------------------------------ - /// - /// Handles the Tick event of the s_timeSinceLexicalProviderUsed control. - /// - /// The source of the event. - /// ------------------------------------------------------------------------------------ - private static void s_timeSinceLexicalProviderUsed_Tick(object sender) - { - FieldWorks.InAppServerMode = false; - if (FieldWorks.ProcessCanBeAutoShutDown) - FieldWorks.GracefullyShutDown(); - } - } -} diff --git a/Src/Common/FieldWorks/LexicalProvider/LexicalServiceProvider.cs b/Src/Common/FieldWorks/LexicalProvider/LexicalServiceProvider.cs deleted file mode 100644 index e42b2d0938..0000000000 --- a/Src/Common/FieldWorks/LexicalProvider/LexicalServiceProvider.cs +++ /dev/null @@ -1,102 +0,0 @@ -// --------------------------------------------------------------------------------------------- -#region // Copyright (c) 2011, SIL International. All Rights Reserved. -// -// Copyright (c) 2011, SIL International. All Rights Reserved. -// -// Distributable under the terms of either the Common Public License or the -// GNU Lesser General Public License, as specified in the LICENSING.txt file. -// -#endregion -// -// File: LexicalServiceProvider.cs -// Responsibility: FW Team -// --------------------------------------------------------------------------------------------- -using System; -using System.Diagnostics.CodeAnalysis; -using System.ServiceModel; -using SIL.FieldWorks.Common.FwUtils; -using SIL.FieldWorks.FDO; - -namespace SIL.FieldWorks.LexicalProvider -{ - /// ---------------------------------------------------------------------------------------- - /// - /// Provides a service contract for getting a lexical provider from an application. - /// - /// ---------------------------------------------------------------------------------------- - [ServiceBehavior(IncludeExceptionDetailInFaults = true, - InstanceContextMode = InstanceContextMode.Single, - MaxItemsInObjectGraph = 2147483647)] - [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", - Justification="m_cache is a reference")] - public sealed class LexicalServiceProvider : ILexicalServiceProvider - { - /// String representing the type of the LexicalProvider - public const string kLexicalProviderType = "LexicalProvider"; - private const int kSupportedLexicalProviderVersion = 3; - - private FdoCache m_cache; - - /// ------------------------------------------------------------------------------------ - /// - /// Initializes a new instance of the class. - /// - /// ------------------------------------------------------------------------------------ - public LexicalServiceProvider(FdoCache cache) - { - m_cache = cache; - } - - #region ILexicalServiceProvider Members - /// ------------------------------------------------------------------------------------ - /// - /// Gets the location for the provider for the specified project and provider type. - /// If the providerType is not supported, return null for the Uri. - /// - /// ------------------------------------------------------------------------------------ - public Uri GetProviderLocation(string projhandle, string providerType) - { - LexicalProviderManager.ResetLexicalProviderTimer(); - - if (providerType == kLexicalProviderType) - { - var url = LexicalProviderManager.UrlPrefix + LexicalProviderManager.FixPipeHandle(FwUtils.GeneratePipeHandle(projhandle + ":LP")); - Uri projUri = new Uri(url); - LexicalProviderManager.StartProvider(projUri, new LexicalProviderImpl(m_cache), typeof(ILexicalProvider)); - return projUri; - } - - return null; - } - - /// ------------------------------------------------------------------------------------ - /// - /// Gets the version of the specified provider that the server supports. If the - /// providerType is not supported, return 0 for the version. - /// - /// ------------------------------------------------------------------------------------ - public int GetSupportedVersion(string providerType) - { - LexicalProviderManager.ResetLexicalProviderTimer(); - if (providerType == kLexicalProviderType) - return kSupportedLexicalProviderVersion; - return 0; - } - - /// ------------------------------------------------------------------------------------ - /// - /// Unlike a normal ping method that gets a response, we just use this ping method - /// to determine if the service provider is actually valid since no exception is - /// thrown until a method is called. - /// - /// ------------------------------------------------------------------------------------ - public void Ping() - { - // Nothing to do for this method except reset our timer for the life of the LexicalProvider. - // See comment for this method. - LexicalProviderManager.ResetLexicalProviderTimer(); - } - - #endregion - } -} diff --git a/Src/FdoUi/LexEntryUi.cs b/Src/FdoUi/LexEntryUi.cs index 106c52a528..929ca5b739 100644 --- a/Src/FdoUi/LexEntryUi.cs +++ b/Src/FdoUi/LexEntryUi.cs @@ -304,13 +304,6 @@ internal static void DisplayEntry(FdoCache cache, IWin32Window owner, Mediator m } } - // Currently only called from WCF (11/21/2013 - AP) - public static void DisplayEntry(FdoCache cache, Mediator mediatorIn, - IHelpTopicProvider helpProvider, string helpFileKey, ITsString tssWfIn, IWfiAnalysis wfa) - { - DisplayEntries(cache, null, mediatorIn, helpProvider, helpFileKey, tssWfIn, wfa); - } - internal static void DisplayEntries(FdoCache cache, IWin32Window owner, Mediator mediatorIn, IHelpTopicProvider helpProvider, string helpFileKey, ITsString tssWfIn, IWfiAnalysis wfa) { @@ -471,63 +464,6 @@ private static void EnsureWindowConfiguration(Mediator mediator) } } - // Currently only called from WCF (11/21/2013 - AP) - public static void DisplayRelatedEntries(FdoCache cache, Mediator mediatorIn, - IHelpTopicProvider helpProvider, string helpFileKey, ITsString tss) - { - DisplayRelatedEntries(cache, null, mediatorIn, helpProvider, helpFileKey, tss, true); - } - - /// ------------------------------------------------------------ - /// - /// Assuming the selection can be expanded to a word and a corresponding LexEntry can - /// be found, show the related words dialog with the words related to the selected one. - /// - /// The cache. - /// The owning window. - /// The mediator. - /// The help provider. - /// The help file key. - /// The ITsString for the word form. - /// - /// ------------------------------------------------------------ - // Currently only called from WCF (11/21/2013 - AP) - public static void DisplayRelatedEntries(FdoCache cache, IWin32Window owner, - Mediator mediatorIn, IHelpTopicProvider helpProvider, string helpFileKey, ITsString tssWf, - bool hideInsertButton) - { - if (tssWf == null || tssWf.Length == 0) - return; - - using (LexEntryUi leui = FindEntryForWordform(cache, tssWf)) - { - // This doesn't work as well (unless we do a commit) because it may not see current typing. - //LexEntryUi leui = LexEntryUi.FindEntryForWordform(cache, hvo, tag, ichMin, ichLim); - if (leui == null) - { - RelatedWords.ShowNotInDictMessage(owner); - return; - } - int hvoEntry = leui.Object.Hvo; - int[] domains; - int[] lexrels; - IVwCacheDa cdaTemp; - if (!RelatedWords.LoadDomainAndRelationInfo(cache, hvoEntry, out domains, out lexrels, out cdaTemp, owner)) - return; - StringTable stOrig; - Mediator mediator; - IVwStylesheet styleSheet; - bool fRestore = EnsureFlexTypeSetup(cache, mediatorIn, out stOrig, out mediator, out styleSheet); - using (RelatedWords rw = new RelatedWords(cache, null, hvoEntry, domains, lexrels, cdaTemp, styleSheet, - mediatorIn, hideInsertButton)) - { - rw.ShowDialog(owner); - } - if (fRestore) - mediator.StringTbl = stOrig; - } - } - /// ------------------------------------------------------------------------------------ /// /// Assuming the selection can be expanded to a word and a corresponding LexEntry can From c554ba56956b4cc06b400cef66f2a81c4bfe658d Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Wed, 15 Jan 2014 15:34:00 +0700 Subject: [PATCH 051/143] made PartOfSpeechForWsTSS method in MoMorphSynAnalysis public Change-Id: Ic58df3c733ff6838080564b844d024dfbfef0045 --- Src/FDO/FdoInterfaceAdditions.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Src/FDO/FdoInterfaceAdditions.cs b/Src/FDO/FdoInterfaceAdditions.cs index 4418c075b1..648e19135f 100644 --- a/Src/FDO/FdoInterfaceAdditions.cs +++ b/Src/FDO/FdoInterfaceAdditions.cs @@ -1522,6 +1522,13 @@ string LongNameAdHoc /// /// IMoMorphSynAnalysis UpdateOrReplace(SandboxGenericMSA sandboxMsa); + + /// + /// + /// + /// The ws. + /// + ITsString PartOfSpeechForWsTSS(int ws); } /// From 3b6f92e684c79bd09d562e7ff18a0ee677e3b65d Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 17 Jan 2014 17:12:59 +0700 Subject: [PATCH 052/143] refactored StringSearcher to be more generic and moved it to CoreImpl Change-Id: I864ebcdab3565f60fd960e71ef1f58dc21f2ab5a --- Src/Common/COMInterfaces/IcuWrappers.cs | 112 +++++++++--- .../DetailControls/PossibilityAutoComplete.cs | 2 +- .../Controls/XMLViews/ConfiguredExport.cs | 18 +- Src/Common/Controls/XMLViews/XmlVc.cs | 44 ++--- Src/Common/CoreImpl/CoreImpl.csproj | 1 + .../CoreImplTests/CoreImplTests.csproj | 1 + .../CoreImplTests}/StringSearcherTests.cs | 12 +- .../{FwUtils => CoreImpl}/StringSearcher.cs | 168 +++++++++++------- Src/Common/CoreImpl/gendarme-CoreImpl.ignore | 2 + .../Program.cs | 6 + Src/Common/FwUtils/FwUtils.csproj | 1 - .../FwUtils/FwUtilsTests/FwUtilsTests.csproj | 1 - Src/Common/FwUtils/gendarme-FwUtils.ignore | 5 - Src/ManagedLgIcuCollator/LgIcuCollator.cs | 92 +--------- 14 files changed, 242 insertions(+), 223 deletions(-) rename Src/Common/{FwUtils/FwUtilsTests => CoreImpl/CoreImplTests}/StringSearcherTests.cs (94%) rename Src/Common/{FwUtils => CoreImpl}/StringSearcher.cs (57%) diff --git a/Src/Common/COMInterfaces/IcuWrappers.cs b/Src/Common/COMInterfaces/IcuWrappers.cs index c38fe7823f..cc8fd4b466 100644 --- a/Src/Common/COMInterfaces/IcuWrappers.cs +++ b/Src/Common/COMInterfaces/IcuWrappers.cs @@ -1272,15 +1272,20 @@ private static extern int uloc_getName(string localeID, IntPtr name, /// /// Gets the name of the locale (e.g. en_US). /// - public static int GetName(string localeID, out string localeName, out UErrorCode err) + public static string GetName(string localeID) { + if (string.IsNullOrEmpty(localeID)) + return string.Empty; + const int nSize = 255; IntPtr resPtr = Marshal.AllocCoTaskMem(nSize); try { + UErrorCode err; int nResult = uloc_getName(localeID, resPtr, nSize, out err); - localeName = Marshal.PtrToStringAnsi(resPtr); - return nResult; + if (err > UErrorCode.U_ZERO_ERROR) + throw new Exception("uloc_getName failed with code " + err); + return Marshal.PtrToStringAnsi(resPtr); } finally { @@ -1366,13 +1371,17 @@ private static extern IntPtr ucol_open( out UErrorCode err); /// - public static IntPtr ucol_Open(byte[] loc, out UErrorCode err) + public static IntPtr OpenCollator(string locale) { - return ucol_open(loc, out err); + UErrorCode err; + IntPtr collator = ucol_open(string.IsNullOrEmpty(locale) ? null : Encoding.UTF8.GetBytes(locale), out err); + if (err > UErrorCode.U_ZERO_ERROR) + throw new Exception("ucol_open failed with code " + err); + return collator; } /// - public static void ucol_Close(IntPtr collator) + public static void CloseCollator(IntPtr collator) { ucol_close(collator); } @@ -1385,9 +1394,25 @@ public static void ucol_Close(IntPtr collator) private static extern int ucol_getSortKey(IntPtr col1, string source, int sourceLength, byte[] result, int resultLength); /// - public static int ucol_GetSortKey(IntPtr col1, string source, int sourceLength, ref byte[] result, int resultLength) + public static byte[] GetSortKey(IntPtr collator, string source) { - return ucol_getSortKey(col1, source, sourceLength, result, resultLength); + const int keyLength = 1024; + var key = new byte[keyLength + 1]; + var len = ucol_getSortKey(collator, source, source.Length, key, keyLength); + if (len > keyLength) + { + key = new byte[len + 1]; + len = ucol_getSortKey(collator, source, source.Length, key, len); + } + // Ensure that the byte array is truncated to its actual data length. + Debug.Assert(len <= key.Length); + if (len < key.Length) + { + var result = new byte[len]; + Array.Copy(key, result, len); + return result; + } + return key; } @@ -1437,14 +1462,63 @@ private static extern IntPtr ucol_openRules(string rules, int rulesLength, UColA /// ------------------------------------------------------------------------------------ public class CollationRuleErrorInfo { + internal CollationRuleErrorInfo(UParseError parseError) + { + Line = parseError.line + 1; + Offset = parseError.offset + 1; + PreContext = parseError.preContext; + PostContext = parseError.postContext; + } + /// Line number (1-based) containing the error - public int Line; + public int Line { get; private set; } /// Character offset (1-based) on Line where the error was detected - public int Offset; + public int Offset { get; private set; } /// Characters preceding the the error - public String PreContext; + public String PreContext { get; private set; } /// Characters following the the error - public String PostContext; + public String PostContext { get; private set; } + } + + /// + /// Collation rule exception + /// + public class CollationRuleException : Exception + { + private readonly CollationRuleErrorInfo m_errorInfo; + + /// + /// Initializes a new instance of the class. + /// + /// The error information. + public CollationRuleException(CollationRuleErrorInfo errorInfo) + { + m_errorInfo = errorInfo; + } + + /// + /// Gets the parse error information. + /// + public CollationRuleErrorInfo ErrorInfo + { + get { return m_errorInfo; } + } + } + + /// + /// Opens the specified collation rules as a collator. + /// + /// The rules. + /// + public static IntPtr OpenRuleBasedCollator(string rules) + { + UErrorCode err; + UParseError parseError; + IntPtr collator = ucol_openRules(rules, rules.Length, UColAttributeValue.UCOL_DEFAULT, + UColAttributeValue.UCOL_DEFAULT_STRENGTH, out parseError, out err); + if (err <= UErrorCode.U_ZERO_ERROR) + return collator; + throw new CollationRuleException(new CollationRuleErrorInfo(parseError)); } /// ------------------------------------------------------------------------------------ @@ -1468,13 +1542,7 @@ public static CollationRuleErrorInfo CheckRules(string rules) if (err == UErrorCode.U_ZERO_ERROR) return null; - return new CollationRuleErrorInfo - { - Line = parseError.line + 1, - Offset = parseError.offset + 1, - PreContext = parseError.preContext, - PostContext = parseError.postContext - }; + return new CollationRuleErrorInfo(parseError); } finally { @@ -1552,13 +1620,13 @@ public static void GetSortKeyBound(byte[] sortKey, UColBoundMode boundType, ref UErrorCode err; int size = ucol_getBound(sortKey, sortKey.Length, boundType, 1, result, result.Length, out err); if (err > 0 && err != UErrorCode.U_BUFFER_OVERFLOW_ERROR) - throw new Exception("Icu.GetSortKeyBound() failed with code " + err); + throw new Exception("ucol_getBound failed with code " + err); if (size > result.Length) { result = new byte[size + 1]; ucol_getBound(sortKey, sortKey.Length, boundType, 1, result, result.Length, out err); if (err > 0) - throw new Exception("Icu.GetSortKeyBound() failed with code " + err); + throw new Exception("ucol_getBound failed with code " + err); } } @@ -1874,7 +1942,7 @@ public static IEnumerable Split(UBreakIteratorType type, string locale, UErrorCode err; IntPtr bi = ubrk_open(type, locale, text, text.Length, out err); if (err > 0) - throw new Exception("Icu.Split() failed with code " + err); + throw new Exception("ubrk_open failed with code " + err); var tokens = new List(); int cur = ubrk_first(bi); while (cur != UBRK_DONE) diff --git a/Src/Common/Controls/DetailControls/PossibilityAutoComplete.cs b/Src/Common/Controls/DetailControls/PossibilityAutoComplete.cs index d52f6505e4..644e8e28c7 100644 --- a/Src/Common/Controls/DetailControls/PossibilityAutoComplete.cs +++ b/Src/Common/Controls/DetailControls/PossibilityAutoComplete.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; using System.Linq; using System.Windows.Forms; +using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.Common.Controls; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Common.Widgets; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices; diff --git a/Src/Common/Controls/XMLViews/ConfiguredExport.cs b/Src/Common/Controls/XMLViews/ConfiguredExport.cs index ad7e224679..8d60eec7b7 100644 --- a/Src/Common/Controls/XMLViews/ConfiguredExport.cs +++ b/Src/Common/Controls/XMLViews/ConfiguredExport.cs @@ -646,14 +646,20 @@ private string GetLeadChar(string sEntryNFD, string sWs) } } // We don't want sFirst for an ignored first character or digraph. - var loc = Encoding.UTF8.GetBytes(sWs); - Icu.UErrorCode err; - var col = Icu.ucol_Open(loc, out err); - if ((int)err > (int)Icu.UErrorCode.U_ZERO_ERROR) + + IntPtr col; + try + { + string icuLocale = Icu.GetName(sWs); + col = Icu.OpenCollator(icuLocale); + } + catch (Exception) + { return sFirst; + } try { - var ka = CmObjectComparer.GetSortKey(col, sFirst); + byte[] ka = Icu.GetSortKey(col, sFirst); if (ka.Length > 0 && ka[0] == 1) { string sT = sEntry.Substring(sFirst.Length); @@ -662,7 +668,7 @@ private string GetLeadChar(string sEntryNFD, string sWs) } finally { - Icu.ucol_Close(col); + Icu.CloseCollator(col); } return sFirst; } diff --git a/Src/Common/Controls/XMLViews/XmlVc.cs b/Src/Common/Controls/XMLViews/XmlVc.cs index d56a276628..1e58b2d6f6 100644 --- a/Src/Common/Controls/XMLViews/XmlVc.cs +++ b/Src/Common/Controls/XMLViews/XmlVc.cs @@ -187,7 +187,7 @@ public class XmlVc : FwBaseVc // This is the new constructor, where we find parts in the master inventory. /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The string table. /// Name of the root layout. @@ -205,7 +205,7 @@ public XmlVc(StringTable stringTable, string rootLayoutName, bool fEditable, // This is a variant which can take a condition element to control which items in a list display. /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The string table. /// Name of the root layout. @@ -229,7 +229,7 @@ public XmlVc(StringTable stringTable, string rootLayoutName, bool fEditable, /// /// This is another new constructor, for using the new approach without a single /// top-level layout name, such as browse view. - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The string table. /// ------------------------------------------------------------------------------------ @@ -4957,7 +4957,7 @@ public class NodeDisplayCommand : DisplayCommand /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The node. /// ------------------------------------------------------------------------------------ @@ -5037,7 +5037,7 @@ public class NodeChildrenDisplayCommand : NodeDisplayCommand { /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The node. /// ------------------------------------------------------------------------------------ @@ -5663,7 +5663,7 @@ public class PropWs { /// ------------------------------------------------------------------------------------ /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The xflid. /// The XWS. @@ -5740,12 +5740,12 @@ public int Compare(int x, int y) string ws = xobj.SortKeyWs; if (string.IsNullOrEmpty(ws)) ws = yobj.SortKeyWs; - Icu.UErrorCode err; - m_col = Icu.ucol_Open(Encoding.UTF8.GetBytes(ws), out err); + string icuLocale = Icu.GetName(ws); + m_col = Icu.OpenCollator(icuLocale); } - byte[] xkey = GetSortKey(m_col, xkeyStr); - byte[] ykey = GetSortKey(m_col, ykeyStr); + byte[] xkey = Icu.GetSortKey(m_col, xkeyStr); + byte[] ykey = Icu.GetSortKey(m_col, ykeyStr); // Simulate strcmp on the two NUL-terminated byte strings. // This avoids marshalling back and forth. // JohnT: but apparently the strings are not null-terminated if the input was empty. @@ -5775,33 +5775,11 @@ public int Compare(int x, int y) return nVal; } - internal static byte[] GetSortKey(IntPtr collater, string keyStr) - { - const int keyLength = 1024; - var key = new byte[keyLength+1]; - var len = Icu.ucol_GetSortKey(collater, keyStr, keyStr.Length, ref key, keyLength); - if (len > keyLength) - { - key = new byte[len + 1]; - len = Icu.ucol_GetSortKey(collater, keyStr, keyStr.Length, ref key, len); - } - // Ensure that the byte array is truncated to its actual data length. - Debug.Assert(len <= key.Length); - if (len < key.Length) - { - var result = new byte[len]; - for (int i = 0; i < len; ++i) - result[i] = key[i]; - return result; - } - return key; - } - protected override void DisposeUnmanagedResources() { if (m_col != IntPtr.Zero) { - Icu.ucol_Close(m_col); + Icu.CloseCollator(m_col); m_col = IntPtr.Zero; } } diff --git a/Src/Common/CoreImpl/CoreImpl.csproj b/Src/Common/CoreImpl/CoreImpl.csproj index 67368ec091..eb3f4caaf5 100644 --- a/Src/Common/CoreImpl/CoreImpl.csproj +++ b/Src/Common/CoreImpl/CoreImpl.csproj @@ -101,6 +101,7 @@ + diff --git a/Src/Common/CoreImpl/CoreImplTests/CoreImplTests.csproj b/Src/Common/CoreImpl/CoreImplTests/CoreImplTests.csproj index ba03fa5fc3..ae2a29e712 100644 --- a/Src/Common/CoreImpl/CoreImplTests/CoreImplTests.csproj +++ b/Src/Common/CoreImpl/CoreImplTests/CoreImplTests.csproj @@ -118,6 +118,7 @@ + diff --git a/Src/Common/FwUtils/FwUtilsTests/StringSearcherTests.cs b/Src/Common/CoreImpl/CoreImplTests/StringSearcherTests.cs similarity index 94% rename from Src/Common/FwUtils/FwUtilsTests/StringSearcherTests.cs rename to Src/Common/CoreImpl/CoreImplTests/StringSearcherTests.cs index 216450f465..f995d16e0e 100644 --- a/Src/Common/FwUtils/FwUtilsTests/StringSearcherTests.cs +++ b/Src/Common/CoreImpl/CoreImplTests/StringSearcherTests.cs @@ -1,16 +1,14 @@ -using System.Linq; +using System.Linq; using NUnit.Framework; -using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Test.TestUtils; -namespace SIL.FieldWorks.Common.FwUtils +namespace SIL.CoreImpl { /// /// StringSearcher tests /// [TestFixture] - public class StringSearcherTests: BaseTest + public class StringSearcherTests { private IWritingSystemManager m_wsManager; private int m_enWs; @@ -21,10 +19,8 @@ public class StringSearcherTests: BaseTest /// Setup the test fixture. /// [TestFixtureSetUp] - public override void FixtureSetup() + public void FixtureSetup() { - base.FixtureSetup(); - m_wsManager = new PalasoWritingSystemManager(); IWritingSystem enWs; m_wsManager.GetOrSet("en", out enWs); diff --git a/Src/Common/FwUtils/StringSearcher.cs b/Src/Common/CoreImpl/StringSearcher.cs similarity index 57% rename from Src/Common/FwUtils/StringSearcher.cs rename to Src/Common/CoreImpl/StringSearcher.cs index 9311a3afdf..fefdb9f74e 100644 --- a/Src/Common/FwUtils/StringSearcher.cs +++ b/Src/Common/CoreImpl/StringSearcher.cs @@ -2,12 +2,10 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using Palaso.WritingSystems.Collation; -using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; using SIL.Utils; -namespace SIL.FieldWorks.Common.FwUtils +namespace SIL.CoreImpl { /// /// Type of string searching. @@ -116,7 +114,8 @@ public IEnumerable GetItems(byte[] lower, byte[] upper) private readonly Dictionary, SortKeyIndex> m_indices = new Dictionary, SortKeyIndex>(); private readonly SearchType m_type; - private readonly IWritingSystemManager m_wsManager; + private readonly Func m_sortKeySelector; + private readonly Func> m_tokenizer; /// /// Initializes a new instance of the class. @@ -125,8 +124,30 @@ public IEnumerable GetItems(byte[] lower, byte[] upper) /// The writing system store. public StringSearcher(SearchType type, IWritingSystemManager wsManager) { + if (wsManager == null) + throw new ArgumentNullException("wsManager"); + m_type = type; - m_wsManager = wsManager; + m_sortKeySelector = (ws, text) => wsManager.Get(ws).Collator.GetSortKey(text).KeyData; + m_tokenizer = (ws, text) => Icu.Split(Icu.UBreakIteratorType.UBRK_WORD, wsManager.Get(ws).IcuLocale, text); + } + + /// + /// Initializes a new instance of the class. + /// + /// The type. + /// The sort key selector. + /// The text tokenizer + public StringSearcher(SearchType type, Func sortKeySelector, Func> tokenizer) + { + if (sortKeySelector == null) + throw new ArgumentNullException("sortKeySelector"); + if (type == SearchType.FullText && tokenizer == null) + throw new ArgumentNullException("tokenizer"); + + m_type = type; + m_sortKeySelector = sortKeySelector; + m_tokenizer = tokenizer; } /// @@ -136,33 +157,35 @@ public void Add(T item, int indexId, ITsString tss) { if (tss.RunCount == 1) // VERY common special case { - Add(indexId, tss.get_WritingSystemAt(0), tss.Text, item); - return; + Add(item, indexId, tss.get_WritingSystemAt(0), tss.Text); } - - foreach (Tuple wsStr in GetWsStrings(tss)) + else { - var wsId = wsStr.Item1; - var text = wsStr.Item2; - Add(indexId, wsId, text, item); + foreach (Tuple wsStr in GetWsStrings(tss)) + { + var wsId = wsStr.Item1; + var text = wsStr.Item2; + Add(item, indexId, wsId, text); + } } } - private void Add(int indexId, int wsId, string text, T item) + /// + /// Adds the specified item to an index using the specified string. + /// + public void Add(T item, int indexId, int wsId, string text) { SortKeyIndex index = GetIndex(indexId, wsId); - IWritingSystem ws = m_wsManager.Get(wsId); - ICollator collator = ws.Collator; switch (m_type) { case SearchType.Exact: case SearchType.Prefix: - index.Add(collator.GetSortKey(text).KeyData, item); + index.Add(m_sortKeySelector(wsId, text), item); break; case SearchType.FullText: - foreach (string token in Icu.Split(Icu.UBreakIteratorType.UBRK_WORD, ws.IcuLocale, text)) - index.Add(collator.GetSortKey(token).KeyData, item); + foreach (string token in m_tokenizer(wsId, text)) + index.Add(m_sortKeySelector(wsId, token), item); break; } } @@ -178,57 +201,76 @@ public IEnumerable Search(int indexId, ITsString tss) if (tss == null || string.IsNullOrEmpty(tss.Text)) return Enumerable.Empty(); - HashSet results = null; + if (tss.RunCount == 1) // VERY common special case + return Search(indexId, tss.get_WritingSystemAt(0), tss.Text); + + IEnumerable results = null; foreach (Tuple wsStr in GetWsStrings(tss)) { - SortKeyIndex index = GetIndex(indexId, wsStr.Item1); - ICollator collator = m_wsManager.Get(wsStr.Item1).Collator; - switch (m_type) - { - case SearchType.Exact: - case SearchType.Prefix: - { - byte[] sortKey = collator.GetSortKey(wsStr.Item2).KeyData; - var lower = new byte[wsStr.Item2.Length * SortKeyFactor]; - Icu.GetSortKeyBound(sortKey, Icu.UColBoundMode.UCOL_BOUND_LOWER, ref lower); - var upper = new byte[wsStr.Item2.Length * SortKeyFactor]; - Icu.GetSortKeyBound(sortKey, - m_type == SearchType.Exact - ? Icu.UColBoundMode.UCOL_BOUND_UPPER - : Icu.UColBoundMode.UCOL_BOUND_UPPER_LONG, ref upper); - IEnumerable items = index.GetItems(lower, upper); - if (results == null) - results = new HashSet(items); - else - results.IntersectWith(items); - break; - } - - case SearchType.FullText: - string locale = m_wsManager.GetStrFromWs(wsStr.Item1); - string[] tokens = Icu.Split(Icu.UBreakIteratorType.UBRK_WORD, locale, wsStr.Item2).ToArray(); - for (int i = 0; i < tokens.Length; i++) - { - byte[] sortKey = collator.GetSortKey(tokens[i]).KeyData; - var lower = new byte[tokens[i].Length*SortKeyFactor]; - Icu.GetSortKeyBound(sortKey, Icu.UColBoundMode.UCOL_BOUND_LOWER, ref lower); - var upper = new byte[tokens[i].Length*SortKeyFactor]; - Icu.GetSortKeyBound(sortKey, - i < tokens.Length - 1 - ? Icu.UColBoundMode.UCOL_BOUND_UPPER - : Icu.UColBoundMode.UCOL_BOUND_UPPER_LONG, ref upper); - IEnumerable items = index.GetItems(lower, upper); - if (results == null) - results = new HashSet(items); - else - results.IntersectWith(items); - } - break; - } + IEnumerable items = Search(indexId, wsStr.Item1, wsStr.Item2); + if (results == null) + results = items; + else + results = results.Intersect(items); } return results ?? Enumerable.Empty(); } + /// + /// Searches an index for the specified string. + /// + /// The index id. + /// The ws id. + /// The text. + /// The search results. + public IEnumerable Search(int indexId, int wsId, string text) + { + if (string.IsNullOrEmpty(text)) + return Enumerable.Empty(); + + SortKeyIndex index = GetIndex(indexId, wsId); + switch (m_type) + { + case SearchType.Exact: + case SearchType.Prefix: + { + byte[] sortKey = m_sortKeySelector(wsId, text); + var lower = new byte[text.Length * SortKeyFactor]; + Icu.GetSortKeyBound(sortKey, Icu.UColBoundMode.UCOL_BOUND_LOWER, ref lower); + var upper = new byte[text.Length * SortKeyFactor]; + Icu.GetSortKeyBound(sortKey, + m_type == SearchType.Exact + ? Icu.UColBoundMode.UCOL_BOUND_UPPER + : Icu.UColBoundMode.UCOL_BOUND_UPPER_LONG, ref upper); + + return index.GetItems(lower, upper); + } + + case SearchType.FullText: + IEnumerable results = null; + string[] tokens = m_tokenizer(wsId, text).ToArray(); + for (int i = 0; i < tokens.Length; i++) + { + byte[] sortKey = m_sortKeySelector(wsId, tokens[i]); + var lower = new byte[tokens[i].Length*SortKeyFactor]; + Icu.GetSortKeyBound(sortKey, Icu.UColBoundMode.UCOL_BOUND_LOWER, ref lower); + var upper = new byte[tokens[i].Length*SortKeyFactor]; + Icu.GetSortKeyBound(sortKey, + i < tokens.Length - 1 + ? Icu.UColBoundMode.UCOL_BOUND_UPPER + : Icu.UColBoundMode.UCOL_BOUND_UPPER_LONG, ref upper); + IEnumerable items = index.GetItems(lower, upper); + if (results == null) + results = items; + else + results = results.Intersect(items); + } + return results; + } + + return null; + } + /// /// Clears all of the indices. /// diff --git a/Src/Common/CoreImpl/gendarme-CoreImpl.ignore b/Src/Common/CoreImpl/gendarme-CoreImpl.ignore index 7b653475d4..ef6495d129 100644 --- a/Src/Common/CoreImpl/gendarme-CoreImpl.ignore +++ b/Src/Common/CoreImpl/gendarme-CoreImpl.ignore @@ -7,3 +7,5 @@ R: Gendarme.Rules.Correctness.EnsureLocalDisposalRule M: System.Collections.IEnumerator SIL.CoreImpl.KernelExtensions/*::System.Collections.IEnumerable.GetEnumerator() M: System.Collections.IEnumerator SIL.CoreImpl.KernelExtensions/*::System.Collections.IEnumerable.GetEnumerator() M: System.Collections.IEnumerator SIL.CoreImpl.TsRunPart/*::System.Collections.IEnumerable.GetEnumerator() +M: System.Collections.IEnumerator SIL.CoreImpl.StringSearcher`1/SortKeyIndex/*::System.Collections.IEnumerable.GetEnumerator() +M: System.Collections.IEnumerator SIL.CoreImpl.StringSearcher`1/*::System.Collections.IEnumerable.GetEnumerator() diff --git a/Src/Common/FwRemoteDatabaseConnectorService/Program.cs b/Src/Common/FwRemoteDatabaseConnectorService/Program.cs index 55a5a7dc5b..922ab04f87 100644 --- a/Src/Common/FwRemoteDatabaseConnectorService/Program.cs +++ b/Src/Common/FwRemoteDatabaseConnectorService/Program.cs @@ -1,4 +1,7 @@ using System.ServiceProcess; +using SIL.FieldWorks.Common.FwUtils; +using SIL.FieldWorks.FDO; +using SIL.FieldWorks.FDO.DomainServices; using SIL.Utils; namespace FwRemoteDatabaseConnectorService @@ -15,6 +18,9 @@ static void Main() // which breaks FwRemoteDatabaseConnectorService.exe. RegistryHelper.ProductName = "FieldWorks"; + ClientServerServices.SetCurrentToDb4OBackend(new SilentFdoUI(new SingleThreadedSynchronizeInvoke()), + FwDirectoryFinder.FdoDirectories, () => FwDirectoryFinder.ProjectsDirectory == FwDirectoryFinder.ProjectsDirectoryLocalMachine); + ServiceBase[] ServicesToRun; ServicesToRun = new ServiceBase[] { diff --git a/Src/Common/FwUtils/FwUtils.csproj b/Src/Common/FwUtils/FwUtils.csproj index 0be6681bc0..5d445de217 100644 --- a/Src/Common/FwUtils/FwUtils.csproj +++ b/Src/Common/FwUtils/FwUtils.csproj @@ -200,7 +200,6 @@ Code - diff --git a/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj b/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj index 75a205cbf9..69d0ee5f24 100644 --- a/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj +++ b/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj @@ -169,7 +169,6 @@ - diff --git a/Src/Common/FwUtils/gendarme-FwUtils.ignore b/Src/Common/FwUtils/gendarme-FwUtils.ignore index a226ed4aa8..0e28754d8c 100644 --- a/Src/Common/FwUtils/gendarme-FwUtils.ignore +++ b/Src/Common/FwUtils/gendarme-FwUtils.ignore @@ -1,8 +1,3 @@ # Gendarme filter file to suppress reporting of defects #----------------------------------------------------------------------------------------------- -R: Gendarme.Rules.Correctness.EnsureLocalDisposalRule - -# Reference -M: System.Collections.IEnumerator SIL.FieldWorks.Common.FwUtils.StringSearcher`1/SortKeyIndex/*::System.Collections.IEnumerable.GetEnumerator() -M: System.Collections.IEnumerator SIL.FieldWorks.Common.FwUtils.StringSearcher`1/*::System.Collections.IEnumerable.GetEnumerator() diff --git a/Src/ManagedLgIcuCollator/LgIcuCollator.cs b/Src/ManagedLgIcuCollator/LgIcuCollator.cs index f06a774b29..4d6650482c 100644 --- a/Src/ManagedLgIcuCollator/LgIcuCollator.cs +++ b/Src/ManagedLgIcuCollator/LgIcuCollator.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics; using System.Runtime.InteropServices; using SIL.FieldWorks.Common.COMInterfaces; @@ -9,7 +8,7 @@ namespace SIL.FieldWorks.Language /// /// Direct port of the C++ class LgIcuCollator /// - [Serializable()] + [Serializable] [ClassInterface(ClassInterfaceType.None)] [Guid("e771361c-ff54-4120-9525-98a0b7a9accf")] public class ManagedLgIcuCollator : ILgCollatingEngine, IDisposable @@ -20,8 +19,6 @@ public class ManagedLgIcuCollator : ILgCollatingEngine, IDisposable private string m_stuLocale; private IntPtr m_pCollator; - private const int keysize = 1024; - #endregion #region Disposable stuff @@ -56,80 +53,20 @@ protected virtual void Dispose(bool fDisposing) } #endregion - protected byte[] GetSortKey(string bstrValue, byte[] prgbKey, ref Int32 pcbKey) - { - byte[] pbKey; - Int32 crgbKey = pcbKey; - EnsureCollator(); - pcbKey = Icu.ucol_GetSortKey(m_pCollator, bstrValue, -1, ref prgbKey, prgbKey.Length); - if (pcbKey > crgbKey) - { - pbKey = null; - } - - else - { - pbKey = prgbKey; - } - - return pbKey; - } - - protected byte[] GetSortKey(string bstrValue, byte[] prgbKey, ref Int32 pcbKey, out byte[] vbKey) - { - vbKey = null; - Int32 cbKey = pcbKey; - byte[] pbKey = GetSortKey(bstrValue, prgbKey, ref cbKey); - if (cbKey > pcbKey) - { - Int32 cbKey1 = cbKey + 1; - vbKey = new byte[cbKey]; - pbKey = GetSortKey(bstrValue, vbKey, ref cbKey1); - Debug.Assert(cbKey == cbKey1, "cbKey == cbKey1"); - // As long as it fits assume OK. - Debug.Assert(cbKey1 + 1 <= vbKey.Length, "cbKey1 + 1 <= vbKey.Length"); - // pure paranoia -- it's supposed to be NUL-terminated. - vbKey[cbKey] = 0; - } - pcbKey = cbKey; - return pbKey; - } - protected void EnsureCollator() { if (m_pCollator != IntPtr.Zero) return; - // we already have one. - Icu.UErrorCode uerr = Icu.UErrorCode.U_ZERO_ERROR; - - if (m_stuLocale == String.Empty) - { - m_pCollator = Icu.ucol_Open(null, out uerr); - } - else - { - byte[] rgchLoc = new byte[128]; - Int32 cch = Icu.uloc_GetName(m_stuLocale, ref rgchLoc, rgchLoc.Length, out uerr); - Debug.Assert(cch < rgchLoc.Length, "cch < rgchLoc.Length"); - rgchLoc[cch] = 0; - if (uerr != Icu.UErrorCode.U_ZERO_ERROR) - throw new ApplicationException(string.Format("uloc_GetName returned {0}", uerr)); - - m_pCollator = Icu.ucol_Open(rgchLoc, out uerr); - } - - if (!(uerr == Icu.UErrorCode.U_ZERO_ERROR || uerr == Icu.UErrorCode.U_ERROR_WARNING_START || uerr == Icu.UErrorCode.U_USING_DEFAULT_WARNING)) - { - throw new ApplicationException(string.Format("ucol_Open returned {0}", uerr)); - } + string icuLocale = Icu.GetName(m_stuLocale); + m_pCollator = Icu.OpenCollator(icuLocale); } internal void DoneCleanup() { if (m_pCollator != IntPtr.Zero) { - Icu.ucol_Close(m_pCollator); + Icu.CloseCollator(m_pCollator); m_pCollator = IntPtr.Zero; } } @@ -137,27 +74,20 @@ internal void DoneCleanup() #region ILgCollatingEngine implementation public string get_SortKey(string bstrValue, LgCollatingOptions colopt) { - throw new System.NotImplementedException(); + throw new NotImplementedException(); } public void SortKeyRgch(string _ch, int cchIn, LgCollatingOptions colopt, int cchMaxOut, ArrayPtr _chKey, out int _cchOut) { - throw new System.NotImplementedException(); + throw new NotImplementedException(); } public int Compare(string bstrValue1, string bstrValue2, LgCollatingOptions colopt) { EnsureCollator(); - Int32 cbKey1 = keysize; - byte[] rgbKey1 = new byte[keysize + 1]; - byte[] vbKey1 = null; - byte[] pbKey1 = GetSortKey(bstrValue1, rgbKey1, ref cbKey1, out vbKey1); - - Int32 cbKey2 = keysize; - byte[] rgbKey2 = new byte[keysize + 1]; - byte[] vbKey2 = null; - byte[] pbKey2 = GetSortKey(bstrValue2, rgbKey2, ref cbKey2, out vbKey2); + byte[] pbKey1 = Icu.GetSortKey(m_pCollator, bstrValue1); + byte[] pbKey2 = Icu.GetSortKey(m_pCollator, bstrValue2); return CompareVariant(pbKey1, pbKey2, colopt); } @@ -166,11 +96,7 @@ public int Compare(string bstrValue1, string bstrValue2, LgCollatingOptions colo public object get_SortKeyVariant(string bstrValue, LgCollatingOptions colopt) { EnsureCollator(); - - Int32 cbKey = keysize; - byte[] rgbKey = new byte[keysize + 1]; - byte[] vbKey = null; - byte[] pbKey = GetSortKey(bstrValue, rgbKey, ref cbKey, out vbKey); + byte[] pbKey = Icu.GetSortKey(m_pCollator, bstrValue); return pbKey; } From 0e2828a493438ba035b478f4c82f18cd919b472e Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Mon, 20 Jan 2014 14:07:29 +0700 Subject: [PATCH 053/143] added Compare method to IcuWrappers Change-Id: I57efaed484fc67103d3b66384bb598fafdc9a7a5 --- Src/Common/COMInterfaces/IcuWrappers.cs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/Src/Common/COMInterfaces/IcuWrappers.cs b/Src/Common/COMInterfaces/IcuWrappers.cs index cc8fd4b466..dbfaaf0d4c 100644 --- a/Src/Common/COMInterfaces/IcuWrappers.cs +++ b/Src/Common/COMInterfaces/IcuWrappers.cs @@ -20,8 +20,6 @@ using System.Globalization; using System.Text; using System.Windows.Forms; -using Microsoft.Win32; - using SIL.Utils; namespace SIL.FieldWorks.Common.COMInterfaces @@ -1630,6 +1628,22 @@ public static void GetSortKeyBound(byte[] sortKey, UColBoundMode boundType, ref } } + [DllImport(kIcuinDllName, EntryPoint = "ucol_strcoll" + kIcuVersion, + CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + private static extern int ucol_strcoll(IntPtr coll, string source, int sourceLength, string target, int targetLength); + + /// + /// Compares strings using the specified collator. + /// + /// The collator. + /// The source. + /// The target. + /// + public static int Compare(IntPtr coll, string source, string target) + { + return ucol_strcoll(coll, source, source.Length, target, target.Length); + } + /// /// Convert the string to title case, using the convention of the specified locale. /// This may be null for the universal locale, or "" for a 'root' locale (whatever that means). From a53c2635b9120509504c529a23d04eab1a41c58c Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Mon, 20 Jan 2014 09:00:10 +0700 Subject: [PATCH 054/143] Remove FwUtils reference from ParserCore Change-Id: Ibf6c25702a3eb830786aba71fdcec2115d7647f2 --- .../ParserEngine/ParserCore/HCWorker.cs | 14 ++++++------- .../ParserCore/M3ToHCTransformer.cs | 8 ++------ .../ParserCore/M3ToParserTransformerBase.cs | 7 ++++--- .../ParserCore/M3ToXAmpleTransformer.cs | 20 +++++++++---------- .../ParserEngine/ParserCore/ParserCore.csproj | 4 ---- .../ParserEngine/ParserCore/Scheduler.cs | 6 +++--- Src/LexText/ParserEngine/ParserCore/Worker.cs | 4 +++- .../ParserEngine/ParserCore/XAmpleWorker.cs | 11 +++++----- Src/LexText/ParserUI/ParserConnection.cs | 3 ++- 9 files changed, 34 insertions(+), 43 deletions(-) diff --git a/Src/LexText/ParserEngine/ParserCore/HCWorker.cs b/Src/LexText/ParserEngine/ParserCore/HCWorker.cs index bbaf6d459b..e37bebbd4b 100644 --- a/Src/LexText/ParserEngine/ParserCore/HCWorker.cs +++ b/Src/LexText/ParserEngine/ParserCore/HCWorker.cs @@ -15,7 +15,6 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; -using System.Windows.Forms; using System.Xml; using System.Collections.Generic; using System.Text; @@ -26,7 +25,6 @@ using SIL.Utils; using SIL.HermitCrab; using PatrParserWrapper; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.Validation; namespace SIL.FieldWorks.WordWorks.Parser @@ -54,9 +52,9 @@ class XmlFwResolver : XmlUrlResolver { readonly Uri m_baseUri; - public XmlFwResolver() + public XmlFwResolver(string appInstallDir) { - m_baseUri = new Uri(FwDirectoryFinder.CodeDirectory + Path.DirectorySeparatorChar); + m_baseUri = new Uri(appInstallDir + Path.DirectorySeparatorChar); } public override Uri ResolveUri(Uri baseUri, string relativeUri) @@ -536,9 +534,9 @@ public override void Write(MorphException me) private PatrParser m_patr; private readonly string m_outputDirectory; - public HCParserWorker(FdoCache cache, Action taskUpdateHandler, IdleQueue idleQueue) + public HCParserWorker(FdoCache cache, Action taskUpdateHandler, IdleQueue idleQueue, string appInstallDir) : base(cache, taskUpdateHandler, idleQueue, - cache.ServiceLocator.GetInstance().GetObject(CmAgentTags.kguidAgentHermitCrabParser)) + cache.ServiceLocator.GetInstance().GetObject(CmAgentTags.kguidAgentHermitCrabParser), appInstallDir) { m_outputDirectory = Path.GetTempPath(); m_patr = new PatrParser @@ -548,7 +546,7 @@ public HCParserWorker(FdoCache cache, Action taskUpdateHandler, Idle }; m_loader = new XmlLoader { - XmlResolver = new XmlFwResolver(), + XmlResolver = new XmlFwResolver(appInstallDir), QuitOnError = false }; } @@ -644,7 +642,7 @@ protected override void LoadParser(ref XmlDocument model, XmlDocument template) } } - var transformer = new M3ToHCTransformer(m_projectName, m_taskUpdateHandler); + var transformer = new M3ToHCTransformer(m_projectName, m_taskUpdateHandler, m_appInstallDir); transformer.MakeHCFiles(ref model); m_patr.LoadGrammarFile(HcGrammarPath); diff --git a/Src/LexText/ParserEngine/ParserCore/M3ToHCTransformer.cs b/Src/LexText/ParserEngine/ParserCore/M3ToHCTransformer.cs index 97d4c8370d..f3b21dbf73 100644 --- a/Src/LexText/ParserEngine/ParserCore/M3ToHCTransformer.cs +++ b/Src/LexText/ParserEngine/ParserCore/M3ToHCTransformer.cs @@ -14,12 +14,8 @@ // -------------------------------------------------------------------------------------------- using System; using System.Xml; -using System.IO; using System.Diagnostics; -using SIL.FieldWorks.Common.FwUtils; -using SIL.Utils; - namespace SIL.FieldWorks.WordWorks.Parser { /// @@ -34,8 +30,8 @@ internal class M3ToHCTransformer : M3ToParserTransformerBase /// Initializes a new instance of the class. /// /// ----------------------------------------------------------------------------------- - public M3ToHCTransformer(string database, Action taskUpdateHandler) - : base(database, taskUpdateHandler) + public M3ToHCTransformer(string database, Action taskUpdateHandler, string appInstallDir) + : base(database, taskUpdateHandler, appInstallDir) { } diff --git a/Src/LexText/ParserEngine/ParserCore/M3ToParserTransformerBase.cs b/Src/LexText/ParserEngine/ParserCore/M3ToParserTransformerBase.cs index 830bda5f20..d74e7417f7 100644 --- a/Src/LexText/ParserEngine/ParserCore/M3ToParserTransformerBase.cs +++ b/Src/LexText/ParserEngine/ParserCore/M3ToParserTransformerBase.cs @@ -2,7 +2,6 @@ using System.Diagnostics; using System.IO; using System.Xml; -using SIL.FieldWorks.Common.FwUtils; using SIL.Utils; namespace SIL.FieldWorks.WordWorks.Parser @@ -16,16 +15,18 @@ abstract internal class M3ToParserTransformerBase protected string m_database; protected Action m_taskUpdateHandler; protected readonly TraceSwitch m_tracingSwitch = new TraceSwitch("ParserCore.TracingSwitch", "Just regular tracking", "Off"); + protected readonly string m_appInstallDir; /// ----------------------------------------------------------------------------------- /// /// Initializes a new instance of the class. /// /// ----------------------------------------------------------------------------------- - public M3ToParserTransformerBase(string database, Action taskUpdateHandler) + public M3ToParserTransformerBase(string database, Action taskUpdateHandler, string appInstallDir) { m_database = database; m_taskUpdateHandler = taskUpdateHandler; + m_appInstallDir = appInstallDir; m_outputDirectory = Path.GetTempPath(); } @@ -33,7 +34,7 @@ protected void TransformDomToFile(string transformName, XmlDocument inputDOM, st { using (task.AddSubTask(String.Format(ParserCoreStrings.ksCreatingX, outputName))) { - XmlUtils.TransformDomToFile(Path.Combine(FwDirectoryFinder.CodeDirectory + "/Language Explorer/Transforms/", transformName), + XmlUtils.TransformDomToFile(Path.Combine(m_appInstallDir + "/Language Explorer/Transforms/", transformName), inputDOM, Path.Combine(m_outputDirectory, outputName)); } } diff --git a/Src/LexText/ParserEngine/ParserCore/M3ToXAmpleTransformer.cs b/Src/LexText/ParserEngine/ParserCore/M3ToXAmpleTransformer.cs index 295f5d451e..769abacc80 100644 --- a/Src/LexText/ParserEngine/ParserCore/M3ToXAmpleTransformer.cs +++ b/Src/LexText/ParserEngine/ParserCore/M3ToXAmpleTransformer.cs @@ -18,8 +18,6 @@ using System.Xml; using System.IO; using System.Diagnostics; -using SIL.Utils; -using SIL.FieldWorks.Common.FwUtils; using SIL.WordWorks.GAFAWS.PositionAnalysis; namespace SIL.FieldWorks.WordWorks.Parser @@ -35,8 +33,8 @@ internal class M3ToXAmpleTransformer : M3ToParserTransformerBase /// Initializes a new instance of the class. /// /// ----------------------------------------------------------------------------------- - public M3ToXAmpleTransformer(string database, Action taskUpdateHandler) - : base(database, taskUpdateHandler) + public M3ToXAmpleTransformer(string database, Action taskUpdateHandler, string appInstallDir) + : base(database, taskUpdateHandler, appInstallDir) { } @@ -116,16 +114,16 @@ internal void MakeAmpleFiles(XmlDocument model) { using (var task = new TaskReport(ParserCoreStrings.ksMakingXAmpleFiles, m_taskUpdateHandler)) { - DateTime startTime = DateTime.Now; + DateTime startTime = DateTime.Now; TransformDomToFile("FxtM3ParserToXAmpleADCtl.xsl", model, m_database + "adctl.txt", task); TransformDomToFile("FxtM3ParserToToXAmpleGrammar.xsl", model, m_database + "gram.txt", task); Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "Grammar XSLTs took : " + (DateTime.Now.Ticks - startTime.Ticks)); - // TODO: Putting this here is not necessarily efficient because it happens every time - // the parser is run. It would be more efficient to run this only when the user - // is trying a word. But we need the "model" to apply this transform an it is - // available here, so we're doing this for now. - startTime = DateTime.Now; - string sName = m_database + "XAmpleWordGrammarDebugger.xsl"; + // TODO: Putting this here is not necessarily efficient because it happens every time + // the parser is run. It would be more efficient to run this only when the user + // is trying a word. But we need the "model" to apply this transform an it is + // available here, so we're doing this for now. + startTime = DateTime.Now; + string sName = m_database + "XAmpleWordGrammarDebugger.xsl"; TransformDomToFile("FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl", model, sName, task); Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "WordGrammarDebugger XSLT took : " + (DateTime.Now.Ticks - startTime.Ticks)); diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj b/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj index 53d62c2192..0e3fa0a247 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj +++ b/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj @@ -136,10 +136,6 @@ FDO ..\..\..\..\Output\Debug\FDO.dll - - False - ..\..\..\..\Output\Debug\FwUtils.dll - GAFAWSAnalysis False diff --git a/Src/LexText/ParserEngine/ParserCore/Scheduler.cs b/Src/LexText/ParserEngine/ParserCore/Scheduler.cs index 59d2c7a286..21677e6ae2 100644 --- a/Src/LexText/ParserEngine/ParserCore/Scheduler.cs +++ b/Src/LexText/ParserEngine/ParserCore/Scheduler.cs @@ -149,7 +149,7 @@ public override void DoWork() /// Initializes a new instance of the class. /// /// ----------------------------------------------------------------------------------- - public ParserScheduler(FdoCache cache, IdleQueue idleQueue) + public ParserScheduler(FdoCache cache, IdleQueue idleQueue, string appInstallDir) { if (cache == null) throw new ArgumentNullException("cache"); @@ -161,10 +161,10 @@ public ParserScheduler(FdoCache cache, IdleQueue idleQueue) { case "XAmple": - m_parserWorker = new XAmpleParserWorker(cache, HandleTaskUpdate, idleQueue); + m_parserWorker = new XAmpleParserWorker(cache, HandleTaskUpdate, idleQueue, appInstallDir); break; case "HC": - m_parserWorker = new HCParserWorker(cache, HandleTaskUpdate, idleQueue); + m_parserWorker = new HCParserWorker(cache, HandleTaskUpdate, idleQueue, appInstallDir); break; default: diff --git a/Src/LexText/ParserEngine/ParserCore/Worker.cs b/Src/LexText/ParserEngine/ParserCore/Worker.cs index ffc7827adb..ea1d880ecd 100644 --- a/Src/LexText/ParserEngine/ParserCore/Worker.cs +++ b/Src/LexText/ParserEngine/ParserCore/Worker.cs @@ -55,6 +55,7 @@ public abstract class ParserWorker : FwDisposableBase { protected readonly FdoCache m_cache; protected readonly Action m_taskUpdateHandler; + protected readonly string m_appInstallDir; private readonly ParseFiler m_parseFiler; private long m_ticksParser; private int m_numberOfWordForms; @@ -68,10 +69,11 @@ public abstract class ParserWorker : FwDisposableBase /// Initializes a new instance of the class. /// /// ----------------------------------------------------------------------------------- - protected ParserWorker(FdoCache cache, Action taskUpdateHandler, IdleQueue idleQueue, ICmAgent agent) + protected ParserWorker(FdoCache cache, Action taskUpdateHandler, IdleQueue idleQueue, ICmAgent agent, string appInstallDir) { m_cache = cache; m_taskUpdateHandler = taskUpdateHandler; + m_appInstallDir = appInstallDir; m_parseFiler = new ParseFiler(cache, taskUpdateHandler, idleQueue, agent); // N.B. m_projectName here is only used to create temporary files for the parser to load. // We convert the name to use strictly ANSI characters so that the parsers (which are or involve diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleWorker.cs b/Src/LexText/ParserEngine/ParserCore/XAmpleWorker.cs index 93dde7e1d2..e6d9a71b6c 100644 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleWorker.cs +++ b/Src/LexText/ParserEngine/ParserCore/XAmpleWorker.cs @@ -19,7 +19,6 @@ using SIL.FieldWorks.FDO; using SIL.Utils; using XAmpleManagedWrapper; -using SIL.FieldWorks.Common.FwUtils; namespace SIL.FieldWorks.WordWorks.Parser { @@ -27,12 +26,12 @@ public class XAmpleParserWorker : ParserWorker { private XAmpleWrapper m_xample; - public XAmpleParserWorker(FdoCache cache, Action taskUpdateHandler, IdleQueue idleQueue) + public XAmpleParserWorker(FdoCache cache, Action taskUpdateHandler, IdleQueue idleQueue, string appInstallDir) : base(cache, taskUpdateHandler, idleQueue, - cache.ServiceLocator.GetInstance().GetObject(CmAgentTags.kguidAgentXAmpleParser)) + cache.ServiceLocator.GetInstance().GetObject(CmAgentTags.kguidAgentXAmpleParser), appInstallDir) { m_xample = new XAmpleWrapper(); - m_xample.Init(FwDirectoryFinder.CodeDirectory); + m_xample.Init(appInstallDir); } protected override string ParseWord(string form, int hvoWordform) @@ -80,7 +79,7 @@ private static string CompleteAmpleResults(string rawAmpleResults, int hvoWordfo /// The template. protected override void LoadParser(ref XmlDocument model, XmlDocument template) { - var transformer = new M3ToXAmpleTransformer(m_projectName, m_taskUpdateHandler); + var transformer = new M3ToXAmpleTransformer(m_projectName, m_taskUpdateHandler, m_appInstallDir); var startTime = DateTime.Now; // PrepareTemplatesForXAmpleFiles adds orderclass elements to MoInflAffixSlot elements transformer.PrepareTemplatesForXAmpleFiles(ref model, template); @@ -101,7 +100,7 @@ protected override void LoadParser(ref XmlDocument model, XmlDocument template) m_xample.SetParameter("MaxAnalysesToReturn", maxAnalCount.ToString()); string tempPath = Path.GetTempPath(); - m_xample.LoadFiles(FwDirectoryFinder.CodeDirectory + @"/Language Explorer/Configuration/Grammar", + m_xample.LoadFiles(m_appInstallDir + @"/Language Explorer/Configuration/Grammar", tempPath, m_projectName); } diff --git a/Src/LexText/ParserUI/ParserConnection.cs b/Src/LexText/ParserUI/ParserConnection.cs index 36bf535d7e..2d93617e44 100644 --- a/Src/LexText/ParserUI/ParserConnection.cs +++ b/Src/LexText/ParserUI/ParserConnection.cs @@ -14,6 +14,7 @@ using System; using System.Collections.Generic; using System.Threading; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.WordWorks.Parser; using SIL.Utils; @@ -41,7 +42,7 @@ public sealed class ParserConnection : FwDisposableBase, IAsyncResult public ParserConnection(FdoCache cache, IdleQueue idleQueue) { m_activity = ""; - m_scheduler = new ParserScheduler(cache, idleQueue); + m_scheduler = new ParserScheduler(cache, idleQueue, FwDirectoryFinder.CodeDirectory); m_scheduler.ParserUpdateVerbose += ParserUpdateHandlerForPolling; } From 0b6e3cbffb4f17f23cc2ee8e43d85f8cc9910059 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Mon, 20 Jan 2014 14:36:26 +0700 Subject: [PATCH 055/143] Set up new IParser interface Change-Id: Ib921afe14c97d7fce5740d4a28d88f836c460d30 --- .../ParserEngine/ParserCore/IParser.cs | 13 ++ .../ParserEngine/ParserCore/ParseFiler.cs | 112 ---------------- .../ParserEngine/ParserCore/ParseResult.cs | 123 ++++++++++++++++++ .../ParserEngine/ParserCore/ParserCore.csproj | 2 + 4 files changed, 138 insertions(+), 112 deletions(-) create mode 100644 Src/LexText/ParserEngine/ParserCore/IParser.cs create mode 100644 Src/LexText/ParserEngine/ParserCore/ParseResult.cs diff --git a/Src/LexText/ParserEngine/ParserCore/IParser.cs b/Src/LexText/ParserEngine/ParserCore/IParser.cs new file mode 100644 index 0000000000..7f84998c43 --- /dev/null +++ b/Src/LexText/ParserEngine/ParserCore/IParser.cs @@ -0,0 +1,13 @@ +using System.Collections; + +namespace SIL.FieldWorks.WordWorks.Parser +{ + interface IParser + { + void Initialize(); + + ParseResult ParseWord(string word); + + string TraceWord(string word); + } +} diff --git a/Src/LexText/ParserEngine/ParserCore/ParseFiler.cs b/Src/LexText/ParserEngine/ParserCore/ParseFiler.cs index 5fcbb9d75c..aa2b4eea72 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParseFiler.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParseFiler.cs @@ -61,118 +61,6 @@ public class ParseFiler : IFWDisposable /// public event EventHandler WordformUpdated; - #region internal class - - private class ParseResult - { - public ParseResult(IWfiWordform wordform, uint crc, ParserPriority priority, IList analyses, - string errorMessage) - { - Wordform = wordform; - Crc = crc; - Priority = priority; - Analyses = analyses; - ErrorMessage = errorMessage; - } - - public IWfiWordform Wordform - { - get; private set; - } - - public uint Crc - { - get; private set; - } - - public IList Analyses - { - get; private set; - } - - public string ErrorMessage - { - get; private set; - } - - public ParserPriority Priority - { - get; private set; - } - - public bool IsValid - { - get - { - if (!Wordform.IsValidObject) - return false; - return Analyses.All(analysis => analysis.IsValid); - } - } - } - - private class ParseAnalysis - { - public ParseAnalysis(IList morphs) - { - Morphs = morphs; - } - - public IList Morphs - { - get; private set; - } - - public bool IsValid - { - get - { - return Morphs.All(morph => morph.IsValid); - } - } - } - - private class ParseMorph - { - public ParseMorph(IMoForm form, IMoMorphSynAnalysis msa) - { - Form = form; - Msa = msa; - } - - public ParseMorph(IMoForm form, IMoMorphSynAnalysis msa, ILexEntryInflType inflType) - { - Form = form; - Msa = msa; - InflType = inflType; - } - - public IMoForm Form - { - get; private set; - } - - public IMoMorphSynAnalysis Msa - { - get; private set; - } - - public ILexEntryInflType InflType - { - get; private set; - } - - public bool IsValid - { - get - { - return Form.IsValidObject && Msa.IsValidObject; - } - } - } - - #endregion internal class - #region Data members private readonly FdoCache m_cache; diff --git a/Src/LexText/ParserEngine/ParserCore/ParseResult.cs b/Src/LexText/ParserEngine/ParserCore/ParseResult.cs new file mode 100644 index 0000000000..f4c6484f87 --- /dev/null +++ b/Src/LexText/ParserEngine/ParserCore/ParseResult.cs @@ -0,0 +1,123 @@ +using System.Collections.Generic; +using System.Linq; +using SIL.FieldWorks.FDO; + +namespace SIL.FieldWorks.WordWorks.Parser +{ + public class ParseResult + { + public ParseResult(IWfiWordform wordform, uint crc, ParserPriority priority, IList analyses, + string errorMessage) + { + Wordform = wordform; + Crc = crc; + Priority = priority; + Analyses = analyses; + ErrorMessage = errorMessage; + } + + public IWfiWordform Wordform + { + get; + private set; + } + + public uint Crc + { + get; + private set; + } + + public IList Analyses + { + get; + private set; + } + + public string ErrorMessage + { + get; + private set; + } + + public ParserPriority Priority + { + get; + private set; + } + + public bool IsValid + { + get + { + if (!Wordform.IsValidObject) + return false; + return Analyses.All(analysis => analysis.IsValid); + } + } + } + + public class ParseAnalysis + { + public ParseAnalysis(IList morphs) + { + Morphs = morphs; + } + + public IList Morphs + { + get; + private set; + } + + public bool IsValid + { + get + { + return Morphs.All(morph => morph.IsValid); + } + } + } + + public class ParseMorph + { + public ParseMorph(IMoForm form, IMoMorphSynAnalysis msa) + { + Form = form; + Msa = msa; + } + + public ParseMorph(IMoForm form, IMoMorphSynAnalysis msa, ILexEntryInflType inflType) + { + Form = form; + Msa = msa; + InflType = inflType; + } + + public IMoForm Form + { + get; + private set; + } + + public IMoMorphSynAnalysis Msa + { + get; + private set; + } + + public ILexEntryInflType InflType + { + get; + private set; + } + + public bool IsValid + { + get + { + return Form.IsValidObject && Msa.IsValidObject; + } + } + } +} diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj b/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj index 0e3fa0a247..8aad282bc6 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj +++ b/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj @@ -196,6 +196,7 @@ + Code @@ -212,6 +213,7 @@ True ParserCoreStrings.resx + Code From b67b32ce0481c8abd4b9b52b331c2436448e1a90 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Tue, 21 Jan 2014 13:04:32 +0700 Subject: [PATCH 056/143] added XAmpleParser and refactored FW parsing to use IParser interface Change-Id: Id14204f4ee308bec8ad0a6dbad2c3f7f67278ccd --- .../ParserEngine/ParserCore/CrcStream.cs | 252 ------- .../ParserEngine/ParserCore/HCWorker.cs | 671 ------------------ .../ParserEngine/ParserCore/IParser.cs | 12 +- .../ParserCore/M3ModelRetriever.cs | 16 +- .../ParserCore/M3ToHCTransformer.cs | 31 +- .../ParserCore/M3ToParserTransformerBase.cs | 16 +- .../ParserCore/M3ToXAmpleTransformer.cs | 58 +- .../ParserEngine/ParserCore/ParseFiler.cs | 414 +++-------- .../ParserEngine/ParserCore/ParseResult.cs | 152 ++-- .../ParserEngine/ParserCore/ParserCore.csproj | 10 +- .../ParserCore/ParserCoreStrings.Designer.cs | 45 -- .../ParserCore/ParserCoreStrings.resx | 15 - .../ParseFilerProcessingTests.cs | 481 ++++++------- .../ParserCore/ParserCoreTests/WorkerTests.cs | 32 +- .../{Scheduler.cs => ParserScheduler.cs} | 45 +- .../ParserEngine/ParserCore/ParserWorker.cs | 169 +++++ Src/LexText/ParserEngine/ParserCore/Worker.cs | 234 ------ .../ParserEngine/ParserCore/XAmpleParser.cs | 266 +++++++ .../ParserEngine/ParserCore/XAmpleWorker.cs | 121 ---- Src/LexText/ParserUI/ParserListener.cs | 3 +- Src/LexText/ParserUI/ParserTrace.cs | 12 +- Src/LexText/ParserUI/ParserTraceBase.cs | 31 +- 22 files changed, 933 insertions(+), 2153 deletions(-) delete mode 100644 Src/LexText/ParserEngine/ParserCore/CrcStream.cs delete mode 100644 Src/LexText/ParserEngine/ParserCore/HCWorker.cs rename Src/LexText/ParserEngine/ParserCore/{Scheduler.cs => ParserScheduler.cs} (85%) create mode 100644 Src/LexText/ParserEngine/ParserCore/ParserWorker.cs delete mode 100644 Src/LexText/ParserEngine/ParserCore/Worker.cs create mode 100644 Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs delete mode 100644 Src/LexText/ParserEngine/ParserCore/XAmpleWorker.cs diff --git a/Src/LexText/ParserEngine/ParserCore/CrcStream.cs b/Src/LexText/ParserEngine/ParserCore/CrcStream.cs deleted file mode 100644 index 9d92deff72..0000000000 --- a/Src/LexText/ParserEngine/ParserCore/CrcStream.cs +++ /dev/null @@ -1,252 +0,0 @@ -// taken verbatim from http://www.codeproject.com/csharp/crcstream.asp -using System; -using System.IO; -using System.Text; - -using SIL.Utils; - -namespace CodeProject.ReiMiyasaka -{ - /// - /// Encapsulates a to calculate the CRC32 checksum on-the-fly as data passes through. - /// - internal class CrcStream : Stream, IFWDisposable - { - Stream stream; - - internal static uint GetCrc(string sResult) - { - UnicodeEncoding enc = new UnicodeEncoding(); - int iCount = enc.GetByteCount(sResult); - using (CrcStream crc = new CrcStream(iCount)) - { - crc.Write(enc.GetBytes(sResult), 0, iCount); - return crc.WriteCrc; - // Closed in the Dispose of 'crc'. - } - } - - /// - /// Encapsulate a . - /// - /// The stream to calculate the checksum for. - private CrcStream(int iCount) - { - this.stream = new MemoryStream(iCount); - } - - private bool m_isDisposed = false; - - public bool IsDisposed - { - get { return m_isDisposed; } - } - - protected override void Dispose(bool disposing) - { - System.Diagnostics.Debug.WriteLineIf(!disposing, "****************** Missing Dispose() call for " + GetType().Name + ". ******************"); - if (IsDisposed) - return; - - if (disposing) - { - if (stream != null) - stream.Close(); - } - stream = null; - - base.Dispose(disposing); - } - - /// - /// Check to see if the object has been disposed. - /// All public Properties and Methods should call this - /// before doing anything else. - /// - public void CheckDisposed() - { - if (IsDisposed) - throw new ObjectDisposedException(String.Format("'{0}' in use after being disposed.", GetType().Name)); - } - - /// - /// Gets the underlying stream. - /// - internal Stream Stream - { - get - { - CheckDisposed(); - return stream; - } - } - - public override bool CanRead - { - get - { - CheckDisposed(); - return stream.CanRead; - } - } - - public override bool CanSeek - { - get - { - CheckDisposed(); - return stream.CanSeek; - } - } - - public override bool CanWrite - { - get - { - CheckDisposed(); - return stream.CanWrite; - } - } - - public override void Flush() - { - CheckDisposed(); - - stream.Flush(); - } - - public override long Length - { - get - { - CheckDisposed(); - return stream.Length; - } - } - - public override long Position - { - get - { - CheckDisposed(); - - return stream.Position; - } - set - { - CheckDisposed(); - - stream.Position = value; - } - } - - public override long Seek(long offset, SeekOrigin origin) - { - CheckDisposed(); - - return stream.Seek(offset, origin); - } - - public override void SetLength(long value) - { - CheckDisposed(); - - stream.SetLength(value); - } - - public override int Read(byte[] buffer, int offset, int count) - { - CheckDisposed(); - - count = stream.Read(buffer, offset, count); - readCrc = CalculateCrc(readCrc, buffer, offset, count); - return count; - } - - public override void Write(byte[] buffer, int offset, int count) - { - CheckDisposed(); - - stream.Write(buffer, offset, count); - - writeCrc = CalculateCrc(writeCrc, buffer, offset, count); - } - - private uint CalculateCrc(uint crc, byte[] buffer, int offset, int count) - { - unchecked - { - for (int i = offset, end = offset + count; i < end; i++) - crc = (crc >> 8) ^ table[(crc ^ buffer[i]) & 0xFF]; - } - return crc; - } - - static private uint[] table = GenerateTable(); - - static private uint[] GenerateTable() - { - unchecked - { - uint[] table = new uint[256]; - - uint crc; - const uint poly = 0xEDB88320; - for (uint i = 0; i < table.Length; i++) - { - crc = i; - for (int j = 8; j > 0; j--) - { - if ((crc & 1) == 1) - crc = (crc >> 1) ^ poly; - else - crc >>= 1; - } - table[i] = crc; - } - - return table; - } - - } - - private uint readCrc = unchecked(0xFFFFFFFF); - - /// - /// Gets the CRC checksum of the data that was read by the stream thus far. - /// - internal uint ReadCrc - { - get - { - CheckDisposed(); - return unchecked(readCrc ^ 0xFFFFFFFF); - } - } - - private uint writeCrc = unchecked(0xFFFFFFFF); - - /// - /// Gets the CRC checksum of the data that was written to the stream thus far. - /// - internal uint WriteCrc - { - get - { - CheckDisposed(); - return unchecked(writeCrc ^ 0xFFFFFFFF); - } - } - - /// - /// Resets the read and write checksums. - /// - internal void ResetChecksum() - { - CheckDisposed(); - - readCrc = unchecked(0xFFFFFFFF); - writeCrc = unchecked(0xFFFFFFFF); - } - } -} diff --git a/Src/LexText/ParserEngine/ParserCore/HCWorker.cs b/Src/LexText/ParserEngine/ParserCore/HCWorker.cs deleted file mode 100644 index e37bebbd4b..0000000000 --- a/Src/LexText/ParserEngine/ParserCore/HCWorker.cs +++ /dev/null @@ -1,671 +0,0 @@ -// -------------------------------------------------------------------------------------------- -#region // Copyright (c) 2009, SIL International. All Rights Reserved. -// -// Copyright (c) 2009, SIL International. All Rights Reserved. -// -// Distributable under the terms of either the Common Public License or the -// GNU Lesser General Public License, as specified in the LICENSING.txt file. -// -#endregion -// -// File: HCWorker.cs -// Responsibility: FLEx Team -// -------------------------------------------------------------------------------------------- -using System; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.Linq; -using System.Xml; -using System.Collections.Generic; -using System.Text; -using System.IO; -using System.Xml.Linq; -using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.FDO; -using SIL.Utils; -using SIL.HermitCrab; -using PatrParserWrapper; -using SIL.FieldWorks.FDO.Validation; - -namespace SIL.FieldWorks.WordWorks.Parser -{ - public class HCParserWorker : ParserWorker - { - class PcPatrMorph - { - public string formId; - public string form; - public string wordType; - public string msaId; - public string featureDescriptors; - public string gloss; - public int formIndex; - - public string Form - { - get - { return String.IsNullOrEmpty(form) ? "0" : form;} - } - } - - class XmlFwResolver : XmlUrlResolver - { - readonly Uri m_baseUri; - - public XmlFwResolver(string appInstallDir) - { - m_baseUri = new Uri(appInstallDir + Path.DirectorySeparatorChar); - } - - public override Uri ResolveUri(Uri baseUri, string relativeUri) - { - return base.ResolveUri(m_baseUri, relativeUri); - } - } - - [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", - Justification="m_cache is a reference and disposed in the parent class")] - class WordGrammarTrace - { - private readonly IEnumerable m_morphs; - private bool m_fSuccess; - private readonly string m_id; - private readonly FdoCache m_cache; - - public WordGrammarTrace(string id, IEnumerable morphs, FdoCache cache) - { - m_id = id; - m_morphs = morphs; - m_cache = cache; - } - /// - /// Get/set success status of word grammar attempt - /// - public bool Success - { - set - { - m_fSuccess = value; - } - - } - - /// - /// Report trace information as XML - /// - /// - public void ToXml(XmlWriter writer) - { - writer.WriteStartElement("WordGrammarAttempt"); - writer.WriteStartAttribute("success"); - writer.WriteValue(m_fSuccess ? "true" : "false"); - writer.WriteEndAttribute(); - writer.WriteStartElement("Id"); - writer.WriteValue(m_id); - writer.WriteEndElement(); - - string sType = "pfx"; // try to guess morph type based on word type - foreach (PcPatrMorph morph in m_morphs) - { - writer.WriteStartElement("Morphs"); - string sWordType = morph.wordType; - writer.WriteStartAttribute("wordType"); - writer.WriteValue(sWordType); - writer.WriteEndAttribute(); - writer.WriteStartAttribute("type"); - if (sType == "pfx" && - sWordType == "root") - sType = "root"; - else if (sType == "root" && - sWordType != "root") - sType = "sfx"; - writer.WriteValue(sType); - writer.WriteEndAttribute(); - writer.WriteStartAttribute("alloid"); - writer.WriteValue(morph.formId); - writer.WriteEndAttribute(); - writer.WriteStartAttribute("morphname"); - writer.WriteValue(morph.msaId); - writer.WriteEndAttribute(); - - writer.WriteStartElement("alloform"); - writer.WriteValue(morph.form); - writer.WriteEndElement(); // alloform - //writer.WriteStartElement("Msa"); - //writer.WriteEndElement(); // Msa - int hvoForm = Convert.ToInt32(morph.formId); - var obj = m_cache.ServiceLocator.GetObject(hvoForm); - var stemAllo = obj as IMoStemAllomorph; - if (stemAllo != null) - { - var stemName = stemAllo.StemNameRA; - if (stemName != null) - { - writer.WriteStartElement("stemName"); - writer.WriteStartAttribute("id"); - writer.WriteValue(stemName.Hvo); - writer.WriteEndAttribute(); - writer.WriteValue(stemName.Name.BestAnalysisAlternative.Text); - writer.WriteEndElement(); // stemName - } - } - writer.WriteStartElement("gloss"); - writer.WriteValue(morph.gloss); - writer.WriteEndElement(); // gloss - writer.WriteStartElement("citationForm"); - var form = obj as IMoForm; - if (form != null) - { - var entry = form.Owner as ILexEntry; - if (entry != null) - writer.WriteValue(entry.HeadWord.Text); - } - writer.WriteEndElement(); // citationForm - writer.WriteEndElement(); // Morphs - } - writer.WriteEndElement(); - } - - } - - private static int WordTypeIndex(int expectedindex, int wordTypesCount) - { - int wordTypeIndex = expectedindex; - if (wordTypeIndex + 1 > wordTypesCount) - { - // something is wrong (perhaps a missing suffix slot for a circumfix) - // we'll use the same as last time, hoping for a parse failure - wordTypeIndex = wordTypeIndex - 1; - } - return wordTypeIndex; - } - - class FwXmlTraceManager : XmlTraceManager - { - public override void ReportSuccess(WordSynthesis output) - { - if (TraceSuccess) - { - XElement wsElem = Write("Result", output); - wsElem.Add(new XAttribute("id", ((uint) output.GetHashCode()).ToString(CultureInfo.InvariantCulture))); - ((XElement) output.CurrentTraceObject).Add(new XElement("ReportSuccessTrace", wsElem)); - } - } - - public override void MorphologicalRuleNotUnapplied(MorphologicalRule rule, WordAnalysis input) - { - } - - public override void MorphologicalRuleNotApplied(MorphologicalRule rule, WordSynthesis input) - { - } - - protected override XElement Write(string name, Allomorph allomorph) - { - XElement elem = Write(name, (HCObject) allomorph); - - string formIdsStr = allomorph.GetProperty("FormID"); - string msaId = allomorph.GetProperty("MsaID"); - if (!String.IsNullOrEmpty(formIdsStr) || !String.IsNullOrEmpty(msaId)) - { - var morphElem = new XElement("Morph"); - - if (!String.IsNullOrEmpty(formIdsStr)) - { - string[] formIds = formIdsStr.Split(' '); - string[] wordTypes = allomorph.GetProperty("WordCategory").Split(' '); - for (int i = 0; i < formIds.Length; i++) - { - int wordTypeIndex = WordTypeIndex(i, wordTypes.Count()); - morphElem.Add(new XElement("MoForm", new XAttribute("DbRef", formIds[i]), new XAttribute("wordType", wordTypes[wordTypeIndex]))); - string featDesc = allomorph.GetProperty("FeatureDescriptors"); - morphElem.Add(string.IsNullOrEmpty(featDesc) ? new XElement("props") : new XElement("props", featDesc)); - } - } - - if (!String.IsNullOrEmpty(msaId)) - morphElem.Add(new XElement("MSI", new XAttribute("DbRef", msaId))); - elem.Add(morphElem); - } - - return elem; - } - } - - class FwXmlOutput : XmlOutput - { - readonly bool m_fDotrace; - readonly PatrParser m_patr; - readonly string m_patrlexPath; - readonly FdoCache m_cache; - - public FwXmlOutput(XmlWriter writer, bool fDotrace, PatrParser patr, string patrlexPath, FdoCache cache) - : base(writer, new FwXmlTraceManager()) - { - m_fDotrace = fDotrace; - m_patr = patr; - m_patrlexPath = patrlexPath; - m_cache = cache; - } - - public override void MorphAndLookupWord(Morpher morpher, string word, bool prettyPrint, bool printTraceInputs) - { - MorphAndLookupWord(morpher, word, printTraceInputs, null); - } - - public void MorphAndLookupWord(Morpher morpher, string word, bool printTraceInputs, string[] selectTraceMorphs) - { - try - { - ICollection wordGrammarTraces = null; - if (m_fDotrace) - wordGrammarTraces = new HashSet(); - XmlTraceManager.WriteInputs = printTraceInputs; - TraceManager.TraceAll = m_fDotrace; - ICollection synthesisRecs = morpher.MorphAndLookupWord(word, TraceManager, selectTraceMorphs); - foreach (WordSynthesis ws in synthesisRecs) - { - WordGrammarTrace wordGrammarTrace = null; - List morphs = GetMorphs(ws); - if (wordGrammarTraces != null) - { - wordGrammarTrace = new WordGrammarTrace(((uint) ws.GetHashCode()).ToString(CultureInfo.InvariantCulture), morphs, m_cache); - wordGrammarTraces.Add(wordGrammarTrace); - } - if (morphs.Count == 1) - { - PcPatrMorph morph = morphs[0]; - string formid = morph.formId; - IMoForm form = m_cache.ServiceLocator.GetInstance().GetObject(int.Parse(formid)); - var morphtype = form.MorphTypeRA; - if (morphtype.IsBoundType) - { - if (wordGrammarTrace != null) - { - wordGrammarTrace.Success = false; // this is not really true; what other options are there? - } - continue; - } - } - WritePcPatrLexiconFile(m_patrlexPath, morphs); - m_patr.LoadLexiconFile(m_patrlexPath, 0); - string sentence = BuildPcPatrInputSentence(morphs); - try - { - if (m_patr.ParseString(sentence) != null) - { - BuildXmlOutput(morphs); - if (wordGrammarTrace != null) - wordGrammarTrace.Success = true; - } - else if (wordGrammarTrace != null) - { - wordGrammarTrace.Success = false; - } - } - catch (Exception) - { - } - } - if (m_fDotrace) - { - WriteTrace(); - ConvertWordGrammarTraceToXml(wordGrammarTraces); - } - XmlTraceManager.Reset(); - } - catch (MorphException exc) - { - Write(exc); - } - } - - private static string BuildPcPatrInputSentence(IEnumerable morphs) - { - var sentence = new StringBuilder(); - bool firstItem = true; - foreach (PcPatrMorph morph in morphs) - { - if (!firstItem) - sentence.Append(" "); - sentence.Append(morph.Form); - firstItem = false; - } - return sentence.ToString(); - } - - void ConvertWordGrammarTraceToXml(IEnumerable wordGrammarTraces) - { - XmlWriter.WriteStartElement("WordGrammarTrace"); - foreach (WordGrammarTrace trace in wordGrammarTraces) - { - trace.ToXml(XmlWriter); - } - XmlWriter.WriteEndElement(); - } - - static List GetMorphs(WordSynthesis ws) - { - var ppMorphs = new Dictionary(); - var result = new List(); - foreach (Morph morph in ws.Morphs) - { - string[] formIds = morph.Allomorph.GetProperty("FormID").Split(' '); - string[] wordTypes = morph.Allomorph.GetProperty("WordCategory").Split(' '); - string form = ws.Stratum.CharacterDefinitionTable.ToString(morph.Shape, ModeType.SYNTHESIS, false); - PcPatrMorph ppMorph; - if (!ppMorphs.TryGetValue(morph.Allomorph.Morpheme.ID, out ppMorph)) - { - ppMorph = new PcPatrMorph - { - formIndex = 0, - formId = formIds[0], - form = form, - wordType = wordTypes[0] - }; - } - else if (formIds.Length == 1) - { - ppMorph.form += form; - continue; - } - else - { - PcPatrMorph oldMorph = ppMorph; - int wordTypeIndex = WordTypeIndex(oldMorph.formIndex + 1, wordTypes.Count()); - ppMorph = new PcPatrMorph - { - formIndex = oldMorph.formIndex + 1, - formId = formIds[oldMorph.formIndex + 1], - form = form, - wordType = wordTypes[wordTypeIndex] - }; - } - - ppMorph.msaId = morph.Allomorph.GetProperty("MsaID"); - ppMorph.featureDescriptors = morph.Allomorph.GetProperty("FeatureDescriptors"); - ppMorph.gloss = morph.Allomorph.Morpheme.Gloss.Description; - ppMorphs[morph.Allomorph.Morpheme.ID] = ppMorph; - - string morphType = morph.Allomorph.GetProperty("MorphType"); - switch (morphType) - { - case MoMorphTypeTags.kMorphInfix: - case MoMorphTypeTags.kMorphInfixingInterfix: - if (result.Count == 0) - result.Add(ppMorph); - else - result.Insert(result.Count - 1, ppMorph); - break; - - default: - result.Add(ppMorph); - break; - } - } - return result; - } - - static void WritePcPatrLexiconFile(string path, IEnumerable morphs) - { - using (var writer = new StreamWriter(path)) - { - foreach (PcPatrMorph morph in morphs) - { - writer.WriteLine("\\w {0}", morph.Form); - writer.WriteLine("\\c {0}", morph.wordType); - writer.WriteLine("\\g {0}", morph.gloss); - if (!String.IsNullOrEmpty(morph.featureDescriptors)) - { - string lastFeatDesc = ""; - string combinedCFPFeatDescs = ""; - string[] featDescs = morph.featureDescriptors.Split(' '); - if (featDescs.Any()) - writer.Write("\\f"); - foreach (string featDesc in featDescs) - { - if (featDesc.StartsWith("CFP")) - { - combinedCFPFeatDescs += featDesc; - lastFeatDesc = featDesc; - continue; - } - if (lastFeatDesc.StartsWith("CFP")) - writer.Write(" {0}", combinedCFPFeatDescs); - writer.Write(" {0}", featDesc); - } - if (lastFeatDesc.StartsWith("CFP")) - writer.Write(" {0}", combinedCFPFeatDescs); - } - writer.WriteLine(); - writer.WriteLine(); - } - writer.Close(); - } - } - - void BuildXmlOutput(IEnumerable morphs) - { - XmlWriter.WriteStartElement("WfiAnalysis"); - XmlWriter.WriteStartElement("Morphs"); - - foreach (PcPatrMorph morph in morphs) - { - XmlWriter.WriteStartElement("Morph"); - - XmlWriter.WriteStartElement("MoForm"); - XmlWriter.WriteAttributeString("DbRef", morph.formId); - XmlWriter.WriteAttributeString("Label", morph.form); - XmlWriter.WriteAttributeString("wordType", morph.wordType); - XmlWriter.WriteEndElement(); - - XmlWriter.WriteStartElement("MSI"); - XmlWriter.WriteAttributeString("DbRef", morph.msaId); - XmlWriter.WriteEndElement(); - - XmlWriter.WriteEndElement(); - } - - XmlWriter.WriteEndElement(); - XmlWriter.WriteEndElement(); - } - - public override void Write(LoadException le) - { - XmlWriter.WriteStartElement("Error"); - switch (le.ErrorType) - { - case LoadException.LoadErrorType.INVALID_ENTRY_SHAPE: - var entryShape = le.Data["shape"] as string; - var entryId = le.Data["entry"] as string; - LexEntry entry = le.Loader.CurrentMorpher.Lexicon.GetEntry(entryId); - XmlWriter.WriteString(String.Format(ParserCoreStrings.ksHCInvalidEntryShape, entryShape, entry.Description)); - break; - - case LoadException.LoadErrorType.INVALID_RULE_SHAPE: - var ruleShape = le.Data["shape"] as string; - var ruleId = le.Data["rule"] as string; - MorphologicalRule rule = le.Loader.CurrentMorpher.GetMorphologicalRule(ruleId); - XmlWriter.WriteString(String.Format(ParserCoreStrings.ksHCInvalidRuleShape, ruleShape, rule.Description)); - break; - - default: - XmlWriter.WriteString(String.Format(ParserCoreStrings.ksHCDefaultErrorMsg, le.Message)); - break; - } - XmlWriter.WriteEndElement(); - } - - public override void Write(MorphException me) - { - XmlWriter.WriteStartElement("Error"); - switch (me.ErrorType) - { - case MorphException.MorphErrorType.INVALID_SHAPE: - var shape = (string) me.Data["shape"]; - var position = (int) me.Data["position"]; - var phonemesFoundSoFar = (string) me.Data["phonemesFoundSoFar"]; - string rest = shape.Substring(position); - string restToUse = rest; - LgGeneralCharCategory cc = m_cache.ServiceLocator.UnicodeCharProps.get_GeneralCategory(rest[0]); - if (cc == LgGeneralCharCategory.kccMn) - { // the first character is a diacritic, combining type of character - // insert a space so it does not show on top of a single quote in the message string - restToUse = " " + rest; - } - XmlWriter.WriteString(String.Format(ParserCoreStrings.ksHCInvalidWordform, shape, position+1, restToUse, phonemesFoundSoFar)); - break; - - case MorphException.MorphErrorType.UNINSTANTIATED_FEATURE: - var featId = me.Data["feature"] as string; - var feat = me.Morpher.PhoneticFeatureSystem.GetFeature(featId); - XmlWriter.WriteString(String.Format(ParserCoreStrings.ksHCUninstFeature, feat.Description)); - break; - - default: - XmlWriter.WriteString(String.Format(ParserCoreStrings.ksHCDefaultErrorMsg, me.Message)); - break; - } - XmlWriter.WriteEndElement(); - } - } - - private readonly XmlLoader m_loader; - private PatrParser m_patr; - private readonly string m_outputDirectory; - - public HCParserWorker(FdoCache cache, Action taskUpdateHandler, IdleQueue idleQueue, string appInstallDir) - : base(cache, taskUpdateHandler, idleQueue, - cache.ServiceLocator.GetInstance().GetObject(CmAgentTags.kguidAgentHermitCrabParser), appInstallDir) - { - m_outputDirectory = Path.GetTempPath(); - m_patr = new PatrParser - { - CommentChar = '|', - CodePage = Encoding.UTF8.CodePage - }; - m_loader = new XmlLoader - { - XmlResolver = new XmlFwResolver(appInstallDir), - QuitOnError = false - }; - } - - protected override void Dispose(bool disposing) - { - if (disposing && !IsDisposed) - { - if (m_patr != null) - { - m_patr.Dispose(); - m_patr = null; - } - } - base.Dispose(disposing); - } - - protected override string ParseWord(string form, int hvoWordform) - { - return ParseWordWithHermitCrab(form, hvoWordform, false, null); - } - - protected override string TraceWord(string form, string selectTraceMorphs) - { - string[] selectTraceMorphIds = null; - if (!String.IsNullOrEmpty(selectTraceMorphs)) - { - selectTraceMorphIds = selectTraceMorphs.TrimEnd().Split(' '); - int i = 0; - foreach (string sId in selectTraceMorphIds) - { - IMoMorphSynAnalysis msa = m_cache.ServiceLocator.GetInstance().GetObject(int.Parse(sId)); - if (msa.ClassID == MoStemMsaTags.kClassId) - selectTraceMorphIds.SetValue("lex" + sId, i); - else - selectTraceMorphIds.SetValue("mrule" + sId, i); - i++; - } - - } - return ParseWordWithHermitCrab(form, 0, true, selectTraceMorphIds); - } - - private string ParseWordWithHermitCrab(string form, int hvoWordform, bool fDotrace, string[] selectTraceMorphs) - { - if (!m_loader.IsLoaded) - return ParserCoreStrings.ksDidNotParse; - - var sb = new StringBuilder(); - var settings = new XmlWriterSettings { OmitXmlDeclaration = true }; - using (var writer = XmlWriter.Create(sb, settings)) - { - writer.WriteStartElement("Wordform"); - writer.WriteAttributeString("DbRef", Convert.ToString(hvoWordform)); - writer.WriteAttributeString("Form", form); - var output = new FwXmlOutput(writer, fDotrace, m_patr, - Path.Combine(m_outputDirectory, m_projectName + "patrlex.txt"), m_cache); - output.MorphAndLookupWord(m_loader.CurrentMorpher, form, true, selectTraceMorphs); - writer.WriteEndElement(); - } - return sb.ToString(); - } - - public string HcInputPath - { - get { return Path.Combine(m_outputDirectory, m_projectName + "HCInput.xml"); } - } - - public string HcGrammarPath - { - get { return Path.Combine(m_outputDirectory, m_projectName + "gram.txt"); } - } - - protected override void LoadParser(ref XmlDocument model, XmlDocument template) - { - string hcPath = HcInputPath; - File.Delete(hcPath); // In case we don't produce one successfully, don't keep an old one. - // Check for errors that will prevent the transformations working. - foreach (var affix in m_cache.ServiceLocator.GetInstance().AllInstances()) - { - string form = affix.Form.VernacularDefaultWritingSystem.Text; - if (String.IsNullOrEmpty(form) || !form.Contains("[")) - continue; - string environment = "/_" + form; - // A form containing a reduplication expression should look like an environment - var validator = new PhonEnvRecognizer( - m_cache.LangProject.PhonologicalDataOA.AllPhonemes().ToArray(), - m_cache.LangProject.PhonologicalDataOA.AllNaturalClassAbbrs().ToArray()); - if (!validator.Recognize(environment)) - { - m_loader.Reset(); // make sure nothing thinks it is in a useful state - throw new InvalidReduplicationEnvironmentException(validator.ErrorMessage, form); - } - } - - var transformer = new M3ToHCTransformer(m_projectName, m_taskUpdateHandler, m_appInstallDir); - transformer.MakeHCFiles(ref model); - - m_patr.LoadGrammarFile(HcGrammarPath); - - LoadHCInfo(hcPath); - - XmlNode delReappsNode = model.SelectSingleNode("/M3Dump/ParserParameters/HC/DelReapps"); - if (delReappsNode != null) - m_loader.CurrentMorpher.DelReapplications = Convert.ToInt32(delReappsNode.InnerText); - } - - private void LoadHCInfo(string hcPath) - { - string loadErrorsFile = Path.Combine(m_outputDirectory, m_projectName + "HCLoadErrors.xml"); - using (XmlWriter writer = new XmlTextWriter(loadErrorsFile, null)) - { - var loadOutput = new XmlOutput(writer); - writer.WriteStartElement("LoadErrors"); - m_loader.Output = loadOutput; - m_loader.Load(hcPath); - writer.WriteEndElement(); - loadOutput.Close(); - } - } - } -} diff --git a/Src/LexText/ParserEngine/ParserCore/IParser.cs b/Src/LexText/ParserEngine/ParserCore/IParser.cs index 7f84998c43..ebed1eed6e 100644 --- a/Src/LexText/ParserEngine/ParserCore/IParser.cs +++ b/Src/LexText/ParserEngine/ParserCore/IParser.cs @@ -1,13 +1,15 @@ -using System.Collections; - -namespace SIL.FieldWorks.WordWorks.Parser +namespace SIL.FieldWorks.WordWorks.Parser { - interface IParser + public interface IParser { void Initialize(); + void Reset(); + ParseResult ParseWord(string word); - string TraceWord(string word); + string ParseWordXml(string word); + + string TraceWordXml(string word, string selectTraceMorphs); } } diff --git a/Src/LexText/ParserEngine/ParserCore/M3ModelRetriever.cs b/Src/LexText/ParserEngine/ParserCore/M3ModelRetriever.cs index 7be937ca58..8c07f06c82 100644 --- a/Src/LexText/ParserEngine/ParserCore/M3ModelRetriever.cs +++ b/Src/LexText/ParserEngine/ParserCore/M3ModelRetriever.cs @@ -35,7 +35,6 @@ namespace SIL.FieldWorks.WordWorks.Parser public class M3ParserModelRetriever : FwDisposableBase, IVwNotifyChange { private readonly FdoCache m_cache; - private readonly Action m_taskUpdateHandler; private readonly string m_modelPath; private readonly string m_templatePath; private readonly string m_outputDirectory; @@ -50,12 +49,11 @@ public class M3ParserModelRetriever : FwDisposableBase, IVwNotifyChange /// Initializes a new instance of the class. /// /// ----------------------------------------------------------------------------------- - public M3ParserModelRetriever(FdoCache cache, Action taskUpdateHandler) + public M3ParserModelRetriever(FdoCache cache) { if (cache == null) throw new ArgumentNullException("cache"); m_cache = cache; - m_taskUpdateHandler = taskUpdateHandler; m_cache.DomainDataByFlid.AddNotification(this); m_outputDirectory = Path.GetTempPath(); @@ -84,25 +82,17 @@ public bool RetrieveModel() using (new WorkerThreadReadHelper(m_cache.ServiceLocator.GetInstance())) { ILangProject lp = m_cache.LanguageProject; - using (var task = new TaskReport(ParserCoreStrings.ksRetrievingGrammarAndLexicon, m_taskUpdateHandler)) - { // 1. Export lexicon and/or grammar. m_modelDom = null; - M3ModelExportServices.ExportGrammarAndLexicon(m_modelPath, lp); - } + M3ModelExportServices.ExportGrammarAndLexicon(m_modelPath, lp); // 2. Export GAFAWS data. - using (var task = new TaskReport(ParserCoreStrings.ksRetrievingTemplateInformation, m_taskUpdateHandler)) - { -// The following needs to be enabled, in order to avoid an exception bieng thrown after the export work, -// but it is such a handy way to get Flex to stop in my profiler. :-) m_templateDom = null; M3ModelExportServices.ExportGafaws(m_outputDirectory, m_cache.ProjectId.Name, lp.PartsOfSpeechOA.PossibilitiesOS); } - } return true; - } + } public void Reset() { diff --git a/Src/LexText/ParserEngine/ParserCore/M3ToHCTransformer.cs b/Src/LexText/ParserEngine/ParserCore/M3ToHCTransformer.cs index f3b21dbf73..7132c30517 100644 --- a/Src/LexText/ParserEngine/ParserCore/M3ToHCTransformer.cs +++ b/Src/LexText/ParserEngine/ParserCore/M3ToHCTransformer.cs @@ -12,9 +12,7 @@ // File: M3ParserTransformer.cs // Responsibility: John Hatton // -------------------------------------------------------------------------------------------- -using System; using System.Xml; -using System.Diagnostics; namespace SIL.FieldWorks.WordWorks.Parser { @@ -30,32 +28,23 @@ internal class M3ToHCTransformer : M3ToParserTransformerBase /// Initializes a new instance of the class. /// /// ----------------------------------------------------------------------------------- - public M3ToHCTransformer(string database, Action taskUpdateHandler, string appInstallDir) - : base(database, taskUpdateHandler, appInstallDir) + public M3ToHCTransformer(string database, string appInstallDir) + : base(database, appInstallDir) { } public void MakeHCFiles(ref XmlDocument model) { - using (var task = new TaskReport(ParserCoreStrings.ksMakingHCFiles, m_taskUpdateHandler)) - { - var startTime = DateTime.Now; - TransformDomToFile("FxtM3ParserToHCInput.xsl", model, m_database + "HCInput.xml", task); - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "Lex XSLT took : " + (DateTime.Now.Ticks - startTime.Ticks)); + TransformDomToFile("FxtM3ParserToHCInput.xsl", model, m_database + "HCInput.xml"); - startTime = DateTime.Now; - TransformDomToFile("FxtM3ParserToToXAmpleGrammar.xsl", model, m_database + "gram.txt", task); - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "Grammar XSLTs took : " + (DateTime.Now.Ticks - startTime.Ticks)); + TransformDomToFile("FxtM3ParserToToXAmpleGrammar.xsl", model, m_database + "gram.txt"); - // TODO: Putting this here is not necessarily efficient because it happens every time - // the parser is run. It would be more efficient to run this only when the user - // is trying a word. But we need the "model" to apply this transform and it is - // available here, so we're doing this for now. - startTime = DateTime.Now; - string sName = m_database + "XAmpleWordGrammarDebugger.xsl"; - TransformDomToFile("FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl", model, sName, task); - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "WordGrammarDebugger XSLT took : " + (DateTime.Now.Ticks - startTime.Ticks)); - } + // TODO: Putting this here is not necessarily efficient because it happens every time + // the parser is run. It would be more efficient to run this only when the user + // is trying a word. But we need the "model" to apply this transform and it is + // available here, so we're doing this for now. + string sName = m_database + "XAmpleWordGrammarDebugger.xsl"; + TransformDomToFile("FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl", model, sName); } } } diff --git a/Src/LexText/ParserEngine/ParserCore/M3ToParserTransformerBase.cs b/Src/LexText/ParserEngine/ParserCore/M3ToParserTransformerBase.cs index d74e7417f7..ce3f520a2c 100644 --- a/Src/LexText/ParserEngine/ParserCore/M3ToParserTransformerBase.cs +++ b/Src/LexText/ParserEngine/ParserCore/M3ToParserTransformerBase.cs @@ -1,5 +1,3 @@ -using System; -using System.Diagnostics; using System.IO; using System.Xml; using SIL.Utils; @@ -13,8 +11,6 @@ abstract internal class M3ToParserTransformerBase { protected string m_outputDirectory; protected string m_database; - protected Action m_taskUpdateHandler; - protected readonly TraceSwitch m_tracingSwitch = new TraceSwitch("ParserCore.TracingSwitch", "Just regular tracking", "Off"); protected readonly string m_appInstallDir; /// ----------------------------------------------------------------------------------- @@ -22,21 +18,17 @@ abstract internal class M3ToParserTransformerBase /// Initializes a new instance of the class. /// /// ----------------------------------------------------------------------------------- - public M3ToParserTransformerBase(string database, Action taskUpdateHandler, string appInstallDir) + public M3ToParserTransformerBase(string database, string appInstallDir) { m_database = database; - m_taskUpdateHandler = taskUpdateHandler; m_appInstallDir = appInstallDir; m_outputDirectory = Path.GetTempPath(); } - protected void TransformDomToFile(string transformName, XmlDocument inputDOM, string outputName, TaskReport task) + protected void TransformDomToFile(string transformName, XmlDocument inputDom, string outputName) { - using (task.AddSubTask(String.Format(ParserCoreStrings.ksCreatingX, outputName))) - { - XmlUtils.TransformDomToFile(Path.Combine(m_appInstallDir + "/Language Explorer/Transforms/", transformName), - inputDOM, Path.Combine(m_outputDirectory, outputName)); - } + XmlUtils.TransformDomToFile(Path.Combine(m_appInstallDir + "/Language Explorer/Transforms/", transformName), + inputDom, Path.Combine(m_outputDirectory, outputName)); } } } diff --git a/Src/LexText/ParserEngine/ParserCore/M3ToXAmpleTransformer.cs b/Src/LexText/ParserEngine/ParserCore/M3ToXAmpleTransformer.cs index 769abacc80..b0ab982a96 100644 --- a/Src/LexText/ParserEngine/ParserCore/M3ToXAmpleTransformer.cs +++ b/Src/LexText/ParserEngine/ParserCore/M3ToXAmpleTransformer.cs @@ -17,7 +17,6 @@ using System.Text; using System.Xml; using System.IO; -using System.Diagnostics; using SIL.WordWorks.GAFAWS.PositionAnalysis; namespace SIL.FieldWorks.WordWorks.Parser @@ -33,8 +32,8 @@ internal class M3ToXAmpleTransformer : M3ToParserTransformerBase /// Initializes a new instance of the class. /// /// ----------------------------------------------------------------------------------- - public M3ToXAmpleTransformer(string database, Action taskUpdateHandler, string appInstallDir) - : base(database, taskUpdateHandler, appInstallDir) + public M3ToXAmpleTransformer(string database, string appInstallDir) + : base(database, appInstallDir) { } @@ -42,19 +41,16 @@ public M3ToXAmpleTransformer(string database, Action taskUpdateHandl Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] internal void PrepareTemplatesForXAmpleFiles(ref XmlDocument domModel, XmlDocument domTemplate) { - using (var task = new TaskReport(ParserCoreStrings.ksPreparingTemplatesForXAmple, m_taskUpdateHandler)) + // get top level POS that has at least one template with slots + XmlNodeList templateNodeList = domTemplate.SelectNodes("//PartsOfSpeech/PartOfSpeech[descendant-or-self::MoInflAffixTemplate[PrefixSlots or SuffixSlots]]"); + foreach (XmlNode templateNode in templateNodeList) { - // get top level POS that has at least one template with slots - XmlNodeList templateNodeList = domTemplate.SelectNodes("//PartsOfSpeech/PartOfSpeech[descendant-or-self::MoInflAffixTemplate[PrefixSlots or SuffixSlots]]"); - foreach (XmlNode templateNode in templateNodeList) - { - // transform the POS that has templates to GAFAWS format - string sGafawsFile = m_database + "gafawsData.xml"; - TransformPOSInfoToGafawsInputFormat(templateNode, sGafawsFile, task); - string sResultFile = ApplyGafawsAlgorithm(sGafawsFile); - //based on results of GAFAWS, modify the model dom by inserting orderclass in slots - InsertOrderclassInfo(ref domModel, sResultFile); - } + // transform the POS that has templates to GAFAWS format + string sGafawsFile = m_database + "gafawsData.xml"; + TransformPosInfoToGafawsInputFormat(templateNode, sGafawsFile); + string sResultFile = ApplyGafawsAlgorithm(sGafawsFile); + //based on results of GAFAWS, modify the model dom by inserting orderclass in slots + InsertOrderclassInfo(ref domModel, sResultFile); } } @@ -102,35 +98,27 @@ protected string ApplyGafawsAlgorithm(string sGafawsFile) /// /// transform the POS that has templates to GAFAWS format /// - protected void TransformPOSInfoToGafawsInputFormat(XmlNode templateNode, string sGafawsFile, TaskReport task) + protected void TransformPosInfoToGafawsInputFormat(XmlNode templateNode, string sGafawsFile) { var dom = new XmlDocument(); dom.CreateElement("GAFAWSData"); // create root element dom.InnerXml = templateNode.OuterXml; // copy in POS elements - TransformDomToFile("FxtM3ParserToGAFAWS.xsl", dom, sGafawsFile, task); + TransformDomToFile("FxtM3ParserToGAFAWS.xsl", dom, sGafawsFile); } internal void MakeAmpleFiles(XmlDocument model) { - using (var task = new TaskReport(ParserCoreStrings.ksMakingXAmpleFiles, m_taskUpdateHandler)) - { - DateTime startTime = DateTime.Now; - TransformDomToFile("FxtM3ParserToXAmpleADCtl.xsl", model, m_database + "adctl.txt", task); - TransformDomToFile("FxtM3ParserToToXAmpleGrammar.xsl", model, m_database + "gram.txt", task); - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "Grammar XSLTs took : " + (DateTime.Now.Ticks - startTime.Ticks)); - // TODO: Putting this here is not necessarily efficient because it happens every time - // the parser is run. It would be more efficient to run this only when the user - // is trying a word. But we need the "model" to apply this transform an it is - // available here, so we're doing this for now. - startTime = DateTime.Now; - string sName = m_database + "XAmpleWordGrammarDebugger.xsl"; - TransformDomToFile("FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl", model, sName, task); - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "WordGrammarDebugger XSLT took : " + (DateTime.Now.Ticks - startTime.Ticks)); + DateTime startTime = DateTime.Now; + TransformDomToFile("FxtM3ParserToXAmpleADCtl.xsl", model, m_database + "adctl.txt"); + TransformDomToFile("FxtM3ParserToToXAmpleGrammar.xsl", model, m_database + "gram.txt"); + // TODO: Putting this here is not necessarily efficient because it happens every time + // the parser is run. It would be more efficient to run this only when the user + // is trying a word. But we need the "model" to apply this transform an it is + // available here, so we're doing this for now. + string sName = m_database + "XAmpleWordGrammarDebugger.xsl"; + TransformDomToFile("FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl", model, sName); - startTime = DateTime.Now; - TransformDomToFile("FxtM3ParserToXAmpleLex.xsl", model, m_database + "lex.txt", task); - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "Lex XSLT took : " + (DateTime.Now.Ticks - startTime.Ticks)); - } + TransformDomToFile("FxtM3ParserToXAmpleLex.xsl", model, m_database + "lex.txt"); } } } diff --git a/Src/LexText/ParserEngine/ParserCore/ParseFiler.cs b/Src/LexText/ParserEngine/ParserCore/ParseFiler.cs index aa2b4eea72..d5ceb6e181 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParseFiler.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParseFiler.cs @@ -20,7 +20,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Xml.Linq; using System.Diagnostics; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.Application; @@ -54,7 +53,7 @@ public ParserPriority Priority /// /// Summary description for ParseFiler. /// - public class ParseFiler : IFWDisposable + public class ParseFiler { /// /// Occurs when a wordform is updated. @@ -67,16 +66,13 @@ public class ParseFiler : IFWDisposable private readonly Action m_taskUpdateHandler; private readonly IdleQueue m_idleQueue; private readonly ICmAgent m_parserAgent; - private readonly Queue m_resultQueue; + private readonly Queue m_workQueue; private readonly object m_syncRoot; - private readonly IWfiWordformRepository m_wordformRepository; private readonly IWfiAnalysisFactory m_analysisFactory; private readonly IWfiMorphBundleFactory m_mbFactory; private readonly ICmBaseAnnotationRepository m_baseAnnotationRepository; private readonly ICmBaseAnnotationFactory m_baseAnnotationFactory; - private readonly IMoFormRepository m_moFormRepository; - private readonly IMoMorphSynAnalysisRepository m_msaRepository; private readonly ICmAgent m_userAgent; /// @@ -84,9 +80,6 @@ public class ParseFiler : IFWDisposable /// These evaluations are considered stale until we set a new evaluation, which removes that item from the set. /// private readonly HashSet m_analysesWithOldEvaluation; - private readonly TraceSwitch m_tracingSwitch = new TraceSwitch("ParserCore.TracingSwitch", "Just regular tracking", "Off"); - private long m_ticksFiler; - private int m_numberOfWordForms; #endregion Data members @@ -114,17 +107,14 @@ public ParseFiler(FdoCache cache, Action taskUpdateHandler, IdleQueu m_taskUpdateHandler = taskUpdateHandler; m_idleQueue = idleQueue; m_parserAgent = parserAgent; - m_resultQueue = new Queue(); + m_workQueue = new Queue(); m_syncRoot = new object(); - var servLoc = cache.ServiceLocator; - m_wordformRepository = servLoc.GetInstance(); + IFdoServiceLocator servLoc = cache.ServiceLocator; m_analysisFactory = servLoc.GetInstance(); m_mbFactory = servLoc.GetInstance(); m_baseAnnotationRepository = servLoc.GetInstance(); m_baseAnnotationFactory = servLoc.GetInstance(); - m_moFormRepository = servLoc.GetInstance(); - m_msaRepository = servLoc.GetInstance(); m_userAgent = m_cache.LanguageProject.DefaultUserAgent; m_analysesWithOldEvaluation = new HashSet( @@ -132,241 +122,27 @@ public ParseFiler(FdoCache cache, Action taskUpdateHandler, IdleQueu analysis => analysis.GetAgentOpinion(m_parserAgent) != Opinions.noopinion)); } - #region IDisposable & Co. implementation - // Region last reviewed: never - - /// - /// Check to see if the object has been disposed. - /// All public Properties and Methods should call this - /// before doing anything else. - /// - public void CheckDisposed() - { - if (IsDisposed) - throw new ObjectDisposedException(String.Format("'{0}' in use after being disposed.", GetType().Name)); - } - - /// - /// True, if the object has been disposed. - /// - private bool m_isDisposed; - - /// - /// See if the object has been disposed. - /// - public bool IsDisposed - { - get { return m_isDisposed; } - } - - /// - /// Finalizer, in case client doesn't dispose it. - /// Force Dispose(false) if not already called (i.e. m_isDisposed is true) - /// - /// - /// In case some clients forget to dispose it directly. - /// - ~ParseFiler() - { - Dispose(false); - // The base class finalizer is called automatically. - } - - /// - /// - /// - /// Must not be virtual. - public void Dispose() - { - Dispose(true); - // This object will be cleaned up by the Dispose method. - // Therefore, you should call GC.SupressFinalize to - // take this object off the finalization queue - // and prevent finalization code for this object - // from executing a second time. - GC.SuppressFinalize(this); - } - - /// - /// Executes in two distinct scenarios. - /// - /// 1. If disposing is true, the method has been called directly - /// or indirectly by a user's code via the Dispose method. - /// Both managed and unmanaged resources can be disposed. - /// - /// 2. If disposing is false, the method has been called by the - /// runtime from inside the finalizer and you should not reference (access) - /// other managed objects, as they already have been garbage collected. - /// Only unmanaged resources can be disposed. - /// - /// - /// - /// If any exceptions are thrown, that is fine. - /// If the method is being done in a finalizer, it will be ignored. - /// If it is thrown by client code calling Dispose, - /// it needs to be handled by fixing the bug. - /// - /// If subclasses override this method, they should call the base implementation. - /// - protected virtual void Dispose(bool disposing) - { - Debug.WriteLineIf(!disposing, "****************** Missing Dispose() call for " + GetType().Name + ". ******************"); - // Must not be run more than once. - if (m_isDisposed) - return; - - if (disposing) - { - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "Total number of wordforms updated = " + m_numberOfWordForms); - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "Total time for parser filer = " + TimeSpan.FromTicks(m_ticksFiler).TotalMilliseconds); - - if (m_numberOfWordForms != 0) - { - long lAvg = m_ticksFiler / m_numberOfWordForms; - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "Average time for parser filer = " + TimeSpan.FromTicks(lAvg).TotalMilliseconds); - } - } - - // Dispose unmanaged resources here, whether disposing is true or false. - m_isDisposed = true; - } - - #endregion IDisposable & Co. implementation - #endregion Construction and Disposal #region Public methods - /// - /// Process the XML data. - /// + /// + /// Process the parse result. + /// + /// The wordform. /// The priority. - /// The XML data to process. - /// The CRC. - /// - /// The 'parser' XML string may, or may not, be well formed XML. - /// If there is an Exception node in the XML, then it may not be well-formed XML beyond that node, - /// since the XAmple parser may have choked. - /// This is why we can't use a DOM to get all of the XML, but we have to read it as it goes by in a stream. - /// - /// ENHANCE (DamienD): right now we are not supporting malformed XML - /// - public bool ProcessParse(ParserPriority priority, string parse, uint crc) + /// The parse result. + public bool ProcessParse(IWfiWordform wordform, ParserPriority priority, ParseResult parseResult) { - var wordformElem = XElement.Parse(parse); - string errorMessage = null; - var exceptionElem = wordformElem.Element("Exception"); - if (exceptionElem != null) - { - var totalAnalysesValue = (string) exceptionElem.Attribute("totalAnalyses"); - switch ((string) exceptionElem.Attribute("code")) - { - case "ReachedMaxAnalyses": - errorMessage = String.Format(ParserCoreStrings.ksReachedMaxAnalysesAllowed, - totalAnalysesValue); - break; - case "ReachedMaxBufferSize": - errorMessage = String.Format(ParserCoreStrings.ksReachedMaxInternalBufferSize, - totalAnalysesValue); - break; - } - } - else - { - errorMessage = (string) wordformElem.Element("Error"); - } - - try - { - ParseResult result; - using (new WorkerThreadReadHelper(m_cache.ServiceLocator.GetInstance())) - { - var wordform = m_wordformRepository.GetObject((int) wordformElem.Attribute("DbRef")); - IList analyses = null; - analyses = (from analysisElem in wordformElem.Descendants("WfiAnalysis") - let morphs = from morphElem in analysisElem.Descendants("Morph") - let morph = CreateParseMorph(morphElem) - where morph != null - select morph - where morphs.Any() - select new ParseAnalysis(morphs.ToList())).ToList(); - result = new ParseResult(wordform, crc, priority, analyses, errorMessage); - } - - lock (m_syncRoot) - m_resultQueue.Enqueue(result); - m_idleQueue.Add(IdleQueuePriority.Low, UpdateWordforms); - return true; - } - catch (KeyNotFoundException) - { - // a wordform, form, or MSA no longer exists, so skip this parse result - } - return false; + lock (m_syncRoot) + m_workQueue.Enqueue(new WordformUpdateWork(wordform, priority, parseResult)); + m_idleQueue.Add(IdleQueuePriority.Low, UpdateWordforms); + return true; } #endregion Public methods #region Private methods - /// - /// Creates a single ParseMorph object - /// Handles special cases where the MoForm hvo and/or MSI hvos are - /// not actual MoForm or MSA objects. - /// - /// A Morph element returned by one of the automated parsers - /// a new ParseMorph object or null if the morpheme should be skipped - private ParseMorph CreateParseMorph(XElement morphElem) - { - // Normally, the hvo for MoForm is a MoForm and the hvo for MSI is an MSA - // There are four exceptions, though, when an irregularly inflected form is involved: - // 1. ().GetObject(hvoForm); - var form = objForm as IMoForm; - - var msaHvo = morphElem.Element("MSI").Attribute("DbRef"); - string sMsaHvo = msaHvo.Value; - // Irregulary inflected forms can have a combination MSA hvo: the LexEntry hvo, a period, and an index to the LexEntryRef - var indexOfPeriod = IndexOfPeriodInMsaHvo(ref sMsaHvo); - ICmObject objMsa = m_cache.ServiceLocator.GetInstance().GetObject(Convert.ToInt32(sMsaHvo)); - var msa = objMsa as IMoMorphSynAnalysis; - - if (form != null && msa != null) - return new ParseMorph(form, msa); - - var msaAsLexEntry = objMsa as ILexEntry; - if (msaAsLexEntry != null && form != null) - { - // is an irregularly inflected form - // get the MoStemMsa of its variant - if (msaAsLexEntry.EntryRefsOS.Count > 0) - { - var index = IndexOfLexEntryRef(msaHvo.Value, indexOfPeriod); // the value of the int after the period - var lexEntryRef = msaAsLexEntry.EntryRefsOS[index]; - var sense = FDO.DomainServices.MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); - var stemMsa = sense.MorphoSyntaxAnalysisRA as IMoStemMsa; - var entryOfForm = form.Owner as ILexEntry; - var inflType = lexEntryRef.VariantEntryTypesRS.ElementAt(0); - return new ParseMorph(form, stemMsa, inflType as ILexEntryInflType); - } - } - // if it is anything else, we ignore it - return null; - } - /// /// Updates the wordform. This will be run in the UI thread when the application is idle. If it can't be done right now, /// it returns false, and the caller should try again later. @@ -375,8 +151,6 @@ private ParseMorph CreateParseMorph(XElement morphElem) /// private bool UpdateWordforms(object parameter) { - if (IsDisposed) - return true; // If a UOW is in progress, the application isn't really idle, so try again later. One case where this used // to be true was the dialog in IText for choosing the writing system of a new text, which was run while // the UOW was active. @@ -385,63 +159,64 @@ private bool UpdateWordforms(object parameter) // update all of the wordforms in a batch, this might slow down the UI thread a little, if it causes too much unresponsiveness // we can bail out early if there is a message in the Win32 message queue - IEnumerable results; + IEnumerable results; lock (m_syncRoot) { - results = m_resultQueue.ToArray(); - m_resultQueue.Clear(); + results = m_workQueue.ToArray(); + m_workQueue.Clear(); } NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, () => { - foreach (ParseResult result in results) + foreach (WordformUpdateWork work in results) { - if (!result.IsValid) + if (!work.IsValid) { // the wordform or the candidate analyses are no longer valid, so just skip this parse - FireWordformUpdated(result.Wordform, result.Priority); + FireWordformUpdated(work.Wordform, work.Priority); continue; } - var startTime = DateTime.Now; - string form = result.Wordform.Form.BestVernacularAlternative.Text; + string form = work.Wordform.Form.BestVernacularAlternative.Text; using (new TaskReport(String.Format(ParserCoreStrings.ksUpdateX, form), m_taskUpdateHandler)) { // delete old problem annotations - var problemAnnotations = from ann in m_baseAnnotationRepository.AllInstances() - where - ann.BeginObjectRA == result.Wordform && - ann.SourceRA == m_parserAgent - select ann; - foreach (var problem in problemAnnotations) + IEnumerable problemAnnotations = + from ann in m_baseAnnotationRepository.AllInstances() + where ann.BeginObjectRA == work.Wordform && ann.SourceRA == m_parserAgent + select ann; + foreach (ICmBaseAnnotation problem in problemAnnotations) m_cache.DomainDataByFlid.DeleteObj(problem.Hvo); - if (result.ErrorMessage != null) + if (work.ParseResult.ErrorMessage != null) { // there was an error, so create a problem annotation - var problemReport = m_baseAnnotationFactory.Create(); + ICmBaseAnnotation problemReport = m_baseAnnotationFactory.Create(); m_cache.LangProject.AnnotationsOC.Add(problemReport); - problemReport.CompDetails = result.ErrorMessage; + problemReport.CompDetails = work.ParseResult.ErrorMessage; problemReport.SourceRA = m_parserAgent; problemReport.AnnotationTypeRA = null; - problemReport.BeginObjectRA = result.Wordform; - FinishWordForm(result.Wordform); + problemReport.BeginObjectRA = work.Wordform; + FinishWordForm(work.Wordform); } else { // update the wordform - foreach (var analysis in result.Analyses) - ProcessAnalysis(result.Wordform, analysis); - FinishWordForm(result.Wordform); - RemoveUnlovedParses(result.Wordform); + foreach (ParseAnalysis analysis in work.ParseResult.Analyses) + ProcessAnalysis(work.Wordform, analysis); + FinishWordForm(work.Wordform); + foreach (IWfiAnalysis analysis in work.Wordform.AnalysesOC.Where(anal => anal.GetAgentOpinion(m_parserAgent) != Opinions.approves)) + { + m_analysesWithOldEvaluation.Remove(analysis); + if (analysis.GetAgentOpinion(m_userAgent) == Opinions.noopinion) + analysis.Delete(); + else + m_parserAgent.SetEvaluation(analysis, Opinions.disapproves); + } } - result.Wordform.Checksum = (int)result.Crc; + work.Wordform.Checksum = work.ParseResult.GetHashCode(); } // notify all listeners that the wordform has been updated - FireWordformUpdated(result.Wordform, result.Priority); - long ttlTicks = DateTime.Now.Ticks - startTime.Ticks; - m_ticksFiler += ttlTicks; - m_numberOfWordForms++; - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "parser filer(" + form + ") took : " + TimeSpan.FromTicks(ttlTicks).TotalMilliseconds); + FireWordformUpdated(work.Wordform, work.Priority); } }); return true; @@ -472,14 +247,14 @@ Try to find matching analysis(analyses) that already exist. */ // Find matching analysis/analyses, if any exist. var matches = new HashSet(); - foreach (var anal in wordform.AnalysesOC) + foreach (IWfiAnalysis anal in wordform.AnalysesOC) { if (anal.MorphBundlesOS.Count == analysis.Morphs.Count) { // Meets match condition (1), above. - var mbMatch = false; //Start pessimistically. - var i = 0; - foreach (var mb in anal.MorphBundlesOS) + bool mbMatch = false; //Start pessimistically. + int i = 0; + foreach (IWfiMorphBundle mb in anal.MorphBundlesOS) { var current = analysis.Morphs[i++]; if (mb.MorphRA == current.Form && mb.MsaRA == current.Msa && mb.InflTypeRA == current.InflType) @@ -507,9 +282,9 @@ Try to find matching analysis(analyses) that already exist. var newAnal = m_analysisFactory.Create(); wordform.AnalysesOC.Add(newAnal); // Make WfiMorphBundle(s). - foreach (var morph in analysis.Morphs) + foreach (ParseMorph morph in analysis.Morphs) { - var mb = m_mbFactory.Create(); + IWfiMorphBundle mb = m_mbFactory.Create(); newAnal.MorphBundlesOS.Add(mb); mb.MorphRA = morph.Form; mb.MsaRA = morph.Msa; @@ -519,35 +294,13 @@ Try to find matching analysis(analyses) that already exist. matches.Add(newAnal); } // (Re)set evaluations. - foreach (var matchingAnal in matches) + foreach (IWfiAnalysis matchingAnal in matches) { - m_parserAgent.SetEvaluation(matchingAnal, - Opinions.approves); + m_parserAgent.SetEvaluation(matchingAnal, Opinions.approves); m_analysesWithOldEvaluation.Remove(matchingAnal); } } - /// - /// - /// - private void RemoveUnlovedParses(IWfiWordform wordform) - { - // Solves LT-1842. - /* - Get all the IDs for Analyses that belong to the wordform, but which don't have an - evaluation belonging to the given agent. These will all be set to FAILED. - */ - foreach (var nobodyCareAboutMeAnalysis in wordform.AnalysesOC.Where(anal => - anal.GetAgentOpinion(m_parserAgent) != Opinions.approves // Parser doesn't like it - && anal.GetAgentOpinion(m_userAgent) == Opinions.noopinion)) // And, Human doesn't care - { - // A parser never has 'Opinions.disapproves' - //m_parserAgent.SetEvaluation(failure, Opinions.disapproves); - m_analysesWithOldEvaluation.Remove(nobodyCareAboutMeAnalysis); - nobodyCareAboutMeAnalysis.Delete(); - } - } - #region Wordform Preparation methods private void FinishWordForm(IWfiWordform wordform) @@ -557,8 +310,7 @@ private void FinishWordForm(IWfiWordform wordform) // Delete stale evaluations on analyses. The only non-stale analyses are new, positive ones, so this // makes all analyses that are not known to be correct no-opinion. Later any of them that survive at all // will be changed to failed (if there was no error in parsing the wordform). - var analysesNotUpdated = from analysis in wordform.AnalysesOC where m_analysesWithOldEvaluation.Contains(analysis) select analysis; - foreach (var analysis in analysesNotUpdated) + foreach (IWfiAnalysis analysis in wordform.AnalysesOC.Where(a => m_analysesWithOldEvaluation.Contains(a))) analysis.SetAgentOpinion(m_parserAgent, Opinions.noopinion); // Make sure all analyses have human evaluations, if they, @@ -567,19 +319,21 @@ private void FinishWordForm(IWfiWordform wordform) // .Where(ann => ann.AnnotationTypeRA != null && ann.AnnotationTypeRA.Guid == CmAnnotationDefnTags.kguidAnnWordformInContext) // .ToLookup(ann => ann.InstanceOfRA); var segmentAnalyses = new HashSet(); - foreach (var seg in wordform.OccurrencesBag) + foreach (ISegment seg in wordform.OccurrencesBag) segmentAnalyses.UnionWith(seg.AnalysesRS.ToArray()); - var analyses = from anal in wordform.AnalysesOC - where segmentAnalyses.Contains(anal) || anal.MeaningsOC.Any(segmentAnalyses.Contains) - select anal; - foreach (var analysis in analyses) + IEnumerable analyses = + from anal in wordform.AnalysesOC + where segmentAnalyses.Contains(anal) || anal.MeaningsOC.Any(segmentAnalyses.Contains) + select anal; + foreach (IWfiAnalysis analysis in analyses) m_userAgent.SetEvaluation(analysis, Opinions.approves); // Delete orphan analyses, which have no evaluations (Review JohnT: should we also check for no owned WfiGlosses?) - var orphanedAnalyses = from anal in wordform.AnalysesOC - where anal.EvaluationsRC.Count == 0 - select anal; - foreach (var analysis in orphanedAnalyses) + IEnumerable orphanedAnalyses = + from anal in wordform.AnalysesOC + where anal.EvaluationsRC.Count == 0 + select anal; + foreach (IWfiAnalysis analysis in orphanedAnalyses) m_cache.DomainDataByFlid.DeleteObj(analysis.Hvo); } @@ -587,26 +341,38 @@ where segmentAnalyses.Contains(anal) || anal.MeaningsOC.Any(segmentAnalyses.Cont #endregion Private methods - public static int IndexOfLexEntryRef(string sHvo, int indexOfPeriod) + private class WordformUpdateWork { - int index = 0; - if (indexOfPeriod >= 0) + private readonly IWfiWordform m_wordform; + private readonly ParserPriority m_priority; + private readonly ParseResult m_parseResult; + + public WordformUpdateWork(IWfiWordform wordform, ParserPriority priority, ParseResult parseResult) { - string sIndex = sHvo.Substring(indexOfPeriod+1); - index = Convert.ToInt32(sIndex); + m_wordform = wordform; + m_priority = priority; + m_parseResult = parseResult; } - return index; - } - public static int IndexOfPeriodInMsaHvo(ref string sObjHvo) - { - // Irregulary inflected forms can a combination MSA hvo: the LexEntry hvo, a period, and an index to the LexEntryRef - int indexOfPeriod = sObjHvo.IndexOf('.'); - if (indexOfPeriod >= 0) + public IWfiWordform Wordform + { + get { return m_wordform; } + } + + public ParserPriority Priority + { + get { return m_priority; } + } + + public ParseResult ParseResult + { + get { return m_parseResult; } + } + + public bool IsValid { - sObjHvo = sObjHvo.Substring(0, indexOfPeriod); + get { return m_wordform.IsValidObject && m_parseResult.IsValid; } } - return indexOfPeriod; } } } diff --git a/Src/LexText/ParserEngine/ParserCore/ParseResult.cs b/Src/LexText/ParserEngine/ParserCore/ParseResult.cs index f4c6484f87..d5ff09db03 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParseResult.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParseResult.cs @@ -1,123 +1,163 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using SIL.FieldWorks.FDO; namespace SIL.FieldWorks.WordWorks.Parser { - public class ParseResult + public class ParseResult : IEquatable { - public ParseResult(IWfiWordform wordform, uint crc, ParserPriority priority, IList analyses, - string errorMessage) + private readonly ReadOnlyCollection m_analyses; + private readonly string m_errorMessage; + + public ParseResult(string errorMessage) + : this(Enumerable.Empty(), errorMessage) { - Wordform = wordform; - Crc = crc; - Priority = priority; - Analyses = analyses; - ErrorMessage = errorMessage; } - public IWfiWordform Wordform + public ParseResult(IEnumerable analyses) + : this(analyses, null) { - get; - private set; } - public uint Crc + public ParseResult(IEnumerable analyses, string errorMessage) { - get; - private set; + m_analyses = new ReadOnlyCollection(analyses.ToArray()); + m_errorMessage = errorMessage; } - public IList Analyses + public ReadOnlyCollection Analyses { - get; - private set; + get { return m_analyses; } } public string ErrorMessage { - get; - private set; + get { return m_errorMessage; } } - public ParserPriority Priority + public bool IsValid { - get; - private set; + get { return Analyses.All(analysis => analysis.IsValid); } } - public bool IsValid + public bool Equals(ParseResult other) + { + return m_analyses.SequenceEqual(other.m_analyses) && m_errorMessage == other.m_errorMessage; + } + + public override bool Equals(object obj) { - get - { - if (!Wordform.IsValidObject) - return false; - return Analyses.All(analysis => analysis.IsValid); - } + var other = obj as ParseResult; + return other != null && Equals(other); + } + + public override int GetHashCode() + { + int code = 23; + foreach (ParseAnalysis analysis in m_analyses) + code = code * 31 + analysis.GetHashCode(); + code = code * 31 + (m_errorMessage == null ? 0 : m_errorMessage.GetHashCode()); + return code; } } - public class ParseAnalysis + public class ParseAnalysis : IEquatable { - public ParseAnalysis(IList morphs) + private readonly ReadOnlyCollection m_morphs; + + public ParseAnalysis(IEnumerable morphs) { - Morphs = morphs; + m_morphs = new ReadOnlyCollection(morphs.ToArray()); } - public IList Morphs + public ReadOnlyCollection Morphs { - get; - private set; + get { return m_morphs; } } public bool IsValid { - get - { - return Morphs.All(morph => morph.IsValid); - } + get { return Morphs.All(morph => morph.IsValid); } + } + + public bool Equals(ParseAnalysis other) + { + return m_morphs.SequenceEqual(other.m_morphs); + } + + public override bool Equals(object obj) + { + var other = obj as ParseAnalysis; + return other != null && Equals(other); + } + + public override int GetHashCode() + { + int code = 23; + foreach (ParseMorph morph in m_morphs) + code = code * 31 + morph.GetHashCode(); + return code; } } - public class ParseMorph + public class ParseMorph : IEquatable { + private readonly IMoForm m_form; + private readonly IMoMorphSynAnalysis m_msa; + private readonly ILexEntryInflType m_inflType; + public ParseMorph(IMoForm form, IMoMorphSynAnalysis msa) + : this(form, msa, null) { - Form = form; - Msa = msa; } public ParseMorph(IMoForm form, IMoMorphSynAnalysis msa, ILexEntryInflType inflType) { - Form = form; - Msa = msa; - InflType = inflType; + m_form = form; + m_msa = msa; + m_inflType = inflType; } public IMoForm Form { - get; - private set; + get { return m_form; } } public IMoMorphSynAnalysis Msa { - get; - private set; + get { return m_msa; } } public ILexEntryInflType InflType { - get; - private set; + get { return m_inflType; } } public bool IsValid { - get - { - return Form.IsValidObject && Msa.IsValidObject; - } + get { return Form.IsValidObject && Msa.IsValidObject && (m_inflType == null || m_inflType.IsValidObject); } + } + + public bool Equals(ParseMorph other) + { + return m_form == other.m_form && m_msa == other.m_msa && m_inflType == other.m_inflType; + } + + public override bool Equals(object obj) + { + var other = obj as ParseMorph; + return other != null && Equals(other); + } + + public override int GetHashCode() + { + int code = 23; + code = code * 31 + m_form.Guid.GetHashCode(); + code = code * 31 + m_msa.Guid.GetHashCode(); + code = code * 31 + (m_inflType == null ? 0 : m_inflType.Guid.GetHashCode()); + return code; } } } diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj b/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj index 8aad282bc6..71b03e62aa 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj +++ b/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj @@ -191,10 +191,6 @@ CommonAssemblyInfo.cs - - Code - - @@ -214,16 +210,16 @@ ParserCoreStrings.resx - + Code Code - + Code - + diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.Designer.cs b/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.Designer.cs index ad75668330..83ad880863 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.Designer.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.Designer.cs @@ -150,33 +150,6 @@ internal static string ksIdle_ { } } - /// - /// Looks up a localized string similar to Making HC Files. - /// - internal static string ksMakingHCFiles { - get { - return ResourceManager.GetString("ksMakingHCFiles", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Making XAmple Files. - /// - internal static string ksMakingXAmpleFiles { - get { - return ResourceManager.GetString("ksMakingXAmpleFiles", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Preparing Templates for XAmple Files. - /// - internal static string ksPreparingTemplatesForXAmple { - get { - return ResourceManager.GetString("ksPreparingTemplatesForXAmple", resourceCulture); - } - } - /// /// Looks up a localized string similar to ???. /// @@ -204,24 +177,6 @@ internal static string ksReachedMaxInternalBufferSize { } } - /// - /// Looks up a localized string similar to Retrieving Grammar and Lexicon. - /// - internal static string ksRetrievingGrammarAndLexicon { - get { - return ResourceManager.GetString("ksRetrievingGrammarAndLexicon", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Retrieving Template Information. - /// - internal static string ksRetrievingTemplateInformation { - get { - return ResourceManager.GetString("ksRetrievingTemplateInformation", resourceCulture); - } - } - /// /// Looks up a localized string similar to started. /// diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.resx b/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.resx index fbcb152889..8108502063 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.resx +++ b/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.resx @@ -147,15 +147,6 @@ - - Making HC Files - - - Making XAmple Files - - - Preparing Templates for XAmple Files - ??? missiing/undefined information @@ -166,12 +157,6 @@ Maximum internal buffer size ({0}) reached. - - Retrieving Grammar and Lexicon - - - Retrieving Template Information - started diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParseFilerProcessingTests.cs b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParseFilerProcessingTests.cs index d44bf33c00..9c3cd3d671 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParseFilerProcessingTests.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParseFilerProcessingTests.cs @@ -22,6 +22,7 @@ using NUnit.Framework; using SIL.CoreImpl; using SIL.FieldWorks.FDO; +using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.FDO.FDOTests; using SIL.Utils; @@ -140,7 +141,6 @@ public override void FixtureSetup() public override void FixtureTeardown() { m_vernacularWS = null; - m_filer.Dispose(); m_filer = null; m_idleQueue.Dispose(); m_idleQueue = null; @@ -185,11 +185,9 @@ protected void UndoAll() [Test] public void TooManyAnalyses() { - var bearsTEST = CheckAnnotationSize("bearsTEST", 0, true); - var xmlFragment = "" + Environment.NewLine - + "" + Environment.NewLine - + ""; - m_filer.ProcessParse(ParserPriority.Low, xmlFragment, 0); + IWfiWordform bearsTest = CheckAnnotationSize("bearsTEST", 0, true); + var result = new ParseResult("Maximum permitted analyses (448) reached."); + m_filer.ProcessParse(bearsTest, ParserPriority.Low, result); ExecuteIdleQueue(); CheckAnnotationSize("bearsTEST", 1, false); } @@ -197,11 +195,9 @@ public void TooManyAnalyses() [Test] public void BufferOverrun() { - var dogsTEST = CheckAnnotationSize("dogsTEST", 0, true); - var xmlFragment = "" + Environment.NewLine - + "" + Environment.NewLine - + ""; - m_filer.ProcessParse(ParserPriority.Low, xmlFragment, 0); + IWfiWordform dogsTest = CheckAnnotationSize("dogsTEST", 0, true); + var result = new ParseResult("Maximum internal buffer size (117) reached."); + m_filer.ProcessParse(dogsTest, ParserPriority.Low, result); ExecuteIdleQueue(); CheckAnnotationSize("dogsTEST", 1, false); } @@ -209,71 +205,57 @@ public void BufferOverrun() [Test] public void TwoAnalyses() { - var catsTEST = CheckAnalysisSize("catsTEST", 0, true); - var ldb = Cache.LanguageProject.LexDbOA; + IWfiWordform catsTest = CheckAnalysisSize("catsTEST", 0, true); + ILexDb ldb = Cache.LanguageProject.LexDbOA; - string xmlFragment = null; + ParseResult result = null; UndoableUnitOfWorkHelper.Do("Undo stuff", "Redo stuff", m_actionHandler, () => { // Noun - var catN = m_entryFactory.Create(); - var catNForm = m_stemAlloFactory.Create(); + ILexEntry catN = m_entryFactory.Create(); + IMoStemAllomorph catNForm = m_stemAlloFactory.Create(); catN.AlternateFormsOS.Add(catNForm); catNForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("catNTEST", m_vernacularWS.Handle); - var catNMSA = m_stemMsaFactory.Create(); - catN.MorphoSyntaxAnalysesOC.Add(catNMSA); + IMoStemMsa catNMsa = m_stemMsaFactory.Create(); + catN.MorphoSyntaxAnalysesOC.Add(catNMsa); - var sPL = m_entryFactory.Create(); - var sPLForm = m_afxAlloFactory.Create(); - sPL.AlternateFormsOS.Add(sPLForm); - sPLForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("sPLTEST", m_vernacularWS.Handle); - var sPLMSA = m_inflAffMsaFactory.Create(); - sPL.MorphoSyntaxAnalysesOC.Add(sPLMSA); + ILexEntry sPl = m_entryFactory.Create(); + IMoAffixAllomorph sPlForm = m_afxAlloFactory.Create(); + sPl.AlternateFormsOS.Add(sPlForm); + sPlForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("sPLTEST", m_vernacularWS.Handle); + IMoInflAffMsa sPlMsa = m_inflAffMsaFactory.Create(); + sPl.MorphoSyntaxAnalysesOC.Add(sPlMsa); // Verb - var catV = m_entryFactory.Create(); - var catVForm = m_stemAlloFactory.Create(); + ILexEntry catV = m_entryFactory.Create(); + IMoStemAllomorph catVForm = m_stemAlloFactory.Create(); catV.AlternateFormsOS.Add(catVForm); catVForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("catVTEST", m_vernacularWS.Handle); - var catVMSA = m_stemMsaFactory.Create(); - catV.MorphoSyntaxAnalysesOC.Add(catVMSA); - - var sAGR = m_entryFactory.Create(); - var sAGRForm = m_afxAlloFactory.Create(); - sAGR.AlternateFormsOS.Add(sAGRForm); - sAGRForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("sAGRTEST", m_vernacularWS.Handle); - var sAGRMSA = m_inflAffMsaFactory.Create(); - sAGR.MorphoSyntaxAnalysesOC.Add(sAGRMSA); - - xmlFragment = "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine; + IMoStemMsa catVMsa = m_stemMsaFactory.Create(); + catV.MorphoSyntaxAnalysesOC.Add(catVMsa); + + ILexEntry sAgr = m_entryFactory.Create(); + IMoAffixAllomorph sAgrForm = m_afxAlloFactory.Create(); + sAgr.AlternateFormsOS.Add(sAgrForm); + sAgrForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("sAGRTEST", m_vernacularWS.Handle); + IMoInflAffMsa sAgrMsa = m_inflAffMsaFactory.Create(); + sAgr.MorphoSyntaxAnalysesOC.Add(sAgrMsa); + + result = new ParseResult(new[] + { + new ParseAnalysis(new[] + { + new ParseMorph(catNForm, catNMsa), + new ParseMorph(sPlForm, sPlMsa) + }), + new ParseAnalysis(new[] + { + new ParseMorph(catVForm, catVMsa), + new ParseMorph(sAgrForm, sAgrMsa) + }) + }); }); - - m_filer.ProcessParse(ParserPriority.Low, xmlFragment, 0); + m_filer.ProcessParse(catsTest, ParserPriority.Low, result); ExecuteIdleQueue(); CheckAnalysisSize("catsTEST", 2, false); } @@ -282,52 +264,43 @@ public void TwoAnalyses() [Ignore("Is it ever possible for a parser to return more than one wordform parse?")] public void TwoWordforms() { - var snakeTEST = CheckAnalysisSize("snakeTEST", 0, true); - var bullTEST = CheckAnalysisSize("bullTEST", 0, true); - var ldb = Cache.LanguageProject.LexDbOA; + IWfiWordform snake = CheckAnalysisSize("snakeTEST", 0, true); + IWfiWordform bull = CheckAnalysisSize("bullTEST", 0, true); + ILexDb ldb = Cache.LanguageProject.LexDbOA; - string xmlFragment = null; + ParseResult result = null; UndoableUnitOfWorkHelper.Do("Undo stuff", "Redo stuff", m_actionHandler, () => { // Snake - var snakeN = m_entryFactory.Create(); - var snakeNForm = m_stemAlloFactory.Create(); + ILexEntry snakeN = m_entryFactory.Create(); + IMoStemAllomorph snakeNForm = m_stemAlloFactory.Create(); snakeN.AlternateFormsOS.Add(snakeNForm); snakeNForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("snakeNTEST", m_vernacularWS.Handle); - var snakeNMSA = m_stemMsaFactory.Create(); - snakeN.MorphoSyntaxAnalysesOC.Add(snakeNMSA); + IMoStemMsa snakeNMsa = m_stemMsaFactory.Create(); + snakeN.MorphoSyntaxAnalysesOC.Add(snakeNMsa); // Bull - var bullN = m_entryFactory.Create(); - var bullNForm = m_stemAlloFactory.Create(); + ILexEntry bullN = m_entryFactory.Create(); + IMoStemAllomorph bullNForm = m_stemAlloFactory.Create(); bullN.AlternateFormsOS.Add(bullNForm); bullNForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("bullNTEST", m_vernacularWS.Handle); - var bullNMSA = m_stemMsaFactory.Create(); - bullN.MorphoSyntaxAnalysesOC.Add(bullNMSA); - - xmlFragment = "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine; + IMoStemMsa bullNMsa = m_stemMsaFactory.Create(); + bullN.MorphoSyntaxAnalysesOC.Add(bullNMsa); + + result = new ParseResult(new[] + { + new ParseAnalysis(new[] + { + new ParseMorph(snakeNForm, snakeNMsa) + }), + new ParseAnalysis(new[] + { + new ParseMorph(bullNForm, bullNMsa) + }) + }); }); - m_filer.ProcessParse(ParserPriority.Low, xmlFragment, 0); + m_filer.ProcessParse(snake, ParserPriority.Low, result); ExecuteIdleQueue(); CheckAnalysisSize("snakeTEST", 1, false); CheckAnalysisSize("bullTEST", 1, false); @@ -340,67 +313,64 @@ public void TwoWordforms() [Test] public void DuplicateAnalysesApproval() { - var pigsTEST = CheckAnalysisSize("pigsTEST", 0, true); + IWfiWordform pigs = CheckAnalysisSize("pigsTEST", 0, true); - string xmlFragment = null; + ParseResult result = null; IWfiAnalysis anal1 = null, anal2 = null, anal3 = null; UndoableUnitOfWorkHelper.Do("Undo stuff", "Redo stuff", m_actionHandler, () => { // Bear entry - var pigN = m_entryFactory.Create(); - var pigNForm = m_stemAlloFactory.Create(); + ILexEntry pigN = m_entryFactory.Create(); + IMoStemAllomorph pigNForm = m_stemAlloFactory.Create(); pigN.AlternateFormsOS.Add(pigNForm); pigNForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("pigNTEST", m_vernacularWS.Handle); - var pigNMSA = m_stemMsaFactory.Create(); - pigN.MorphoSyntaxAnalysesOC.Add(pigNMSA); - var pigNLS = Cache.ServiceLocator.GetInstance().Create(); - pigN.SensesOS.Add(pigNLS); + IMoStemMsa pigNMsa = m_stemMsaFactory.Create(); + pigN.MorphoSyntaxAnalysesOC.Add(pigNMsa); + ILexSense pigNSense = Cache.ServiceLocator.GetInstance().Create(); + pigN.SensesOS.Add(pigNSense); var analFactory = Cache.ServiceLocator.GetInstance(); var mbFactory = Cache.ServiceLocator.GetInstance(); // First of two duplicate analyses - var anal = analFactory.Create(); - pigsTEST.AnalysesOC.Add(anal); + IWfiAnalysis anal = analFactory.Create(); + pigs.AnalysesOC.Add(anal); anal1 = anal; - var mb = mbFactory.Create(); + IWfiMorphBundle mb = mbFactory.Create(); anal.MorphBundlesOS.Add(mb); mb.MorphRA = pigNForm; - mb.MsaRA = pigNMSA; + mb.MsaRA = pigNMsa; CheckEvaluationSize(anal1, 0, true, "anal1"); // Non-duplicate, to make sure it does not get approved. anal = analFactory.Create(); - pigsTEST.AnalysesOC.Add(anal); + pigs.AnalysesOC.Add(anal); anal2 = anal; mb = mbFactory.Create(); anal.MorphBundlesOS.Add(mb); - mb.SenseRA = pigNLS; + mb.SenseRA = pigNSense; CheckEvaluationSize(anal2, 0, true, "anal2"); // Second of two duplicate analyses anal = analFactory.Create(); - pigsTEST.AnalysesOC.Add(anal); + pigs.AnalysesOC.Add(anal); anal3 = anal; mb = mbFactory.Create(); anal.MorphBundlesOS.Add(mb); mb.MorphRA = pigNForm; - mb.MsaRA = pigNMSA; + mb.MsaRA = pigNMsa; CheckEvaluationSize(anal3, 0, true, "anal3"); CheckAnalysisSize("pigsTEST", 3, false); - xmlFragment = "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine; + result = new ParseResult(new[] + { + new ParseAnalysis(new[] + { + new ParseMorph(pigNForm, pigNMsa) + }) + }); }); - m_filer.ProcessParse(ParserPriority.Low, xmlFragment, 0); + m_filer.ProcessParse(pigs, ParserPriority.Low, result); ExecuteIdleQueue(); CheckEvaluationSize(anal1, 1, false, "anal1Hvo"); Assert.IsFalse(anal2.IsValidObject, "analysis 2 should end up with no evaluations and so be deleted"); @@ -410,46 +380,45 @@ public void DuplicateAnalysesApproval() [Test] public void HumanApprovedParserPreviouslyApprovedButNowRejectedAnalysisSurvives() { - var theThreeLittlePigsTEST = CheckAnalysisSize("theThreeLittlePigsTEST", 0, true); + IWfiWordform theThreeLittlePigs = CheckAnalysisSize("theThreeLittlePigsTEST", 0, true); - string xmlFragment = null; + ParseResult result = null; IWfiAnalysis anal = null; UndoableUnitOfWorkHelper.Do("Undo stuff", "Redo stuff", m_actionHandler, () => { // Pig entry - var pigN = m_entryFactory.Create(); - var pigNForm = m_stemAlloFactory.Create(); + ILexEntry pigN = m_entryFactory.Create(); + IMoStemAllomorph pigNForm = m_stemAlloFactory.Create(); pigN.AlternateFormsOS.Add(pigNForm); pigNForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("pigNTEST", m_vernacularWS.Handle); - var pigNMSA = m_stemMsaFactory.Create(); - pigN.MorphoSyntaxAnalysesOC.Add(pigNMSA); - var pigNLS = Cache.ServiceLocator.GetInstance().Create(); - pigN.SensesOS.Add(pigNLS); + IMoStemMsa pigNMsa = m_stemMsaFactory.Create(); + pigN.MorphoSyntaxAnalysesOC.Add(pigNMsa); + ILexSense pigNSense = Cache.ServiceLocator.GetInstance().Create(); + pigN.SensesOS.Add(pigNSense); // Human approved anal. Start with parser approved, but then it failed. var analFactory = Cache.ServiceLocator.GetInstance(); var mbFactory = Cache.ServiceLocator.GetInstance(); // Only analysis: human approved, previously parser approved but no longer produced. anal = analFactory.Create(); - theThreeLittlePigsTEST.AnalysesOC.Add(anal); - var mb = mbFactory.Create(); + theThreeLittlePigs.AnalysesOC.Add(anal); + IWfiMorphBundle mb = mbFactory.Create(); anal.MorphBundlesOS.Add(mb); mb.MorphRA = pigNForm; - mb.MsaRA = pigNMSA; + mb.MsaRA = pigNMsa; HumanAgent.SetEvaluation(anal, Opinions.approves); ParserAgent.SetEvaluation(anal, Opinions.approves); CheckEvaluationSize(anal, 2, true, "anal"); CheckAnalysisSize("theThreeLittlePigsTEST", 1, true); - xmlFragment = "" + Environment.NewLine - + "" + Environment.NewLine; + result = new ParseResult(Enumerable.Empty()); }); using (var idleQueue = new IdleQueue()) - using (var filer = new ParseFiler(Cache, task => { }, idleQueue, ParserAgent)) { + var filer = new ParseFiler(Cache, task => { }, idleQueue, ParserAgent); idleQueue.IsPaused = true; - filer.ProcessParse(ParserPriority.Low, xmlFragment, 0); + filer.ProcessParse(theThreeLittlePigs, ParserPriority.Low, result); foreach (var task in idleQueue) task.Delegate(task.Parameter); idleQueue.Clear(); @@ -461,46 +430,45 @@ public void HumanApprovedParserPreviouslyApprovedButNowRejectedAnalysisSurvives( [Test] public void HumanHasNoopinionParserHadApprovedButNoLongerApprovesRemovesAnalisys() { - var threeLittlePigsTEST = CheckAnalysisSize("threeLittlePigsTEST", 0, true); + IWfiWordform threeLittlePigs = CheckAnalysisSize("threeLittlePigsTEST", 0, true); - string xmlFragment = null; + ParseResult result = null; IWfiAnalysis anal = null; UndoableUnitOfWorkHelper.Do("Undo stuff", "Redo stuff", m_actionHandler, () => { // Pig entry - var pigN = m_entryFactory.Create(); - var pigNForm = m_stemAlloFactory.Create(); + ILexEntry pigN = m_entryFactory.Create(); + IMoStemAllomorph pigNForm = m_stemAlloFactory.Create(); pigN.AlternateFormsOS.Add(pigNForm); pigNForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("pigNTEST", m_vernacularWS.Handle); - var pigNMSA = m_stemMsaFactory.Create(); - pigN.MorphoSyntaxAnalysesOC.Add(pigNMSA); - var pigNLS = Cache.ServiceLocator.GetInstance().Create(); - pigN.SensesOS.Add(pigNLS); + IMoStemMsa pigNMsa = m_stemMsaFactory.Create(); + pigN.MorphoSyntaxAnalysesOC.Add(pigNMsa); + ILexSense pigNSense = Cache.ServiceLocator.GetInstance().Create(); + pigN.SensesOS.Add(pigNSense); // Human no-opinion anal. Parser had approved, but then it failed to produce it. var analFactory = Cache.ServiceLocator.GetInstance(); var mbFactory = Cache.ServiceLocator.GetInstance(); // Human no-opinion anal. Parser had approved, but then it failed to produce it. anal = analFactory.Create(); - threeLittlePigsTEST.AnalysesOC.Add(anal); - var mb = mbFactory.Create(); + threeLittlePigs.AnalysesOC.Add(anal); + IWfiMorphBundle mb = mbFactory.Create(); anal.MorphBundlesOS.Add(mb); mb.MorphRA = pigNForm; - mb.MsaRA = pigNMSA; + mb.MsaRA = pigNMsa; HumanAgent.SetEvaluation(anal, Opinions.noopinion); ParserAgent.SetEvaluation(anal, Opinions.approves); CheckEvaluationSize(anal, 1, true, "anal"); CheckAnalysisSize("threeLittlePigsTEST", 1, true); - xmlFragment = "" + Environment.NewLine - + "" + Environment.NewLine; + result = new ParseResult(Enumerable.Empty()); }); using (var idleQueue = new IdleQueue()) - using (var filer = new ParseFiler(Cache, task => { }, idleQueue, ParserAgent)) { + var filer = new ParseFiler(Cache, task => { }, idleQueue, ParserAgent); idleQueue.IsPaused = true; - filer.ProcessParse(ParserPriority.Low, xmlFragment, 0); + filer.ProcessParse(threeLittlePigs, ParserPriority.Low, result); foreach (var task in idleQueue) task.Delegate(task.Parameter); idleQueue.Clear(); @@ -512,46 +480,46 @@ public void HumanHasNoopinionParserHadApprovedButNoLongerApprovesRemovesAnalisys [Test] public void LexEntryInflTypeTwoAnalyses() { - var crebTEST = CheckAnalysisSize("crebTEST", 0, true); - var ldb = Cache.LanguageProject.LexDbOA; + IWfiWordform creb = CheckAnalysisSize("crebTEST", 0, true); + ILexDb ldb = Cache.LanguageProject.LexDbOA; - string xmlFragment = null; + ParseResult result = null; UndoableUnitOfWorkHelper.Do("Undo stuff", "Redo stuff", m_actionHandler, () => { // Verb creb which is a past tense, plural irregularly inflected form of 'believe' and also 'seek' // with automatically generated null Tense slot and an automatically generated null Number slot filler // (This is not supposed to be English, in case you're wondering....) - var pastTenseLexEntryInflType = m_lexEntryInflTypeFactory.Create(); - var pluralTenseLexEntryInflType = m_lexEntryInflTypeFactory.Create(); + ILexEntryInflType pastTenseLexEntryInflType = m_lexEntryInflTypeFactory.Create(); + ILexEntryInflType pluralTenseLexEntryInflType = m_lexEntryInflTypeFactory.Create(); Cache.LangProject.LexDbOA.VariantEntryTypesOA.PossibilitiesOS.Add(pastTenseLexEntryInflType); Cache.LangProject.LexDbOA.VariantEntryTypesOA.PossibilitiesOS.Add(pluralTenseLexEntryInflType); - var believeV = m_entryFactory.Create(); - var believeVForm = m_stemAlloFactory.Create(); + ILexEntry believeV = m_entryFactory.Create(); + IMoStemAllomorph believeVForm = m_stemAlloFactory.Create(); believeV.AlternateFormsOS.Add(believeVForm); believeVForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("believeVTEST", m_vernacularWS.Handle); - var believeVMSA = m_stemMsaFactory.Create(); - believeV.MorphoSyntaxAnalysesOC.Add(believeVMSA); - var believeVSense = m_senseFactory.Create(); + IMoStemMsa believeVMsa = m_stemMsaFactory.Create(); + believeV.MorphoSyntaxAnalysesOC.Add(believeVMsa); + ILexSense believeVSense = m_senseFactory.Create(); believeV.SensesOS.Add(believeVSense); - believeVSense.MorphoSyntaxAnalysisRA = believeVMSA; + believeVSense.MorphoSyntaxAnalysisRA = believeVMsa; - var seekV = m_entryFactory.Create(); - var seekVForm = m_stemAlloFactory.Create(); + ILexEntry seekV = m_entryFactory.Create(); + IMoStemAllomorph seekVForm = m_stemAlloFactory.Create(); believeV.AlternateFormsOS.Add(seekVForm); seekVForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("seekVTEST", m_vernacularWS.Handle); - var seekVMSA = m_stemMsaFactory.Create(); - seekV.MorphoSyntaxAnalysesOC.Add(seekVMSA); - var seekVSense = m_senseFactory.Create(); + IMoStemMsa seekVMsa = m_stemMsaFactory.Create(); + seekV.MorphoSyntaxAnalysesOC.Add(seekVMsa); + ILexSense seekVSense = m_senseFactory.Create(); seekV.SensesOS.Add(seekVSense); - seekVSense.MorphoSyntaxAnalysisRA = seekVMSA; + seekVSense.MorphoSyntaxAnalysisRA = seekVMsa; - var crebV = m_entryFactory.Create(); - var crebVForm = m_stemAlloFactory.Create(); + ILexEntry crebV = m_entryFactory.Create(); + IMoStemAllomorph crebVForm = m_stemAlloFactory.Create(); crebV.AlternateFormsOS.Add(crebVForm); crebVForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("crebVTEST", m_vernacularWS.Handle); - var lexEntryref = m_lexEntryRefFactory.Create(); + ILexEntryRef lexEntryref = m_lexEntryRefFactory.Create(); crebV.EntryRefsOS.Add(lexEntryref); lexEntryref.ComponentLexemesRS.Add(believeV); lexEntryref.VariantEntryTypesRS.Add(pastTenseLexEntryInflType); @@ -562,59 +530,39 @@ public void LexEntryInflTypeTwoAnalyses() lexEntryref.VariantEntryTypesRS.Add(pastTenseLexEntryInflType); lexEntryref.VariantEntryTypesRS.Add(pluralTenseLexEntryInflType); - var nullPAST = m_entryFactory.Create(); - var nullPASTForm = m_afxAlloFactory.Create(); - nullPAST.AlternateFormsOS.Add(nullPASTForm); - nullPASTForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("nullPASTTEST", m_vernacularWS.Handle); - var nullPASTMSA = m_inflAffMsaFactory.Create(); - nullPAST.MorphoSyntaxAnalysesOC.Add(nullPASTMSA); - - var nullPLURAL = m_entryFactory.Create(); - var nullPLURALForm = m_afxAlloFactory.Create(); - nullPLURAL.AlternateFormsOS.Add(nullPLURALForm); - nullPLURALForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("nullPLURALTEST", m_vernacularWS.Handle); - var nullPluralMSA = m_inflAffMsaFactory.Create(); - nullPLURAL.MorphoSyntaxAnalysesOC.Add(nullPluralMSA); - - xmlFragment = "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine + "" + Environment.NewLine; + ILexEntry nullPast = m_entryFactory.Create(); + IMoAffixAllomorph nullPastForm = m_afxAlloFactory.Create(); + nullPast.AlternateFormsOS.Add(nullPastForm); + nullPastForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("nullPASTTEST", m_vernacularWS.Handle); + IMoInflAffMsa nullPastMsa = m_inflAffMsaFactory.Create(); + nullPast.MorphoSyntaxAnalysesOC.Add(nullPastMsa); + + ILexEntry nullPlural = m_entryFactory.Create(); + IMoAffixAllomorph nullPluralForm = m_afxAlloFactory.Create(); + nullPlural.AlternateFormsOS.Add(nullPluralForm); + nullPluralForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("nullPLURALTEST", m_vernacularWS.Handle); + IMoInflAffMsa nullPluralMsa = m_inflAffMsaFactory.Create(); + nullPlural.MorphoSyntaxAnalysesOC.Add(nullPluralMsa); + + result = new ParseResult(new[] + { + new ParseAnalysis(new[] + { + new ParseMorph(crebVForm, MorphServices.GetMainOrFirstSenseOfVariant(crebV.EntryRefsOS[1]).MorphoSyntaxAnalysisRA, + (ILexEntryInflType) crebV.EntryRefsOS[1].VariantEntryTypesRS[0]) + }), + new ParseAnalysis(new[] + { + new ParseMorph(crebVForm, MorphServices.GetMainOrFirstSenseOfVariant(crebV.EntryRefsOS[0]).MorphoSyntaxAnalysisRA, + (ILexEntryInflType) crebV.EntryRefsOS[0].VariantEntryTypesRS[0]) + }) + }); }); - m_filer.ProcessParse(ParserPriority.Low, xmlFragment, 0); + m_filer.ProcessParse(creb, ParserPriority.Low, result); ExecuteIdleQueue(); CheckAnalysisSize("crebTEST", 2, false); - foreach (var analysis in crebTEST.AnalysesOC) + foreach (var analysis in creb.AnalysesOC) { Assert.AreEqual(1, analysis.MorphBundlesOS.Count, "Expected only 1 morph in the analysis"); var morphBundle = analysis.MorphBundlesOS.ElementAt(0); @@ -627,76 +575,67 @@ public void LexEntryInflTypeTwoAnalyses() [Test] public void LexEntryInflTypeAnalysisWithNullForSlotFiller() { - var brubsTEST = CheckAnalysisSize("brubsTEST", 0, true); - var ldb = Cache.LanguageProject.LexDbOA; + IWfiWordform brubs = CheckAnalysisSize("brubsTEST", 0, true); + ILexDb ldb = Cache.LanguageProject.LexDbOA; - string xmlFragment = null; + ParseResult result = null; UndoableUnitOfWorkHelper.Do("Undo stuff", "Redo stuff", m_actionHandler, () => { // Verb brub which is a present tense irregularly inflected form of 'believe' // with automatically generated null Tense slot and an -s Plural Number slot filler // (This is not supposed to be English, in case you're wondering....) - var presentTenseLexEntryInflType = m_lexEntryInflTypeFactory.Create(); + ILexEntryInflType presentTenseLexEntryInflType = m_lexEntryInflTypeFactory.Create(); Cache.LangProject.LexDbOA.VariantEntryTypesOA.PossibilitiesOS.Add(presentTenseLexEntryInflType); - var believeV = m_entryFactory.Create(); - var believeVForm = m_stemAlloFactory.Create(); + ILexEntry believeV = m_entryFactory.Create(); + IMoStemAllomorph believeVForm = m_stemAlloFactory.Create(); believeV.AlternateFormsOS.Add(believeVForm); believeVForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("believeVTEST", m_vernacularWS.Handle); - var believeVMSA = m_stemMsaFactory.Create(); - believeV.MorphoSyntaxAnalysesOC.Add(believeVMSA); - var believeVSense = m_senseFactory.Create(); + IMoStemMsa believeVMsa = m_stemMsaFactory.Create(); + believeV.MorphoSyntaxAnalysesOC.Add(believeVMsa); + ILexSense believeVSense = m_senseFactory.Create(); believeV.SensesOS.Add(believeVSense); - believeVSense.MorphoSyntaxAnalysisRA = believeVMSA; + believeVSense.MorphoSyntaxAnalysisRA = believeVMsa; - var brubV = m_entryFactory.Create(); - var brubVForm = m_stemAlloFactory.Create(); + ILexEntry brubV = m_entryFactory.Create(); + IMoStemAllomorph brubVForm = m_stemAlloFactory.Create(); brubV.AlternateFormsOS.Add(brubVForm); brubVForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("brubVTEST", m_vernacularWS.Handle); - var lexEntryref = m_lexEntryRefFactory.Create(); + ILexEntryRef lexEntryref = m_lexEntryRefFactory.Create(); brubV.EntryRefsOS.Add(lexEntryref); lexEntryref.ComponentLexemesRS.Add(believeV); lexEntryref.VariantEntryTypesRS.Add(presentTenseLexEntryInflType); - var nullPRESENT = m_entryFactory.Create(); - var nullPRESENTForm = m_afxAlloFactory.Create(); - nullPRESENT.AlternateFormsOS.Add(nullPRESENTForm); - nullPRESENTForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("nullPRESENTTEST", m_vernacularWS.Handle); - var nullPRESENTMSA = m_inflAffMsaFactory.Create(); - nullPRESENT.MorphoSyntaxAnalysesOC.Add(nullPRESENTMSA); - - var sPLURAL = m_entryFactory.Create(); - var sPLURALForm = m_afxAlloFactory.Create(); - sPLURAL.AlternateFormsOS.Add(sPLURALForm); - sPLURALForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("sPLURALTEST", m_vernacularWS.Handle); - var sPluralMSA = m_inflAffMsaFactory.Create(); - sPLURAL.MorphoSyntaxAnalysesOC.Add(sPluralMSA); - - xmlFragment = "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine - + "" + Environment.NewLine; + ILexEntry nullPresent = m_entryFactory.Create(); + IMoAffixAllomorph nullPresentForm = m_afxAlloFactory.Create(); + nullPresent.AlternateFormsOS.Add(nullPresentForm); + nullPresentForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("nullPRESENTTEST", m_vernacularWS.Handle); + IMoInflAffMsa nullPresentMsa = m_inflAffMsaFactory.Create(); + nullPresent.MorphoSyntaxAnalysesOC.Add(nullPresentMsa); + + ILexEntry sPlural = m_entryFactory.Create(); + IMoAffixAllomorph sPluralForm = m_afxAlloFactory.Create(); + sPlural.AlternateFormsOS.Add(sPluralForm); + sPluralForm.Form.VernacularDefaultWritingSystem = Cache.TsStrFactory.MakeString("sPLURALTEST", m_vernacularWS.Handle); + IMoInflAffMsa sPluralMsa = m_inflAffMsaFactory.Create(); + sPlural.MorphoSyntaxAnalysesOC.Add(sPluralMsa); + + result = new ParseResult(new[] + { + new ParseAnalysis(new[] + { + new ParseMorph(brubVForm, MorphServices.GetMainOrFirstSenseOfVariant(brubV.EntryRefsOS[0]).MorphoSyntaxAnalysisRA, + (ILexEntryInflType) brubV.EntryRefsOS[0].VariantEntryTypesRS[0]), + new ParseMorph(sPluralForm, sPluralMsa) + }) + }); }); - m_filer.ProcessParse(ParserPriority.Low, xmlFragment, 0); + m_filer.ProcessParse(brubs, ParserPriority.Low, result); ExecuteIdleQueue(); CheckAnalysisSize("brubsTEST", 1, false); - var analysis = brubsTEST.AnalysesOC.ElementAt(0); + var analysis = brubs.AnalysesOC.ElementAt(0); Assert.AreEqual(2, analysis.MorphBundlesOS.Count, "Expected only 2 morphs in the analysis"); var morphBundle = analysis.MorphBundlesOS.ElementAt(0); Assert.IsNotNull(morphBundle.Form, "First bundle: form is not null"); diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/WorkerTests.cs b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/WorkerTests.cs index d5c80b16b8..df14cb9615 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/WorkerTests.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/WorkerTests.cs @@ -33,22 +33,22 @@ public class WorkerTests : BaseTest [Test] public void ConvertNameToUseANSICharactersTest() { - // plain, simple ASCII - string name = "abc 123"; - string convertedName = ParserWorker.ConvertNameToUseANSICharacters(name); - Assert.AreEqual("abc 123", convertedName); - // Using upper ANSI characters as well as ASCII - name = "ÿýúadctl"; - convertedName = ParserWorker.ConvertNameToUseANSICharacters(name); - Assert.AreEqual("ÿýúadctl", convertedName); - // Using characters just above ANSI as well as ASCII - name = "ąćălex"; - convertedName = ParserWorker.ConvertNameToUseANSICharacters(name); - Assert.AreEqual("010501070103lex", convertedName); - // Using Cyrillic characters as well as ASCII - name = "Английский для семинараgram"; - convertedName = ParserWorker.ConvertNameToUseANSICharacters(name); - Assert.AreEqual("0410043D0433043B043804390441043A04380439 0434043B044F 04410435043C0438043D043004400430gram", convertedName); + //// plain, simple ASCII + //string name = "abc 123"; + //string convertedName = ParserWorker.ConvertNameToUseANSICharacters(name); + //Assert.AreEqual("abc 123", convertedName); + //// Using upper ANSI characters as well as ASCII + //name = "ÿýúadctl"; + //convertedName = ParserWorker.ConvertNameToUseANSICharacters(name); + //Assert.AreEqual("ÿýúadctl", convertedName); + //// Using characters just above ANSI as well as ASCII + //name = "ąćălex"; + //convertedName = ParserWorker.ConvertNameToUseANSICharacters(name); + //Assert.AreEqual("010501070103lex", convertedName); + //// Using Cyrillic characters as well as ASCII + //name = "Английский для семинараgram"; + //convertedName = ParserWorker.ConvertNameToUseANSICharacters(name); + //Assert.AreEqual("0410043D0433043B043804390441043A04380439 0434043B044F 04410435043C0438043D043004400430gram", convertedName); } } } diff --git a/Src/LexText/ParserEngine/ParserCore/Scheduler.cs b/Src/LexText/ParserEngine/ParserCore/ParserScheduler.cs similarity index 85% rename from Src/LexText/ParserEngine/ParserCore/Scheduler.cs rename to Src/LexText/ParserEngine/ParserCore/ParserScheduler.cs index 21677e6ae2..6cc796473e 100644 --- a/Src/LexText/ParserEngine/ParserCore/Scheduler.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserScheduler.cs @@ -17,9 +17,8 @@ // // -------------------------------------------------------------------------------------------- using System; -using System.Diagnostics; using System.Collections.Generic; -using SIL.Utils; // for Win32 message defns. +using SIL.Utils; using SIL.FieldWorks.FDO; namespace SIL.FieldWorks.WordWorks.Parser @@ -135,15 +134,12 @@ public override void DoWork() public event EventHandler ParserUpdateNormal; private readonly ConsumerThread m_thread; - private readonly ParserWorker m_parserWorker; - private readonly FdoCache m_cache; + private ParserWorker m_parserWorker; private readonly object m_syncRoot = new object(); private readonly int[] m_queueCounts = new int[5]; private volatile bool m_tryAWordDialogRunning; private TaskReport m_TaskReport; - private readonly TraceSwitch m_tracingSwitch = new TraceSwitch("ParserCore.TracingSwitch", "Just regular tracking", "Off"); - /// ----------------------------------------------------------------------------------- /// /// Initializes a new instance of the class. @@ -151,25 +147,7 @@ public override void DoWork() /// ----------------------------------------------------------------------------------- public ParserScheduler(FdoCache cache, IdleQueue idleQueue, string appInstallDir) { - if (cache == null) throw new ArgumentNullException("cache"); - - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "ParserScheduler(): CurrentThreadId = " + Win32.GetCurrentThreadId()); - - m_cache = cache; - - switch (m_cache.LanguageProject.MorphologicalDataOA.ActiveParser) - { - - case "XAmple": - m_parserWorker = new XAmpleParserWorker(cache, HandleTaskUpdate, idleQueue, appInstallDir); - break; - case "HC": - m_parserWorker = new HCParserWorker(cache, HandleTaskUpdate, idleQueue, appInstallDir); - break; - - default: - throw new InvalidOperationException("The language project is set to use an unrecognized parser."); - } + m_parserWorker = new ParserWorker(cache, HandleTaskUpdate, idleQueue, appInstallDir); m_parserWorker.ParseFiler.WordformUpdated += ParseFiler_WordformUpdated; m_thread = new ConsumerThread(Work) {IsBackground = true}; @@ -224,14 +202,14 @@ public bool TryAWordDialogIsRunning protected override void DisposeManagedResources() { - if (m_thread.Stop()) - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "==== ParserScheduler thread Successfully shutdown."); - else - Trace.WriteLineIf(m_tracingSwitch.TraceError, "**** ERROR : ParserScheduler Thread didn't shutdown."); m_thread.Dispose(); - m_parserWorker.ParseFiler.WordformUpdated -= ParseFiler_WordformUpdated; - m_parserWorker.Dispose(); + if (m_parserWorker != null) + { + m_parserWorker.ParseFiler.WordformUpdated -= ParseFiler_WordformUpdated; + m_parserWorker.Dispose(); + m_parserWorker = null; + } if (m_TaskReport != null) { @@ -328,8 +306,6 @@ private void HandleTaskUpdate(TaskReport task) { CheckDisposed(); - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "Scheduler.HandleTaskUpdate() " + task.Description + " " + task.PhaseDescription); - if (ParserUpdateNormal != null && ((task.Depth == 0) || (task.NotificationMessage != null))) { //notify any delegates @@ -341,9 +317,6 @@ private void HandleTaskUpdate(TaskReport task) //notify any delegates ParserUpdateVerbose(this, new ParserUpdateEventArgs(task.MostRecentTask)/*not sure this is right*/); } - - - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, " Exiting HandleTaskUpdate()" + task.Description); } private void ParseFiler_WordformUpdated(object sender, WordformUpdatedEventArgs e) diff --git a/Src/LexText/ParserEngine/ParserCore/ParserWorker.cs b/Src/LexText/ParserEngine/ParserCore/ParserWorker.cs new file mode 100644 index 0000000000..aef278699e --- /dev/null +++ b/Src/LexText/ParserEngine/ParserCore/ParserWorker.cs @@ -0,0 +1,169 @@ +// -------------------------------------------------------------------------------------------- +#region // Copyright (c) 2009, SIL International. All Rights Reserved. +// +// Copyright (c) 2009, SIL International. All Rights Reserved. +// +// Distributable under the terms of either the Common Public License or the +// GNU Lesser General Public License, as specified in the LICENSING.txt file. +// +#endregion +// +// File: ParserWorker.cs +// Responsibility: +// +// +// The name here, "worker" would lead one to think that this is the +// class which is the top of the heap of the worker thread. +// However, it is actually the "Scheduler" class which controls the thread and calls this. +// +// -------------------------------------------------------------------------------------------- +/* + +throws exception: * One way I recall is that they would create an inflectional template, but not put anything in it yet (i.e. no slots at all). + * This causes XAmple to die because it produces a PC-PATR load error. + * This could be fixed, of course, in the XSLT that generates the grammar file. + * This one's on my TODO list (I've got the sticky note from Dallas)... + + +no exception: Try an adhoc prohibition with only one item in it + +no exception: Create a compound with neither member specified or only one specified. + +no exception: Create an allomorph with an environment that is ill-formed. (Presumably this will result in the same problem as breaking an environment for an existing allomorph.) + +no exception: Create an infl affix slot with no affixes in it and then use this slot in a template (though this just might not cause the parser to fail - it would just be useless!). + +*/ +using System; +using SIL.Utils; +using SIL.FieldWorks.FDO; +using SIL.FieldWorks.FDO.Infrastructure; +using SIL.FieldWorks.Common.COMInterfaces; + +namespace SIL.FieldWorks.WordWorks.Parser +{ + /// + /// Summary description for ParserWorker. + /// + public class ParserWorker : FwDisposableBase + { + private readonly FdoCache m_cache; + private readonly Action m_taskUpdateHandler; + private readonly ParseFiler m_parseFiler; + private int m_numberOfWordForms; + private IParser m_parser; + + /// ----------------------------------------------------------------------------------- + /// + /// Initializes a new instance of the class. + /// + /// ----------------------------------------------------------------------------------- + public ParserWorker(FdoCache cache, Action taskUpdateHandler, IdleQueue idleQueue, string appInstallDir) + { + m_cache = cache; + m_taskUpdateHandler = taskUpdateHandler; + ICmAgent agent; + switch (m_cache.LanguageProject.MorphologicalDataOA.ActiveParser) + { + case "XAmple": + m_parser = new XAmpleParser(cache, appInstallDir); + agent = cache.ServiceLocator.GetInstance().GetObject(CmAgentTags.kguidAgentXAmpleParser); + break; + case "HC": + // create HCParser here + agent = cache.ServiceLocator.GetInstance().GetObject(CmAgentTags.kguidAgentHermitCrabParser); + break; + default: + throw new InvalidOperationException("The language project is set to use an unrecognized parser."); + } + m_parseFiler = new ParseFiler(cache, taskUpdateHandler, idleQueue, agent); + } + + protected override void DisposeManagedResources() + { + var disposeParser = m_parser as IDisposable; + if (disposeParser != null) + { + disposeParser.Dispose(); + m_parser = null; + } + } + + public ParseFiler ParseFiler + { + get + { + CheckDisposed(); + return m_parseFiler; + } + } + + /// + /// Try parsing a wordform, optionally getting a trace of the parse + /// + /// the word form to parse + /// whether or not to trace the parse + /// list of msa hvos to limit trace to + public void TryAWord(string sForm, bool fDoTrace, string sSelectTraceMorphs) + { + CheckDisposed(); + + if (sForm == null) + throw new ArgumentNullException("sForm", "TryAWord cannot trace a Null string."); + if (sForm == String.Empty) + throw new ArgumentException("Can't try a word with no content.", "sForm"); + + CheckNeedsUpdate(); + using (var task = new TaskReport(string.Format(ParserCoreStrings.ksTraceWordformX, sForm), m_taskUpdateHandler)) + { + string normForm = Icu.Normalize(sForm, Icu.UNormalizationMode.UNORM_NFD); + var result = fDoTrace ? m_parser.TraceWordXml(normForm, sSelectTraceMorphs) : m_parser.ParseWordXml(normForm); + task.Details = fDoTrace ? result : Icu.Normalize(result, Icu.UNormalizationMode.UNORM_NFD); + } + } + + public bool UpdateWordform(IWfiWordform wordform, ParserPriority priority) + { + CheckDisposed(); + + int wordformHash = 0; + ITsString form = null; + int hvo = 0; + using (new WorkerThreadReadHelper(m_cache.ServiceLocator.GetInstance())) + { + if (wordform.IsValidObject) + { + wordformHash = wordform.Checksum; + form = wordform.Form.VernacularDefaultWritingSystem; + } + } + // 'form' will now be null, if it could not find the wordform for whatever reason. + // uiCRCWordform will also now be 0, if 'form' is null. + if (form == null || string.IsNullOrEmpty(form.Text)) + return false; + + CheckNeedsUpdate(); + ParseResult result = m_parser.ParseWord(Icu.Normalize(form.Text.Replace(' ', '.'), Icu.UNormalizationMode.UNORM_NFD)); + if (wordformHash == result.GetHashCode()) + return false; + + return m_parseFiler.ProcessParse(wordform, priority, result); + } + + private void CheckNeedsUpdate() + { + using (var task = new TaskReport(ParserCoreStrings.ksUpdatingGrammarAndLexicon, m_taskUpdateHandler)) + { + m_parser.Initialize(); + } + } + + public void ReloadGrammarAndLexicon() + { + CheckDisposed(); + + m_parser.Reset(); + CheckNeedsUpdate(); + } + } +} diff --git a/Src/LexText/ParserEngine/ParserCore/Worker.cs b/Src/LexText/ParserEngine/ParserCore/Worker.cs deleted file mode 100644 index ea1d880ecd..0000000000 --- a/Src/LexText/ParserEngine/ParserCore/Worker.cs +++ /dev/null @@ -1,234 +0,0 @@ -// -------------------------------------------------------------------------------------------- -#region // Copyright (c) 2009, SIL International. All Rights Reserved. -// -// Copyright (c) 2009, SIL International. All Rights Reserved. -// -// Distributable under the terms of either the Common Public License or the -// GNU Lesser General Public License, as specified in the LICENSING.txt file. -// -#endregion -// -// File: ParserWorker.cs -// Responsibility: -// -// -// The name here, "worker" would lead one to think that this is the -// class which is the top of the heap of the worker thread. -// However, it is actually the "Scheduler" class which controls the thread and calls this. -// -// -------------------------------------------------------------------------------------------- -/* - -throws exception: * One way I recall is that they would create an inflectional template, but not put anything in it yet (i.e. no slots at all). - * This causes XAmple to die because it produces a PC-PATR load error. - * This could be fixed, of course, in the XSLT that generates the grammar file. - * This one's on my TODO list (I've got the sticky note from Dallas)... - - -no exception: Try an adhoc prohibition with only one item in it - -no exception: Create a compound with neither member specified or only one specified. - -no exception: Create an allomorph with an environment that is ill-formed. (Presumably this will result in the same problem as breaking an environment for an existing allomorph.) - -no exception: Create an infl affix slot with no affixes in it and then use this slot in a template (though this just might not cause the parser to fail - it would just be useless!). - -*/ -using System; -using System.Diagnostics; -using System.Text; -using System.Xml; - -using CodeProject.ReiMiyasaka; - -using SIL.Utils; -using SIL.FieldWorks.FDO; -using SIL.FieldWorks.FDO.Infrastructure; -using SIL.FieldWorks.Common.COMInterfaces; - -namespace SIL.FieldWorks.WordWorks.Parser -{ - /// - /// Summary description for ParserWorker. - /// - public abstract class ParserWorker : FwDisposableBase - { - protected readonly FdoCache m_cache; - protected readonly Action m_taskUpdateHandler; - protected readonly string m_appInstallDir; - private readonly ParseFiler m_parseFiler; - private long m_ticksParser; - private int m_numberOfWordForms; - protected readonly M3ParserModelRetriever m_retriever; - - protected string m_projectName; - protected TraceSwitch m_tracingSwitch = new TraceSwitch("ParserCore.TracingSwitch", "Just regular tracking", "Off"); - - /// ----------------------------------------------------------------------------------- - /// - /// Initializes a new instance of the class. - /// - /// ----------------------------------------------------------------------------------- - protected ParserWorker(FdoCache cache, Action taskUpdateHandler, IdleQueue idleQueue, ICmAgent agent, string appInstallDir) - { - m_cache = cache; - m_taskUpdateHandler = taskUpdateHandler; - m_appInstallDir = appInstallDir; - m_parseFiler = new ParseFiler(cache, taskUpdateHandler, idleQueue, agent); - // N.B. m_projectName here is only used to create temporary files for the parser to load. - // We convert the name to use strictly ANSI characters so that the parsers (which are or involve - // legacy C programs) can read the file names. - m_projectName = ConvertNameToUseANSICharacters(cache.ProjectId.Name); - m_retriever = new M3ParserModelRetriever(m_cache, m_taskUpdateHandler); - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "ParserWorker(): CurrentThreadId = " + Win32.GetCurrentThreadId()); - } - - /// - /// Convert any characters in the name which are higher than 0x00FF to hex. - /// Neither XAmple nor PC-PATR can read a file name containing letters above 0x00FF. - /// - /// The original name to be converted - /// Converted name - public static string ConvertNameToUseANSICharacters(string originalName) - { - StringBuilder sb = new StringBuilder(); - char[] letters = originalName.ToCharArray(); - foreach (var letter in letters) - { - int value = Convert.ToInt32(letter); - if (value > 255) - { - string hex = value.ToString("X4"); - sb.Append(hex); - } - else - { - sb.Append(letter); - } - } - return sb.ToString(); - } - - protected override void DisposeManagedResources() - { - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "Total number of wordforms parsed = " + m_numberOfWordForms); - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "Total time for parser = " + m_ticksParser); - - if (m_numberOfWordForms != 0) - { - long lAvg = m_ticksParser/m_numberOfWordForms; - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "Average time for parser = " + lAvg); - } - - m_parseFiler.Dispose(); - m_retriever.Dispose(); - } - - public ParseFiler ParseFiler - { - get - { - CheckDisposed(); - return m_parseFiler; - } - } - - protected abstract string ParseWord(string form, int hvoWordform); - protected abstract string TraceWord(string form, string selectTraceMorphs); - - private string GetOneWordformResult(int hvoWordform, string form) - { - Debug.Assert(hvoWordform > 0, "Wordform ID must be greater than zero."); - Debug.Assert(form != null, "Wordform form must not be null."); - - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "GetOneWordformResult(): CurrentThreadId = " + Win32.GetCurrentThreadId()); - var startTime = DateTime.Now; - var results = ParseWord(Icu.Normalize(form, Icu.UNormalizationMode.UNORM_NFD), hvoWordform); - long ttlTicks = DateTime.Now.Ticks - startTime.Ticks; - m_ticksParser += ttlTicks; - m_numberOfWordForms++; - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "ParseWord(" + form + ") took : " + ttlTicks); - return Icu.Normalize(results, Icu.UNormalizationMode.UNORM_NFD); - } - - /// - /// Try parsing a wordform, optionally getting a trace of the parse - /// - /// the word form to parse - /// whether or not to trace the parse - /// list of msa hvos to limit trace to - public void TryAWord(string sForm, bool fDoTrace, string sSelectTraceMorphs) - { - CheckDisposed(); - - if (sForm == null) - throw new ArgumentNullException("sForm", "TryAWord cannot trace a Null string."); - if (sForm == String.Empty) - throw new ArgumentException("Can't try a word with no content.", "sForm"); - - CheckNeedsUpdate(); - using (var task = new TaskReport(string.Format(ParserCoreStrings.ksTraceWordformX, sForm), m_taskUpdateHandler)) - { - var normForm = Icu.Normalize(sForm, Icu.UNormalizationMode.UNORM_NFD); - var result = fDoTrace ? TraceWord(normForm, sSelectTraceMorphs) : ParseWord(normForm, 0); - if (fDoTrace) - task.Details = result; - else - task.Details = Icu.Normalize(result, Icu.UNormalizationMode.UNORM_NFD); - } - } - - public bool UpdateWordform(IWfiWordform wordform, ParserPriority priority) - { - CheckDisposed(); - - uint crcWordform = 0; - ITsString form = null; - int hvo = 0; - using (new WorkerThreadReadHelper(m_cache.ServiceLocator.GetInstance())) - { - if (wordform.IsValidObject) - { - crcWordform = (uint) wordform.Checksum; - form = wordform.Form.VernacularDefaultWritingSystem; - hvo = wordform.Hvo; - } - } - // 'form' will now be null, if it could not find the wordform for whatever reason. - // uiCRCWordform will also now be 0, if 'form' is null. - if (form == null || string.IsNullOrEmpty(form.Text)) - return false; - - CheckNeedsUpdate(); - string result = GetOneWordformResult(hvo, form.Text.Replace(' ', '.')); // LT-7334 to allow for phrases - uint crc = CrcStream.GetCrc(result); - if (crcWordform == crc) - return false; - - return m_parseFiler.ProcessParse(priority, result, crc); - } - - public void ReloadGrammarAndLexicon() - { - CheckDisposed(); - - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "ParserWorker.ReloadGrammarAndLexicon"); - m_retriever.Reset(); - CheckNeedsUpdate(); - } - - private void CheckNeedsUpdate() - { - DateTime startTime = DateTime.Now; - if (m_retriever.RetrieveModel()) - { - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "Model retrieval took : " + (DateTime.Now.Ticks - startTime.Ticks)); - XmlDocument fxtResult = m_retriever.ModelDom; - XmlDocument gafawsFxtResult = m_retriever.TemplateDom; - LoadParser(ref fxtResult, gafawsFxtResult); - } - } - - protected abstract void LoadParser(ref XmlDocument model, XmlDocument template); - } -} diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs b/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs new file mode 100644 index 0000000000..ffd5408d75 --- /dev/null +++ b/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs @@ -0,0 +1,266 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Text; +using System.Xml; +using System.Xml.Linq; +using SIL.FieldWorks.FDO; +using SIL.FieldWorks.FDO.DomainServices; +using SIL.FieldWorks.FDO.Infrastructure; +using SIL.Utils; +using XAmpleManagedWrapper; + +namespace SIL.FieldWorks.WordWorks.Parser +{ + public class XAmpleParser : FwDisposableBase, IParser + { + private XAmpleWrapper m_xample; + private readonly string m_appInstallDir; + private readonly FdoCache m_cache; + private M3ParserModelRetriever m_retriever; + + public XAmpleParser(FdoCache cache, string appInstallDir) + { + m_cache = cache; + m_xample = new XAmpleWrapper(); + m_xample.Init(appInstallDir); + m_appInstallDir = appInstallDir; + m_retriever = new M3ParserModelRetriever(m_cache); + } + + public void Initialize() + { + CheckDisposed(); + + if (!m_retriever.RetrieveModel()) + return; + + XmlDocument fxtResult = m_retriever.ModelDom; + XmlDocument gafawsFxtResult = m_retriever.TemplateDom; + string projectName = ConvertNameToUseAnsiCharacters(m_cache.ProjectId.Name); + + var transformer = new M3ToXAmpleTransformer(projectName, m_appInstallDir); + // PrepareTemplatesForXAmpleFiles adds orderclass elements to MoInflAffixSlot elements + transformer.PrepareTemplatesForXAmpleFiles(ref fxtResult, gafawsFxtResult); + + transformer.MakeAmpleFiles(fxtResult); + + int maxAnalCount = 20; + XmlNode maxAnalCountNode = fxtResult.SelectSingleNode("/M3Dump/ParserParameters/XAmple/MaxAnalysesToReturn"); + if (maxAnalCountNode != null) + { + maxAnalCount = Convert.ToInt16(maxAnalCountNode.FirstChild.Value); + if (maxAnalCount < 1) + maxAnalCount = -1; + } + + m_xample.SetParameter("MaxAnalysesToReturn", maxAnalCount.ToString(CultureInfo.InvariantCulture)); + + string tempPath = Path.GetTempPath(); + m_xample.LoadFiles(m_appInstallDir + @"/Language Explorer/Configuration/Grammar", tempPath, projectName); + } + + public void Reset() + { + CheckDisposed(); + + m_retriever.Reset(); + } + + public ParseResult ParseWord(string word) + { + CheckDisposed(); + + string results = m_xample.ParseWord(word); + results = results.Replace("DB_REF_HERE", "'0'"); + results = results.Replace("<...>", "[...]"); + var wordformElem = XElement.Parse(results); + string errorMessage = null; + var exceptionElem = wordformElem.Element("Exception"); + if (exceptionElem != null) + { + var totalAnalysesValue = (string) exceptionElem.Attribute("totalAnalyses"); + switch ((string) exceptionElem.Attribute("code")) + { + case "ReachedMaxAnalyses": + errorMessage = String.Format(ParserCoreStrings.ksReachedMaxAnalysesAllowed, + totalAnalysesValue); + break; + case "ReachedMaxBufferSize": + errorMessage = String.Format(ParserCoreStrings.ksReachedMaxInternalBufferSize, + totalAnalysesValue); + break; + } + } + else + { + errorMessage = (string) wordformElem.Element("Error"); + } + + ParseResult result; + using (new WorkerThreadReadHelper(m_cache.ServiceLocator.GetInstance())) + { + var analyses = new List(); + foreach (XElement analysisElem in wordformElem.Descendants("WfiAnalysis")) + { + var morphs = new List(); + bool skip = false; + foreach (XElement morphElem in analysisElem.Descendants("Morph")) + { + ParseMorph morph; + if (!TryCreateParseMorph(morphElem, out morph)) + { + skip = true; + break; + } + if (morph != null) + morphs.Add(morph); + } + + if (!skip && morphs.Count > 0) + analyses.Add(new ParseAnalysis(morphs)); + } + result = new ParseResult(analyses, errorMessage); + } + + return result; + } + + /// + /// Creates a single ParseMorph object + /// Handles special cases where the MoForm hvo and/or MSI hvos are + /// not actual MoForm or MSA objects. + /// + /// A Morph element returned by one of the automated parsers + /// a new ParseMorph object or null if the morpheme should be skipped + /// + private bool TryCreateParseMorph(XElement morphElem, out ParseMorph morph) + { + // Normally, the hvo for MoForm is a MoForm and the hvo for MSI is an MSA + // There are four exceptions, though, when an irregularly inflected form is involved: + // 1. ().TryGetObject(hvoForm, out objForm)) + { + morph = null; + return false; + } + var form = objForm as IMoForm; + if (form == null) + { + morph = null; + return true; + } + + // Irregulary inflected forms can have a combination MSA hvo: the LexEntry hvo, a period, and an index to the LexEntryRef + XElement msiElement = morphElem.Element("MSI"); + Debug.Assert(msiElement != null); + var msaHvoStr = (string) msiElement.Attribute("DbRef"); + string[] msaHvoParts = msaHvoStr.Split('.'); + ICmObject objMsa; + if (!m_cache.ServiceLocator.GetInstance().TryGetObject(int.Parse(msaHvoParts[0]), out objMsa)) + { + morph = null; + return false; + } + var msa = objMsa as IMoMorphSynAnalysis; + if (msa != null) + { + morph = new ParseMorph(form, msa); + return true; + } + + var msaAsLexEntry = objMsa as ILexEntry; + if (msaAsLexEntry != null) + { + // is an irregularly inflected form + // get the MoStemMsa of its variant + if (msaAsLexEntry.EntryRefsOS.Count > 0) + { + int index = msaHvoParts.Length == 2 ? int.Parse(msaHvoParts[1]) : 0; + ILexEntryRef lexEntryRef = msaAsLexEntry.EntryRefsOS[index]; + ILexSense sense = MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); + var inflType = (ILexEntryInflType) lexEntryRef.VariantEntryTypesRS[0]; + morph = new ParseMorph(form, sense.MorphoSyntaxAnalysisRA, inflType); + return true; + } + } + + // if it is anything else, we ignore it + morph = null; + return true; + } + + public string ParseWordXml(string word) + { + CheckDisposed(); + + return m_xample.ParseWord(word); + } + + public string TraceWordXml(string word, string selectTraceMorphs) + { + CheckDisposed(); + + return m_xample.TraceWord(word, selectTraceMorphs); + } + + /// + /// Convert any characters in the name which are higher than 0x00FF to hex. + /// Neither XAmple nor PC-PATR can read a file name containing letters above 0x00FF. + /// + /// The original name to be converted + /// Converted name + private static string ConvertNameToUseAnsiCharacters(string originalName) + { + var sb = new StringBuilder(); + char[] letters = originalName.ToCharArray(); + foreach (var letter in letters) + { + int value = Convert.ToInt32(letter); + if (value > 255) + { + string hex = value.ToString("X4"); + sb.Append(hex); + } + else + { + sb.Append(letter); + } + } + return sb.ToString(); + } + + protected override void DisposeManagedResources() + { + if (m_xample != null) + { + m_xample.Dispose(); + m_xample = null; + } + + if (m_retriever != null) + { + m_retriever.Dispose(); + m_retriever = null; + } + } + } +} diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleWorker.cs b/Src/LexText/ParserEngine/ParserCore/XAmpleWorker.cs deleted file mode 100644 index e6d9a71b6c..0000000000 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleWorker.cs +++ /dev/null @@ -1,121 +0,0 @@ -// -------------------------------------------------------------------------------------------- -#region // Copyright (c) 2009, SIL International. All Rights Reserved. -// -// Copyright (c) 2009, SIL International. All Rights Reserved. -// -// Distributable under the terms of either the Common Public License or the -// GNU Lesser General Public License, as specified in the LICENSING.txt file. -// -#endregion -// -// File: XAmpleWorker.cs -// Responsibility: FLEx Team -// -------------------------------------------------------------------------------------------- -using System; -using System.Diagnostics; -using System.Xml; -using System.IO; - -using SIL.FieldWorks.FDO; -using SIL.Utils; -using XAmpleManagedWrapper; - -namespace SIL.FieldWorks.WordWorks.Parser -{ - public class XAmpleParserWorker : ParserWorker - { - private XAmpleWrapper m_xample; - - public XAmpleParserWorker(FdoCache cache, Action taskUpdateHandler, IdleQueue idleQueue, string appInstallDir) - : base(cache, taskUpdateHandler, idleQueue, - cache.ServiceLocator.GetInstance().GetObject(CmAgentTags.kguidAgentXAmpleParser), appInstallDir) - { - m_xample = new XAmpleWrapper(); - m_xample.Init(appInstallDir); - } - - protected override string ParseWord(string form, int hvoWordform) - { - return CompleteAmpleResults(m_xample.ParseWord(form), hvoWordform); - } - - protected override string TraceWord(string form, string selectTraceMorphs) - { - return m_xample.TraceWord(form, selectTraceMorphs); - } - - /// - /// XAmple does not know the hvo of the Wordform. - /// Thus it leaves a pattern which we need to replace with the actual hvo. - /// - /// It would be nice if this was done down in the XAmple wrapper. - /// However, I despaired of doing this simple replacement using bstrs, so I am doing it here. - /// - /// - /// - /// - private static string CompleteAmpleResults(string rawAmpleResults, int hvoWordform) - { - // REVIEW Jonh(RandyR): This should probably be a simple assert, - // since it is a programming error in the XAmple COM dll. - if (rawAmpleResults == null) - throw new ApplicationException("XAmpleCOM Dll failed to return any results. " - + "[NOTE: This is a programming error. See WPS-24 in JIRA.]"); - - //find any instance of "<...>" which must be replaced with "[..]" - this indicates full reduplication - const string ksFullRedupMarker = "<...>"; - var sTemp = rawAmpleResults.Replace(ksFullRedupMarker, "[...]"); - //find the "DB_REF_HERE" which must be replaced with the actual hvo - const string kmatch = "DB_REF_HERE"; - Debug.Assert(sTemp.IndexOf(kmatch) > 0, - "There was a problem interpretting the response from XAMPLE. " + kmatch + " was not found."); - return sTemp.Replace(kmatch, "'" + hvoWordform + "'"); - } - - /// - /// Loads the parser. - /// - /// The model. - /// The template. - protected override void LoadParser(ref XmlDocument model, XmlDocument template) - { - var transformer = new M3ToXAmpleTransformer(m_projectName, m_taskUpdateHandler, m_appInstallDir); - var startTime = DateTime.Now; - // PrepareTemplatesForXAmpleFiles adds orderclass elements to MoInflAffixSlot elements - transformer.PrepareTemplatesForXAmpleFiles(ref model, template); - var ttlTicks = DateTime.Now.Ticks - startTime.Ticks; - Trace.WriteLineIf(m_tracingSwitch.TraceInfo, "GAFAWS prep took : " + ttlTicks); - - transformer.MakeAmpleFiles(model); - - int maxAnalCount = 20; - XmlNode maxAnalCountNode = model.SelectSingleNode("/M3Dump/ParserParameters/XAmple/MaxAnalysesToReturn"); - if (maxAnalCountNode != null) - { - maxAnalCount = Convert.ToInt16(maxAnalCountNode.FirstChild.Value); - if (maxAnalCount < 1) - maxAnalCount = -1; - } - - m_xample.SetParameter("MaxAnalysesToReturn", maxAnalCount.ToString()); - - string tempPath = Path.GetTempPath(); - m_xample.LoadFiles(m_appInstallDir + @"/Language Explorer/Configuration/Grammar", - tempPath, m_projectName); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Override to dispose unmanaged resources. - /// - /// ------------------------------------------------------------------------------------ - protected override void DisposeUnmanagedResources() - { - if (m_xample != null) - { - m_xample.Dispose(); - m_xample = null; - } - } - } -} \ No newline at end of file diff --git a/Src/LexText/ParserUI/ParserListener.cs b/Src/LexText/ParserUI/ParserListener.cs index 3376eb522b..7a72db0054 100644 --- a/Src/LexText/ParserUI/ParserListener.cs +++ b/Src/LexText/ParserUI/ParserListener.cs @@ -468,8 +468,7 @@ public bool OnClearSelectedWordParserAnalyses(object dummyObj) if (analysis.EvaluationsRC.Count == 0) wf.AnalysesOC.Remove(analysis); - if (parserEvals.Length > 0) - wf.Checksum = 0; + wf.Checksum = 0; } }); return true; //we handled this. diff --git a/Src/LexText/ParserUI/ParserTrace.cs b/Src/LexText/ParserUI/ParserTrace.cs index d7a2dddf76..a0ae4e44fe 100644 --- a/Src/LexText/ParserUI/ParserTrace.cs +++ b/Src/LexText/ParserUI/ParserTrace.cs @@ -1,18 +1,10 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Drawing; -using System.IO; using System.Text; using System.Xml; -using System.Xml.XPath; -using System.Xml.Xsl; - using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; -using SIL.FieldWorks.WordWorks.Parser; using SIL.Utils; -using SIL.FieldWorks.Common.Widgets; using SIL.FieldWorks.FDO; using XCore; @@ -171,7 +163,7 @@ protected void ConvertMorphs(XmlDocument doc, string sNodeListToFind, bool fIdsI else msaid = node.SelectSingleNode("MSI/@DbRef"); string sMsaHvo = msaid.InnerText; - var indexOfPeriod = ParseFiler.IndexOfPeriodInMsaHvo(ref sMsaHvo); + var indexOfPeriod = IndexOfPeriodInMsaHvo(ref sMsaHvo); int hvoMsa = Convert.ToInt32(sMsaHvo); var msaObj = m_cache.ServiceLocator.GetObject(hvoMsa); if (msaObj.ClassID == LexEntryTags.kClassId) @@ -179,7 +171,7 @@ protected void ConvertMorphs(XmlDocument doc, string sNodeListToFind, bool fIdsI var entry = msaObj as ILexEntry; if (entry.EntryRefsOS.Count > 0) { - var index = ParseFiler.IndexOfLexEntryRef(msaid.Value, indexOfPeriod); // the value of the int after the period + var index = IndexOfLexEntryRef(msaid.Value, indexOfPeriod); // the value of the int after the period var lexEntryRef = entry.EntryRefsOS[index]; ITsIncStrBldr sbGlossPrepend; ITsIncStrBldr sbGlossAppend; diff --git a/Src/LexText/ParserUI/ParserTraceBase.cs b/Src/LexText/ParserUI/ParserTraceBase.cs index bd3ec5abdb..cea218be7e 100644 --- a/Src/LexText/ParserUI/ParserTraceBase.cs +++ b/Src/LexText/ParserUI/ParserTraceBase.cs @@ -1,17 +1,12 @@ using System; using System.Collections.Generic; -using System.Drawing; using System.IO; using System.Xml; -using System.Xml.XPath; -using System.Xml.Xsl; - using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Common.Widgets; using SIL.FieldWorks.FDO; -using SIL.FieldWorks.WordWorks.Parser; using SIL.Utils; using XCore; @@ -266,7 +261,7 @@ protected void CreateMsaXmlElement(XmlNode node, XmlDocument doc, XmlNode morphN { string sObjHvo = attr.Value; // Irregulary inflected forms can have a combination MSA hvo: the LexEntry hvo, a period, and an index to the LexEntryRef - var indexOfPeriod = ParseFiler.IndexOfPeriodInMsaHvo(ref sObjHvo); + var indexOfPeriod = IndexOfPeriodInMsaHvo(ref sObjHvo); ICmObject obj = m_cache.ServiceLocator.GetInstance().GetObject(Convert.ToInt32(sObjHvo)); switch (obj.GetType().Name) { @@ -295,7 +290,7 @@ protected void CreateMsaXmlElement(XmlNode node, XmlDocument doc, XmlNode morphN var entry = obj as ILexEntry; if (entry.EntryRefsOS.Count > 0) { - var index = ParseFiler.IndexOfLexEntryRef(attr.Value, indexOfPeriod); + var index = IndexOfLexEntryRef(attr.Value, indexOfPeriod); var lexEntryRef = entry.EntryRefsOS[index]; var sense = FDO.DomainServices.MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); stemMsa = sense.MorphoSyntaxAnalysisRA as IMoStemMsa; @@ -312,6 +307,28 @@ protected void CreateMsaXmlElement(XmlNode node, XmlDocument doc, XmlNode morphN } } + protected static int IndexOfLexEntryRef(string sHvo, int indexOfPeriod) + { + int index = 0; + if (indexOfPeriod >= 0) + { + string sIndex = sHvo.Substring(indexOfPeriod+1); + index = Convert.ToInt32(sIndex); + } + return index; + } + + protected static int IndexOfPeriodInMsaHvo(ref string sObjHvo) + { + // Irregulary inflected forms can a combination MSA hvo: the LexEntry hvo, a period, and an index to the LexEntryRef + int indexOfPeriod = sObjHvo.IndexOf('.'); + if (indexOfPeriod >= 0) + { + sObjHvo = sObjHvo.Substring(0, indexOfPeriod); + } + return indexOfPeriod; + } + protected void CreateInflMsaForLexEntryInflType(XmlDocument doc, XmlNode node, ILexEntryInflType lexEntryInflType) { /*var slots = lexEntryInflType.SlotsRC; From 40d160084b6ad5701b9db72a4ced035e8b9585d6 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Tue, 21 Jan 2014 14:57:20 +0700 Subject: [PATCH 057/143] Add HCParser Change-Id: I5c1703b7c1e87f5cd8e48a85fd2a7425b1a853f2 --- .../ParserEngine/ParserCore/HCParser.cs | 813 ++++++++++++++++++ .../ParserEngine/ParserCore/ParseFiler.cs | 5 + .../ParserEngine/ParserCore/ParserCore.csproj | 2 + .../{WorkerTests.cs => HelperTests.cs} | 39 +- .../ParserCoreTests/ParserCoreTests.csproj | 2 +- .../ParserEngine/ParserCore/ParserHelper.cs | 137 +++ .../ParserEngine/ParserCore/ParserWorker.cs | 2 +- .../ParserEngine/ParserCore/XAmpleParser.cs | 113 +-- 8 files changed, 980 insertions(+), 133 deletions(-) create mode 100644 Src/LexText/ParserEngine/ParserCore/HCParser.cs rename Src/LexText/ParserEngine/ParserCore/ParserCoreTests/{WorkerTests.cs => HelperTests.cs} (54%) create mode 100644 Src/LexText/ParserEngine/ParserCore/ParserHelper.cs diff --git a/Src/LexText/ParserEngine/ParserCore/HCParser.cs b/Src/LexText/ParserEngine/ParserCore/HCParser.cs new file mode 100644 index 0000000000..46964aae3d --- /dev/null +++ b/Src/LexText/ParserEngine/ParserCore/HCParser.cs @@ -0,0 +1,813 @@ +// -------------------------------------------------------------------------------------------- +#region // Copyright (c) 2014, SIL International. All Rights Reserved. +// +// Copyright (c) 2014, SIL International. All Rights Reserved. +// +// Distributable under the terms of either the Common Public License or the +// GNU Lesser General Public License, as specified in the LICENSING.txt file. +// +#endregion +// -------------------------------------------------------------------------------------------- +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml; +using System.Xml.Linq; +using PatrParserWrapper; +using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.FDO; +using SIL.FieldWorks.FDO.Infrastructure; +using SIL.FieldWorks.FDO.Validation; +using SIL.HermitCrab; +using SIL.Utils; + +namespace SIL.FieldWorks.WordWorks.Parser +{ + public class HCParser : FwDisposableBase, IParser + { + private readonly FdoCache m_cache; + private PatrParser m_patr; + private readonly Loader m_loader; + private M3ParserModelRetriever m_retriever; + private readonly string m_appInstallDir; + private readonly string m_outputDirectory; + // m_projectName here is only used to create temporary files for the parser to load. + // We convert the name to use strictly ANSI characters so that the patr parsers (which is + // a legacy C program) can read the file names. + private readonly string m_projectName; + + public HCParser(FdoCache cache, string appInstallDir) + { + m_cache = cache; + m_appInstallDir = appInstallDir; + + m_retriever = new M3ParserModelRetriever(m_cache); + m_patr = new PatrParser + { + CommentChar = '|', + CodePage = Encoding.UTF8.CodePage + }; + m_loader = new XmlLoader + { + XmlResolver = new XmlFwResolver(appInstallDir), + QuitOnError = false + }; + + m_outputDirectory = Path.GetTempPath(); + m_projectName = ParserHelper.ConvertNameToUseAnsiCharacters(cache.ProjectId.Name); + } + + #region IParser implementation + public void Initialize() + { + CheckDisposed(); + + if (!m_retriever.RetrieveModel()) + return; + + XmlDocument fxtResult = m_retriever.ModelDom; + XmlDocument gafawsFxtResult = m_retriever.TemplateDom; + LoadParser(ref fxtResult); + } + + public void Reset() + { + CheckDisposed(); + + m_retriever.Reset(); + } + + public ParseResult ParseWord(string word) + { + CheckDisposed(); + + if (!m_loader.IsLoaded) + return null; + + ICollection synthesisRecs; + try + { + synthesisRecs = m_loader.CurrentMorpher.MorphAndLookupWord(word); + } + catch (MorphException me) + { + return new ParseResult(ProcessMorphException(me)); + } + + ParseResult result; + using (new WorkerThreadReadHelper(m_cache.ServiceLocator.GetInstance())) + { + IEnumerable patrResults = ProcessPatr(synthesisRecs, Path.Combine(m_outputDirectory, m_projectName + "patrlex.txt"), false); + + var analyses = new List(); + foreach (PatrResult patrResult in patrResults) + { + var morphs = new List(); + bool skip = false; + foreach (PcPatrMorph pcPatrMorph in patrResult.Morphs) + { + ParseMorph morph; + if (!ParserHelper.TryCreateParseMorph(m_cache, pcPatrMorph.formId, pcPatrMorph.msaId, out morph)) + { + skip = true; + break; + } + if (morph != null) + morphs.Add(morph); + } + + if (!skip && morphs.Count > 0) + analyses.Add(new ParseAnalysis(morphs)); + } + result = new ParseResult(analyses); + } + + return result; + } + + public string TraceWordXml(string form, string selectTraceMorphs) + { + CheckDisposed(); + + return TraceWordXml(form, GetArrayFromString(selectTraceMorphs)); + } + + public string ParseWordXml(string form) + { + CheckDisposed(); + + return ParseToXML(form, false, null); + } + #endregion + + public string TraceWordXml(string form, string[] selectTraceMorphs) + { + CheckDisposed(); + + return ParseToXML(form, true, selectTraceMorphs); + } + + protected override void DisposeManagedResources() + { + if (m_patr != null) + { + m_patr.Dispose(); + m_patr = null; + } + + if (m_retriever != null) + { + m_retriever.Dispose(); + m_retriever = null; + } + } + + #region Load + private void LoadParser(ref XmlDocument model) + { + string hcPath = HcInputPath; + File.Delete(hcPath); // In case we don't produce one successfully, don't keep an old one. + // Check for errors that will prevent the transformations working. + using (new WorkerThreadReadHelper(m_cache.ServiceLocator.GetInstance())) + { + foreach (var affix in m_cache.ServiceLocator.GetInstance().AllInstances()) + { + string form = affix.Form.VernacularDefaultWritingSystem.Text; + if (String.IsNullOrEmpty(form) || !form.Contains("[")) + continue; + string environment = "/_" + form; + // A form containing a reduplication expression should look like an environment + var validator = new PhonEnvRecognizer( + m_cache.LangProject.PhonologicalDataOA.AllPhonemes().ToArray(), + m_cache.LangProject.PhonologicalDataOA.AllNaturalClassAbbrs().ToArray()); + if (!validator.Recognize(environment)) + { + m_loader.Reset(); // make sure nothing thinks it is in a useful state + throw new InvalidReduplicationEnvironmentException(validator.ErrorMessage, form); + } + } + } + + var transformer = new M3ToHCTransformer(m_projectName, m_appInstallDir); + transformer.MakeHCFiles(ref model); + + m_patr.LoadGrammarFile(HcGrammarPath); + + LoadHCInfo(hcPath); + + XmlNode delReappsNode = model.SelectSingleNode("/M3Dump/ParserParameters/HC/DelReapps"); + if (delReappsNode != null) + m_loader.CurrentMorpher.DelReapplications = Convert.ToInt32(delReappsNode.InnerText); + } + + private void LoadHCInfo(string hcPath) + { + string loadErrorsFile = Path.Combine(m_outputDirectory, m_projectName + "HCLoadErrors.xml"); + using (XmlWriter writer = new XmlTextWriter(loadErrorsFile, null)) + { + var loadOutput = new XmlOutput(writer); + writer.WriteStartElement("LoadErrors"); + m_loader.Output = loadOutput; + m_loader.Load(hcPath); + writer.WriteEndElement(); + loadOutput.Close(); + } + } + + private string HcInputPath + { + get { return Path.Combine(m_outputDirectory, m_projectName + "HCInput.xml"); } + } + + private string HcGrammarPath + { + get { return Path.Combine(m_outputDirectory, m_projectName + "gram.txt"); } + } + #endregion + + private string[] GetArrayFromString(string selectTraceMorphs) + { + string[] selectTraceMorphIds = null; + if (!String.IsNullOrEmpty(selectTraceMorphs)) + { + selectTraceMorphIds = selectTraceMorphs.TrimEnd().Split(' '); + int i = 0; + using (new WorkerThreadReadHelper(m_cache.ServiceLocator.GetInstance())) + { + foreach (string sId in selectTraceMorphIds) + { + IMoMorphSynAnalysis msa = m_cache.ServiceLocator.GetInstance().GetObject(int.Parse(sId)); + if (msa.ClassID == MoStemMsaTags.kClassId) + selectTraceMorphIds.SetValue("lex" + sId, i); + else + selectTraceMorphIds.SetValue("mrule" + sId, i); + i++; + } + } + } + return selectTraceMorphIds; + } + + private string ParseToXML(string form, bool trace, string[] selectTraceMorphs) + { + if (!m_loader.IsLoaded) + return ParserCoreStrings.ksDidNotParse; + + var sb = new StringBuilder(); + var settings = new XmlWriterSettings { OmitXmlDeclaration = true }; + + using (new WorkerThreadReadHelper(m_cache.ServiceLocator.GetInstance())) + { + using (var writer = XmlWriter.Create(sb, settings)) + { + writer.WriteStartElement("Wordform"); + writer.WriteAttributeString("DbRef", Convert.ToString(0)); + writer.WriteAttributeString("Form", form); + var output = new FwXmlOutput(this, writer, trace, + Path.Combine(m_outputDirectory, m_projectName + "patrlex.txt")); + output.MorphAndLookupWord(m_loader.CurrentMorpher, form, true, selectTraceMorphs); + writer.WriteEndElement(); + } + } + return sb.ToString(); + } + + private IEnumerable ProcessPatr(IEnumerable synthesisRecs, string patrlexPath, bool trace) + { + IList patrResults = new List(); + bool passedPatr = false; + foreach (WordSynthesis ws in synthesisRecs) + { + WordGrammarTrace wordGrammarTrace = null; + List morphs = GetMorphs(ws); + if (trace) + wordGrammarTrace = new WordGrammarTrace(((uint)ws.GetHashCode()).ToString(CultureInfo.InvariantCulture), morphs, m_cache); + if (morphs.Count == 1) + { + PcPatrMorph morph = morphs[0]; + string formid = morph.formId; + IMoForm form = m_cache.ServiceLocator.GetInstance().GetObject(Int32.Parse(formid)); + var morphtype = form.MorphTypeRA; + if (morphtype.IsBoundType) + { + if (wordGrammarTrace != null) + wordGrammarTrace.Success = false; // this is not really true; what other options are there? + continue; + } + } + WritePcPatrLexiconFile(patrlexPath, morphs); + m_patr.LoadLexiconFile(patrlexPath, 0); + string sentence = BuildPcPatrInputSentence(morphs); + try + { + if (m_patr.ParseString(sentence) != null) + { + passedPatr = true; + if (wordGrammarTrace != null) + wordGrammarTrace.Success = true; + } + else if (wordGrammarTrace != null) + { + wordGrammarTrace.Success = false; + } + } + catch (Exception) + { + } + patrResults.Add(new PatrResult { Morphs = morphs, WordGrammarTrace = wordGrammarTrace, PassedPatr = passedPatr }); + } + return patrResults; + } + + private static List GetMorphs(WordSynthesis ws) + { + var ppMorphs = new Dictionary(); + var result = new List(); + foreach (Morph morph in ws.Morphs) + { + string[] formIds = morph.Allomorph.GetProperty("FormID").Split(' '); + string[] wordTypes = morph.Allomorph.GetProperty("WordCategory").Split(' '); + string form = ws.Stratum.CharacterDefinitionTable.ToString(morph.Shape, ModeType.SYNTHESIS, false); + PcPatrMorph ppMorph; + if (!ppMorphs.TryGetValue(morph.Allomorph.Morpheme.ID, out ppMorph)) + { + ppMorph = new PcPatrMorph + { + formIndex = 0, + formId = formIds[0], + form = form, + wordType = wordTypes[0] + }; + } + else if (formIds.Length == 1) + { + ppMorph.form += form; + continue; + } + else + { + PcPatrMorph oldMorph = ppMorph; + int wordTypeIndex = WordTypeIndex(oldMorph.formIndex + 1, wordTypes.Count()); + ppMorph = new PcPatrMorph + { + formIndex = oldMorph.formIndex + 1, + formId = formIds[oldMorph.formIndex + 1], + form = form, + wordType = wordTypes[wordTypeIndex] + }; + } + + ppMorph.msaId = morph.Allomorph.GetProperty("MsaID"); + ppMorph.featureDescriptors = morph.Allomorph.GetProperty("FeatureDescriptors"); + ppMorph.gloss = morph.Allomorph.Morpheme.Gloss.Description; + ppMorphs[morph.Allomorph.Morpheme.ID] = ppMorph; + + string morphType = morph.Allomorph.GetProperty("MorphType"); + switch (morphType) + { + case MoMorphTypeTags.kMorphInfix: + case MoMorphTypeTags.kMorphInfixingInterfix: + if (result.Count == 0) + result.Add(ppMorph); + else + result.Insert(result.Count - 1, ppMorph); + break; + + default: + result.Add(ppMorph); + break; + } + } + return result; + } + + private static void WritePcPatrLexiconFile(string path, IEnumerable morphs) + { + using (var writer = new StreamWriter(path)) + { + foreach (PcPatrMorph morph in morphs) + { + writer.WriteLine("\\w {0}", morph.Form); + writer.WriteLine("\\c {0}", morph.wordType); + writer.WriteLine("\\g {0}", morph.gloss); + if (!String.IsNullOrEmpty(morph.featureDescriptors)) + { + string lastFeatDesc = ""; + string combinedCFPFeatDescs = ""; + string[] featDescs = morph.featureDescriptors.Split(' '); + if (featDescs.Any()) + writer.Write("\\f"); + foreach (string featDesc in featDescs) + { + if (featDesc.StartsWith("CFP")) + { + combinedCFPFeatDescs += featDesc; + lastFeatDesc = featDesc; + continue; + } + if (lastFeatDesc.StartsWith("CFP")) + writer.Write(" {0}", combinedCFPFeatDescs); + writer.Write(" {0}", featDesc); + } + if (lastFeatDesc.StartsWith("CFP")) + writer.Write(" {0}", combinedCFPFeatDescs); + } + writer.WriteLine(); + writer.WriteLine(); + } + writer.Close(); + } + } + + private static string BuildPcPatrInputSentence(IEnumerable morphs) + { + var sentence = new StringBuilder(); + bool firstItem = true; + foreach (PcPatrMorph morph in morphs) + { + if (!firstItem) + sentence.Append(" "); + sentence.Append(morph.Form); + firstItem = false; + } + return sentence.ToString(); + } + + private static int WordTypeIndex(int expectedindex, int wordTypesCount) + { + int wordTypeIndex = expectedindex; + if (wordTypeIndex + 1 > wordTypesCount) + { + // something is wrong (perhaps a missing suffix slot for a circumfix) + // we'll use the same as last time, hoping for a parse failure + wordTypeIndex = wordTypeIndex - 1; + } + return wordTypeIndex; + } + + private string ProcessMorphException(MorphException me) + { + string errorMessage; + switch (me.ErrorType) + { + case MorphException.MorphErrorType.INVALID_SHAPE: + var shape = (string)me.Data["shape"]; + var position = (int)me.Data["position"]; + var phonemesFoundSoFar = (string)me.Data["phonemesFoundSoFar"]; + string rest = shape.Substring(position); + string restToUse = rest; + LgGeneralCharCategory cc = m_cache.ServiceLocator.UnicodeCharProps.get_GeneralCategory(rest[0]); + if (cc == LgGeneralCharCategory.kccMn) + { + // the first character is a diacritic, combining type of character + // insert a space so it does not show on top of a single quote in the message string + restToUse = " " + rest; + } + errorMessage = String.Format(ParserCoreStrings.ksHCInvalidWordform, shape, position + 1, restToUse, phonemesFoundSoFar); + break; + + case MorphException.MorphErrorType.UNINSTANTIATED_FEATURE: + var featId = me.Data["feature"] as string; + var feat = me.Morpher.PhoneticFeatureSystem.GetFeature(featId); + errorMessage = String.Format(ParserCoreStrings.ksHCUninstFeature, feat.Description); + break; + + default: + errorMessage = String.Format(ParserCoreStrings.ksHCDefaultErrorMsg, me.Message); + break; + } + return errorMessage; + } + + private class PatrResult + { + public List Morphs { get; set; } + public WordGrammarTrace WordGrammarTrace { get; set; } + public bool PassedPatr { get; set; } + } + + #region class FwXmlOutput + [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", + Justification = "m_parser is a reference to the parent class")] + private class FwXmlOutput : XmlOutput + { + private readonly HCParser m_parser; + private readonly bool m_fDotrace; + private readonly string m_patrlexPath; + + public FwXmlOutput(HCParser parser, XmlWriter writer, bool fDotrace, string patrlexPath) + : base(writer, new FwXmlTraceManager()) + { + m_parser = parser; + m_fDotrace = fDotrace; + m_patrlexPath = patrlexPath; + } + + public override void MorphAndLookupWord(Morpher morpher, string word, bool prettyPrint, bool printTraceInputs) + { + MorphAndLookupWord(morpher, word, printTraceInputs, null); + } + + public void MorphAndLookupWord(Morpher morpher, string word, bool printTraceInputs, string[] selectTraceMorphs) + { + try + { + ICollection wordGrammarTraces = null; + if (m_fDotrace) + wordGrammarTraces = new HashSet(); + XmlTraceManager.WriteInputs = printTraceInputs; + TraceManager.TraceAll = m_fDotrace; + ICollection synthesisRecs = morpher.MorphAndLookupWord(word, TraceManager, selectTraceMorphs); + + IEnumerable patrResults = m_parser.ProcessPatr(synthesisRecs, m_patrlexPath, m_fDotrace); + foreach (PatrResult patrResult in patrResults) + { + if (patrResult.PassedPatr) + BuildXmlOutput(patrResult.Morphs); + if (wordGrammarTraces != null) + wordGrammarTraces.Add(patrResult.WordGrammarTrace); + } + + if (m_fDotrace) + { + WriteTrace(); + ConvertWordGrammarTraceToXml(wordGrammarTraces); + } + XmlTraceManager.Reset(); + } + catch (MorphException exc) + { + Write(exc); + } + } + + private void BuildXmlOutput(IEnumerable morphs) + { + XmlWriter.WriteStartElement("WfiAnalysis"); + XmlWriter.WriteStartElement("Morphs"); + + foreach (PcPatrMorph morph in morphs) + { + XmlWriter.WriteStartElement("Morph"); + + XmlWriter.WriteStartElement("MoForm"); + XmlWriter.WriteAttributeString("DbRef", morph.formId); + XmlWriter.WriteAttributeString("Label", morph.form); + XmlWriter.WriteAttributeString("wordType", morph.wordType); + XmlWriter.WriteEndElement(); + + XmlWriter.WriteStartElement("MSI"); + XmlWriter.WriteAttributeString("DbRef", morph.msaId); + XmlWriter.WriteEndElement(); + + XmlWriter.WriteEndElement(); + } + + XmlWriter.WriteEndElement(); + XmlWriter.WriteEndElement(); + } + + private void ConvertWordGrammarTraceToXml(IEnumerable wordGrammarTraces) + { + XmlWriter.WriteStartElement("WordGrammarTrace"); + foreach (WordGrammarTrace trace in wordGrammarTraces) + { + trace.ToXml(XmlWriter); + } + XmlWriter.WriteEndElement(); + } + + public override void Write(LoadException le) + { + XmlWriter.WriteStartElement("Error"); + switch (le.ErrorType) + { + case LoadException.LoadErrorType.INVALID_ENTRY_SHAPE: + var entryShape = le.Data["shape"] as string; + var entryId = le.Data["entry"] as string; + LexEntry entry = le.Loader.CurrentMorpher.Lexicon.GetEntry(entryId); + XmlWriter.WriteString(String.Format(ParserCoreStrings.ksHCInvalidEntryShape, entryShape, entry.Description)); + break; + + case LoadException.LoadErrorType.INVALID_RULE_SHAPE: + var ruleShape = le.Data["shape"] as string; + var ruleId = le.Data["rule"] as string; + MorphologicalRule rule = le.Loader.CurrentMorpher.GetMorphologicalRule(ruleId); + XmlWriter.WriteString(String.Format(ParserCoreStrings.ksHCInvalidRuleShape, ruleShape, rule.Description)); + break; + + default: + XmlWriter.WriteString(String.Format(ParserCoreStrings.ksHCDefaultErrorMsg, le.Message)); + break; + } + XmlWriter.WriteEndElement(); + } + + public override void Write(MorphException me) + { + XmlWriter.WriteStartElement("Error"); + XmlWriter.WriteString(m_parser.ProcessMorphException(me)); + XmlWriter.WriteEndElement(); + } + } + #endregion + + #region class WordGrammarTrace + [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", + Justification = "m_cache is a reference and disposed in the parent class")] + private class WordGrammarTrace + { + private readonly IEnumerable m_morphs; + private bool m_fSuccess; + private readonly string m_id; + private readonly FdoCache m_cache; + + public WordGrammarTrace(string id, IEnumerable morphs, FdoCache cache) + { + m_id = id; + m_morphs = morphs; + m_cache = cache; + } + + /// + /// Get/set success status of word grammar attempt + /// + public bool Success + { + set { m_fSuccess = value; } + + } + + /// + /// Report trace information as XML + /// + /// + public void ToXml(XmlWriter writer) + { + writer.WriteStartElement("WordGrammarAttempt"); + writer.WriteStartAttribute("success"); + writer.WriteValue(m_fSuccess ? "true" : "false"); + writer.WriteEndAttribute(); + writer.WriteStartElement("Id"); + writer.WriteValue(m_id); + writer.WriteEndElement(); + + string sType = "pfx"; // try to guess morph type based on word type + foreach (PcPatrMorph morph in m_morphs) + { + writer.WriteStartElement("Morphs"); + string sWordType = morph.wordType; + writer.WriteStartAttribute("wordType"); + writer.WriteValue(sWordType); + writer.WriteEndAttribute(); + writer.WriteStartAttribute("type"); + if (sType == "pfx" && + sWordType == "root") + sType = "root"; + else if (sType == "root" && + sWordType != "root") + sType = "sfx"; + writer.WriteValue(sType); + writer.WriteEndAttribute(); + writer.WriteStartAttribute("alloid"); + writer.WriteValue(morph.formId); + writer.WriteEndAttribute(); + writer.WriteStartAttribute("morphname"); + writer.WriteValue(morph.msaId); + writer.WriteEndAttribute(); + + writer.WriteStartElement("alloform"); + writer.WriteValue(morph.form); + writer.WriteEndElement(); // alloform + //writer.WriteStartElement("Msa"); + //writer.WriteEndElement(); // Msa + int hvoForm = Convert.ToInt32(morph.formId); + var obj = m_cache.ServiceLocator.GetObject(hvoForm); + var stemAllo = obj as IMoStemAllomorph; + if (stemAllo != null) + { + var stemName = stemAllo.StemNameRA; + if (stemName != null) + { + writer.WriteStartElement("stemName"); + writer.WriteStartAttribute("id"); + writer.WriteValue(stemName.Hvo); + writer.WriteEndAttribute(); + writer.WriteValue(stemName.Name.BestAnalysisAlternative.Text); + writer.WriteEndElement(); // stemName + } + } + writer.WriteStartElement("gloss"); + writer.WriteValue(morph.gloss); + writer.WriteEndElement(); // gloss + writer.WriteStartElement("citationForm"); + var form = obj as IMoForm; + if (form != null) + { + var entry = form.Owner as ILexEntry; + if (entry != null) + writer.WriteValue(entry.HeadWord.Text); + } + writer.WriteEndElement(); // citationForm + writer.WriteEndElement(); // Morphs + } + writer.WriteEndElement(); + } + } + #endregion + + #region class FwXmlTraceManager + private class FwXmlTraceManager : XmlTraceManager + { + public override void ReportSuccess(WordSynthesis output) + { + if (TraceSuccess) + { + XElement wsElem = Write("Result", output); + wsElem.Add(new XAttribute("id", ((uint)output.GetHashCode()).ToString(CultureInfo.InvariantCulture))); + ((XElement)output.CurrentTraceObject).Add(new XElement("ReportSuccessTrace", wsElem)); + } + } + + public override void MorphologicalRuleNotUnapplied(MorphologicalRule rule, WordAnalysis input) + { + } + + public override void MorphologicalRuleNotApplied(MorphologicalRule rule, WordSynthesis input) + { + } + + protected override XElement Write(string name, Allomorph allomorph) + { + XElement elem = Write(name, (HCObject)allomorph); + + string formIdsStr = allomorph.GetProperty("FormID"); + string msaId = allomorph.GetProperty("MsaID"); + if (!String.IsNullOrEmpty(formIdsStr) || !String.IsNullOrEmpty(msaId)) + { + var morphElem = new XElement("Morph"); + + if (!String.IsNullOrEmpty(formIdsStr)) + { + string[] formIds = formIdsStr.Split(' '); + string[] wordTypes = allomorph.GetProperty("WordCategory").Split(' '); + for (int i = 0; i < formIds.Length; i++) + { + int wordTypeIndex = WordTypeIndex(i, wordTypes.Count()); + morphElem.Add(new XElement("MoForm", new XAttribute("DbRef", formIds[i]), new XAttribute("wordType", wordTypes[wordTypeIndex]))); + string featDesc = allomorph.GetProperty("FeatureDescriptors"); + morphElem.Add(string.IsNullOrEmpty(featDesc) ? new XElement("props") : new XElement("props", featDesc)); + } + } + + if (!String.IsNullOrEmpty(msaId)) + morphElem.Add(new XElement("MSI", new XAttribute("DbRef", msaId))); + elem.Add(morphElem); + } + + return elem; + } + } + #endregion + + #region class PcPatrMorph + class PcPatrMorph + { + public string formId; + public string form; + public string wordType; + public string msaId; + public string featureDescriptors; + public string gloss; + public int formIndex; + + public string Form + { + get + { return String.IsNullOrEmpty(form) ? "0" : form; } + } + } + #endregion + + #region class XmlFwResolver + class XmlFwResolver : XmlUrlResolver + { + readonly Uri m_baseUri; + + public XmlFwResolver(string appInstallDir) + { + m_baseUri = new Uri(appInstallDir + Path.DirectorySeparatorChar); + } + + public override Uri ResolveUri(Uri baseUri, string relativeUri) + { + return base.ResolveUri(m_baseUri, relativeUri); + } + } + #endregion + } +} diff --git a/Src/LexText/ParserEngine/ParserCore/ParseFiler.cs b/Src/LexText/ParserEngine/ParserCore/ParseFiler.cs index d5ceb6e181..44d70ebb58 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParseFiler.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParseFiler.cs @@ -19,6 +19,7 @@ // -------------------------------------------------------------------------------------------- using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Diagnostics; using SIL.FieldWorks.FDO; @@ -62,8 +63,12 @@ public class ParseFiler #region Data members + [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", + Justification = "m_cache is a reference and is disposed in a parent class")] private readonly FdoCache m_cache; private readonly Action m_taskUpdateHandler; + [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", + Justification = "m_idleQueue is a reference and is disposed in a parent class")] private readonly IdleQueue m_idleQueue; private readonly ICmAgent m_parserAgent; private readonly Queue m_workQueue; diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj b/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj index 71b03e62aa..3b4fafe144 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj +++ b/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj @@ -191,6 +191,7 @@ CommonAssemblyInfo.cs + @@ -210,6 +211,7 @@ ParserCoreStrings.resx + Code diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/WorkerTests.cs b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/HelperTests.cs similarity index 54% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/WorkerTests.cs rename to Src/LexText/ParserEngine/ParserCore/ParserCoreTests/HelperTests.cs index df14cb9615..58086f3a97 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/WorkerTests.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/HelperTests.cs @@ -8,10 +8,9 @@ // #endregion // -// File: WorkerTests.cs +// File: HelperTests.cs // Responsibility: AndyBlack // --------------------------------------------------------------------------------------------- -using System; using NUnit.Framework; using SIL.FieldWorks.Test.TestUtils; @@ -23,7 +22,7 @@ namespace SIL.FieldWorks.WordWorks.Parser /// /// ---------------------------------------------------------------------------------------- [TestFixture] - public class WorkerTests : BaseTest + public class HelperTests : BaseTest { ///-------------------------------------------------------------------------------------- /// @@ -31,24 +30,24 @@ public class WorkerTests : BaseTest /// ///-------------------------------------------------------------------------------------- [Test] - public void ConvertNameToUseANSICharactersTest() + public void ConvertNameToUseAnsiCharactersTest() { - //// plain, simple ASCII - //string name = "abc 123"; - //string convertedName = ParserWorker.ConvertNameToUseANSICharacters(name); - //Assert.AreEqual("abc 123", convertedName); - //// Using upper ANSI characters as well as ASCII - //name = "ÿýúadctl"; - //convertedName = ParserWorker.ConvertNameToUseANSICharacters(name); - //Assert.AreEqual("ÿýúadctl", convertedName); - //// Using characters just above ANSI as well as ASCII - //name = "ąćălex"; - //convertedName = ParserWorker.ConvertNameToUseANSICharacters(name); - //Assert.AreEqual("010501070103lex", convertedName); - //// Using Cyrillic characters as well as ASCII - //name = "Английский для семинараgram"; - //convertedName = ParserWorker.ConvertNameToUseANSICharacters(name); - //Assert.AreEqual("0410043D0433043B043804390441043A04380439 0434043B044F 04410435043C0438043D043004400430gram", convertedName); + // plain, simple ASCII + string name = "abc 123"; + string convertedName = ParserHelper.ConvertNameToUseAnsiCharacters(name); + Assert.AreEqual("abc 123", convertedName); + // Using upper ANSI characters as well as ASCII + name = "ÿýúadctl"; + convertedName = ParserHelper.ConvertNameToUseAnsiCharacters(name); + Assert.AreEqual("ÿýúadctl", convertedName); + // Using characters just above ANSI as well as ASCII + name = "ąćălex"; + convertedName = ParserHelper.ConvertNameToUseAnsiCharacters(name); + Assert.AreEqual("010501070103lex", convertedName); + // Using Cyrillic characters as well as ASCII + name = "Английский для семинараgram"; + convertedName = ParserHelper.ConvertNameToUseAnsiCharacters(name); + Assert.AreEqual("0410043D0433043B043804390441043A04380439 0434043B044F 04410435043C0438043D043004400430gram", convertedName); } } } diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParserCoreTests.csproj b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParserCoreTests.csproj index 91ef5d493c..21c029424d 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParserCoreTests.csproj +++ b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParserCoreTests.csproj @@ -146,7 +146,7 @@ AssemblyInfoForTests.cs - + Code diff --git a/Src/LexText/ParserEngine/ParserCore/ParserHelper.cs b/Src/LexText/ParserEngine/ParserCore/ParserHelper.cs new file mode 100644 index 0000000000..58046483df --- /dev/null +++ b/Src/LexText/ParserEngine/ParserCore/ParserHelper.cs @@ -0,0 +1,137 @@ +// -------------------------------------------------------------------------------------------- +#region // Copyright (c) 2014, SIL International. All Rights Reserved. +// +// Copyright (c) 2014, SIL International. All Rights Reserved. +// +// Distributable under the terms of either the Common Public License or the +// GNU Lesser General Public License, as specified in the LICENSING.txt file. +// +#endregion +// -------------------------------------------------------------------------------------------- +using System; +using System.Diagnostics; +using System.Text; +using System.Xml.Linq; +using SIL.FieldWorks.FDO; +using SIL.FieldWorks.FDO.DomainServices; + +namespace SIL.FieldWorks.WordWorks.Parser +{ + public class ParserHelper + { + public static bool TryCreateParseMorph(FdoCache cache, XElement morphElem, out ParseMorph morph) + { + XElement formElement = morphElem.Element("MoForm"); + Debug.Assert(formElement != null); + var hvoForm = (string)formElement.Attribute("DbRef"); + + XElement msiElement = morphElem.Element("MSI"); + Debug.Assert(msiElement != null); + var msaHvoStr = (string)msiElement.Attribute("DbRef"); + + return TryCreateParseMorph(cache, hvoForm, msaHvoStr, out morph); + } + + /// + /// Creates a single ParseMorph object + /// Handles special cases where the MoForm hvo and/or MSI hvos are + /// not actual MoForm or MSA objects. + /// + /// The FDO cache. + /// The form hvo. + /// The msa hvo. + /// a new ParseMorph object or null if the morpheme should be skipped + /// + public static bool TryCreateParseMorph(FdoCache cache, string formHvo, string msaHvo, out ParseMorph morph) + { + // Normally, the hvo for MoForm is a MoForm and the hvo for MSI is an MSA + // There are four exceptions, though, when an irregularly inflected form is involved: + // 1. ().TryGetObject(int.Parse(formHvo), out objForm)) + { + morph = null; + return false; + } + var form = objForm as IMoForm; + if (form == null) + { + morph = null; + return true; + } + + // Irregulary inflected forms can have a combination MSA hvo: the LexEntry hvo, a period, and an index to the LexEntryRef + string[] msaHvoParts = msaHvo.Split('.'); + ICmObject objMsa; + if (!cache.ServiceLocator.GetInstance().TryGetObject(int.Parse(msaHvoParts[0]), out objMsa)) + { + morph = null; + return false; + } + var msa = objMsa as IMoMorphSynAnalysis; + if (msa != null) + { + morph = new ParseMorph(form, msa); + return true; + } + + var msaAsLexEntry = objMsa as ILexEntry; + if (msaAsLexEntry != null) + { + // is an irregularly inflected form + // get the MoStemMsa of its variant + if (msaAsLexEntry.EntryRefsOS.Count > 0) + { + int index = msaHvoParts.Length == 2 ? int.Parse(msaHvoParts[1]) : 0; + ILexEntryRef lexEntryRef = msaAsLexEntry.EntryRefsOS[index]; + ILexSense sense = MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); + var inflType = (ILexEntryInflType)lexEntryRef.VariantEntryTypesRS[0]; + morph = new ParseMorph(form, sense.MorphoSyntaxAnalysisRA, inflType); + return true; + } + } + + // if it is anything else, we ignore it + morph = null; + return true; + } + + /// + /// Convert any characters in the name which are higher than 0x00FF to hex. + /// Neither XAmple nor PC-PATR can read a file name containing letters above 0x00FF. + /// + /// The original name to be converted + /// Converted name + public static string ConvertNameToUseAnsiCharacters(string originalName) + { + var sb = new StringBuilder(); + char[] letters = originalName.ToCharArray(); + foreach (var letter in letters) + { + int value = Convert.ToInt32(letter); + if (value > 255) + { + string hex = value.ToString("X4"); + sb.Append(hex); + } + else + { + sb.Append(letter); + } + } + return sb.ToString(); + } + } +} diff --git a/Src/LexText/ParserEngine/ParserCore/ParserWorker.cs b/Src/LexText/ParserEngine/ParserCore/ParserWorker.cs index aef278699e..e952deabe5 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserWorker.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserWorker.cs @@ -70,7 +70,7 @@ public ParserWorker(FdoCache cache, Action taskUpdateHandler, IdleQu agent = cache.ServiceLocator.GetInstance().GetObject(CmAgentTags.kguidAgentXAmpleParser); break; case "HC": - // create HCParser here + m_parser = new HCParser(cache, appInstallDir); agent = cache.ServiceLocator.GetInstance().GetObject(CmAgentTags.kguidAgentHermitCrabParser); break; default: diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs b/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs index ffd5408d75..21353234a4 100644 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs +++ b/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs @@ -1,13 +1,10 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Globalization; using System.IO; -using System.Text; using System.Xml; using System.Xml.Linq; using SIL.FieldWorks.FDO; -using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.Infrastructure; using SIL.Utils; using XAmpleManagedWrapper; @@ -39,7 +36,7 @@ public void Initialize() XmlDocument fxtResult = m_retriever.ModelDom; XmlDocument gafawsFxtResult = m_retriever.TemplateDom; - string projectName = ConvertNameToUseAnsiCharacters(m_cache.ProjectId.Name); + string projectName = ParserHelper.ConvertNameToUseAnsiCharacters(m_cache.ProjectId.Name); var transformer = new M3ToXAmpleTransformer(projectName, m_appInstallDir); // PrepareTemplatesForXAmpleFiles adds orderclass elements to MoInflAffixSlot elements @@ -110,7 +107,7 @@ public ParseResult ParseWord(string word) foreach (XElement morphElem in analysisElem.Descendants("Morph")) { ParseMorph morph; - if (!TryCreateParseMorph(morphElem, out morph)) + if (!ParserHelper.TryCreateParseMorph(m_cache, morphElem, out morph)) { skip = true; break; @@ -128,86 +125,6 @@ public ParseResult ParseWord(string word) return result; } - /// - /// Creates a single ParseMorph object - /// Handles special cases where the MoForm hvo and/or MSI hvos are - /// not actual MoForm or MSA objects. - /// - /// A Morph element returned by one of the automated parsers - /// a new ParseMorph object or null if the morpheme should be skipped - /// - private bool TryCreateParseMorph(XElement morphElem, out ParseMorph morph) - { - // Normally, the hvo for MoForm is a MoForm and the hvo for MSI is an MSA - // There are four exceptions, though, when an irregularly inflected form is involved: - // 1. ().TryGetObject(hvoForm, out objForm)) - { - morph = null; - return false; - } - var form = objForm as IMoForm; - if (form == null) - { - morph = null; - return true; - } - - // Irregulary inflected forms can have a combination MSA hvo: the LexEntry hvo, a period, and an index to the LexEntryRef - XElement msiElement = morphElem.Element("MSI"); - Debug.Assert(msiElement != null); - var msaHvoStr = (string) msiElement.Attribute("DbRef"); - string[] msaHvoParts = msaHvoStr.Split('.'); - ICmObject objMsa; - if (!m_cache.ServiceLocator.GetInstance().TryGetObject(int.Parse(msaHvoParts[0]), out objMsa)) - { - morph = null; - return false; - } - var msa = objMsa as IMoMorphSynAnalysis; - if (msa != null) - { - morph = new ParseMorph(form, msa); - return true; - } - - var msaAsLexEntry = objMsa as ILexEntry; - if (msaAsLexEntry != null) - { - // is an irregularly inflected form - // get the MoStemMsa of its variant - if (msaAsLexEntry.EntryRefsOS.Count > 0) - { - int index = msaHvoParts.Length == 2 ? int.Parse(msaHvoParts[1]) : 0; - ILexEntryRef lexEntryRef = msaAsLexEntry.EntryRefsOS[index]; - ILexSense sense = MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); - var inflType = (ILexEntryInflType) lexEntryRef.VariantEntryTypesRS[0]; - morph = new ParseMorph(form, sense.MorphoSyntaxAnalysisRA, inflType); - return true; - } - } - - // if it is anything else, we ignore it - morph = null; - return true; - } - public string ParseWordXml(string word) { CheckDisposed(); @@ -222,32 +139,6 @@ public string TraceWordXml(string word, string selectTraceMorphs) return m_xample.TraceWord(word, selectTraceMorphs); } - /// - /// Convert any characters in the name which are higher than 0x00FF to hex. - /// Neither XAmple nor PC-PATR can read a file name containing letters above 0x00FF. - /// - /// The original name to be converted - /// Converted name - private static string ConvertNameToUseAnsiCharacters(string originalName) - { - var sb = new StringBuilder(); - char[] letters = originalName.ToCharArray(); - foreach (var letter in letters) - { - int value = Convert.ToInt32(letter); - if (value > 255) - { - string hex = value.ToString("X4"); - sb.Append(hex); - } - else - { - sb.Append(letter); - } - } - return sb.ToString(); - } - protected override void DisposeManagedResources() { if (m_xample != null) From b8221bebad87f93a885f58c84d3a11e53e84e25d Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Tue, 21 Jan 2014 16:21:19 +0700 Subject: [PATCH 058/143] Fix MONO build bug in FdoIFwMetaDataCache Change-Id: I7076c27858df25d47db74f6d5b9b2b0fa9440220 --- Src/FDO/Infrastructure/Impl/FdoIFwMetaDataCache.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Src/FDO/Infrastructure/Impl/FdoIFwMetaDataCache.cs b/Src/FDO/Infrastructure/Impl/FdoIFwMetaDataCache.cs index aef3e55886..981645753b 100644 --- a/Src/FDO/Infrastructure/Impl/FdoIFwMetaDataCache.cs +++ b/Src/FDO/Infrastructure/Impl/FdoIFwMetaDataCache.cs @@ -122,10 +122,9 @@ private void InitializeMetaDataCache(IEnumerable cmObjectTypes) continue; // ScrFootnote does not have the 'ModelClassAttribute'. //throw new InvalidOperationException("CmObjects must use 'ModelClassAttribute'."); - int clid = ((ModelClassAttribute)classAttrs[0]).Clsid; // Add its class information. AddClass(fdoType.Name, - clid, + ((ModelClassAttribute)classAttrs[0]).Clsid, fdoType.Name == "CmObject" ? "CmObject" : fdoType.BaseType.Name, fdoType.IsAbstract); #else @@ -157,7 +156,7 @@ private void InitializeMetaDataCache(IEnumerable cmObjectTypes) #endif if (fdoType.GetInterface("IAnalysis") != null) - m_analysisClids.Add(clid); + m_analysisClids.Add(((ModelClassAttribute)classAttrs[0]).Clsid); // Cache properties. // Regular foreach loop is faster. //PropertyInfo[] pis = fdoType.GetProperties(); From ed79ce3b087006cc09b9f47846bc2f93eb86618b Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Tue, 21 Jan 2014 16:23:09 +0700 Subject: [PATCH 059/143] fixed ParseFiler tests Change-Id: I7777eef267da0ffb1930ffa06447ad482869a3ed --- .../ParserEngine/ParserCore/AssemblyInfo.cs | 2 + .../ParserEngine/ParserCore/ParseFiler.cs | 72 ++++++------------- .../ParseFilerProcessingTests.cs | 49 +++++-------- .../ParserEngine/ParserCore/ParserHelper.cs | 2 +- 4 files changed, 40 insertions(+), 85 deletions(-) diff --git a/Src/LexText/ParserEngine/ParserCore/AssemblyInfo.cs b/Src/LexText/ParserEngine/ParserCore/AssemblyInfo.cs index 939c374016..fd4a0d7552 100644 --- a/Src/LexText/ParserEngine/ParserCore/AssemblyInfo.cs +++ b/Src/LexText/ParserEngine/ParserCore/AssemblyInfo.cs @@ -14,3 +14,5 @@ [assembly: AssemblyTitle("FieldWorks Morphological Parser")] [assembly: System.Runtime.InteropServices.ComVisible(false)] + +[assembly: InternalsVisibleTo("ParserCoreTests")] diff --git a/Src/LexText/ParserEngine/ParserCore/ParseFiler.cs b/Src/LexText/ParserEngine/ParserCore/ParseFiler.cs index 44d70ebb58..8215b22237 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParseFiler.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParseFiler.cs @@ -80,12 +80,6 @@ public class ParseFiler private readonly ICmBaseAnnotationFactory m_baseAnnotationFactory; private readonly ICmAgent m_userAgent; - /// - /// Set of analyses which had a recorded evaluation by this parser agent when the engine was loaded. - /// These evaluations are considered stale until we set a new evaluation, which removes that item from the set. - /// - private readonly HashSet m_analysesWithOldEvaluation; - #endregion Data members #region Properties @@ -121,10 +115,6 @@ public ParseFiler(FdoCache cache, Action taskUpdateHandler, IdleQueu m_baseAnnotationRepository = servLoc.GetInstance(); m_baseAnnotationFactory = servLoc.GetInstance(); m_userAgent = m_cache.LanguageProject.DefaultUserAgent; - - m_analysesWithOldEvaluation = new HashSet( - m_cache.ServiceLocator.GetInstance().AllInstances().Where( - analysis => analysis.GetAgentOpinion(m_parserAgent) != Opinions.noopinion)); } #endregion Construction and Disposal @@ -192,6 +182,9 @@ from ann in m_baseAnnotationRepository.AllInstances() foreach (ICmBaseAnnotation problem in problemAnnotations) m_cache.DomainDataByFlid.DeleteObj(problem.Hvo); + foreach (IWfiAnalysis analysis in work.Wordform.AnalysesOC) + m_parserAgent.SetEvaluation(analysis, Opinions.noopinion); + if (work.ParseResult.ErrorMessage != null) { // there was an error, so create a problem annotation @@ -201,22 +194,14 @@ from ann in m_baseAnnotationRepository.AllInstances() problemReport.SourceRA = m_parserAgent; problemReport.AnnotationTypeRA = null; problemReport.BeginObjectRA = work.Wordform; - FinishWordForm(work.Wordform); + SetUnsuccessfulParseEvals(work.Wordform, Opinions.noopinion); } else { // update the wordform foreach (ParseAnalysis analysis in work.ParseResult.Analyses) ProcessAnalysis(work.Wordform, analysis); - FinishWordForm(work.Wordform); - foreach (IWfiAnalysis analysis in work.Wordform.AnalysesOC.Where(anal => anal.GetAgentOpinion(m_parserAgent) != Opinions.approves)) - { - m_analysesWithOldEvaluation.Remove(analysis); - if (analysis.GetAgentOpinion(m_userAgent) == Opinions.noopinion) - analysis.Delete(); - else - m_parserAgent.SetEvaluation(analysis, Opinions.disapproves); - } + SetUnsuccessfulParseEvals(work.Wordform, Opinions.disapproves); } work.Wordform.Checksum = work.ParseResult.GetHashCode(); } @@ -300,46 +285,29 @@ Try to find matching analysis(analyses) that already exist. } // (Re)set evaluations. foreach (IWfiAnalysis matchingAnal in matches) - { m_parserAgent.SetEvaluation(matchingAnal, Opinions.approves); - m_analysesWithOldEvaluation.Remove(matchingAnal); - } } #region Wordform Preparation methods - private void FinishWordForm(IWfiWordform wordform) + private void SetUnsuccessfulParseEvals(IWfiWordform wordform, Opinions opinion) { - // the following is a port of the SP RemoveUnusedAnalyses - - // Delete stale evaluations on analyses. The only non-stale analyses are new, positive ones, so this - // makes all analyses that are not known to be correct no-opinion. Later any of them that survive at all - // will be changed to failed (if there was no error in parsing the wordform). - foreach (IWfiAnalysis analysis in wordform.AnalysesOC.Where(a => m_analysesWithOldEvaluation.Contains(a))) - analysis.SetAgentOpinion(m_parserAgent, Opinions.noopinion); - - // Make sure all analyses have human evaluations, if they, - // or glosses they own, are referred to by an ISegment. - //var annLookup = m_baseAnnotationRepository.AllInstances() - // .Where(ann => ann.AnnotationTypeRA != null && ann.AnnotationTypeRA.Guid == CmAnnotationDefnTags.kguidAnnWordformInContext) - // .ToLookup(ann => ann.InstanceOfRA); var segmentAnalyses = new HashSet(); foreach (ISegment seg in wordform.OccurrencesBag) - segmentAnalyses.UnionWith(seg.AnalysesRS.ToArray()); - IEnumerable analyses = - from anal in wordform.AnalysesOC - where segmentAnalyses.Contains(anal) || anal.MeaningsOC.Any(segmentAnalyses.Contains) - select anal; - foreach (IWfiAnalysis analysis in analyses) - m_userAgent.SetEvaluation(analysis, Opinions.approves); - - // Delete orphan analyses, which have no evaluations (Review JohnT: should we also check for no owned WfiGlosses?) - IEnumerable orphanedAnalyses = - from anal in wordform.AnalysesOC - where anal.EvaluationsRC.Count == 0 - select anal; - foreach (IWfiAnalysis analysis in orphanedAnalyses) - m_cache.DomainDataByFlid.DeleteObj(analysis.Hvo); + segmentAnalyses.UnionWith(seg.AnalysesRS); + foreach (IWfiAnalysis analysis in wordform.AnalysesOC) + { + // ensure that used analyses have a user evaluation + if (segmentAnalyses.Contains(analysis) || analysis.MeaningsOC.Any(gloss => segmentAnalyses.Contains(gloss))) + m_userAgent.SetEvaluation(analysis, Opinions.approves); + if (analysis.GetAgentOpinion(m_parserAgent) == Opinions.noopinion) + { + if (analysis.GetAgentOpinion(m_userAgent) == Opinions.noopinion) + analysis.Delete(); + else if (opinion != Opinions.noopinion) + m_parserAgent.SetEvaluation(analysis, opinion); + } + } } #endregion Wordform Preparation methods diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParseFilerProcessingTests.cs b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParseFilerProcessingTests.cs index 9c3cd3d671..e7a0ad7d83 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParseFilerProcessingTests.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParseFilerProcessingTests.cs @@ -71,22 +71,22 @@ protected ICmAgent HumanAgent protected IWfiWordform CheckAnnotationSize(string form, int expectedSize, bool isStarting) { - var servLoc = Cache.ServiceLocator; - var wf = FindOrCreateWordform(form); - var actualSize = + IFdoServiceLocator servLoc = Cache.ServiceLocator; + IWfiWordform wf = FindOrCreateWordform(form); + int actualSize = (from ann in servLoc.GetInstance().AllInstances() where ann.BeginObjectRA == wf select ann).Count(); // wf.RefsFrom_CmBaseAnnotation_BeginObject.Count; - var msg = String.Format("Wrong number of {0} annotations for: {1}", isStarting ? "starting" : "ending", form); + string msg = String.Format("Wrong number of {0} annotations for: {1}", isStarting ? "starting" : "ending", form); Assert.AreEqual(expectedSize, actualSize, msg); return wf; } private IWfiWordform FindOrCreateWordform(string form) { - var servLoc = Cache.ServiceLocator; - var wf = servLoc.GetInstance().GetMatchingWordform(m_vernacularWS.Handle, form); + IFdoServiceLocator servLoc = Cache.ServiceLocator; + IWfiWordform wf = servLoc.GetInstance().GetMatchingWordform(m_vernacularWS.Handle, form); if (wf == null) { UndoableUnitOfWorkHelper.Do("Undo create", "Redo create", m_actionHandler, @@ -97,17 +97,17 @@ private IWfiWordform FindOrCreateWordform(string form) protected IWfiWordform CheckAnalysisSize(string form, int expectedSize, bool isStarting) { - var wf = FindOrCreateWordform(form); - var actualSize = wf.AnalysesOC.Count; - var msg = String.Format("Wrong number of {0} analyses for: {1}", isStarting ? "starting" : "ending", form); + IWfiWordform wf = FindOrCreateWordform(form); + int actualSize = wf.AnalysesOC.Count; + string msg = String.Format("Wrong number of {0} analyses for: {1}", isStarting ? "starting" : "ending", form); Assert.AreEqual(expectedSize, actualSize, msg); return wf; } protected void CheckEvaluationSize(IWfiAnalysis analysis, int expectedSize, bool isStarting, string additionalMessage) { - var actualSize = analysis.EvaluationsRC.Count; - var msg = String.Format("Wrong number of {0} evaluations for analysis: {1} ({2})", isStarting ? "starting" : "ending", analysis.Hvo, additionalMessage); + int actualSize = analysis.EvaluationsRC.Count; + string msg = String.Format("Wrong number of {0} evaluations for analysis: {1} ({2})", isStarting ? "starting" : "ending", analysis.Hvo, additionalMessage); Assert.AreEqual(expectedSize, actualSize, msg); } @@ -414,21 +414,14 @@ public void HumanApprovedParserPreviouslyApprovedButNowRejectedAnalysisSurvives( result = new ParseResult(Enumerable.Empty()); }); - using (var idleQueue = new IdleQueue()) - { - var filer = new ParseFiler(Cache, task => { }, idleQueue, ParserAgent); - idleQueue.IsPaused = true; - filer.ProcessParse(theThreeLittlePigs, ParserPriority.Low, result); - foreach (var task in idleQueue) - task.Delegate(task.Parameter); - idleQueue.Clear(); - } - CheckEvaluationSize(anal, 1, false, "analHvo"); + m_filer.ProcessParse(theThreeLittlePigs, ParserPriority.Low, result); + ExecuteIdleQueue(); + CheckEvaluationSize(anal, 2, false, "analHvo"); Assert.IsTrue(anal.IsValidObject, "analysis should end up with one evaluation and not be deleted"); } [Test] - public void HumanHasNoopinionParserHadApprovedButNoLongerApprovesRemovesAnalisys() + public void HumanHasNoopinionParserHadApprovedButNoLongerApprovesRemovesAnalysis() { IWfiWordform threeLittlePigs = CheckAnalysisSize("threeLittlePigsTEST", 0, true); @@ -464,16 +457,8 @@ public void HumanHasNoopinionParserHadApprovedButNoLongerApprovesRemovesAnalisys result = new ParseResult(Enumerable.Empty()); }); - using (var idleQueue = new IdleQueue()) - { - var filer = new ParseFiler(Cache, task => { }, idleQueue, ParserAgent); - idleQueue.IsPaused = true; - filer.ProcessParse(threeLittlePigs, ParserPriority.Low, result); - foreach (var task in idleQueue) - task.Delegate(task.Parameter); - idleQueue.Clear(); - } - //CheckEvaluationSize(anal, 0, false, "analHvo"); + m_filer.ProcessParse(threeLittlePigs, ParserPriority.Low, result); + ExecuteIdleQueue(); Assert.IsFalse(anal.IsValidObject, "analysis should end up with no evaluations and be deleted."); } diff --git a/Src/LexText/ParserEngine/ParserCore/ParserHelper.cs b/Src/LexText/ParserEngine/ParserCore/ParserHelper.cs index 58046483df..2435bfeb72 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserHelper.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserHelper.cs @@ -17,7 +17,7 @@ namespace SIL.FieldWorks.WordWorks.Parser { - public class ParserHelper + internal class ParserHelper { public static bool TryCreateParseMorph(FdoCache cache, XElement morphElem, out ParseMorph morph) { From 051baa4fbd468b99c7df0cd13bee13944aec8885 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Wed, 22 Jan 2014 10:40:37 +0700 Subject: [PATCH 060/143] Pass the data directory rather than the root directory Change-Id: Ic6672e2895d2b23d4156d000033efdbca67590c0 --- .../Transforms/FxtM3ParserToHCInput.xsl | 2 +- Src/LexText/ParserEngine/ParserCore/HCParser.cs | 16 ++++++++-------- Src/LexText/ParserEngine/ParserCore/IParser.cs | 2 +- .../ParserEngine/ParserCore/M3ToHCTransformer.cs | 4 ++-- .../ParserCore/M3ToParserTransformerBase.cs | 8 ++++---- .../ParserCore/M3ToXAmpleTransformer.cs | 4 ++-- .../ParserEngine/ParserCore/ParserScheduler.cs | 4 ++-- .../ParserEngine/ParserCore/ParserWorker.cs | 8 ++++---- .../XAmpleManagedWrapper/IXAmpleWrapper.cs | 2 +- .../XAmpleManagedWrapper/XAmpleDLLWrapper.cs | 2 +- .../TestXAmpleDLLWrapper.cs | 2 +- .../TestXAmpleWrapper.cs | 2 +- .../XAmpleManagedWrapper/XAmpleWrapper.cs | 6 +++--- .../ParserEngine/ParserCore/XAmpleParser.cs | 14 +++++++------- Src/LexText/ParserUI/ParserConnection.cs | 3 ++- 15 files changed, 40 insertions(+), 39 deletions(-) diff --git a/DistFiles/Language Explorer/Transforms/FxtM3ParserToHCInput.xsl b/DistFiles/Language Explorer/Transforms/FxtM3ParserToHCInput.xsl index 2c9b0baff6..1baa1e9f60 100644 --- a/DistFiles/Language Explorer/Transforms/FxtM3ParserToHCInput.xsl +++ b/DistFiles/Language Explorer/Transforms/FxtM3ParserToHCInput.xsl @@ -1,6 +1,6 @@ - + diff --git a/Src/LexText/ParserEngine/ParserCore/HCParser.cs b/Src/LexText/ParserEngine/ParserCore/HCParser.cs index 46964aae3d..63ace2e882 100644 --- a/Src/LexText/ParserEngine/ParserCore/HCParser.cs +++ b/Src/LexText/ParserEngine/ParserCore/HCParser.cs @@ -33,17 +33,17 @@ public class HCParser : FwDisposableBase, IParser private PatrParser m_patr; private readonly Loader m_loader; private M3ParserModelRetriever m_retriever; - private readonly string m_appInstallDir; + private readonly string m_dataDir; private readonly string m_outputDirectory; // m_projectName here is only used to create temporary files for the parser to load. // We convert the name to use strictly ANSI characters so that the patr parsers (which is // a legacy C program) can read the file names. private readonly string m_projectName; - public HCParser(FdoCache cache, string appInstallDir) + public HCParser(FdoCache cache, string dataDir) { m_cache = cache; - m_appInstallDir = appInstallDir; + m_dataDir = dataDir; m_retriever = new M3ParserModelRetriever(m_cache); m_patr = new PatrParser @@ -53,7 +53,7 @@ public HCParser(FdoCache cache, string appInstallDir) }; m_loader = new XmlLoader { - XmlResolver = new XmlFwResolver(appInstallDir), + XmlResolver = new XmlFwResolver(dataDir), QuitOnError = false }; @@ -62,7 +62,7 @@ public HCParser(FdoCache cache, string appInstallDir) } #region IParser implementation - public void Initialize() + public void Update() { CheckDisposed(); @@ -192,7 +192,7 @@ private void LoadParser(ref XmlDocument model) } } - var transformer = new M3ToHCTransformer(m_projectName, m_appInstallDir); + var transformer = new M3ToHCTransformer(m_projectName, m_dataDir); transformer.MakeHCFiles(ref model); m_patr.LoadGrammarFile(HcGrammarPath); @@ -798,9 +798,9 @@ class XmlFwResolver : XmlUrlResolver { readonly Uri m_baseUri; - public XmlFwResolver(string appInstallDir) + public XmlFwResolver(string dataDir) { - m_baseUri = new Uri(appInstallDir + Path.DirectorySeparatorChar); + m_baseUri = new Uri(dataDir + Path.DirectorySeparatorChar); } public override Uri ResolveUri(Uri baseUri, string relativeUri) diff --git a/Src/LexText/ParserEngine/ParserCore/IParser.cs b/Src/LexText/ParserEngine/ParserCore/IParser.cs index ebed1eed6e..9d0444c172 100644 --- a/Src/LexText/ParserEngine/ParserCore/IParser.cs +++ b/Src/LexText/ParserEngine/ParserCore/IParser.cs @@ -2,7 +2,7 @@ { public interface IParser { - void Initialize(); + void Update(); void Reset(); diff --git a/Src/LexText/ParserEngine/ParserCore/M3ToHCTransformer.cs b/Src/LexText/ParserEngine/ParserCore/M3ToHCTransformer.cs index 7132c30517..6392768c1c 100644 --- a/Src/LexText/ParserEngine/ParserCore/M3ToHCTransformer.cs +++ b/Src/LexText/ParserEngine/ParserCore/M3ToHCTransformer.cs @@ -28,8 +28,8 @@ internal class M3ToHCTransformer : M3ToParserTransformerBase /// Initializes a new instance of the class. /// /// ----------------------------------------------------------------------------------- - public M3ToHCTransformer(string database, string appInstallDir) - : base(database, appInstallDir) + public M3ToHCTransformer(string database, string dataDir) + : base(database, dataDir) { } diff --git a/Src/LexText/ParserEngine/ParserCore/M3ToParserTransformerBase.cs b/Src/LexText/ParserEngine/ParserCore/M3ToParserTransformerBase.cs index ce3f520a2c..8a683c7b29 100644 --- a/Src/LexText/ParserEngine/ParserCore/M3ToParserTransformerBase.cs +++ b/Src/LexText/ParserEngine/ParserCore/M3ToParserTransformerBase.cs @@ -11,23 +11,23 @@ abstract internal class M3ToParserTransformerBase { protected string m_outputDirectory; protected string m_database; - protected readonly string m_appInstallDir; + protected readonly string m_dataDir; /// ----------------------------------------------------------------------------------- /// /// Initializes a new instance of the class. /// /// ----------------------------------------------------------------------------------- - public M3ToParserTransformerBase(string database, string appInstallDir) + public M3ToParserTransformerBase(string database, string dataDir) { m_database = database; - m_appInstallDir = appInstallDir; + m_dataDir = dataDir; m_outputDirectory = Path.GetTempPath(); } protected void TransformDomToFile(string transformName, XmlDocument inputDom, string outputName) { - XmlUtils.TransformDomToFile(Path.Combine(m_appInstallDir + "/Language Explorer/Transforms/", transformName), + XmlUtils.TransformDomToFile(Path.Combine(m_dataDir + "/Transforms/", transformName), inputDom, Path.Combine(m_outputDirectory, outputName)); } } diff --git a/Src/LexText/ParserEngine/ParserCore/M3ToXAmpleTransformer.cs b/Src/LexText/ParserEngine/ParserCore/M3ToXAmpleTransformer.cs index b0ab982a96..6894c40fc8 100644 --- a/Src/LexText/ParserEngine/ParserCore/M3ToXAmpleTransformer.cs +++ b/Src/LexText/ParserEngine/ParserCore/M3ToXAmpleTransformer.cs @@ -32,8 +32,8 @@ internal class M3ToXAmpleTransformer : M3ToParserTransformerBase /// Initializes a new instance of the class. /// /// ----------------------------------------------------------------------------------- - public M3ToXAmpleTransformer(string database, string appInstallDir) - : base(database, appInstallDir) + public M3ToXAmpleTransformer(string database, string dataDir) + : base(database, dataDir) { } diff --git a/Src/LexText/ParserEngine/ParserCore/ParserScheduler.cs b/Src/LexText/ParserEngine/ParserCore/ParserScheduler.cs index 6cc796473e..51523a5b1a 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserScheduler.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserScheduler.cs @@ -145,9 +145,9 @@ public override void DoWork() /// Initializes a new instance of the class. /// /// ----------------------------------------------------------------------------------- - public ParserScheduler(FdoCache cache, IdleQueue idleQueue, string appInstallDir) + public ParserScheduler(FdoCache cache, IdleQueue idleQueue, string dataDir) { - m_parserWorker = new ParserWorker(cache, HandleTaskUpdate, idleQueue, appInstallDir); + m_parserWorker = new ParserWorker(cache, HandleTaskUpdate, idleQueue, dataDir); m_parserWorker.ParseFiler.WordformUpdated += ParseFiler_WordformUpdated; m_thread = new ConsumerThread(Work) {IsBackground = true}; diff --git a/Src/LexText/ParserEngine/ParserCore/ParserWorker.cs b/Src/LexText/ParserEngine/ParserCore/ParserWorker.cs index e952deabe5..1dc696bde3 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserWorker.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserWorker.cs @@ -58,7 +58,7 @@ public class ParserWorker : FwDisposableBase /// Initializes a new instance of the class. /// /// ----------------------------------------------------------------------------------- - public ParserWorker(FdoCache cache, Action taskUpdateHandler, IdleQueue idleQueue, string appInstallDir) + public ParserWorker(FdoCache cache, Action taskUpdateHandler, IdleQueue idleQueue, string dataDir) { m_cache = cache; m_taskUpdateHandler = taskUpdateHandler; @@ -66,11 +66,11 @@ public ParserWorker(FdoCache cache, Action taskUpdateHandler, IdleQu switch (m_cache.LanguageProject.MorphologicalDataOA.ActiveParser) { case "XAmple": - m_parser = new XAmpleParser(cache, appInstallDir); + m_parser = new XAmpleParser(cache, dataDir); agent = cache.ServiceLocator.GetInstance().GetObject(CmAgentTags.kguidAgentXAmpleParser); break; case "HC": - m_parser = new HCParser(cache, appInstallDir); + m_parser = new HCParser(cache, dataDir); agent = cache.ServiceLocator.GetInstance().GetObject(CmAgentTags.kguidAgentHermitCrabParser); break; default: @@ -154,7 +154,7 @@ private void CheckNeedsUpdate() { using (var task = new TaskReport(ParserCoreStrings.ksUpdatingGrammarAndLexicon, m_taskUpdateHandler)) { - m_parser.Initialize(); + m_parser.Update(); } } diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/IXAmpleWrapper.cs b/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/IXAmpleWrapper.cs index 50e0caa67d..77b0df1fa0 100644 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/IXAmpleWrapper.cs +++ b/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/IXAmpleWrapper.cs @@ -4,7 +4,7 @@ namespace XAmpleManagedWrapper { public interface IXAmpleWrapper { - void Init(string folderContainingXampleDll); + void Init(); // returns xmlResult string ParseWord(string wordform); diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleDLLWrapper.cs b/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleDLLWrapper.cs index 4873e4db8d..3023f9d22e 100644 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleDLLWrapper.cs +++ b/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleDLLWrapper.cs @@ -308,7 +308,7 @@ protected void AssignDelegates () AmpleRemoveSelectiveAnalysisMorphsDelegate = AmpleRemoveSelectiveAnalysisMorphMarshaled; } - public void Init (string lpszFolderContainingXAmpleDll) + public void Init () { // TODO: Currently we are using fixed DllImports. AssignDelegates (); diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleDLLWrapper.cs b/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleDLLWrapper.cs index 3ddcdee166..d0e787a32c 100644 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleDLLWrapper.cs +++ b/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleDLLWrapper.cs @@ -11,7 +11,7 @@ public class TestXAmpleDLLWrapper protected XAmpleDLLWrapper CreateXAmpleDllWrapper() { var xAmple = new XAmpleDLLWrapper(); - xAmple.Init(""); // assume libample.so/XAMPLE.DLL is in the same directory. + xAmple.Init(); return xAmple; } diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleWrapper.cs b/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleWrapper.cs index 33de1ed829..6e21046768 100644 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleWrapper.cs +++ b/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleWrapper.cs @@ -9,7 +9,7 @@ public class TestXAmpleWrapper: SIL.FieldWorks.Test.TestUtils.BaseTest protected XAmpleWrapper InitHelper() { var xAmple = new XAmpleWrapper(); - xAmple.Init(""); + xAmple.Init(); return xAmple; } diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleWrapper.cs b/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleWrapper.cs index 8dd9209cac..07f3f9976d 100644 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleWrapper.cs +++ b/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleWrapper.cs @@ -43,10 +43,10 @@ protected virtual void Dispose(bool fDisposing) #endregion #region IXAmpleWrapper implementation - public void Init (string folderContainingXampleDll) + public void Init() { - m_xample = new XAmpleDLLWrapper (); - m_xample.Init (folderContainingXampleDll); + m_xample = new XAmpleDLLWrapper(); + m_xample.Init(); } diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs b/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs index 21353234a4..2996bf7712 100644 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs +++ b/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs @@ -14,20 +14,20 @@ namespace SIL.FieldWorks.WordWorks.Parser public class XAmpleParser : FwDisposableBase, IParser { private XAmpleWrapper m_xample; - private readonly string m_appInstallDir; + private readonly string m_dataDir; private readonly FdoCache m_cache; private M3ParserModelRetriever m_retriever; - public XAmpleParser(FdoCache cache, string appInstallDir) + public XAmpleParser(FdoCache cache, string dataDir) { m_cache = cache; m_xample = new XAmpleWrapper(); - m_xample.Init(appInstallDir); - m_appInstallDir = appInstallDir; + m_xample.Init(); + m_dataDir = dataDir; m_retriever = new M3ParserModelRetriever(m_cache); } - public void Initialize() + public void Update() { CheckDisposed(); @@ -38,7 +38,7 @@ public void Initialize() XmlDocument gafawsFxtResult = m_retriever.TemplateDom; string projectName = ParserHelper.ConvertNameToUseAnsiCharacters(m_cache.ProjectId.Name); - var transformer = new M3ToXAmpleTransformer(projectName, m_appInstallDir); + var transformer = new M3ToXAmpleTransformer(projectName, m_dataDir); // PrepareTemplatesForXAmpleFiles adds orderclass elements to MoInflAffixSlot elements transformer.PrepareTemplatesForXAmpleFiles(ref fxtResult, gafawsFxtResult); @@ -56,7 +56,7 @@ public void Initialize() m_xample.SetParameter("MaxAnalysesToReturn", maxAnalCount.ToString(CultureInfo.InvariantCulture)); string tempPath = Path.GetTempPath(); - m_xample.LoadFiles(m_appInstallDir + @"/Language Explorer/Configuration/Grammar", tempPath, projectName); + m_xample.LoadFiles(m_dataDir + @"/Configuration/Grammar", tempPath, projectName); } public void Reset() diff --git a/Src/LexText/ParserUI/ParserConnection.cs b/Src/LexText/ParserUI/ParserConnection.cs index 2d93617e44..db40122c78 100644 --- a/Src/LexText/ParserUI/ParserConnection.cs +++ b/Src/LexText/ParserUI/ParserConnection.cs @@ -13,6 +13,7 @@ // -------------------------------------------------------------------------------------------- using System; using System.Collections.Generic; +using System.IO; using System.Threading; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; @@ -42,7 +43,7 @@ public sealed class ParserConnection : FwDisposableBase, IAsyncResult public ParserConnection(FdoCache cache, IdleQueue idleQueue) { m_activity = ""; - m_scheduler = new ParserScheduler(cache, idleQueue, FwDirectoryFinder.CodeDirectory); + m_scheduler = new ParserScheduler(cache, idleQueue, Path.Combine(FwDirectoryFinder.CodeDirectory, FwDirectoryFinder.ksFlexFolderName)); m_scheduler.ParserUpdateVerbose += ParserUpdateHandlerForPolling; } From 22a5b9c01f87aa0305b948e1348b9612e988351d Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Wed, 29 Jan 2014 15:10:43 +0700 Subject: [PATCH 061/143] Expose parser up-to-date property Change-Id: I7eb154f9816c0bff282beba0b4d911567144c742 --- Src/LexText/ParserEngine/ParserCore/HCParser.cs | 5 +++++ Src/LexText/ParserEngine/ParserCore/IParser.cs | 4 ++++ .../ParserEngine/ParserCore/M3ModelRetriever.cs | 11 ++++++----- Src/LexText/ParserEngine/ParserCore/ParserWorker.cs | 3 ++- Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs | 5 +++++ 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/Src/LexText/ParserEngine/ParserCore/HCParser.cs b/Src/LexText/ParserEngine/ParserCore/HCParser.cs index 9a047534c3..c3332fb5bd 100644 --- a/Src/LexText/ParserEngine/ParserCore/HCParser.cs +++ b/Src/LexText/ParserEngine/ParserCore/HCParser.cs @@ -56,6 +56,11 @@ public HCParser(FdoCache cache, string dataDir) } #region IParser implementation + public bool IsUpToDate() + { + return m_retriever.Loaded; + } + public void Update() { CheckDisposed(); diff --git a/Src/LexText/ParserEngine/ParserCore/IParser.cs b/Src/LexText/ParserEngine/ParserCore/IParser.cs index 9d0444c172..3158b94383 100644 --- a/Src/LexText/ParserEngine/ParserCore/IParser.cs +++ b/Src/LexText/ParserEngine/ParserCore/IParser.cs @@ -2,6 +2,10 @@ { public interface IParser { + // Warning: This method is not thread-safe. + // The parser could end up using stale data. + bool IsUpToDate(); + void Update(); void Reset(); diff --git a/Src/LexText/ParserEngine/ParserCore/M3ModelRetriever.cs b/Src/LexText/ParserEngine/ParserCore/M3ModelRetriever.cs index b4a99e1ed8..f623fa02f4 100644 --- a/Src/LexText/ParserEngine/ParserCore/M3ModelRetriever.cs +++ b/Src/LexText/ParserEngine/ParserCore/M3ModelRetriever.cs @@ -28,13 +28,14 @@ namespace SIL.FieldWorks.WordWorks.Parser /// Is public for testing purposes public class M3ParserModelRetriever : FwDisposableBase, IVwNotifyChange { + public bool Loaded { get; private set; } + private readonly FdoCache m_cache; private readonly string m_modelPath; private readonly string m_templatePath; private readonly string m_outputDirectory; private XmlDocument m_modelDom; private XmlDocument m_templateDom; - private bool m_loaded; private readonly object m_syncRoot = new object(); @@ -67,9 +68,9 @@ public bool RetrieveModel() { lock (m_syncRoot) { - if (m_loaded) + if (Loaded) return false; - m_loaded = true; + Loaded = true; } // According to the fxt template files, GAFAWS is NFC, all others are NFD. @@ -91,7 +92,7 @@ public bool RetrieveModel() public void Reset() { lock (m_syncRoot) - m_loaded = false; + Loaded = false; m_modelDom = null; m_templateDom = null; } @@ -193,7 +194,7 @@ void IVwNotifyChange.PropChanged(int hvo, int tag, int ivMin, int cvIns, int cvD case PhSimpleContextSegTags.kClassId: case PhVariableTags.kClassId: case PhEnvironmentTags.kClassId: - m_loaded = false; + Loaded = false; break; } } diff --git a/Src/LexText/ParserEngine/ParserCore/ParserWorker.cs b/Src/LexText/ParserEngine/ParserCore/ParserWorker.cs index 371eca45b6..a19f9442a8 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserWorker.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserWorker.cs @@ -148,7 +148,8 @@ private void CheckNeedsUpdate() { using (var task = new TaskReport(ParserCoreStrings.ksUpdatingGrammarAndLexicon, m_taskUpdateHandler)) { - m_parser.Update(); + if (!m_parser.IsUpToDate()) + m_parser.Update(); } } diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs b/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs index 2996bf7712..5399d2e851 100644 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs +++ b/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs @@ -27,6 +27,11 @@ public XAmpleParser(FdoCache cache, string dataDir) m_retriever = new M3ParserModelRetriever(m_cache); } + public bool IsUpToDate() + { + return m_retriever.Loaded; + } + public void Update() { CheckDisposed(); From f3826bc916b8845752dab34f54550d92ddde4267 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Fri, 31 Jan 2014 11:58:11 +0700 Subject: [PATCH 062/143] Create FdoFileLockedException to extend StartupException Change-Id: Ie2dbe17c9e258f6b2537fbbbf501425f2a8da627 --- Src/FDO/FDO.csproj | 1 + Src/FDO/FdoFileLockedException.cs | 40 +++++++++++++++++++ .../Infrastructure/Impl/XMLBackendProvider.cs | 2 +- 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 Src/FDO/FdoFileLockedException.cs diff --git a/Src/FDO/FDO.csproj b/Src/FDO/FDO.csproj index 759fae2489..1b57c3acf7 100644 --- a/Src/FDO/FDO.csproj +++ b/Src/FDO/FDO.csproj @@ -183,6 +183,7 @@ + diff --git a/Src/FDO/FdoFileLockedException.cs b/Src/FDO/FdoFileLockedException.cs new file mode 100644 index 0000000000..dfedc0bb3c --- /dev/null +++ b/Src/FDO/FdoFileLockedException.cs @@ -0,0 +1,40 @@ +// Copyright (c) 2013-2014 SIL International +// This software is licensed under the LGPL, version 2.1 or later +// (http://www.gnu.org/licenses/lgpl-2.1.html) + +using System; +using SIL.CoreImpl; + +namespace SIL.FieldWorks.FDO +{ + /// + /// Exception thrown when we try to open a project that is locked + /// + public class FdoFileLockedException : StartupException + { + /// ------------------------------------------------------------------------------------ + /// + /// Initializes a new instance of the class. + /// + /// The message. + /// ------------------------------------------------------------------------------------ + public FdoFileLockedException(string message) + : base(message) + { + } + + /// ------------------------------------------------------------------------------------ + /// + /// Initializes a new instance of the class. + /// + /// The message. + /// The inner exception. + /// True to report this error to the user, false otherwise + /// + /// ------------------------------------------------------------------------------------ + public FdoFileLockedException(string message, Exception innerException, bool fReportToUser) : + base(message, innerException, fReportToUser) + { + } + } +} \ No newline at end of file diff --git a/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs b/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs index 3c2a126409..607ce69d29 100644 --- a/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs @@ -369,7 +369,7 @@ private void BasicInit() } catch (IOException e) { - throw new StartupException(String.Format(Properties.Resources.kstidLockFileLocked, ProjectId.Name), e, true); + throw new FdoFileLockedException(String.Format(Properties.Resources.kstidLockFileLocked, ProjectId.Name), e, true); } } From 530c46203bd831cb0575b6eab1dca0fea7ea5c8d Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Wed, 5 Feb 2014 11:53:15 +0700 Subject: [PATCH 063/143] Find in Dictionary will only return entries from approved analyses Change-Id: If24fbf02f2d021a51b55ab895da9be0a77a1de26 --- .../Impl/FdoRepositoryAdditions.cs | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/Src/FDO/Infrastructure/Impl/FdoRepositoryAdditions.cs b/Src/FDO/Infrastructure/Impl/FdoRepositoryAdditions.cs index 20313cf4d3..b03aa621d9 100644 --- a/Src/FDO/Infrastructure/Impl/FdoRepositoryAdditions.cs +++ b/Src/FDO/Infrastructure/Impl/FdoRepositoryAdditions.cs @@ -1473,54 +1473,52 @@ public List FindEntriesForWordformWorker(FdoCache cache, ITsString ts if (tssWf == null) return new List(); - var wf = tssWf.Text; + string wf = tssWf.Text; if (string.IsNullOrEmpty(wf)) return new List(); - var wsVern = TsStringUtils.GetWsAtOffset(tssWf, 0); + int wsVern = TsStringUtils.GetWsAtOffset(tssWf, 0); var entries = new Set(); // Get the entries from the matching wordform. // Get matching wordform. - var matchingWordforms = cache.ServiceLocator.GetInstance().AllInstances() - .Where(wrdfrm => wrdfrm.Form.get_String(wsVern).Text == wf); + IWfiWordform[] matchingWordforms = cache.ServiceLocator.GetInstance().AllInstances() + .Where(wrdfrm => wrdfrm.Form.get_String(wsVern).Text == wf).ToArray(); - duplicates = matchingWordforms.Count() > 1; + duplicates = matchingWordforms.Length > 1; - if (matchingWordforms.Count() > 0) + if (matchingWordforms.Length > 0) { - if (wfa != null && matchingWordforms.First().AnalysesOC.Contains(wfa)) + if (wfa != null && matchingWordforms[0].AnalysesOC.Contains(wfa)) { entries.AddRange(wfa.MorphBundlesOS - .Where(mb => mb.MsaRA != null) - .Select(mb => mb.MsaRA.Owner as ILexEntry)); + .Where(mb => mb.MorphRA != null) + .Select(mb => mb.MorphRA.OwnerOfClass())); } else { - foreach (var analysis in matchingWordforms.First().AnalysesOC) + foreach (IWfiAnalysis analysis in matchingWordforms[0].AnalysesOC.Where(a => a.ApprovalStatusIcon == (int) Opinions.approves)) { entries.AddRange(analysis.MorphBundlesOS - .Where(mb => mb.MsaRA != null) - .Select(mb => mb.MsaRA.Owner as ILexEntry)); + .Where(mb => mb.MorphRA != null) + .Select(mb => mb.MorphRA.OwnerOfClass())); } } } // Get the entries from the matching MoForms. entries.AddRange( cache.ServiceLocator.GetInstance().AllInstances() - .Cast() .Where(mf => mf.Form.get_String(wsVern) != null && mf.Form.get_String(wsVern).Text == wf) - .Select(mf => mf.Owner as ILexEntry)); + .Select(mf => mf.OwnerOfClass())); // Get the entries from the citation form entries.AddRange( cache.ServiceLocator.GetInstance().AllInstances() - .Cast() .Where(entry => entry.CitationForm.get_String(wsVern) != null && entry.CitationForm.get_String(wsVern).Text == wf)); // Put the enrties in a List and sort it by the HomographNumber. - var retval = new List(entries.ToArray()); + var retval = new List(entries); retval.Sort(CompareEntriesByHomographNumber); return retval; } From 602eb8debd4442218a8b232b0e0edf1c623e8af5 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Wed, 5 Feb 2014 17:09:49 +0700 Subject: [PATCH 064/143] Add unit test to UpdateParserDataTests for empty lexicon Change-Id: I9cd6ebbbcccc331ab4bebebc8a8437493f56a4a6 --- .../ParserCoreTests/UpdateParserDataTests.cs | 39 ++++++++++++++++--- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/UpdateParserDataTests.cs b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/UpdateParserDataTests.cs index c9d89083b3..6691c1b5ff 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/UpdateParserDataTests.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/UpdateParserDataTests.cs @@ -10,18 +10,45 @@ // Implements the UpdateParserDataTests unit tests. // -using System; -using System.Diagnostics; -using System.IO; -using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.FDOTests; -using System.Xml; using NUnit.Framework; -using SIL.Utils; +using SIL.FieldWorks.FDO.Infrastructure; namespace SIL.FieldWorks.WordWorks.Parser { + [TestFixture] + public class UpdateParserDataTests : MemoryOnlyBackendProviderTestBase + { + private FdoCache m_cache; + private M3ParserModelRetriever m_retriever; + + public UpdateParserDataTests() : base() + { + } + + [TestFixtureSetUp] + public override void FixtureSetup() + { + base.FixtureSetup(); + + var projectId = new TestProjectId(FDOBackendProviderType.kMemoryOnly, "Test.fwdata"); + m_cache = FdoCache.CreateCacheWithNewBlankLangProj(projectId, "en", "fr", "en", new DummyFdoUI(), FwDirectoryFinder.FdoDirectories); + NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, + () => m_cache.LangProject.MorphologicalDataOA.ParserParameters = "1515010XAmple"); + //string activeParser = m_cache.LangProject.MorphologicalDataOA.ActiveParser; + //m_cache.LangProject.MorphologicalDataOA.ActiveParser = "XAmple"; + m_retriever = new M3ParserModelRetriever(m_cache); + } + + [Test] + public void EmptyLexicon() + { + Assert.IsTrue(m_retriever.RetrieveModel()); + } + } + #if WANTTESTPORT // Will we even want the updater stuff? Surely, we won't want it to use FXT. [TestFixture] public class UpdateParserDataTests : MemoryOnlyBackendProviderTestBase From cd7b6937d062b76543fee3b8d0a3ac3f768b4e58 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Thu, 6 Feb 2014 14:58:58 +0700 Subject: [PATCH 065/143] Add ability to forbid data migration when creating FDO cache Also fix some Gendarme issues. Change-Id: I58b1f10b990655872dc5722a45e9d13923f3752d --- .../FwUtilsTests/FwRegistryHelperTests.cs | 6 +++++ Src/FDO/FDO.csproj | 1 + .../PersistingBackendProviderTests.cs | 4 ++-- Src/FDO/FdoDataMigrationForbiddenException.cs | 15 ++++++++++++ .../IPersistenceStrategyInterfaces.cs | 3 ++- .../Infrastructure/Impl/FDOBackendProvider.cs | 10 +++++--- Src/FDO/fdoCache.cs | 24 ++++++++++++++++--- .../ParserCoreTests/UpdateParserDataTests.cs | 15 ++++++------ .../gendarme-ParserCoreTests.ignore | 1 + 9 files changed, 63 insertions(+), 16 deletions(-) create mode 100644 Src/FDO/FdoDataMigrationForbiddenException.cs diff --git a/Src/Common/FwUtils/FwUtilsTests/FwRegistryHelperTests.cs b/Src/Common/FwUtils/FwUtilsTests/FwRegistryHelperTests.cs index a6f10cff72..742b830a58 100644 --- a/Src/Common/FwUtils/FwUtilsTests/FwRegistryHelperTests.cs +++ b/Src/Common/FwUtils/FwUtilsTests/FwRegistryHelperTests.cs @@ -19,6 +19,9 @@ public class FwRegistryHelperTests : BaseTest { private DummyFwRegistryHelper m_helper; + /// + /// Setups the test bed + /// [SetUp] public void Setup() { @@ -27,6 +30,9 @@ public void Setup() m_helper.DeleteAllSubTreesIfPresent(); } + /// + /// Tears down the test bed + /// [TearDown] public void TearDown() { diff --git a/Src/FDO/FDO.csproj b/Src/FDO/FDO.csproj index 1b57c3acf7..36dba37da8 100644 --- a/Src/FDO/FDO.csproj +++ b/Src/FDO/FDO.csproj @@ -183,6 +183,7 @@ + diff --git a/Src/FDO/FDOTests/PersistingBackendProviderTests.cs b/Src/FDO/FDOTests/PersistingBackendProviderTests.cs index e0db8d5121..790cfafe45 100644 --- a/Src/FDO/FDOTests/PersistingBackendProviderTests.cs +++ b/Src/FDO/FDOTests/PersistingBackendProviderTests.cs @@ -769,7 +769,7 @@ public void StartupExtant() ProjectId = new TestProjectId(FDOBackendProviderType.kXML, Project); // This will throw an UnauthorizedAccessException because of the // StartupInternalWithDataMigrationIfNeeded() override below - StartupExtantLanguageProject(ProjectId, false, new DummyProgressDlg()); + StartupExtantLanguageProject(ProjectId, false, new DummyProgressDlg(), false); } /// @@ -790,7 +790,7 @@ internal override void ReportDuplicateGuidsIfTheyExist() { } - protected override void StartupInternalWithDataMigrationIfNeeded(IThreadedProgress progressDlg) + protected override void StartupInternalWithDataMigrationIfNeeded(IThreadedProgress progressDlg, bool forbidDataMigration) { throw new UnauthorizedAccessException(); } diff --git a/Src/FDO/FdoDataMigrationForbiddenException.cs b/Src/FDO/FdoDataMigrationForbiddenException.cs new file mode 100644 index 0000000000..f0400e25ee --- /dev/null +++ b/Src/FDO/FdoDataMigrationForbiddenException.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2014-2014 SIL International +// This software is licensed under the LGPL, version 2.1 or later +// (http://www.gnu.org/licenses/lgpl-2.1.html) + +using System; + +namespace SIL.FieldWorks.FDO +{ + /// + /// Exception thrown when we try to open a project which requires data migration but data migration has been forbidden by the application + /// + public class FdoDataMigrationForbiddenException : Exception + { + } +} \ No newline at end of file diff --git a/Src/FDO/Infrastructure/IPersistenceStrategyInterfaces.cs b/Src/FDO/Infrastructure/IPersistenceStrategyInterfaces.cs index 6651885a82..eb7eeb1ee8 100644 --- a/Src/FDO/Infrastructure/IPersistenceStrategyInterfaces.cs +++ b/Src/FDO/Infrastructure/IPersistenceStrategyInterfaces.cs @@ -42,7 +42,8 @@ public interface IDataSetup : IFWDisposable /// True to bootstrap the existing system, false to skip that /// step /// The progress dialog box - void StartupExtantLanguageProject(IProjectIdentifier projectId, bool fBootstrapSystem, IThreadedProgress progressDlg); + /// True if the application forbids data migration + void StartupExtantLanguageProject(IProjectIdentifier projectId, bool fBootstrapSystem, IThreadedProgress progressDlg, bool forbidDataMigration); /// /// Create a new LanguageProject for the BEP with the given parameters. diff --git a/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs b/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs index 3e1f2a9b66..acf86bf275 100644 --- a/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs @@ -350,7 +350,7 @@ protected static string GetFlidTypeAsString(CellarPropertyType flidType) /// /// Protected for testing (see MockXMLBackendProvider) /// - protected virtual void StartupInternalWithDataMigrationIfNeeded(IThreadedProgress progressDlg) + protected virtual void StartupInternalWithDataMigrationIfNeeded(IThreadedProgress progressDlg, bool forbidDataMigration) { var currentDataStoreVersion = StartupInternal(ModelVersion); @@ -360,6 +360,9 @@ protected virtual void StartupInternalWithDataMigrationIfNeeded(IThreadedProgres if (currentDataStoreVersion == ModelVersion) return; + if (!forbidDataMigration) + throw new FdoDataMigrationForbiddenException(); + // See if migration involves real data migration(s). // If it does not, just update the stored version number, and keep going. if (!m_dataMigrationManager.NeedsRealMigration(currentDataStoreVersion, ModelVersion)) @@ -738,14 +741,15 @@ public bool UseMemoryWritingSystemManager /// True to bootstrap the existing system, false to skip /// that step /// The progress dialog box + /// True if the application forbids a data migration /// ------------------------------------------------------------------------------------ public void StartupExtantLanguageProject(IProjectIdentifier projectId, bool fBootstrapSystem, - IThreadedProgress progressDlg) + IThreadedProgress progressDlg, bool forbidDataMigration) { ProjectId = projectId; try { - StartupInternalWithDataMigrationIfNeeded(progressDlg); + StartupInternalWithDataMigrationIfNeeded(progressDlg, forbidDataMigration); InitializeWritingSystemManager(); if (fBootstrapSystem) BootstrapExtantSystem(); diff --git a/Src/FDO/fdoCache.cs b/Src/FDO/fdoCache.cs index 2b265b8455..1c6e3a121b 100644 --- a/Src/FDO/fdoCache.cs +++ b/Src/FDO/fdoCache.cs @@ -143,9 +143,27 @@ public static FdoCache CreateCacheWithNewBlankLangProj(IProjectIdentifier projec /// ------------------------------------------------------------------------------------ public static FdoCache CreateCacheFromExistingData(IProjectIdentifier projectId, string userWsIcuLocale, IFdoUI ui, IFdoDirectories dirs, IThreadedProgress progressDlg) + { + return CreateCacheFromExistingData(projectId, userWsIcuLocale, ui, dirs, progressDlg, false); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Creates a new FdoCache that uses a specified data provider type that loads the + /// language project data from an existing source. + /// + /// Identifies the project to load. + /// The ICU locale of the default user WS. + /// + /// + /// The progress dialog box + /// True if data migration is forbidden by the application + /// ------------------------------------------------------------------------------------ + public static FdoCache CreateCacheFromExistingData(IProjectIdentifier projectId, + string userWsIcuLocale, IFdoUI ui, IFdoDirectories dirs, IThreadedProgress progressDlg, bool forbidDataMigration) { return CreateCacheInternal(projectId, userWsIcuLocale, ui, dirs, - dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg), + dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg, forbidDataMigration), cache => cache.Initialize()); } @@ -165,7 +183,7 @@ public static FdoCache CreateCacheFromLocalProjectFile(string projectPath, { var projectId = new SimpleProjectId(FDOBackendProviderType.kXML, projectPath); return CreateCacheInternal(projectId, userWsIcuLocale, ui, dirs, - dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg), + dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg, false), cache => cache.Initialize()); } @@ -377,7 +395,7 @@ public static string CreateNewLangProj(IThreadedProgress progressDlg, params obj var projectId = new SimpleProjectId(FDOBackendProviderType.kXML, dbFileName); using (FdoCache cache = CreateCacheInternal(projectId, userIcuLocale, new SilentFdoUI(synchronizeInvoke), dirs, - dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg))) + dataSetup => dataSetup.StartupExtantLanguageProject(projectId, true, progressDlg, false))) { if (progressDlg != null) { diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/UpdateParserDataTests.cs b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/UpdateParserDataTests.cs index 6691c1b5ff..05e2c70b55 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/UpdateParserDataTests.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/UpdateParserDataTests.cs @@ -24,11 +24,6 @@ public class UpdateParserDataTests : MemoryOnlyBackendProviderTestBase private FdoCache m_cache; private M3ParserModelRetriever m_retriever; - public UpdateParserDataTests() : base() - { - } - - [TestFixtureSetUp] public override void FixtureSetup() { base.FixtureSetup(); @@ -37,11 +32,17 @@ public override void FixtureSetup() m_cache = FdoCache.CreateCacheWithNewBlankLangProj(projectId, "en", "fr", "en", new DummyFdoUI(), FwDirectoryFinder.FdoDirectories); NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, () => m_cache.LangProject.MorphologicalDataOA.ParserParameters = "1515010XAmple"); - //string activeParser = m_cache.LangProject.MorphologicalDataOA.ActiveParser; - //m_cache.LangProject.MorphologicalDataOA.ActiveParser = "XAmple"; m_retriever = new M3ParserModelRetriever(m_cache); } + public override void FixtureTeardown() + { + m_retriever.Dispose(); + m_cache.Dispose(); + + base.FixtureTeardown(); + } + [Test] public void EmptyLexicon() { diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/gendarme-ParserCoreTests.ignore b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/gendarme-ParserCoreTests.ignore index 8044598111..ee5a0a4fc6 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/gendarme-ParserCoreTests.ignore +++ b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/gendarme-ParserCoreTests.ignore @@ -11,3 +11,4 @@ R: Gendarme.Rules.Design.TypesWithDisposableFieldsShouldBeDisposableRule # Unit test. Object disposed in tear down method. T: SIL.FieldWorks.WordWorks.Parser.ParseFilerProcessingTests +T: SIL.FieldWorks.WordWorks.Parser.UpdateParserDataTests From 10d1deff788aefae7d6fa73ea97b85bcad8d72be Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Thu, 6 Feb 2014 15:35:19 +0700 Subject: [PATCH 066/143] UOWs now only invoke on the UI thread when necessary Change-Id: I09e3387b4927acdcbbef231075a3206858972bf0 --- Src/FDO/Infrastructure/Impl/UndoStack.cs | 41 ++++++++++--------- .../Infrastructure/Impl/UnitOfWorkService.cs | 26 ++++++++---- 2 files changed, 40 insertions(+), 27 deletions(-) diff --git a/Src/FDO/Infrastructure/Impl/UndoStack.cs b/Src/FDO/Infrastructure/Impl/UndoStack.cs index dfccf3e71c..1883e85f7f 100644 --- a/Src/FDO/Infrastructure/Impl/UndoStack.cs +++ b/Src/FDO/Infrastructure/Impl/UndoStack.cs @@ -99,7 +99,7 @@ internal sealed class UndoStack : IActionHandler, IActionHandlerExtensions // Negative values count unsaved bundles in m_redoBundles, that is, things Undone since the last Save. private int m_countUnsavedBundles; - private List m_actionsToDoAtEndOfPropChanged = new List(); + private readonly List m_actionsToDoAtEndOfPropChanged = new List(); #endregion #region Constructor @@ -313,10 +313,10 @@ private void EndUndoTaskCommon(bool updateDateModified) dmObj.UpdateDateModified(); } // Update the project DateModified, but only once every 2 minutes at most. - if (m_currentBundle.DirtyObjects.Count() > 0) + if (m_currentBundle.DirtyObjects.Any()) { - LangProject proj = m_currentBundle.DirtyObjects.ElementAt(0).Cache.LangProject as LangProject; - TimeSpan span = new TimeSpan(DateTime.Now.Ticks - proj.DateModified.Ticks); + var proj = (LangProject) m_currentBundle.DirtyObjects.ElementAt(0).Cache.LangProject; + var span = new TimeSpan(DateTime.Now.Ticks - proj.DateModified.Ticks); if (span.Minutes >= 2 || m_currentBundle.DirtyObjects.Contains(proj)) proj.UpdateDateModifiedInternal(); } @@ -369,22 +369,25 @@ private void EndUndoTaskCommon(bool updateDateModified) /// ------------------------------------------------------------------------------------ private void DoTasksForEndOfPropChanged(FdoUnitOfWork uow, bool fromUndoRedo) { - m_ui.SynchronizeInvoke.Invoke(() => - { - if (!fromUndoRedo) + var tasks = new List(); + if (!fromUndoRedo) + { + // These notifications must be sent only once. + // In particular they must not be sent again if one of the tasks in the list makes a new UOW. + // Since this method will execute at the end of such a task, we must make sure that there is + // a fresh m_actionsToDoAtEndOfPropChanged for any such UOW so it will not see our list. + tasks.AddRange(m_actionsToDoAtEndOfPropChanged); + m_actionsToDoAtEndOfPropChanged.Clear(); + } + tasks.AddRange(uow.ActionsToDoAtEndOfPropChanged); + if (tasks.Count > 0) + { + m_ui.SynchronizeInvoke.Invoke(() => { - // These notifications must be sent only once. - // In particular they must not be sent again if one of the tasks in the list makes a new UOW. - // Since this method will execute at the end of such a task, we must make sure that there is - // a fresh m_actionsToDoAtEndOfPropChanged for any such UOW so it will not see our list. - var temp = m_actionsToDoAtEndOfPropChanged; - m_actionsToDoAtEndOfPropChanged = new List(); - foreach (var task in temp) + foreach (Action task in tasks) task(); - } - foreach (var task in uow.ActionsToDoAtEndOfPropChanged) - task(); - }); + }); + } } /// @@ -819,7 +822,7 @@ public bool CollapseToMark(int hMark, string bstrUndo, string bstrRedo) bool fActionsCollapsed = false; if (m_undoBundles.Count > markIndex) { - FdoUndoableUnitOfWork newUow = new FdoUndoableUnitOfWork(m_uowService, bstrUndo, bstrRedo); + var newUow = new FdoUndoableUnitOfWork(m_uowService, bstrUndo, bstrRedo); while (m_undoBundles.Count > markIndex) newUow.InsertActionsFrom(PopUndoStack()); diff --git a/Src/FDO/Infrastructure/Impl/UnitOfWorkService.cs b/Src/FDO/Infrastructure/Impl/UnitOfWorkService.cs index d449f4dee1..996aacf651 100644 --- a/Src/FDO/Infrastructure/Impl/UnitOfWorkService.cs +++ b/Src/FDO/Infrastructure/Impl/UnitOfWorkService.cs @@ -526,23 +526,28 @@ internal void SendPropChangedNotifications(IEnumerable change // This is very likely to modify the UI, so if the UOW is not being done on the UI thread, we need // to do at least this part on that thread. One known case is a task being done in the background // thread of ProgressDialogWithTask. + IVwNotifyChange[] subscribers = m_changeWatchers.ToArray(); + ChangeInformation[] changes = subscribers.Length == 0 ? changesEnum.Where(ci => ci.HasNotifier).ToArray() : changesEnum.ToArray(); + if (changes.Length == 0) + return; + m_ui.SynchronizeInvoke.Invoke(() => { - var subscribers = m_changeWatchers.ToArray(); - var changes = changesEnum.ToList(); - foreach (var sub in subscribers) + foreach (IVwNotifyChange sub in subscribers) { - if (sub is IBulkPropChanged) - ((IBulkPropChanged)sub).BeginBroadcastingChanges(changes.Count); + var bulkPropChanged = sub as IBulkPropChanged; + if (bulkPropChanged != null) + bulkPropChanged.BeginBroadcastingChanges(changes.Length); } foreach (ChangeInformation change in changes) { change.BroadcastChanges(SubscriberCanReceivePropChangeCallDelegate, subscribers); } - foreach (var sub in subscribers) + foreach (IVwNotifyChange sub in subscribers) { - if (sub is IBulkPropChanged) - ((IBulkPropChanged)sub).EndBroadcastingChanges(); + var bulkPropChanged = sub as IBulkPropChanged; + if (bulkPropChanged != null) + bulkPropChanged.EndBroadcastingChanges(); } }); } @@ -1071,6 +1076,11 @@ private ChangeInformation(int hvo, int tag, int ivMin, int cvIns, int cvDel, IPr m_notifier = notifier; } + internal bool HasNotifier + { + get { return m_notifier != null; } + } + internal void BroadcastChanges(SubscriberCanReceivePropChangeCallDelegate subscriberChecker, IVwNotifyChange[] subscribers) { if (subscriberChecker == null) throw new ArgumentNullException("subscriberChecker"); From b5fa299eff6f77ad0efcafc9524379aa67ae827f Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Thu, 6 Feb 2014 15:36:36 +0700 Subject: [PATCH 067/143] Add ability to forbid data migration when creating FDO cache Fixing logic of previous commit. Change-Id: I38a235831f78bd0a37aabec0a9513537e1470ef6 --- Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs b/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs index acf86bf275..37c1cab4e3 100644 --- a/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/FDOBackendProvider.cs @@ -360,7 +360,7 @@ protected virtual void StartupInternalWithDataMigrationIfNeeded(IThreadedProgres if (currentDataStoreVersion == ModelVersion) return; - if (!forbidDataMigration) + if (forbidDataMigration) throw new FdoDataMigrationForbiddenException(); // See if migration involves real data migration(s). From 83651d54440cb872c826cc65373b8cb9a25e9827 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Mon, 10 Feb 2014 16:49:25 +0700 Subject: [PATCH 068/143] updated to latest version of Machine Change-Id: I57f8d82e97fb5d115dc6abcfaeace1ba8e4df6ad --- Lib/debug/SIL.Collections.dll | Bin 102912 -> 114176 bytes Lib/debug/SIL.Collections.pdb | Bin 366080 -> 374272 bytes Lib/debug/SIL.Machine.dll | Bin 225792 -> 324608 bytes Lib/debug/SIL.Machine.pdb | Bin 685568 -> 890368 bytes Lib/release/SIL.Collections.dll | Bin 91136 -> 101888 bytes Lib/release/SIL.Collections.pdb | Bin 321024 -> 327168 bytes Lib/release/SIL.Machine.dll | Bin 200704 -> 290304 bytes Lib/release/SIL.Machine.pdb | Bin 591360 -> 767488 bytes Lib/src/Machine | 2 +- .../Interlinear/ComplexConcGroupNode.cs | 2 +- .../Interlinear/ComplexConcMorphNode.cs | 2 +- Src/LexText/Interlinear/ComplexConcOrNode.cs | 2 +- .../Interlinear/ComplexConcParagraphData.cs | 4 ++-- .../Interlinear/ComplexConcPatternModel.cs | 2 +- .../Interlinear/ComplexConcPatternNode.cs | 2 +- Src/LexText/Interlinear/ComplexConcTagNode.cs | 2 +- .../Interlinear/ComplexConcWordBdryNode.cs | 2 +- .../Interlinear/ComplexConcWordNode.cs | 2 +- 18 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Lib/debug/SIL.Collections.dll b/Lib/debug/SIL.Collections.dll index 376a32c006116935ed38e338bb5cb0e155c15715..c8109102478d4ee4e67a3f829ae503717264e0e4 100644 GIT binary patch literal 114176 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 literal 102912 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 protected string m_sWordGrammarDebuggerXmlFile; - public ParserTraceBase() + protected ParserTraceBase() {} - /// + + /// /// The real deal /// /// @@ -48,117 +51,18 @@ protected void CopyXmlAttribute(XmlDocument doc, XmlNode node, string sAttrName, if (attr != null && sAttrName != null) CreateXmlAttribute(doc, sAttrName, attr.InnerText, morphNode); } - - protected void CreateDerivMsaXmlElement(XmlDocument doc, XmlNode morphNode, IMoDerivAffMsa derivMsa) - { - XmlNode derivMsaNode = CreateXmlElement(doc, "derivMsa", morphNode); - CreatePOSXmlAttribute(doc, derivMsaNode, derivMsa.FromPartOfSpeechRA, "fromCat"); - CreatePOSXmlAttribute(doc, derivMsaNode, derivMsa.ToPartOfSpeechRA, "toCat"); - CreateInflectionClassXmlAttribute(doc, derivMsaNode, derivMsa.FromInflectionClassRA, "fromInflClass"); - CreateInflectionClassXmlAttribute(doc, derivMsaNode, derivMsa.ToInflectionClassRA, "toInflClass"); - CreateRequiresInflectionXmlAttribute(doc, derivMsa.ToPartOfSpeechRA, derivMsaNode); - CreateFeatureStructureNodes(doc, derivMsaNode, derivMsa.FromMsFeaturesOA, derivMsa.Hvo, "fromFS"); - CreateFeatureStructureNodes(doc, derivMsaNode, derivMsa.ToMsFeaturesOA, derivMsa.Hvo, "toFS"); - CreateProductivityRestrictionNodes(doc, derivMsaNode, derivMsa.FromProdRestrictRC, "fromProductivityRestriction"); - CreateProductivityRestrictionNodes(doc, derivMsaNode, derivMsa.ToProdRestrictRC, "toProductivityRestriction"); - } - protected void CreateFeatureStructureNodes(XmlDocument doc, XmlNode msaNode, IFsFeatStruc fs, int id) - { - CreateFeatureStructureNodes(doc, msaNode, fs, id, "fs"); - } - protected void CreateFeatureStructureNodes(XmlDocument doc, XmlNode msaNode, IFsFeatStruc fs, int id, string sFSName) - { - if (fs == null) - return; - XmlNode fsNode = CreateXmlElement(doc, sFSName, msaNode); - CreateXmlAttribute(doc, "id", id.ToString(), fsNode); - foreach (IFsFeatureSpecification spec in fs.FeatureSpecsOC) - { - XmlNode feature = CreateXmlElement(doc, "feature", fsNode); - XmlNode name = CreateXmlElement(doc, "name", feature); - name.InnerText = spec.FeatureRA.Abbreviation.BestAnalysisAlternative.Text; - XmlNode fvalue = CreateXmlElement(doc, "value", feature); - IFsClosedValue cv = spec as IFsClosedValue; - if (cv != null) - fvalue.InnerText = cv.ValueRA.Abbreviation.BestAnalysisAlternative.Text; - else - { - IFsComplexValue complex = spec as IFsComplexValue; - if (complex == null) - continue; // skip this one since we're not dealing with it yet - IFsFeatStruc nestedFs = complex.ValueOA as IFsFeatStruc; - if (nestedFs != null) - CreateFeatureStructureNodes(doc, fvalue, nestedFs, 0, "fs"); - } - } - } - protected void CreateFromPOSNodes(XmlDocument doc, XmlNode msaNode, IFdoReferenceCollection fromPOSes, string sElementName) - { - if (fromPOSes == null || fromPOSes.Count < 1) - return; - foreach (IPartOfSpeech pos in fromPOSes) - { - XmlNode posNode = CreateXmlElement(doc, sElementName, msaNode); - CreateXmlAttribute(doc, "fromCat", pos.Hvo.ToString(), posNode); - CreateXmlAttribute(doc, "fromCatAbbr", pos.Abbreviation.BestAnalysisAlternative.Text, posNode); - } - } - protected void CreateInflectionClasses(XmlDocument doc, XmlNode morphNode) - { - string sAlloId = XmlUtils.GetOptionalAttributeValue(morphNode, "alloid"); - if (sAlloId == null) - return; - int hvoAllomorph = Convert.ToInt32(sAlloId); - // use IMoForm instead of IMoAffixForm or IMoAffixAllomorph because it could be an IMoStemAllomorph - IMoForm form = m_cache.ServiceLocator.GetInstance().GetObject(hvoAllomorph); - if (form == null) - return; - if (!(form is IMoAffixForm)) - return; - foreach (IMoInflClass ic in ((IMoAffixForm)form).InflectionClassesRC) - { - XmlNode icNode = CreateXmlElement(doc, "inflectionClass", morphNode); - CreateXmlAttribute(doc, "id", ic.Hvo.ToString(), icNode); - CreateXmlAttribute(doc, "abbr", ic.Abbreviation.BestAnalysisAlternative.Text, icNode); - } - } private void CreateInflectionClassesAndSubclassesXmlElement(XmlDocument doc, - System.Collections.Generic.IEnumerable inflectionClasses, - XmlNode inflClasses) + IEnumerable inflectionClasses, + XmlNode inflClasses) { foreach (IMoInflClass ic in inflectionClasses) { XmlNode inflClass = CreateXmlElement(doc, "inflClass", inflClasses); - CreateXmlAttribute(doc, "hvo", ic.Hvo.ToString(), inflClass); + CreateXmlAttribute(doc, "hvo", ic.Hvo.ToString(CultureInfo.InvariantCulture), inflClass); CreateXmlAttribute(doc, "abbr", ic.Abbreviation.BestAnalysisAlternative.Text, inflClass); CreateInflectionClassesAndSubclassesXmlElement(doc, ic.SubclassesOC, inflClasses); } } - protected void CreateInflectionClassXmlAttribute(XmlDocument doc, XmlNode msaNode, IMoInflClass inflClass, string sInflClass) - { - if (inflClass != null) - { - CreateXmlAttribute(doc, sInflClass, inflClass.Hvo.ToString(), msaNode); - string sInflClassAbbr; - if (inflClass.Hvo > 0) - sInflClassAbbr = inflClass.Abbreviation.BestAnalysisAlternative.Text; - else - sInflClassAbbr = ""; - CreateXmlAttribute(doc, sInflClass + "Abbr", sInflClassAbbr, msaNode); - } - else - CreateXmlAttribute(doc, sInflClass, "0", msaNode); - } - - protected void CreateInflMsaXmlElement(XmlDocument doc, XmlNode morphNode, IMoInflAffMsa inflMsa) - { - XmlNode inflMsaNode = CreateXmlElement(doc, "inflMsa", morphNode); - CreatePOSXmlAttribute(doc, inflMsaNode, inflMsa.PartOfSpeechRA, "cat"); - // handle any slot - HandleSlotInfoForInflectionalMsa(inflMsa, doc, inflMsaNode, morphNode); - CreateFeatureStructureNodes(doc, inflMsaNode, inflMsa.InflFeatsOA, inflMsa.Hvo); - CreateProductivityRestrictionNodes(doc, inflMsaNode, inflMsa.FromProdRestrictRC, "fromProductivityRestriction"); - } protected virtual void CreateMorphAffixAlloFeatsXmlElement(XmlNode node, XmlNode morphNode) { XmlNode affixAlloFeatsNode = node.SelectSingleNode("affixAlloFeats"); @@ -188,14 +92,13 @@ protected void CreateMorphGlossXmlElement(XmlNode node, XmlNode morphNode) } protected void CreateMorphInflectionClassesXmlElement(XmlDocument doc, XmlNode node, XmlNode morphNode) { - XmlNode attr; - attr = node.SelectSingleNode("@alloid"); - if (attr != null) + XmlNode attr = node.SelectSingleNode("@alloid"); + if (attr != null && node.Attributes != null) { XmlNode alloid = node.Attributes.GetNamedItem("alloid"); int hvo = Convert.ToInt32(alloid.InnerText); ICmObject obj = m_cache.ServiceLocator.GetInstance().GetObject(hvo); - IMoAffixForm form = obj as IMoAffixForm; // only for affix forms + var form = obj as IMoAffixForm; // only for affix forms if (form != null) { if (form.InflectionClassesRC.Count > 0) @@ -208,7 +111,6 @@ protected void CreateMorphInflectionClassesXmlElement(XmlDocument doc, XmlNode n } } - protected abstract void CreateMorphNodes(XmlDocument doc, XmlNode seqNode, string sNodeId); protected virtual void CreateMorphShortNameXmlElement(XmlNode node, XmlNode morphNode) @@ -250,154 +152,7 @@ protected void CreateMorphXmlElement(XmlDocument doc, XmlNode seqNode, XmlNode n CreateMorphGlossXmlElement(node, morphNode); CreateMorphCitationFormXmlElement(node, morphNode); CreateMorphInflectionClassesXmlElement(doc, node, morphNode); - CreateMsaXmlElement(node, doc, morphNode, "@morphname"); - } - protected void CreateMsaXmlElement(XmlNode node, XmlDocument doc, XmlNode morphNode, string sHvo) - { - XmlNode attr; - // morphname contains the hvo of the msa - attr = node.SelectSingleNode(sHvo); - if (attr != null) - { - string sObjHvo = attr.Value; - // Irregulary inflected forms can have a combination MSA hvo: the LexEntry hvo, a period, and an index to the LexEntryRef - var indexOfPeriod = IndexOfPeriodInMsaHvo(ref sObjHvo); - ICmObject obj = m_cache.ServiceLocator.GetInstance().GetObject(Convert.ToInt32(sObjHvo)); - switch (obj.GetType().Name) - { - default: - throw new ApplicationException(String.Format("Invalid MSA type: {0}.", obj.GetType().Name)); - case "MoStemMsa": - IMoStemMsa stemMsa = obj as IMoStemMsa; - CreateStemMsaXmlElement(doc, morphNode, stemMsa); - break; - case "MoInflAffMsa": - IMoInflAffMsa inflMsa = obj as IMoInflAffMsa; - CreateInflectionClasses(doc, morphNode); - CreateInflMsaXmlElement(doc, morphNode, inflMsa); - break; - case "MoDerivAffMsa": - IMoDerivAffMsa derivMsa = obj as IMoDerivAffMsa; - CreateDerivMsaXmlElement(doc, morphNode, derivMsa); - break; - case "MoUnclassifiedAffixMsa": - IMoUnclassifiedAffixMsa unclassMsa = obj as IMoUnclassifiedAffixMsa; - CreateUnclassifedMsaXmlElement(doc, morphNode, unclassMsa); - break; - case "LexEntry": - // is an irregularly inflected form - // get the MoStemMsa of its variant - var entry = obj as ILexEntry; - if (entry.EntryRefsOS.Count > 0) - { - var index = IndexOfLexEntryRef(attr.Value, indexOfPeriod); - var lexEntryRef = entry.EntryRefsOS[index]; - var sense = FDO.DomainServices.MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); - stemMsa = sense.MorphoSyntaxAnalysisRA as IMoStemMsa; - CreateStemMsaXmlElement(doc, morphNode, stemMsa); - } - break; - case "LexEntryInflType": - // This is one of the null allomorphs we create when building the - // input for the parser in order to still get the Word Grammar to have something in any - // required slots in affix templates. - CreateInflMsaForLexEntryInflType(doc, morphNode, obj as ILexEntryInflType); - break; - } - } - } - - protected static int IndexOfLexEntryRef(string sHvo, int indexOfPeriod) - { - int index = 0; - if (indexOfPeriod >= 0) - { - string sIndex = sHvo.Substring(indexOfPeriod+1); - index = Convert.ToInt32(sIndex); - } - return index; - } - - protected static int IndexOfPeriodInMsaHvo(ref string sObjHvo) - { - // Irregulary inflected forms can a combination MSA hvo: the LexEntry hvo, a period, and an index to the LexEntryRef - int indexOfPeriod = sObjHvo.IndexOf('.'); - if (indexOfPeriod >= 0) - { - sObjHvo = sObjHvo.Substring(0, indexOfPeriod); - } - return indexOfPeriod; - } - - protected void CreateInflMsaForLexEntryInflType(XmlDocument doc, XmlNode node, ILexEntryInflType lexEntryInflType) - { - /*var slots = lexEntryInflType.SlotsRC; - IMoInflAffixSlot firstSlot = null; - foreach (var slot in slots) - { - if (firstSlot == null) - firstSlot = slot; - }*/ - IMoInflAffixSlot slot; - var slotId = node.SelectSingleNode("MoForm/@wordType"); - if (slotId != null) - slot = m_cache.ServiceLocator.GetInstance().GetObject(Convert.ToInt32(slotId.InnerText)); - else - { - var slots = lexEntryInflType.SlotsRC; - IMoInflAffixSlot firstSlot = null; - foreach (var slot1 in slots) // there's got to be a better way to do this... - { - firstSlot = slot1; - break; - } - slot = firstSlot; - } - XmlNode nullInflMsaNode; - nullInflMsaNode = CreateXmlElement(doc, "inflMsa", node); - CreatePOSXmlAttribute(doc, nullInflMsaNode, slot.Owner as IPartOfSpeech, "cat"); - CreateXmlAttribute(doc, "slot", slot.Hvo.ToString(), nullInflMsaNode); - CreateXmlAttribute(doc, "slotAbbr", slot.Name.BestAnalysisAlternative.Text, nullInflMsaNode); - CreateXmlAttribute(doc, "slotOptional", "false", nullInflMsaNode); - CreateFeatureStructureNodes(doc, nullInflMsaNode, lexEntryInflType.InflFeatsOA, lexEntryInflType.Hvo); - } - - protected void CreatePOSXmlAttribute(XmlDocument doc, XmlNode msaNode, IPartOfSpeech pos, string sCat) - { - if (pos != null) - { - CreateXmlAttribute(doc, sCat, pos.Hvo.ToString(), msaNode); - string sPosAbbr; - if (pos.Hvo > 0) - sPosAbbr = pos.Abbreviation.BestAnalysisAlternative.Text; - else - sPosAbbr = "??"; - CreateXmlAttribute(doc, sCat + "Abbr", sPosAbbr, msaNode); - } - else - CreateXmlAttribute(doc, sCat, "0", msaNode); - } - - protected void CreateProductivityRestrictionNodes(XmlDocument doc, XmlNode msaNode, IFdoReferenceCollection prodRests, string sElementName) - { - if (prodRests == null || prodRests.Count < 1) - return; - foreach (ICmPossibility pr in prodRests) - { - XmlNode prNode = CreateXmlElement(doc, sElementName, msaNode); - CreateXmlAttribute(doc, "id", pr.Hvo.ToString(), prNode); - XmlNode prName = CreateXmlElement(doc, "name", prNode); - prName.InnerText = pr.Name.BestAnalysisAlternative.Text; - } - } - protected void CreateRequiresInflectionXmlAttribute(XmlDocument doc, IPartOfSpeech pos, XmlNode msaNode) - { - string sPlusMinus; - if (RequiresInflection(pos)) - sPlusMinus = "+"; - else - sPlusMinus = "-"; - CreateXmlAttribute(doc, "requiresInfl", sPlusMinus, msaNode); + ParserXMLGenerator.CreateMsaXmlElement(node, doc, morphNode, "@morphname", m_cache); } public string CreateTempFile(string sPrefix, string sExtension) { @@ -406,110 +161,6 @@ public string CreateTempFile(string sPrefix, string sExtension) sw.Close(); return sTempFileName; } - protected static void CreateXmlAttribute(XmlDocument doc, string sAttrName, string sAttrValue, XmlNode elementNode) - { - XmlNode attr = doc.CreateNode(XmlNodeType.Attribute, sAttrName, null); - attr.Value = sAttrValue; - elementNode.Attributes.SetNamedItem(attr); - } - /// - /// Create an xml element and add it to the tree - /// - /// Xml document containing the element - /// name of the element to create - /// owner of the newly created element - /// newly created element node - protected XmlNode CreateXmlElement(XmlDocument doc, string sElementName, XmlNode parentNode) - { - XmlNode node = doc.CreateNode(XmlNodeType.Element, sElementName, null); - parentNode.AppendChild(node); - return node; - } - protected void HandleSlotInfoForInflectionalMsa(IMoInflAffMsa inflMsa, XmlDocument doc, XmlNode inflMsaNode, XmlNode morphNode) - { - int slotHvo = 0; - int iCount = inflMsa.SlotsRC.Count; - if (iCount > 0) - { - if (iCount > 1) - { // have a circumfix; assume only two slots and assume that the first is prefix and second is suffix - // TODO: ideally would figure out if the slots are prefix or suffix slots and then align the - // o and 1 indices to the appropriate slot. Will just do this for now (hab 2005.08.04). - XmlNode attrType = morphNode.SelectSingleNode("@type"); - if (attrType != null && attrType.InnerText != "sfx") - slotHvo = inflMsa.SlotsRC.ToHvoArray()[0]; - else - slotHvo = inflMsa.SlotsRC.ToHvoArray()[1]; - } - else - slotHvo = inflMsa.SlotsRC.ToHvoArray()[0]; - } - CreateXmlAttribute(doc, "slot", slotHvo.ToString(), inflMsaNode); - string sSlotOptional = "false"; - string sSlotAbbr = "??"; - if (slotHvo > 0) - { - var slot = m_cache.ServiceLocator.GetInstance().GetObject(slotHvo); - if (slot != null) - { - sSlotAbbr = slot.Name.BestAnalysisAlternative.Text; - if (slot.Optional) - sSlotOptional = "true"; - } - } - CreateXmlAttribute(doc, "slotAbbr", sSlotAbbr, inflMsaNode); - CreateXmlAttribute(doc, "slotOptional", sSlotOptional, inflMsaNode); - } - protected void CreateStemMsaXmlElement(XmlDocument doc, XmlNode morphNode, IMoStemMsa stemMsa) - { - XmlNode stemMsaNode = CreateXmlElement(doc, "stemMsa", morphNode); - CreatePOSXmlAttribute(doc, stemMsaNode, stemMsa.PartOfSpeechRA, "cat"); - IMoInflClass inflClass = stemMsa.InflectionClassRA; - if (inflClass == null) - { // use default inflection class of the POS or - // the first ancestor POS that has a non-zero default inflection class - int inflClassHvo = 0; - IPartOfSpeech pos = stemMsa.PartOfSpeechRA; - while (pos != null && inflClassHvo == 0) - { - if (pos.DefaultInflectionClassRA != null) - inflClassHvo = pos.DefaultInflectionClassRA.Hvo; - else - { - int clsid = m_cache.ServiceLocator.GetInstance().GetObject(pos.Owner.Hvo).ClassID; - if (clsid == PartOfSpeechTags.kClassId) - pos = m_cache.ServiceLocator.GetInstance().GetObject(pos.Owner.Hvo); - else - pos = null; - } - } - if (inflClassHvo != 0) - inflClass = m_cache.ServiceLocator.GetInstance().GetObject(inflClassHvo); - } - CreateInflectionClassXmlAttribute(doc, stemMsaNode, inflClass, "inflClass"); - CreateRequiresInflectionXmlAttribute(doc, - stemMsa.PartOfSpeechRA, - stemMsaNode); - CreateFeatureStructureNodes(doc, stemMsaNode, stemMsa.MsFeaturesOA, stemMsa.Hvo); - CreateProductivityRestrictionNodes(doc, stemMsaNode, stemMsa.ProdRestrictRC, "productivityRestriction"); - CreateFromPOSNodes(doc, stemMsaNode, stemMsa.FromPartsOfSpeechRC, "fromPartsOfSpeech"); - } - protected void CreateUnclassifedMsaXmlElement(XmlDocument doc, XmlNode morphNode, IMoUnclassifiedAffixMsa unclassMsa) - { - XmlNode unclassMsaNode = CreateXmlElement(doc, "unclassMsa", morphNode); - CreatePOSXmlAttribute(doc, unclassMsaNode, unclassMsa.PartOfSpeechRA, "fromCat"); - } - /// - /// Determine if a PartOfSpeech requires inflection. - /// If it or any of its parent POSes have a template, it requires inflection. - /// If it is null we default to not requiring inflection. - /// - /// the Part of Speech - /// true if it does, false otherwise - protected bool RequiresInflection(IPartOfSpeech pos) - { - return pos != null && pos.RequiresInflection; - } /// /// Path to transforms /// @@ -545,13 +196,23 @@ private void SetWritingSystemBasedArguments(List args) args.Add(new XmlUtils.XSLParameter("prmVernacularFontSize", myFont.Size + "pt")); } - string sRTL = defVernWs.RightToLeftScript ? "Y" : "N"; - args.Add(new XmlUtils.XSLParameter("prmVernacularRTL", sRTL)); + string sRtl = defVernWs.RightToLeftScript ? "Y" : "N"; + args.Add(new XmlUtils.XSLParameter("prmVernacularRTL", sRtl)); } protected virtual void AddParserSpecificArguments(List args) { // default is to do nothing } + + protected static XmlNode CreateXmlElement(XmlDocument doc, string sElementName, XmlNode parentNode) + { + return ParserXMLGenerator.CreateXmlElement(doc, sElementName, parentNode); + } + + protected static void CreateXmlAttribute(XmlDocument doc, string sAttrName, string sAttrValue, XmlNode elementNode) + { + ParserXMLGenerator.CreateXmlAttribute(doc, sAttrName, sAttrValue, elementNode); + } } } diff --git a/Src/LexText/ParserUI/ParserUIStrings.Designer.cs b/Src/LexText/ParserUI/ParserUIStrings.Designer.cs index 0283b72683..6571da794e 100644 --- a/Src/LexText/ParserUI/ParserUIStrings.Designer.cs +++ b/Src/LexText/ParserUI/ParserUIStrings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.18052 +// Runtime Version:4.0.30319.1008 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -159,15 +159,6 @@ internal static string ksImportedFromFileX { } } - /// - /// Looks up a localized string similar to Automatically generated null affix for the {0} irregularly inflected form. - /// - internal static string ksIrregularlyInflectedFormNullAffix { - get { - return ResourceManager.GetString("ksIrregularlyInflectedFormNullAffix", resourceCulture); - } - } - /// /// Looks up a localized string similar to Loading Files for Word Set {0}. /// @@ -384,24 +375,6 @@ internal static string ksUnknownAllomorph { } } - /// - /// Looks up a localized string similar to Unknown CitationForm!. - /// - internal static string ksUnknownCitationForm { - get { - return ResourceManager.GetString("ksUnknownCitationForm", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unknown Gloss!. - /// - internal static string ksUnknownGloss { - get { - return ResourceManager.GetString("ksUnknownGloss", resourceCulture); - } - } - /// /// Looks up a localized string similar to Unknown Morpheme!. /// @@ -429,15 +402,6 @@ internal static string ksUpdate { } } - /// - /// Looks up a localized string similar to {0} ({1}): {2}. - /// - internal static string ksX_Y_Z { - get { - return ResourceManager.GetString("ksX_Y_Z", resourceCulture); - } - } - /// /// Looks up a localized string similar to The XML is not well-formed; you need to correct it and try again.. /// diff --git a/Src/LexText/ParserUI/ParserUIStrings.resx b/Src/LexText/ParserUI/ParserUIStrings.resx index 2b8cedd185..d9e8d24a9b 100644 --- a/Src/LexText/ParserUI/ParserUIStrings.resx +++ b/Src/LexText/ParserUI/ParserUIStrings.resx @@ -197,12 +197,6 @@ Unknown Allomorph! - - Unknown CitationForm! - - - Unknown Gloss! - Unknown Morpheme! @@ -213,10 +207,6 @@ Update related to ParserCoreStrings.ksUpdateX - - {0} ({1}): {2} - {0} is the lexical form, {1} is the gloss, {2} is the citation form - The XML is not well-formed; you need to correct it and try again. @@ -251,10 +241,6 @@ , Separator to use between multiple slot names when an irregularly inflected form variant fills two or more inflectional affix slots - - Automatically generated null affix for the {0} irregularly inflected form - Content used when showing the details of a parse in Try a Word for these inflectional affix slot fillers. {0} is the Name of the irregularly inflected form variant type. - NoDefaultCompounding If true, no default compounding rules will be used. (Do Not Localize) diff --git a/Src/LexText/ParserUI/XAmpleTrace.cs b/Src/LexText/ParserUI/XAmpleTrace.cs index 23662f1ba3..efbc53331a 100644 --- a/Src/LexText/ParserUI/XAmpleTrace.cs +++ b/Src/LexText/ParserUI/XAmpleTrace.cs @@ -19,6 +19,7 @@ using System.Xml; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.FDO; +using SIL.FieldWorks.WordWorks.Parser; using XCore; using System.Xml.XPath; @@ -125,15 +126,15 @@ private string ConvertHvosToStrings(string sAdjusted, bool fIsTrace) // When we switched to VS 2005, the result from XAmple had a final trailing null character. // I'm not sure why (Andy). Remove it. string sNoFinalNull = RemoveAnyFinalNull(sAdjusted); - XmlDocument doc = new XmlDocument(); + var doc = new XmlDocument(); doc.LoadXml(sNoFinalNull); if (fIsTrace) { - ConvertMorphs(doc, "//morph", true); + ParserXMLGenerator.ConvertMorphs(doc, "//morph", true, m_cache); ConvertFailures(doc); } else - ConvertMorphs(doc, "//Morph", false); + ParserXMLGenerator.ConvertMorphs(doc, "//Morph", false, m_cache); return doc.InnerXml; } @@ -204,7 +205,7 @@ private void ConvertEntities(string sTestName, XmlDocument doc) { XmlNode test = node.Attributes.GetNamedItem("test"); string s = test.InnerText; - test.InnerText = CreateEntities(s); + test.InnerText = ParserXMLGenerator.CreateEntities(s); } } } From e5685a62892d0887f4f4aa2128d33fcd4ff0e5d2 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Wed, 12 Feb 2014 10:26:54 +0700 Subject: [PATCH 070/143] moved XML generation code from XAmpleTrace to XAmpleParser Change-Id: Iea6bff8d296ed90d29d28d721379ebb85a745c2f --- .../ParserEngine/ParserCore/ParserCore.csproj | 2 +- .../ParserCore/ParserCoreStrings.Designer.cs | 20 +- .../ParserCore/ParserCoreStrings.resx | 6 + .../ParserCoreTests}/ConvertFailuresTests.cs | 35 +- .../ParserCoreTests/ParserCoreTests.csproj | 1 + ...rXMLGenerator.cs => ParserXmlGenerator.cs} | 2 +- .../ParserEngine/ParserCore/XAmpleParser.cs | 185 +++++++++- Src/LexText/ParserUI/HCTrace.cs | 4 +- Src/LexText/ParserUI/ParserTrace.cs | 2 +- Src/LexText/ParserUI/ParserTraceBase.cs | 6 +- .../ParserUI/ParserUIStrings.Designer.cs | 29 +- Src/LexText/ParserUI/ParserUIStrings.resx | 9 - .../ParserUITests/ParserUITests.csproj | 7 +- Src/LexText/ParserUI/XAmpleTrace.cs | 324 +----------------- 14 files changed, 241 insertions(+), 391 deletions(-) rename Src/LexText/{ParserUI/ParserUITests => ParserEngine/ParserCore/ParserCoreTests}/ConvertFailuresTests.cs (87%) rename Src/LexText/ParserEngine/ParserCore/{ParserXMLGenerator.cs => ParserXmlGenerator.cs} (99%) diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj b/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj index 12cdcb7a28..1b7311c32f 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj +++ b/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj @@ -215,7 +215,7 @@ Code - + Code diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.Designer.cs b/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.Designer.cs index b75c519b4c..e354272279 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.Designer.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.1008 +// Runtime Version:4.0.30319.18408 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -204,6 +204,15 @@ internal static string ksTraceWordformX { } } + /// + /// Looks up a localized string similar to Unknown Allomorph!. + /// + internal static string ksUnknownAllomorph { + get { + return ResourceManager.GetString("ksUnknownAllomorph", resourceCulture); + } + } + /// /// Looks up a localized string similar to Unknown CitationForm!. /// @@ -231,6 +240,15 @@ internal static string ksUnknownMorpheme { } } + /// + /// Looks up a localized string similar to Unknown Natural Class!. + /// + internal static string ksUnknownNaturalClass { + get { + return ResourceManager.GetString("ksUnknownNaturalClass", resourceCulture); + } + } + /// /// Looks up a localized string similar to Updating: {0}. /// diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.resx b/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.resx index 161ba7c27f..72b5acecfd 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.resx +++ b/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.resx @@ -189,4 +189,10 @@ {0} ({1}): {2} {0} is the lexical form, {1} is the gloss, {2} is the citation form + + Unknown Allomorph! + + + Unknown Natural Class! + \ No newline at end of file diff --git a/Src/LexText/ParserUI/ParserUITests/ConvertFailuresTests.cs b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ConvertFailuresTests.cs similarity index 87% rename from Src/LexText/ParserUI/ParserUITests/ConvertFailuresTests.cs rename to Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ConvertFailuresTests.cs index f93916c90c..422fd00679 100644 --- a/Src/LexText/ParserUI/ParserUITests/ConvertFailuresTests.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ConvertFailuresTests.cs @@ -5,29 +5,25 @@ // File: ConvertFailuresTests.cs // Responsibility: -using System; -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Xml; -using System.Xml.Xsl; - -using SIL.FieldWorks.Common.FwUtils; - using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Test.TestUtils; -namespace SIL.FieldWorks.LexText.Controls +namespace SIL.FieldWorks.WordWorks.Parser { /// /// Summary description for ConvertFailuresTests. /// [TestFixture] - public class ConvertFailuresTests: BaseTest + public class ConvertFailuresTests : BaseTest { - private XmlDocument m_doc; + private static readonly string[] SaTesting = { "A", "AB", "ABC", "ABCD", "ABCDE", "ABCDEF" }; - private XAmpleTrace m_xampleTrace = new XAmpleTrace(); + private XmlDocument m_doc; + private int m_testingCount; /// /// Location of simple test FXT files @@ -50,6 +46,13 @@ public void FixtureCleanUp() { } + private string GetRepresentation(int hvo) + { + if (m_testingCount > 5) + m_testingCount = 0; + return SaTesting[m_testingCount++]; + } + [Test] [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] @@ -57,7 +60,8 @@ public void ConvertANCCFailureStrings() { XmlNodeList nl = m_doc.SelectNodes("//failure[contains(@test,'ANCC_FT')]"); Assert.IsTrue(nl.Count == 2, "Two ANCC failures"); - m_xampleTrace.ConvertANCCFailures(m_doc, true); + m_testingCount = 0; + XAmpleParser.ConvertAdHocFailures(m_doc, "ANCC_FT", GetRepresentation); int i = 1; foreach (XmlNode node in nl) { @@ -83,7 +87,8 @@ public void ConvertMCCFailureStrings() { XmlNodeList nl = m_doc.SelectNodes("//failure[contains(@test,'MCC_FT')]"); Assert.IsTrue(nl.Count == 2, "Two MCC failures"); - m_xampleTrace.ConvertMCCFailures(m_doc, true); + m_testingCount = 0; + XAmpleParser.ConvertAdHocFailures(m_doc, "MCC_FT", GetRepresentation); int i = 1; foreach (XmlNode node in nl) { @@ -109,7 +114,8 @@ public void ConvertSECFailureStrings() { XmlNodeList nl = m_doc.SelectNodes("//failure[contains(@test,'SEC_ST') and contains(@test,'[')]"); Assert.IsTrue(nl.Count == 8, "Eight SEC failures with classes"); - m_xampleTrace.ConvertSECFailures(m_doc, true); + m_testingCount = 0; + XAmpleParser.ConvertNaturalClasses(m_doc, "SEC_ST", GetRepresentation); int i = 1; foreach (XmlNode node in nl) { @@ -152,7 +158,8 @@ public void ConvertInfixEnvironmentFailureStrings() { XmlNodeList nl = m_doc.SelectNodes("//failure[contains(@test,'InfixEnvironment') and contains(@test,'[')]"); Assert.IsTrue(nl.Count == 8, "Eight Infix Environment failures with classes"); - m_xampleTrace.ConvertInfixEnvironmentFailures(m_doc, true); + m_testingCount = 0; + XAmpleParser.ConvertNaturalClasses(m_doc, "InfixEnvironment", GetRepresentation); int i = 1; foreach (XmlNode node in nl) { diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParserCoreTests.csproj b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParserCoreTests.csproj index 21c029424d..786b42c57d 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParserCoreTests.csproj +++ b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParserCoreTests.csproj @@ -146,6 +146,7 @@ AssemblyInfoForTests.cs + diff --git a/Src/LexText/ParserEngine/ParserCore/ParserXMLGenerator.cs b/Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs similarity index 99% rename from Src/LexText/ParserEngine/ParserCore/ParserXMLGenerator.cs rename to Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs index 55e7ffc950..a26970268f 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserXMLGenerator.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs @@ -11,7 +11,7 @@ namespace SIL.FieldWorks.WordWorks.Parser { - public class ParserXMLGenerator + public static class ParserXmlGenerator { public static void CreateMsaXmlElement(XmlNode node, XmlDocument doc, XmlNode morphNode, string sHvo, FdoCache fdoCache) { diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs b/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs index 5399d2e851..04f3121701 100644 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs +++ b/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; +using System.Text; using System.Xml; using System.Xml.Linq; using SIL.FieldWorks.FDO; @@ -13,6 +15,8 @@ namespace SIL.FieldWorks.WordWorks.Parser { public class XAmpleParser : FwDisposableBase, IParser { + private static readonly char[] Digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; + private XAmpleWrapper m_xample; private readonly string m_dataDir; private readonly FdoCache m_cache; @@ -75,10 +79,10 @@ public ParseResult ParseWord(string word) { CheckDisposed(); - string results = m_xample.ParseWord(word); + var results = new StringBuilder(m_xample.ParseWord(word)); results = results.Replace("DB_REF_HERE", "'0'"); results = results.Replace("<...>", "[...]"); - var wordformElem = XElement.Parse(results); + var wordformElem = XElement.Parse(results.ToString()); string errorMessage = null; var exceptionElem = wordformElem.Element("Exception"); if (exceptionElem != null) @@ -134,14 +138,187 @@ public string ParseWordXml(string word) { CheckDisposed(); - return m_xample.ParseWord(word); + var sb = new StringBuilder(m_xample.ParseWord(word)); + sb.Replace("<...>", "[...]"); + sb.Replace("DB_REF_HERE", "'0'"); + while (sb[sb.Length - 1] == '\x0') + sb.Remove(sb.Length - 1, 1); + + var doc = new XmlDocument(); + doc.LoadXml(sb.ToString()); + ParserXmlGenerator.ConvertMorphs(doc, "//Morph", false, m_cache); + + XmlNodeList nl = doc.SelectNodes("//Morph/MSI"); + if (nl != null) + { + foreach (XmlNode node in nl) + ParserXmlGenerator.CreateMsaXmlElement(node, doc, node, "@DbRef", m_cache); + } + + return doc.OuterXml; } public string TraceWordXml(string word, string selectTraceMorphs) { CheckDisposed(); - return m_xample.TraceWord(word, selectTraceMorphs); + var sb = new StringBuilder(m_xample.TraceWord(word, selectTraceMorphs)); + sb.Remove(0, 47); + sb.Replace("]", "]"); + while (sb[sb.Length - 1] == '\x0') + sb.Remove(sb.Length - 1, 1); + + var doc = new XmlDocument(); + doc.LoadXml(sb.ToString()); + ParserXmlGenerator.ConvertMorphs(doc, "//morph", true, m_cache); + ConvertFailures(doc); + + XmlNodeList nl = doc.SelectNodes("//morph[@morphname]"); + if (nl != null) + { + foreach (XmlNode node in nl) + ParserXmlGenerator.CreateMsaXmlElement(node, doc, node, "@morphname", m_cache); + } + + return doc.OuterXml; + } + + private void ConvertFailures(XmlDocument doc) + { + ConvertNaturalClasses(doc, "SEC_ST", GetNCRepresentation); + ConvertNaturalClasses(doc, "InfixEnvironment", GetNCRepresentation); + ConvertAdHocFailures(doc, "ANCC_FT", GetFormRepresentation); + ConvertAdHocFailures(doc, "MCC_FT", GetMsaRepresentation); + ConvertWordGrammarFailures(doc); + } + + private string GetFormRepresentation(int hvo) + { + ICmObject obj = m_cache.ServiceLocator.GetInstance().GetObject(hvo); + var form = obj as IMoForm; + if (form != null) + return form.ShortName; + + throw new ApplicationException(ParserCoreStrings.ksUnknownAllomorph); + } + + private string GetMsaRepresentation(int hvo) + { + ICmObject obj = m_cache.ServiceLocator.GetInstance().GetObject(hvo); + var msa = obj as IMoMorphSynAnalysis; + if (msa != null) + return msa.LongName; + + throw new ApplicationException(ParserCoreStrings.ksUnknownMorpheme); + } + + private string GetNCRepresentation(int hvo) + { + ICmObject obj = m_cache.ServiceLocator.GetInstance().GetObject(hvo); + var nc = obj as IPhNCSegments; + if (nc != null) + return nc.Name.BestAnalysisAlternative.Text; + + throw new ApplicationException(ParserCoreStrings.ksUnknownNaturalClass); + } + + [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", + Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] + internal static void ConvertNaturalClasses(XmlDocument doc, string sTestName, Func repSelector) + { + var sbXPath = new StringBuilder(); + sbXPath.Append("//failure[contains(@test,'"); + sbXPath.Append(sTestName); + sbXPath.Append("') and contains(@test,'[')]"); + XmlNodeList nl = doc.SelectNodes(sbXPath.ToString()); + if (nl != null) + { + int testingCount = 0; + + foreach (XmlNode node in nl) + { + XmlNode test = node.Attributes.GetNamedItem("test"); + string s = test.InnerText; + int i = test.InnerText.IndexOf('/'); + string s0 = s.Substring(i); + string[] sa = s0.Split('[', ']'); // split into hunks using brackets + var sb = new StringBuilder(); + foreach (string str in sa) // for each hunk + { + if (str.IndexOfAny(Digits) >= 0) + { + // assume it is an hvo + sb.Append("["); + string sHvo = str; + int hvo = Convert.ToInt32(sHvo); + sb.Append(repSelector(hvo)); + sb.Append("]"); + } + else + { + sb.Append(str); + } + } + test.InnerText = s.Substring(0, i) + sb; + } + } + } + + [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", + Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] + internal static void ConvertAdHocFailures(XmlDocument doc, string testName, Func repSelector) + { + string sXPath = "//failure[contains(@test,'" + testName + + "') and not(contains(@test,'ExcpFeat')) and not(contains(@test,'StemName')) and not(contains(@test,'IrregInflForm'))]"; + XmlNodeList nl = doc.SelectNodes(sXPath); + if (nl != null) + { + int testingCount = 0; + foreach (XmlNode node in nl) + { + XmlNode test = node.Attributes.GetNamedItem("test"); + string s = test.InnerText; + int iStartingPos = s.IndexOf("::", StringComparison.Ordinal) + 2; // skip to the double colon portion + string[] sa = s.Substring(iStartingPos).Split(' '); + + var sb = new StringBuilder(); + sb.Append(testName); + sb.Append(":"); + foreach (string str in sa) + { + sb.Append(" "); + if (str.IndexOfAny(Digits) >= 0) + { + string sHvo = str; + int hvo = Convert.ToInt32(sHvo); + sb.Append(repSelector(hvo)); + } + else + { + sb.Append(str); + } + } + test.InnerText = sb.ToString(); + } + } + } + + + [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", + Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] + private void ConvertWordGrammarFailures(XmlDocument doc) + { + const string sXPath = "//failure[contains(@test,'PC-PATR')]"; + XmlNodeList nl = doc.SelectNodes(sXPath); + if (nl != null) + { + int iCount = 1; + foreach (XmlNode node in nl) + { + ParserXmlGenerator.CreateXmlAttribute(doc, "id", iCount.ToString(CultureInfo.InvariantCulture), node); + iCount++; + } + } } protected override void DisposeManagedResources() diff --git a/Src/LexText/ParserUI/HCTrace.cs b/Src/LexText/ParserUI/HCTrace.cs index 958a839919..99cd08e8ca 100644 --- a/Src/LexText/ParserUI/HCTrace.cs +++ b/Src/LexText/ParserUI/HCTrace.cs @@ -72,11 +72,11 @@ private void ConvertHvosToStrings(bool fIsTrace) { if (fIsTrace) { - ParserXMLGenerator.ConvertMorphs(m_parseResult, "//RuleAllomorph/Morph | //RootAllomorph/Morph | //Morphs/Morph", false, m_cache); + ParserXmlGenerator.ConvertMorphs(m_parseResult, "//RuleAllomorph/Morph | //RootAllomorph/Morph | //Morphs/Morph", false, m_cache); } else { - ParserXMLGenerator.ConvertMorphs(m_parseResult, "//Morphs/Morph", false, m_cache); + ParserXmlGenerator.ConvertMorphs(m_parseResult, "//Morphs/Morph", false, m_cache); } } diff --git a/Src/LexText/ParserUI/ParserTrace.cs b/Src/LexText/ParserUI/ParserTrace.cs index f9ba5cd297..d78002e10f 100644 --- a/Src/LexText/ParserUI/ParserTrace.cs +++ b/Src/LexText/ParserUI/ParserTrace.cs @@ -137,7 +137,7 @@ protected void AddMsaNodes(bool fIsTrace) { foreach (XmlNode node in nl) { - ParserXMLGenerator.CreateMsaXmlElement(node, m_parseResult, node, sAttrXPath, m_cache); + ParserXmlGenerator.CreateMsaXmlElement(node, m_parseResult, node, sAttrXPath, m_cache); } } } diff --git a/Src/LexText/ParserUI/ParserTraceBase.cs b/Src/LexText/ParserUI/ParserTraceBase.cs index 24a45f23c9..7d9f6d1107 100644 --- a/Src/LexText/ParserUI/ParserTraceBase.cs +++ b/Src/LexText/ParserUI/ParserTraceBase.cs @@ -152,7 +152,7 @@ protected void CreateMorphXmlElement(XmlDocument doc, XmlNode seqNode, XmlNode n CreateMorphGlossXmlElement(node, morphNode); CreateMorphCitationFormXmlElement(node, morphNode); CreateMorphInflectionClassesXmlElement(doc, node, morphNode); - ParserXMLGenerator.CreateMsaXmlElement(node, doc, morphNode, "@morphname", m_cache); + ParserXmlGenerator.CreateMsaXmlElement(node, doc, morphNode, "@morphname", m_cache); } public string CreateTempFile(string sPrefix, string sExtension) { @@ -207,12 +207,12 @@ protected virtual void AddParserSpecificArguments(List ar protected static XmlNode CreateXmlElement(XmlDocument doc, string sElementName, XmlNode parentNode) { - return ParserXMLGenerator.CreateXmlElement(doc, sElementName, parentNode); + return ParserXmlGenerator.CreateXmlElement(doc, sElementName, parentNode); } protected static void CreateXmlAttribute(XmlDocument doc, string sAttrName, string sAttrValue, XmlNode elementNode) { - ParserXMLGenerator.CreateXmlAttribute(doc, sAttrName, sAttrValue, elementNode); + ParserXmlGenerator.CreateXmlAttribute(doc, sAttrName, sAttrValue, elementNode); } } } diff --git a/Src/LexText/ParserUI/ParserUIStrings.Designer.cs b/Src/LexText/ParserUI/ParserUIStrings.Designer.cs index 6571da794e..8585847ad3 100644 --- a/Src/LexText/ParserUI/ParserUIStrings.Designer.cs +++ b/Src/LexText/ParserUI/ParserUIStrings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.1008 +// Runtime Version:4.0.30319.18408 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -366,33 +366,6 @@ internal static string ksUnknown { } } - /// - /// Looks up a localized string similar to Unknown Allomorph!. - /// - internal static string ksUnknownAllomorph { - get { - return ResourceManager.GetString("ksUnknownAllomorph", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unknown Morpheme!. - /// - internal static string ksUnknownMorpheme { - get { - return ResourceManager.GetString("ksUnknownMorpheme", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unknown Natural Class!. - /// - internal static string ksUnknownNaturalClass { - get { - return ResourceManager.GetString("ksUnknownNaturalClass", resourceCulture); - } - } - /// /// Looks up a localized string similar to Update. /// diff --git a/Src/LexText/ParserUI/ParserUIStrings.resx b/Src/LexText/ParserUI/ParserUIStrings.resx index d9e8d24a9b..bcdaf47207 100644 --- a/Src/LexText/ParserUI/ParserUIStrings.resx +++ b/Src/LexText/ParserUI/ParserUIStrings.resx @@ -194,15 +194,6 @@ Unknown - - Unknown Allomorph! - - - Unknown Morpheme! - - - Unknown Natural Class! - Update related to ParserCoreStrings.ksUpdateX diff --git a/Src/LexText/ParserUI/ParserUITests/ParserUITests.csproj b/Src/LexText/ParserUI/ParserUITests/ParserUITests.csproj index 0668149a84..56cee34718 100644 --- a/Src/LexText/ParserUI/ParserUITests/ParserUITests.csproj +++ b/Src/LexText/ParserUI/ParserUITests/ParserUITests.csproj @@ -112,7 +112,7 @@ System.XML - + False ..\..\..\..\Output\Debug\TestUtils.dll @@ -126,9 +126,6 @@ AssemblyInfoForTests.cs - - Code - Code @@ -143,4 +140,4 @@ - + \ No newline at end of file diff --git a/Src/LexText/ParserUI/XAmpleTrace.cs b/Src/LexText/ParserUI/XAmpleTrace.cs index efbc53331a..bad8866116 100644 --- a/Src/LexText/ParserUI/XAmpleTrace.cs +++ b/Src/LexText/ParserUI/XAmpleTrace.cs @@ -13,16 +13,8 @@ // XAmpleTrace - Deal with results of an XAmple trace // -using System; -using System.Diagnostics.CodeAnalysis; -using System.Text; using System.Xml; -using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.FDO; -using SIL.FieldWorks.WordWorks.Parser; using XCore; -using System.Xml.XPath; - namespace SIL.FieldWorks.LexText.Controls { @@ -76,18 +68,12 @@ public override string SetUpWordGrammarDebuggerPage(string sNodeId, string sForm /// URL of the resulting HTML page public override string CreateResultPage(string result) { - string sAdjusted; - bool fIsTrace; - AdjustResultContent(result, out sAdjusted, out fIsTrace); - m_parseResult = new XmlDocument(); - m_parseResult.LoadXml(ConvertHvosToStrings(sAdjusted, fIsTrace)); - - AddMsaNodes(fIsTrace); + m_parseResult.LoadXml(result); string sInput = CreateTempFile(m_ksXAmpleTrace, "xml"); m_parseResult.Save(sInput); - TransformKind kind = (fIsTrace ? TransformKind.kcptTrace : TransformKind.kcptParse); + TransformKind kind = (m_parseResult.DocumentElement.Name == "AmpleTrace" ? TransformKind.kcptTrace : TransformKind.kcptParse); string sOutput = TransformToHtml(sInput, kind); return sOutput; } @@ -111,314 +97,8 @@ private void CreateMorphNode(XmlDocument doc, XmlNode seqNode, XmlNode node) } CreateMorphXmlElement(doc, seqNode, node); } - - -#if false // CS 169 - private void CreateMorphGenericXmlElement(XmlNode node, XmlNode morphNode, string sName) - { - XmlNode nameNode = node.SelectSingleNode(sName); - if (nameNode != null) - morphNode.InnerXml = "<" + sName +">" + nameNode.InnerXml + ""; - } -#endif - private string ConvertHvosToStrings(string sAdjusted, bool fIsTrace) - { - // When we switched to VS 2005, the result from XAmple had a final trailing null character. - // I'm not sure why (Andy). Remove it. - string sNoFinalNull = RemoveAnyFinalNull(sAdjusted); - var doc = new XmlDocument(); - doc.LoadXml(sNoFinalNull); - if (fIsTrace) - { - ParserXMLGenerator.ConvertMorphs(doc, "//morph", true, m_cache); - ConvertFailures(doc); - } - else - ParserXMLGenerator.ConvertMorphs(doc, "//Morph", false, m_cache); - return doc.InnerXml; - } - - private void AdjustResultContent(string sXml, out string sAdjusted, out bool fIsTrace) - { - - - if (sXml.Contains("", "[...]"); - sAdjusted = sFullRedup.Replace("DbRef=DB_REF_HERE", "DbRef=\"DB_REF_HERE\""); - fIsTrace = false; - } - } - - private string RemoveAnyFinalNull(string sInput) - { - string sResult; - int i = sInput.LastIndexOf('\x0'); - if (i >= 0) - sResult = sInput.Substring(0, i); - else - sResult = sInput; - return sResult; - } - private string AdjustEntities(string sInput) - { - string sResult = sInput.Replace("]", "]"); // Created by XAmple - return sResult; - } - - - private void ConvertFailures(XmlDocument doc) - { - ConvertSECFailures(doc, false); - ConvertInfixEnvironmentFailures(doc, false); - ConvertANCCFailures(doc, false); - ConvertMCCFailures(doc, false); - ConvertWordGrammarFailures(doc, false); - } - - public void ConvertSECFailures(XmlDocument doc, bool fTesting) - { - const string ksSEC_ST = "SEC_ST"; - ConvertNaturalClasses(ksSEC_ST, doc, fTesting); - ConvertEntities(ksSEC_ST, doc); - } - - [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", - Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] - private void ConvertEntities(string sTestName, XmlDocument doc) - { - StringBuilder sb = new StringBuilder(); - sb.Append("//failure[contains(@test,'"); - sb.Append(sTestName); - sb.Append("') and contains(@test,'&')]"); - XmlNodeList nl = doc.SelectNodes(sb.ToString()); - if (nl != null) - { - foreach (XmlNode node in nl) - { - XmlNode test = node.Attributes.GetNamedItem("test"); - string s = test.InnerText; - test.InnerText = ParserXMLGenerator.CreateEntities(s); - } - } - } - - [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", - Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] - private void ConvertNaturalClasses(string sTestName, XmlDocument doc, bool fTesting) - { - StringBuilder sbXPath = new StringBuilder(); - sbXPath.Append("//failure[contains(@test,'"); - sbXPath.Append(sTestName); - sbXPath.Append("') and contains(@test,'[')]"); - XmlNodeList nl = doc.SelectNodes(sbXPath.ToString()); - if (nl != null) - { - m_iTestingCount = 0; - - foreach (XmlNode node in nl) - { - XmlNode test = node.Attributes.GetNamedItem("test"); - string s = test.InnerText; - int i = test.InnerText.IndexOf('/'); - string s0 = s.Substring(i); - char[] brackets = {'[', ']'}; - string[] sa = s0.Split(brackets); // split into hunks using brackets - StringBuilder sb = new StringBuilder(); - foreach (string str in sa) // for each hunk - { - if (str.IndexOfAny(m_digits) >= 0) - { // assume it is an hvo - sb.Append("["); - if (fTesting) - { - if (m_iTestingCount > 5) - m_iTestingCount = 0; - sb.Append(m_saTesting[m_iTestingCount++]); - } - else - { - string sHvo = str; - int hvo = Convert.ToInt32(sHvo); - ICmObject obj = m_cache.ServiceLocator.GetInstance().GetObject(hvo); - IPhNCSegments nc = obj as IPhNCSegments; - string sName; - if (nc != null) - sName = nc.Name.BestAnalysisAlternative.Text; - else - { - sName = ParserUIStrings.ksUnknownNaturalClass; // in case the user continues... - throw new ApplicationException(sName); - } - sb.Append(sName); - } - sb.Append("]"); - } - else - sb.Append(str); - } - test.InnerText = s.Substring(0,i) + sb.ToString(); - } - } - } - public void ConvertInfixEnvironmentFailures(XmlDocument doc, bool fTesting) - { - const string ksInfixEnvironment = "InfixEnvironment"; - ConvertNaturalClasses(ksInfixEnvironment, doc, fTesting); - ConvertEntities(ksInfixEnvironment, doc); - } - - public void ConvertMCCFailures(XmlDocument doc, bool fTesting) - { - MCCTraceTest mcc = new MCCTraceTest(); - ConvertAdHocFailures(doc, fTesting, mcc); - } - - public void ConvertANCCFailures(XmlDocument doc, bool fTesting) - { - ANCCTraceTest ancc = new ANCCTraceTest(); - ConvertAdHocFailures(doc, fTesting, ancc); - } - - [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", - Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] - private void ConvertAdHocFailures(XmlDocument doc, bool fTesting, AdhocTraceTest tt) - { - string sXPath = "//failure[contains(@test,'" + tt.Name + - "') and not(contains(@test,'ExcpFeat')) and not(contains(@test,'StemName')) and not(contains(@test,'IrregInflForm'))]"; - XmlNodeList nl = doc.SelectNodes(sXPath); - if (nl != null) - { - m_iTestingCount = 0; - foreach (XmlNode node in nl) - { - XmlNode test = node.Attributes.GetNamedItem("test"); - string s = test.InnerText; - int iStartingPos = s.IndexOf("::") + 2; // skip to the double colon portion - string[] sa = s.Substring(iStartingPos).Split(m_space); - - StringBuilder sb = new StringBuilder(); - sb.Append(tt.Name); - sb.Append(":"); - foreach (string str in sa) - { - sb.Append(" "); - if (str.IndexOfAny(m_digits) >= 0) - { - if (fTesting) - { - if (m_iTestingCount > 5) - m_iTestingCount = 0; - sb.Append(m_saTesting[m_iTestingCount++]); - } - else - { - string sHvo = str; - int hvo = Convert.ToInt32(sHvo); - sb.Append(tt.GetHvoRepresentation(m_cache, hvo)); - // get msa PhNCSegments nc = m_cache.ServiceLocator.GetInstance().GetObject(hvo); - // string name = nc.Name.BestAnalysisAlternative.Text; - } - } - else - sb.Append(str); - } - test.InnerText = sb.ToString(); - } - } - } - - [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", - Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] - private void ConvertWordGrammarFailures(XmlDocument doc, bool fTesting) - { - string sXPath = "//failure[contains(@test,'PC-PATR')]"; - XmlNodeList nl = doc.SelectNodes(sXPath); - if (nl != null) - { - int iCount = 1; - foreach (XmlNode node in nl) - { - CreateXmlAttribute(doc, "id", iCount.ToString(), node); - iCount++; - } - } - } - - - } - public abstract class AdhocTraceTest - { - protected string m_Name; - - public AdhocTraceTest() - { - } - - public virtual string GetHvoRepresentation(FdoCache cache, int hvo) - { - return ""; - } - - public string Name - { - get - { - return m_Name; - } - } - } - public class ANCCTraceTest : AdhocTraceTest - { - public ANCCTraceTest() - { - m_Name = "ANCC_FT"; - } - - public override string GetHvoRepresentation(FdoCache cache, int hvo) - { - ICmObject obj = cache.ServiceLocator.GetInstance().GetObject(hvo); - IMoForm form = obj as IMoForm; - string sResult; - if (form != null) - sResult = form.ShortName; - else - { - sResult = ParserUIStrings.ksUnknownAllomorph; // in case the user continues... - throw new ApplicationException(sResult); - } - return sResult; - } } - public class MCCTraceTest : AdhocTraceTest - { - public MCCTraceTest() - { - m_Name = "MCC_FT"; - } - public override string GetHvoRepresentation(FdoCache cache, int hvo) - { - var obj = cache.ServiceLocator.GetInstance().GetObject(hvo); - IMoMorphSynAnalysis msa = obj as IMoMorphSynAnalysis; - string sResult; - if (msa != null) - sResult = msa.LongName; - else - { - sResult = ParserUIStrings.ksUnknownMorpheme; // in case the user continues... - throw new ApplicationException(sResult); - } - return sResult; - } - } public class WordGrammarStepPair { protected string m_sXmlFile; From 3e0bb413a47320ce9f2a91df48d6bdbbbc35aed6 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Wed, 12 Feb 2014 11:06:37 +0700 Subject: [PATCH 071/143] Create writer methods as duplicates in ParserXMLGenerator One more step in the refactor process. Change-Id: I0e32abd472eb3667471e8b3d37d27a03e1cc57fa --- .../ParserCore/ParserXmlGenerator.cs | 364 ++++++++++++++++++ Src/LexText/ParserUI/HCTrace.cs | 22 +- Src/LexText/ParserUI/ParserTrace.cs | 2 +- Src/LexText/ParserUI/XAmpleTrace.cs | 4 +- 4 files changed, 376 insertions(+), 16 deletions(-) diff --git a/Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs b/Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs index a26970268f..ab00cd436c 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs @@ -67,6 +67,54 @@ public static void CreateMsaXmlElement(XmlNode node, XmlDocument doc, XmlNode mo } } } + public static void CreateMsaXmlElement(XmlWriter writer, string sObjHvo, string sAlloId, string slotHvo, FdoCache fdoCache) + { + // Irregulary inflected forms can have a combination MSA hvo: the LexEntry hvo, a period, and an index to the LexEntryRef + var indexOfPeriod = IndexOfPeriodInMsaHvo(ref sObjHvo); + ICmObject obj = fdoCache.ServiceLocator.GetInstance().GetObject(Convert.ToInt32(sObjHvo)); + switch (obj.GetType().Name) + { + default: + throw new ApplicationException(String.Format("Invalid MSA type: {0}.", obj.GetType().Name)); + case "MoStemMsa": + var stemMsa = obj as IMoStemMsa; + CreateStemMsaXmlElement(writer, stemMsa, fdoCache); + break; + case "MoInflAffMsa": + var inflMsa = obj as IMoInflAffMsa; + CreateInflectionClasses(writer, sAlloId, fdoCache); + CreateInflMsaXmlElement(writer, inflMsa, slotHvo, fdoCache); + break; + case "MoDerivAffMsa": + var derivMsa = obj as IMoDerivAffMsa; + CreateDerivMsaXmlElement(writer, derivMsa); + break; + case "MoUnclassifiedAffixMsa": + var unclassMsa = obj as IMoUnclassifiedAffixMsa; + CreateUnclassifedMsaXmlElement(writer, unclassMsa); + break; + case "LexEntry": + // is an irregularly inflected form + // get the MoStemMsa of its variant + var entry = obj as ILexEntry; + Debug.Assert(entry != null); + if (entry.EntryRefsOS.Count > 0) + { + var index = IndexOfLexEntryRef(sObjHvo, indexOfPeriod); + var lexEntryRef = entry.EntryRefsOS[index]; + var sense = FDO.DomainServices.MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); + stemMsa = sense.MorphoSyntaxAnalysisRA as IMoStemMsa; + CreateStemMsaXmlElement(writer, stemMsa, fdoCache); + } + break; + case "LexEntryInflType": + // This is one of the null allomorphs we create when building the + // input for the parser in order to still get the Word Grammar to have something in any + // required slots in affix templates. + CreateInflMsaForLexEntryInflType(writer, slotHvo, obj as ILexEntryInflType, fdoCache); + break; + } + } private static int IndexOfLexEntryRef(string sHvo, int indexOfPeriod) { @@ -134,6 +182,37 @@ private static void CreateStemMsaXmlElement(XmlDocument doc, XmlNode morphNode, CreateFromPOSNodes(doc, stemMsaNode, stemMsa.FromPartsOfSpeechRC, "fromPartsOfSpeech"); } + private static void CreateStemMsaXmlElement(XmlWriter writer, IMoStemMsa stemMsa, FdoCache fdoCache) + { + writer.WriteStartElement("stemMsa"); + CreatePOSXmlAttribute(writer, stemMsa.PartOfSpeechRA, "cat"); + IMoInflClass inflClass = stemMsa.InflectionClassRA; + if (inflClass == null) + { // use default inflection class of the POS or + // the first ancestor POS that has a non-zero default inflection class + int inflClassHvo = 0; + IPartOfSpeech pos = stemMsa.PartOfSpeechRA; + while (pos != null && inflClassHvo == 0) + { + if (pos.DefaultInflectionClassRA != null) + inflClassHvo = pos.DefaultInflectionClassRA.Hvo; + else + { + int clsid = fdoCache.ServiceLocator.GetInstance().GetObject(pos.Owner.Hvo).ClassID; + pos = clsid == PartOfSpeechTags.kClassId ? fdoCache.ServiceLocator.GetInstance().GetObject(pos.Owner.Hvo) : null; + } + } + if (inflClassHvo != 0) + inflClass = fdoCache.ServiceLocator.GetInstance().GetObject(inflClassHvo); + } + CreateInflectionClassXmlAttribute(writer, inflClass, "inflClass"); + CreateRequiresInflectionXmlAttribute(writer, stemMsa.PartOfSpeechRA); + CreateFeatureStructureNodes(writer, stemMsa.MsFeaturesOA, stemMsa.Hvo); + CreateProductivityRestrictionNodes(writer, stemMsa.ProdRestrictRC, "productivityRestriction"); + CreateFromPOSNodes(writer, stemMsa.FromPartsOfSpeechRC, "fromPartsOfSpeech"); + writer.WriteEndElement(); //stemMsa + } + private static void CreateInflectionClasses(XmlDocument doc, XmlNode morphNode, FdoCache fdoCache) { string sAlloId = XmlUtils.GetOptionalAttributeValue(morphNode, "alloid"); @@ -154,6 +233,26 @@ private static void CreateInflectionClasses(XmlDocument doc, XmlNode morphNode, } } + private static void CreateInflectionClasses(XmlWriter writer, string sAlloId, FdoCache fdoCache) + { + if (sAlloId == null) + return; + int hvoAllomorph = Convert.ToInt32(sAlloId); + // use IMoForm instead of IMoAffixForm or IMoAffixAllomorph because it could be an IMoStemAllomorph + IMoForm form = fdoCache.ServiceLocator.GetInstance().GetObject(hvoAllomorph); + if (form == null) + return; + if (!(form is IMoAffixForm)) + return; + foreach (IMoInflClass ic in ((IMoAffixForm)form).InflectionClassesRC) + { + writer.WriteStartElement("inflectionClass"); + writer.WriteAttributeString("id", ic.Hvo.ToString(CultureInfo.InvariantCulture)); + writer.WriteAttributeString("abbr", ic.Abbreviation.BestAnalysisAlternative.Text); + writer.WriteEndElement(); //inflectionClass + } + } + private static void CreateInflMsaXmlElement(XmlDocument doc, XmlNode morphNode, IMoInflAffMsa inflMsa, FdoCache fdoCache) { XmlNode inflMsaNode = CreateXmlElement(doc, "inflMsa", morphNode); @@ -164,6 +263,17 @@ private static void CreateInflMsaXmlElement(XmlDocument doc, XmlNode morphNode, CreateProductivityRestrictionNodes(doc, inflMsaNode, inflMsa.FromProdRestrictRC, "fromProductivityRestriction"); } + private static void CreateInflMsaXmlElement(XmlWriter writer, IMoInflAffMsa inflMsa, string slotHvo, FdoCache fdoCache) + { + writer.WriteStartElement("inflMsa"); + CreatePOSXmlAttribute(writer, inflMsa.PartOfSpeechRA, "cat"); + // handle any slot + HandleSlotInfoForInflectionalMsa(writer, slotHvo, fdoCache); + CreateFeatureStructureNodes(writer, inflMsa.InflFeatsOA, inflMsa.Hvo); + CreateProductivityRestrictionNodes(writer, inflMsa.FromProdRestrictRC, "fromProductivityRestriction"); + writer.WriteEndElement(); //inflMsa + } + private static void CreateDerivMsaXmlElement(XmlDocument doc, XmlNode morphNode, IMoDerivAffMsa derivMsa) { XmlNode derivMsaNode = CreateXmlElement(doc, "derivMsa", morphNode); @@ -178,12 +288,34 @@ private static void CreateDerivMsaXmlElement(XmlDocument doc, XmlNode morphNode, CreateProductivityRestrictionNodes(doc, derivMsaNode, derivMsa.ToProdRestrictRC, "toProductivityRestriction"); } + private static void CreateDerivMsaXmlElement(XmlWriter writer, IMoDerivAffMsa derivMsa) + { + writer.WriteStartElement("derivMsa"); + CreatePOSXmlAttribute(writer, derivMsa.FromPartOfSpeechRA, "fromCat"); + CreatePOSXmlAttribute(writer, derivMsa.ToPartOfSpeechRA, "toCat"); + CreateInflectionClassXmlAttribute(writer, derivMsa.FromInflectionClassRA, "fromInflClass"); + CreateInflectionClassXmlAttribute(writer, derivMsa.ToInflectionClassRA, "toInflClass"); + CreateRequiresInflectionXmlAttribute(writer, derivMsa.ToPartOfSpeechRA); + CreateFeatureStructureNodes(writer, derivMsa.FromMsFeaturesOA, derivMsa.Hvo, "fromFS"); + CreateFeatureStructureNodes(writer, derivMsa.ToMsFeaturesOA, derivMsa.Hvo, "toFS"); + CreateProductivityRestrictionNodes(writer, derivMsa.FromProdRestrictRC, "fromProductivityRestriction"); + CreateProductivityRestrictionNodes(writer, derivMsa.ToProdRestrictRC, "toProductivityRestriction"); + writer.WriteEndElement(); //derivMsa + } + private static void CreateUnclassifedMsaXmlElement(XmlDocument doc, XmlNode morphNode, IMoUnclassifiedAffixMsa unclassMsa) { XmlNode unclassMsaNode = CreateXmlElement(doc, "unclassMsa", morphNode); CreatePOSXmlAttribute(doc, unclassMsaNode, unclassMsa.PartOfSpeechRA, "fromCat"); } + private static void CreateUnclassifedMsaXmlElement(XmlWriter writer, IMoUnclassifiedAffixMsa unclassMsa) + { + writer.WriteStartElement("unclassMsa"); + CreatePOSXmlAttribute(writer, unclassMsa.PartOfSpeechRA, "fromCat"); + writer.WriteEndElement(); //unclassMsa + } + private static void CreateInflMsaForLexEntryInflType(XmlDocument doc, XmlNode node, ILexEntryInflType lexEntryInflType, FdoCache fdoCache) { /*var slots = lexEntryInflType.SlotsRC; @@ -214,6 +346,30 @@ private static void CreateInflMsaForLexEntryInflType(XmlDocument doc, XmlNode no } } + private static void CreateInflMsaForLexEntryInflType(XmlWriter writer, string slotHvo, ILexEntryInflType lexEntryInflType, FdoCache fdoCache) + { + IMoInflAffixSlot slot; + //var slotId = node.SelectSingleNode("MoForm/@wordType"); + if (slotHvo != null) + slot = fdoCache.ServiceLocator.GetInstance().GetObject(Convert.ToInt32(slotHvo)); + else + { + var slots = lexEntryInflType.SlotsRC; + IMoInflAffixSlot firstSlot = slots.FirstOrDefault(); + slot = firstSlot; + } + if (slot != null) + { + writer.WriteStartElement("inflMsa"); + CreatePOSXmlAttribute(writer, slot.Owner as IPartOfSpeech, "cat"); + writer.WriteAttributeString("slot", slot.Hvo.ToString(CultureInfo.InvariantCulture)); + writer.WriteAttributeString("slotAbbr", slot.Name.BestAnalysisAlternative.Text); + writer.WriteAttributeString("slotOptional", "false"); + CreateFeatureStructureNodes(writer, lexEntryInflType.InflFeatsOA, lexEntryInflType.Hvo); + writer.WriteEndElement(); //inflMsa + } + } + private static void CreateInflectionClassXmlAttribute(XmlDocument doc, XmlNode msaNode, IMoInflClass inflClass, string sInflClass) { if (inflClass != null) @@ -226,12 +382,28 @@ private static void CreateInflectionClassXmlAttribute(XmlDocument doc, XmlNode m CreateXmlAttribute(doc, sInflClass, "0", msaNode); } + private static void CreateInflectionClassXmlAttribute(XmlWriter writer, IMoInflClass inflClass, string sInflClass) + { + if (inflClass != null) + { + writer.WriteAttributeString(sInflClass, inflClass.Hvo.ToString(CultureInfo.InvariantCulture)); + writer.WriteAttributeString(sInflClass + "Abbr", inflClass.Hvo > 0 ? inflClass.Abbreviation.BestAnalysisAlternative.Text : ""); + } + else + writer.WriteAttributeString(sInflClass, "0"); + } + private static void CreateRequiresInflectionXmlAttribute(XmlDocument doc, IPartOfSpeech pos, XmlNode msaNode) { string sPlusMinus = RequiresInflection(pos) ? "+" : "-"; CreateXmlAttribute(doc, "requiresInfl", sPlusMinus, msaNode); } + private static void CreateRequiresInflectionXmlAttribute(XmlWriter writer, IPartOfSpeech pos) + { + writer.WriteAttributeString("requiresInfl", RequiresInflection(pos) ? "+" : "-"); + } + private static void CreateFeatureStructureNodes(XmlDocument doc, XmlNode msaNode, IFsFeatStruc fs, int id, string sFsName = "fs") { if (fs == null) @@ -259,6 +431,35 @@ private static void CreateFeatureStructureNodes(XmlDocument doc, XmlNode msaNode } } + private static void CreateFeatureStructureNodes(XmlWriter writer, IFsFeatStruc fs, int id, string sFsName = "fs") + { + if (fs == null) + return; + writer.WriteStartElement(sFsName); + writer.WriteAttributeString("id", id.ToString(CultureInfo.InvariantCulture)); + foreach (IFsFeatureSpecification spec in fs.FeatureSpecsOC) + { + writer.WriteStartElement("feature"); + writer.WriteElementString("name", spec.FeatureRA.Abbreviation.BestAnalysisAlternative.Text); + writer.WriteStartElement("value"); + var cv = spec as IFsClosedValue; + if (cv != null) + writer.WriteString(cv.ValueRA.Abbreviation.BestAnalysisAlternative.Text); + else + { + var complex = spec as IFsComplexValue; + if (complex == null) + continue; // skip this one since we're not dealing with it yet + var nestedFs = complex.ValueOA as IFsFeatStruc; + if (nestedFs != null) + CreateFeatureStructureNodes(writer, nestedFs, 0); + } + writer.WriteEndElement(); //value + writer.WriteEndElement(); //feature + } + writer.WriteEndElement(); //sFsName + } + private static void CreateProductivityRestrictionNodes(XmlDocument doc, XmlNode msaNode, IFdoReferenceCollection prodRests, string sElementName) { if (prodRests == null || prodRests.Count < 1) @@ -272,6 +473,19 @@ private static void CreateProductivityRestrictionNodes(XmlDocument doc, XmlNode } } + private static void CreateProductivityRestrictionNodes(XmlWriter writer, IFdoReferenceCollection prodRests, string sElementName) + { + if (prodRests == null || prodRests.Count < 1) + return; + foreach (ICmPossibility pr in prodRests) + { + writer.WriteStartElement(sElementName); + writer.WriteAttributeString("id", pr.Hvo.ToString(CultureInfo.InvariantCulture)); + writer.WriteElementString("name", pr.Name.BestAnalysisAlternative.Text); + writer.WriteEndElement(); //sElementName + } + } + private static void CreateFromPOSNodes(XmlDocument doc, XmlNode msaNode, IFdoReferenceCollection fromPoSes, string sElementName) { if (fromPoSes == null || fromPoSes.Count < 1) @@ -284,6 +498,19 @@ private static void CreateFromPOSNodes(XmlDocument doc, XmlNode msaNode, IFdoRef } } + private static void CreateFromPOSNodes(XmlWriter writer, IFdoReferenceCollection fromPoSes, string sElementName) + { + if (fromPoSes == null || fromPoSes.Count < 1) + return; + foreach (IPartOfSpeech pos in fromPoSes) + { + writer.WriteStartElement(sElementName); + writer.WriteAttributeString("fromCat", pos.Hvo.ToString(CultureInfo.InvariantCulture)); + writer.WriteAttributeString("fromCatAbbr", pos.Abbreviation.BestAnalysisAlternative.Text); + writer.WriteEndElement(); //sElementName + } + } + private static void HandleSlotInfoForInflectionalMsa(IMoInflAffMsa inflMsa, XmlDocument doc, XmlNode inflMsaNode, XmlNode morphNode, FdoCache fdoCache) { int slotHvo = 0; @@ -320,6 +547,25 @@ private static void HandleSlotInfoForInflectionalMsa(IMoInflAffMsa inflMsa, XmlD CreateXmlAttribute(doc, "slotOptional", sSlotOptional, inflMsaNode); } + private static void HandleSlotInfoForInflectionalMsa(XmlWriter writer, string slotHvo, FdoCache fdoCache) + { + writer.WriteAttributeString("slot", slotHvo.ToString(CultureInfo.InvariantCulture)); + string sSlotOptional = "false"; + string sSlotAbbr = "??"; + if (Convert.ToInt32(slotHvo) > 0) + { + var slot = fdoCache.ServiceLocator.GetInstance().GetObject(Convert.ToInt32(slotHvo)); + if (slot != null) + { + sSlotAbbr = slot.Name.BestAnalysisAlternative.Text; + if (slot.Optional) + sSlotOptional = "true"; + } + } + writer.WriteAttributeString("slotAbbr", sSlotAbbr); + writer.WriteAttributeString("slotOptional", sSlotOptional); + } + [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] public static void ConvertMorphs(XmlDocument doc, string sNodeListToFind, bool fIdsInAttribute, FdoCache fdoCache) @@ -469,6 +715,27 @@ private static void ConvertStemName(XmlDocument doc, XmlNode node, IMoForm form) } } +// private static void ConvertStemName(XmlWriter writer, IMoForm form) +// { +// var sallo = form as IMoStemAllomorph; +// Debug.Assert(sallo != null); +// IMoStemName sn = sallo.StemNameRA; +// if (sn != null) +// { +// writer.WriteStartElement("stemName"); +// writer.WriteAttributeString("id", sn.Hvo.ToString(CultureInfo.InvariantCulture)); +// writer.WriteString(sn.Name.BestAnalysisAlternative.Text); +// writer.WriteEndElement(); //stemName +// } +// else +// { // There's no overt stem name on this allomorph, but there might be overt stem names +// // on other allomorphs in this lexical entry. This allomorph, then, cannot bear any +// // of the features of these other stem names. If so, there will be a property named +// // NotStemNameddd or NotStemNamedddNotStemNamedddd, etc. +// CreateNotStemNameElement(writer); +// } +// } + private static void ConvertStemNameAffix(XmlDocument doc, XmlNode node, FdoCache fdoCache) { XmlNode props = node.SelectSingleNode("props"); @@ -511,6 +778,23 @@ private static void CreateNotStemNameElement(XmlDocument doc, XmlNode node) } } + private static void CreateNotStemNameElement(XmlWriter writer, string propsText) + { + if (propsText != null) + { + int i = propsText.IndexOf("NotStemName", StringComparison.Ordinal); + if (i > -1) + { + string s = propsText.Substring(i); + int iSpace = s.IndexOf(" ", StringComparison.Ordinal); + string sNotStemName = iSpace > -1 ? s.Substring(0, iSpace - 1) : s; + writer.WriteStartElement("stemName"); + writer.WriteAttributeString("id", sNotStemName); + writer.WriteEndElement(); //stemName + } + } + } + private static void ConvertAffixAlloFeats(XmlDocument doc, XmlNode node, IMoForm form, FdoCache fdoCache) { var sallo = form as IMoAffixAllomorph; @@ -531,6 +815,27 @@ private static void ConvertAffixAlloFeats(XmlDocument doc, XmlNode node, IMoForm } } + private static void ConvertAffixAlloFeats(XmlWriter writer, IMoForm form, string propsText, FdoCache fdoCache) + { + var sallo = form as IMoAffixAllomorph; + if (sallo == null) + return; // the form could be an IMoAffixProcess in which case there are no MsEnvFeatures. + IFsFeatStruc fsFeatStruc = sallo.MsEnvFeaturesOA; + if (fsFeatStruc != null && !fsFeatStruc.IsEmpty) + { + writer.WriteStartElement("affixAlloFeats"); + CreateFeatureStructureNodes(writer, fsFeatStruc, fsFeatStruc.Hvo); + writer.WriteEndElement(); //affixAlloFeats + } + else + { // There's no overt stem name on this allomorph, but there might be overt stem names + // on other allomorphs in this lexical entry. This allomorph, then, cannot bear any + // of the features of these other stem names. If so, there will be a property named + // NotStemNameddd or NotStemNamedddNotStemNamedddd, etc. + CreateNotAffixAlloFeatsElement(writer, propsText, fdoCache); + } + } + private static void CreateNotAffixAlloFeatsElement(XmlDocument doc, XmlNode node, FdoCache fdoCache) { XmlNode props = node.SelectSingleNode("props"); @@ -569,6 +874,45 @@ private static void CreateNotAffixAlloFeatsElement(XmlDocument doc, XmlNode node } } + private static void CreateNotAffixAlloFeatsElement(XmlWriter writer, string propsText, FdoCache fdoCache) + { + if (propsText != null) + { + int i = propsText.IndexOf("MSEnvFSNot", StringComparison.Ordinal); + if (i > -1) + { + writer.WriteStartElement("affixAlloFeats"); + writer.WriteStartElement("not"); + string s = propsText.Substring(i); + int j = s.IndexOf(' '); + if (j > 0) + s = propsText.Substring(i, j + 1); + int iNot = s.IndexOf("Not", StringComparison.Ordinal) + 3; + while (iNot > 3) + { + int iNextNot = s.IndexOf("Not", iNot, StringComparison.Ordinal); + string sFsHvo; + if (iNextNot > -1) + { + // there are more + sFsHvo = s.Substring(iNot, iNextNot - iNot); + CreateFeatureStructureFromHvoString(writer, sFsHvo, fdoCache); + iNot = iNextNot + 3; + } + else + { + // is the last one + sFsHvo = s.Substring(iNot); + CreateFeatureStructureFromHvoString(writer, sFsHvo, fdoCache); + iNot = 0; + } + } + writer.WriteEndElement(); //not + writer.WriteEndElement(); //affixAlloFeats + } + } + } + private static void CreateFeatureStructureFromHvoString(XmlDocument doc, string sFsHvo, XmlNode parentNode, FdoCache fdoCache) { int fsHvo = Convert.ToInt32(sFsHvo); @@ -579,6 +923,14 @@ private static void CreateFeatureStructureFromHvoString(XmlDocument doc, string } } + private static void CreateFeatureStructureFromHvoString(XmlWriter writer, string sFsHvo, FdoCache fdoCache) + { + int fsHvo = Convert.ToInt32(sFsHvo); + var fsFeatStruc = (IFsFeatStruc)fdoCache.ServiceLocator.GetInstance().GetObject(fsHvo); + if (fsFeatStruc != null) + CreateFeatureStructureNodes(writer, fsFeatStruc, fsHvo); + } + public static string CreateEntities(string sInput) { if (sInput == null) @@ -600,6 +952,18 @@ private static void CreatePOSXmlAttribute(XmlDocument doc, XmlNode msaNode, IPar CreateXmlAttribute(doc, sCat, "0", msaNode); } + private static void CreatePOSXmlAttribute(XmlWriter writer, IPartOfSpeech pos, string sCat) + { + if (pos != null) + { + writer.WriteAttributeString(sCat, pos.Hvo.ToString(CultureInfo.InvariantCulture)); + string sPosAbbr = pos.Hvo > 0 ? pos.Abbreviation.BestAnalysisAlternative.Text : "??"; + writer.WriteAttributeString(sCat + "Abbr", sPosAbbr); + } + else + writer.WriteAttributeString(sCat, "0"); + } + /// /// Create an xml element and add it to the tree /// diff --git a/Src/LexText/ParserUI/HCTrace.cs b/Src/LexText/ParserUI/HCTrace.cs index 99cd08e8ca..0afd27a3f7 100644 --- a/Src/LexText/ParserUI/HCTrace.cs +++ b/Src/LexText/ParserUI/HCTrace.cs @@ -42,12 +42,12 @@ public HCTrace(Mediator mediator) /// /// Id of the node to use /// the wordform being tried - /// + /// /// temporary html file showing the results of the first step - public override string SetUpWordGrammarDebuggerPage(string sNodeId, string sForm, string sLastURL) + public override string SetUpWordGrammarDebuggerPage(string sNodeId, string sForm, string sLastUrl) { m_wordGrammarDebugger = new HCWordGrammarDebugger(m_mediator, m_parseResult); - return m_wordGrammarDebugger.SetUpWordGrammarDebuggerPage(sNodeId, sForm, sLastURL); + return m_wordGrammarDebugger.SetUpWordGrammarDebuggerPage(sNodeId, sForm, sLastUrl); } public override string CreateResultPage(string result) @@ -70,14 +70,7 @@ public override string CreateResultPage(string result) private void ConvertHvosToStrings(bool fIsTrace) { - if (fIsTrace) - { - ParserXmlGenerator.ConvertMorphs(m_parseResult, "//RuleAllomorph/Morph | //RootAllomorph/Morph | //Morphs/Morph", false, m_cache); - } - else - { - ParserXmlGenerator.ConvertMorphs(m_parseResult, "//Morphs/Morph", false, m_cache); - } + ParserXmlGenerator.ConvertMorphs(m_parseResult, fIsTrace ? "//RuleAllomorph/Morph | //RootAllomorph/Morph | //Morphs/Morph" : "//Morphs/Morph", false, m_cache); } [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", @@ -89,9 +82,12 @@ protected override void CreateMorphNodes(XmlDocument doc, XmlNode seqNode, strin if (node != null) { XmlNodeList morphs = node.SelectNodes("Morphs"); - foreach (XmlNode morph in morphs) + if (morphs != null) { - CreateMorphXmlElement(doc, seqNode, morph); + foreach (XmlNode morph in morphs) + { + CreateMorphXmlElement(doc, seqNode, morph); + } } } } diff --git a/Src/LexText/ParserUI/ParserTrace.cs b/Src/LexText/ParserUI/ParserTrace.cs index d78002e10f..ea2b2999f0 100644 --- a/Src/LexText/ParserUI/ParserTrace.cs +++ b/Src/LexText/ParserUI/ParserTrace.cs @@ -70,7 +70,7 @@ protected ParserTrace(Mediator mediator) /// Id of the node to use /// the wordform being tried /// temporary html file showing the results of the first step - public abstract string SetUpWordGrammarDebuggerPage(string sNodeId, string sForm, string sLastURL); + public abstract string SetUpWordGrammarDebuggerPage(string sNodeId, string sForm, string sLastUrl); /// /// Perform another step in the word grammar debugging process and diff --git a/Src/LexText/ParserUI/XAmpleTrace.cs b/Src/LexText/ParserUI/XAmpleTrace.cs index bad8866116..b13015344d 100644 --- a/Src/LexText/ParserUI/XAmpleTrace.cs +++ b/Src/LexText/ParserUI/XAmpleTrace.cs @@ -55,10 +55,10 @@ public XAmpleTrace(Mediator mediator) : base(mediator) /// Id of the node to use /// the wordform being tried /// temporary html file showing the results of the first step - public override string SetUpWordGrammarDebuggerPage(string sNodeId, string sForm, string sLastURL) + public override string SetUpWordGrammarDebuggerPage(string sNodeId, string sForm, string sLastUrl) { m_wordGrammarDebugger = new XAmpleWordGrammarDebugger(m_mediator, m_parseResult); - return m_wordGrammarDebugger.SetUpWordGrammarDebuggerPage(sNodeId, sForm, sLastURL); + return m_wordGrammarDebugger.SetUpWordGrammarDebuggerPage(sNodeId, sForm, sLastUrl); } /// From fdfb58dea242106d9df4927b0c395348f2489bfd Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Wed, 12 Feb 2014 14:06:36 +0700 Subject: [PATCH 072/143] converted WordGrammarDebugger to use XmlWriter Change-Id: I808087d3df701099b445e833bcdd99c62a19f412 --- .../ParserCore/ParserXmlGenerator.cs | 34 ++- Src/LexText/ParserUI/HCTrace.cs | 47 +--- Src/LexText/ParserUI/HCWordGrammarDebugger.cs | 34 ++- Src/LexText/ParserUI/ParserTrace.cs | 28 +-- Src/LexText/ParserUI/ParserTraceBase.cs | 132 +---------- Src/LexText/ParserUI/ParserUI.csproj | 1 + Src/LexText/ParserUI/WordGrammarDebugger.cs | 224 ++++++++++++------ Src/LexText/ParserUI/WordGrammarStepPair.cs | 47 ++++ Src/LexText/ParserUI/XAmpleTrace.cs | 96 +------- .../ParserUI/XAmpleWordGrammarDebugger.cs | 39 +-- 10 files changed, 283 insertions(+), 399 deletions(-) create mode 100644 Src/LexText/ParserUI/WordGrammarStepPair.cs diff --git a/Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs b/Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs index ab00cd436c..881634aa34 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs @@ -67,7 +67,7 @@ public static void CreateMsaXmlElement(XmlNode node, XmlDocument doc, XmlNode mo } } } - public static void CreateMsaXmlElement(XmlWriter writer, string sObjHvo, string sAlloId, string slotHvo, FdoCache fdoCache) + public static void CreateMsaXmlElement(XmlWriter writer, string sObjHvo, string sAlloId, string type, string wordType, FdoCache fdoCache) { // Irregulary inflected forms can have a combination MSA hvo: the LexEntry hvo, a period, and an index to the LexEntryRef var indexOfPeriod = IndexOfPeriodInMsaHvo(ref sObjHvo); @@ -83,7 +83,7 @@ public static void CreateMsaXmlElement(XmlWriter writer, string sObjHvo, string case "MoInflAffMsa": var inflMsa = obj as IMoInflAffMsa; CreateInflectionClasses(writer, sAlloId, fdoCache); - CreateInflMsaXmlElement(writer, inflMsa, slotHvo, fdoCache); + CreateInflMsaXmlElement(writer, inflMsa, type, fdoCache); break; case "MoDerivAffMsa": var derivMsa = obj as IMoDerivAffMsa; @@ -111,7 +111,7 @@ public static void CreateMsaXmlElement(XmlWriter writer, string sObjHvo, string // This is one of the null allomorphs we create when building the // input for the parser in order to still get the Word Grammar to have something in any // required slots in affix templates. - CreateInflMsaForLexEntryInflType(writer, slotHvo, obj as ILexEntryInflType, fdoCache); + CreateInflMsaForLexEntryInflType(writer, wordType, obj as ILexEntryInflType, fdoCache); break; } } @@ -263,12 +263,12 @@ private static void CreateInflMsaXmlElement(XmlDocument doc, XmlNode morphNode, CreateProductivityRestrictionNodes(doc, inflMsaNode, inflMsa.FromProdRestrictRC, "fromProductivityRestriction"); } - private static void CreateInflMsaXmlElement(XmlWriter writer, IMoInflAffMsa inflMsa, string slotHvo, FdoCache fdoCache) + private static void CreateInflMsaXmlElement(XmlWriter writer, IMoInflAffMsa inflMsa, string type, FdoCache fdoCache) { writer.WriteStartElement("inflMsa"); CreatePOSXmlAttribute(writer, inflMsa.PartOfSpeechRA, "cat"); // handle any slot - HandleSlotInfoForInflectionalMsa(writer, slotHvo, fdoCache); + HandleSlotInfoForInflectionalMsa(writer, inflMsa, type, fdoCache); CreateFeatureStructureNodes(writer, inflMsa.InflFeatsOA, inflMsa.Hvo); CreateProductivityRestrictionNodes(writer, inflMsa.FromProdRestrictRC, "fromProductivityRestriction"); writer.WriteEndElement(); //inflMsa @@ -346,12 +346,12 @@ private static void CreateInflMsaForLexEntryInflType(XmlDocument doc, XmlNode no } } - private static void CreateInflMsaForLexEntryInflType(XmlWriter writer, string slotHvo, ILexEntryInflType lexEntryInflType, FdoCache fdoCache) + private static void CreateInflMsaForLexEntryInflType(XmlWriter writer, string wordType, ILexEntryInflType lexEntryInflType, FdoCache fdoCache) { IMoInflAffixSlot slot; //var slotId = node.SelectSingleNode("MoForm/@wordType"); - if (slotHvo != null) - slot = fdoCache.ServiceLocator.GetInstance().GetObject(Convert.ToInt32(slotHvo)); + if (wordType != null) + slot = fdoCache.ServiceLocator.GetInstance().GetObject(Convert.ToInt32(wordType)); else { var slots = lexEntryInflType.SlotsRC; @@ -547,8 +547,24 @@ private static void HandleSlotInfoForInflectionalMsa(IMoInflAffMsa inflMsa, XmlD CreateXmlAttribute(doc, "slotOptional", sSlotOptional, inflMsaNode); } - private static void HandleSlotInfoForInflectionalMsa(XmlWriter writer, string slotHvo, FdoCache fdoCache) + private static void HandleSlotInfoForInflectionalMsa(XmlWriter writer, IMoInflAffMsa inflMsa, string type, FdoCache fdoCache) { + int slotHvo = 0; + int iCount = inflMsa.SlotsRC.Count; + if (iCount > 0) + { + if (iCount > 1) + { // have a circumfix; assume only two slots and assume that the first is prefix and second is suffix + // TODO: ideally would figure out if the slots are prefix or suffix slots and then align the + // o and 1 indices to the appropriate slot. Will just do this for now (hab 2005.08.04). + if (type != null && type != "sfx") + slotHvo = inflMsa.SlotsRC.ToHvoArray()[0]; + else + slotHvo = inflMsa.SlotsRC.ToHvoArray()[1]; + } + else + slotHvo = inflMsa.SlotsRC.ToHvoArray()[0]; + } writer.WriteAttributeString("slot", slotHvo.ToString(CultureInfo.InvariantCulture)); string sSlotOptional = "false"; string sSlotAbbr = "??"; diff --git a/Src/LexText/ParserUI/HCTrace.cs b/Src/LexText/ParserUI/HCTrace.cs index 0afd27a3f7..07bdfca736 100644 --- a/Src/LexText/ParserUI/HCTrace.cs +++ b/Src/LexText/ParserUI/HCTrace.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.IO; using System.Xml; using SIL.FieldWorks.WordWorks.Parser; @@ -10,18 +9,6 @@ namespace SIL.FieldWorks.LexText.Controls { public class HCTrace : ParserTrace { - /// - /// Temp File names - /// - const string m_ksHCParse = "HCParse"; - const string m_ksHCTrace = "HCTrace"; - - /// - /// For testing - /// - public HCTrace() - { - } /// /// The real deal /// @@ -29,25 +16,24 @@ public HCTrace() public HCTrace(Mediator mediator) : base(mediator) { - m_sParse = m_ksHCParse; - m_sTrace = m_ksHCTrace; + m_sParse = "HCParse"; + m_sTrace = "HCTrace"; m_sFormatParse = "FormatXAmpleParse.xsl"; // the XAmple one works fine with Hermit Crab parse output m_sFormatTrace = "FormatHCTrace.xsl"; - } /// /// Initialize what is needed to perform the word grammar debugging and /// produce an html page showing the results /// - /// Id of the node to use - /// the wordform being tried - /// + /// Id of the node to use + /// the wordform being tried + /// /// temporary html file showing the results of the first step - public override string SetUpWordGrammarDebuggerPage(string sNodeId, string sForm, string sLastUrl) + public override string SetUpWordGrammarDebuggerPage(string nodeId, string form, string lastUrl) { m_wordGrammarDebugger = new HCWordGrammarDebugger(m_mediator, m_parseResult); - return m_wordGrammarDebugger.SetUpWordGrammarDebuggerPage(sNodeId, sForm, sLastUrl); + return m_wordGrammarDebugger.SetUpWordGrammarDebuggerPage(nodeId, form, lastUrl); } public override string CreateResultPage(string result) @@ -73,25 +59,6 @@ private void ConvertHvosToStrings(bool fIsTrace) ParserXmlGenerator.ConvertMorphs(m_parseResult, fIsTrace ? "//RuleAllomorph/Morph | //RootAllomorph/Morph | //Morphs/Morph" : "//Morphs/Morph", false, m_cache); } - [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", - Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] - protected override void CreateMorphNodes(XmlDocument doc, XmlNode seqNode, string sNodeId) - { - string s = "//WordGrammarAttempt[Id=\"" + sNodeId + "\"]"; - XmlNode node = m_parseResult.SelectSingleNode(s); - if (node != null) - { - XmlNodeList morphs = node.SelectNodes("Morphs"); - if (morphs != null) - { - foreach (XmlNode morph in morphs) - { - CreateMorphXmlElement(doc, seqNode, morph); - } - } - } - } - protected override void AddParserSpecificArguments(List args) { string sLoadErrorFile = Path.Combine(Path.GetTempPath(), m_sDataBaseName + "HCLoadErrors.xml"); diff --git a/Src/LexText/ParserUI/HCWordGrammarDebugger.cs b/Src/LexText/ParserUI/HCWordGrammarDebugger.cs index e57ab7279c..dcfb54d798 100644 --- a/Src/LexText/ParserUI/HCWordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/HCWordGrammarDebugger.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Text; +using System.Diagnostics.CodeAnalysis; using System.Xml; using XCore; @@ -10,9 +6,6 @@ namespace SIL.FieldWorks.LexText.Controls { public class HCWordGrammarDebugger : WordGrammarDebugger { - public HCWordGrammarDebugger() - {} - public HCWordGrammarDebugger(Mediator mediator, XmlDocument parseResult) : base(mediator) { @@ -21,21 +14,19 @@ public HCWordGrammarDebugger(Mediator mediator, XmlDocument parseResult) [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] - protected override void CreateMorphNodes(XmlDocument doc, XmlNode seqNode, string sNodeId) + protected override void CreateMorphNodes(XmlWriter writer, string nodeId) { - string s = "//WordGrammarAttempt[Id=\"" + sNodeId + "\"]"; + string s = "//WordGrammarAttempt[Id=\"" + nodeId + "\"]"; XmlNode node = m_parseResult.SelectSingleNode(s); if (node != null) { XmlNodeList morphs = node.SelectNodes("Morphs"); foreach (XmlNode morph in morphs) - { - CreateMorphXmlElement(doc, seqNode, morph); - } - + CreateMorphXmlElement(writer, morph); } } - protected override void CreateMorphAffixAlloFeatsXmlElement(XmlNode node, XmlNode morphNode) + + protected override void CreateMorphAffixAlloFeatsXmlElement(XmlWriter writer, XmlNode node) { XmlNode alloid = node.SelectSingleNode("@alloid"); if (alloid != null) @@ -43,22 +34,27 @@ protected override void CreateMorphAffixAlloFeatsXmlElement(XmlNode node, XmlNod XmlNode affixAlloFeatsNode = m_parseResult.SelectSingleNode("//Morph[MoForm/@DbRef='" + alloid.InnerText + "']/affixAlloFeats"); if (affixAlloFeatsNode != null) { - morphNode.InnerXml += affixAlloFeatsNode.OuterXml; + writer.WriteStartElement("affixAlloFeats"); + writer.WriteRaw(affixAlloFeatsNode.InnerXml); + writer.WriteEndElement(); } } } - protected override void CreateMorphShortNameXmlElement(XmlNode node, XmlNode morphNode) + + protected override void CreateMorphShortNameXmlElement(XmlWriter writer, XmlNode node) { XmlNode formNode = node.SelectSingleNode("shortName"); if (formNode != null) - morphNode.InnerXml = "" + formNode.InnerXml + ""; + { + writer.WriteElementString("shortName", formNode.InnerText); + } else { XmlNode alloFormNode = node.SelectSingleNode("alloform"); XmlNode glossNode = node.SelectSingleNode("gloss"); XmlNode citationFormNode = node.SelectSingleNode("citationForm"); if (alloFormNode != null && glossNode != null && citationFormNode != null) - morphNode.InnerXml = "" + alloFormNode.InnerXml + " (" + glossNode.InnerText + "): " + citationFormNode.InnerText + ""; + writer.WriteElementString("shortName", string.Format("{0} ({1}): {2}", alloFormNode.InnerText, glossNode.InnerText, citationFormNode.InnerText)); } } } diff --git a/Src/LexText/ParserUI/ParserTrace.cs b/Src/LexText/ParserUI/ParserTrace.cs index ea2b2999f0..dc0b7ca613 100644 --- a/Src/LexText/ParserUI/ParserTrace.cs +++ b/Src/LexText/ParserUI/ParserTrace.cs @@ -32,21 +32,6 @@ protected enum TransformKind protected string m_sFormatParse; protected string m_sFormatTrace; - protected const string m_ksWordGrammarDebugger = "WordGrammarDebugger"; - /// Testing variables - protected string[] m_saTesting = { "A", "AB", "ABC", "ABCD", "ABCDE", "ABCDEF" }; - protected int m_iTestingCount = 0; - protected char[] m_space = { ' ' }; - - protected char[] m_digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; - - /// - /// For testing - /// - public ParserTrace() - : base() - { - } /// /// The real deal /// @@ -67,20 +52,23 @@ protected ParserTrace(Mediator mediator) /// Initialize what is needed to perform the word grammar debugging and /// produce an html page showing the results /// - /// Id of the node to use - /// the wordform being tried + /// Id of the node to use + /// the wordform being tried + /// /// temporary html file showing the results of the first step - public abstract string SetUpWordGrammarDebuggerPage(string sNodeId, string sForm, string sLastUrl); + public abstract string SetUpWordGrammarDebuggerPage(string nodeId, string form, string lastUrl); /// /// Perform another step in the word grammar debugging process and /// produce an html page showing the results /// /// Id of the selected node to use + /// + /// /// temporary html file showing the results of the next step - public string PerformAnotherWordGrammarDebuggerStepPage(string sNodeId, string sForm, string sLastURL) + public string PerformAnotherWordGrammarDebuggerStepPage(string sNodeId, string form, string lastUrl) { - return m_wordGrammarDebugger.PerformAnotherWordGrammarDebuggerStepPage(sNodeId, sForm, sLastURL); + return m_wordGrammarDebugger.PerformAnotherWordGrammarDebuggerStepPage(sNodeId, form, lastUrl); } public string PopWordGrammarStack() diff --git a/Src/LexText/ParserUI/ParserTraceBase.cs b/Src/LexText/ParserUI/ParserTraceBase.cs index 7d9f6d1107..847fe5b33b 100644 --- a/Src/LexText/ParserUI/ParserTraceBase.cs +++ b/Src/LexText/ParserUI/ParserTraceBase.cs @@ -1,6 +1,4 @@ -using System; using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Xml; using SIL.CoreImpl; @@ -8,7 +6,6 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Common.Widgets; using SIL.FieldWorks.FDO; -using SIL.FieldWorks.WordWorks.Parser; using SIL.Utils; using XCore; @@ -27,13 +24,6 @@ public abstract class ParserTraceBase /// The parse result xml document /// protected XmlDocument m_parseResult; - /// - /// the latest word grammar debugging step xml document - /// - protected string m_sWordGrammarDebuggerXmlFile; - - protected ParserTraceBase() - {} /// /// The real deal @@ -45,122 +35,15 @@ protected ParserTraceBase(Mediator mediator) m_cache = (FdoCache)m_mediator.PropertyTable.GetValue("cache"); m_sDataBaseName = m_cache.ProjectId.Name; } - protected void CopyXmlAttribute(XmlDocument doc, XmlNode node, string sAttrName, XmlNode morphNode) - { - XmlNode attr = node.SelectSingleNode("@" + sAttrName); - if (attr != null && sAttrName != null) - CreateXmlAttribute(doc, sAttrName, attr.InnerText, morphNode); - } - private void CreateInflectionClassesAndSubclassesXmlElement(XmlDocument doc, - IEnumerable inflectionClasses, - XmlNode inflClasses) - { - foreach (IMoInflClass ic in inflectionClasses) - { - XmlNode inflClass = CreateXmlElement(doc, "inflClass", inflClasses); - CreateXmlAttribute(doc, "hvo", ic.Hvo.ToString(CultureInfo.InvariantCulture), inflClass); - CreateXmlAttribute(doc, "abbr", ic.Abbreviation.BestAnalysisAlternative.Text, inflClass); - CreateInflectionClassesAndSubclassesXmlElement(doc, ic.SubclassesOC, inflClasses); - } - } - protected virtual void CreateMorphAffixAlloFeatsXmlElement(XmlNode node, XmlNode morphNode) - { - XmlNode affixAlloFeatsNode = node.SelectSingleNode("affixAlloFeats"); - if (affixAlloFeatsNode != null) - { - morphNode.InnerXml += affixAlloFeatsNode.OuterXml; - } - } - protected void CreateMorphAlloformXmlElement(XmlNode node, XmlNode morphNode) - { - XmlNode formNode = node.SelectSingleNode("alloform"); - if (formNode != null) - morphNode.InnerXml += "" + formNode.InnerXml + ""; - } - protected void CreateMorphCitationFormXmlElement(XmlNode node, XmlNode morphNode) - { - XmlNode citationFormNode = node.SelectSingleNode("citationForm"); - if (citationFormNode != null) - morphNode.InnerXml += "" + citationFormNode.InnerXml + ""; - } - - protected void CreateMorphGlossXmlElement(XmlNode node, XmlNode morphNode) - { - XmlNode glossNode = node.SelectSingleNode("gloss"); - if (glossNode != null) - morphNode.InnerXml += "" + glossNode.InnerXml + ""; - } - protected void CreateMorphInflectionClassesXmlElement(XmlDocument doc, XmlNode node, XmlNode morphNode) - { - XmlNode attr = node.SelectSingleNode("@alloid"); - if (attr != null && node.Attributes != null) - { - XmlNode alloid = node.Attributes.GetNamedItem("alloid"); - int hvo = Convert.ToInt32(alloid.InnerText); - ICmObject obj = m_cache.ServiceLocator.GetInstance().GetObject(hvo); - var form = obj as IMoAffixForm; // only for affix forms - if (form != null) - { - if (form.InflectionClassesRC.Count > 0) - { - XmlNode inflClasses = CreateXmlElement(doc, "inflClasses", morphNode); - IFdoReferenceCollection inflectionClasses = form.InflectionClassesRC; - CreateInflectionClassesAndSubclassesXmlElement(doc, inflectionClasses, inflClasses); - } - } - } - } - - protected abstract void CreateMorphNodes(XmlDocument doc, XmlNode seqNode, string sNodeId); - protected virtual void CreateMorphShortNameXmlElement(XmlNode node, XmlNode morphNode) - { - XmlNode formNode = node.SelectSingleNode("shortName"); - if (formNode != null) - morphNode.InnerXml = "" + formNode.InnerXml + ""; - } - protected void CreateMorphStemNameXmlElement(XmlNode node, XmlNode morphNode) - { - XmlNode stemNameNode = node.SelectSingleNode("stemName"); - if (stemNameNode != null) - { - XmlNode idNode = stemNameNode.SelectSingleNode("@id"); - if (idNode != null) - morphNode.InnerXml += "" + stemNameNode.InnerXml + ""; - } - } - - protected void CreateMorphWordTypeXmlAttribute(XmlNode node, XmlDocument doc, XmlNode morphNode) - { - XmlNode attr = node.SelectSingleNode("@type"); - if (attr != null) - CreateXmlAttribute(doc, "type", attr.Value, morphNode); - attr = node.SelectSingleNode("@wordType"); - if (attr != null) - CreateXmlAttribute(doc, "wordType", attr.Value, morphNode); - } - protected void CreateMorphXmlElement(XmlDocument doc, XmlNode seqNode, XmlNode node) - { - XmlNode morphNode = CreateXmlElement(doc, "morph", seqNode); - CopyXmlAttribute(doc, node, "alloid", morphNode); - CopyXmlAttribute(doc, node, "morphname", morphNode); - CreateMorphWordTypeXmlAttribute(node, doc, morphNode); - CreateMorphShortNameXmlElement(node, morphNode); - CreateMorphAlloformXmlElement(node, morphNode); - CreateMorphStemNameXmlElement(node, morphNode); - CreateMorphAffixAlloFeatsXmlElement(node, morphNode); - CreateMorphGlossXmlElement(node, morphNode); - CreateMorphCitationFormXmlElement(node, morphNode); - CreateMorphInflectionClassesXmlElement(doc, node, morphNode); - ParserXmlGenerator.CreateMsaXmlElement(node, doc, morphNode, "@morphname", m_cache); - } - public string CreateTempFile(string sPrefix, string sExtension) + protected string CreateTempFile(string sPrefix, string sExtension) { string sTempFileName = Path.Combine(Path.GetTempPath(), m_sDataBaseName + sPrefix) + "." + sExtension; using (StreamWriter sw = File.CreateText(sTempFileName)) sw.Close(); return sTempFileName; } + /// /// Path to transforms /// @@ -168,6 +51,7 @@ protected string TransformPath { get { return FwDirectoryFinder.GetCodeSubDirectory(@"Language Explorer/Configuration/Words/Analyses/TraceParse"); } } + protected string TransformToHtml(string sInputFile, string sTempFileBase, string sTransformFile, List args) { string sOutput = CreateTempFile(sTempFileBase, "htm"); @@ -204,15 +88,5 @@ protected virtual void AddParserSpecificArguments(List ar { // default is to do nothing } - - protected static XmlNode CreateXmlElement(XmlDocument doc, string sElementName, XmlNode parentNode) - { - return ParserXmlGenerator.CreateXmlElement(doc, sElementName, parentNode); - } - - protected static void CreateXmlAttribute(XmlDocument doc, string sAttrName, string sAttrValue, XmlNode elementNode) - { - ParserXmlGenerator.CreateXmlAttribute(doc, sAttrName, sAttrValue, elementNode); - } } } diff --git a/Src/LexText/ParserUI/ParserUI.csproj b/Src/LexText/ParserUI/ParserUI.csproj index d5be23739d..8ac6bd2f34 100644 --- a/Src/LexText/ParserUI/ParserUI.csproj +++ b/Src/LexText/ParserUI/ParserUI.csproj @@ -252,6 +252,7 @@ + Code diff --git a/Src/LexText/ParserUI/WordGrammarDebugger.cs b/Src/LexText/ParserUI/WordGrammarDebugger.cs index 3cb4b8617f..b4166c8f31 100644 --- a/Src/LexText/ParserUI/WordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/WordGrammarDebugger.cs @@ -1,16 +1,10 @@ using System; using System.Collections.Generic; -using System.Drawing; +using System.Globalization; using System.IO; -using System.Linq; -using System.Text; using System.Xml; -using System.Xml.XPath; -using System.Xml.Xsl; -using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; -using SIL.FieldWorks.Common.Widgets; using SIL.FieldWorks.FDO; +using SIL.FieldWorks.WordWorks.Parser; using SIL.Utils; using XCore; @@ -21,119 +15,190 @@ public abstract class WordGrammarDebugger : ParserTraceBase /// /// Word Grammar step stack /// - protected Stack m_XmlHtmlStack; + private readonly Stack m_xmlHtmlStack; - protected const string m_ksWordGrammarDebugger = "WordGrammarDebugger"; + /// + /// the latest word grammar debugging step xml document + /// + private string m_wordGrammarDebuggerXmlFile; - public WordGrammarDebugger() - { - } /// /// The real deal /// /// - public WordGrammarDebugger(Mediator mediator) + protected WordGrammarDebugger(Mediator mediator) : base(mediator) { - m_XmlHtmlStack = new Stack(); + m_xmlHtmlStack = new Stack(); } - /// /// Initialize what is needed to perform the word grammar debugging and /// produce an html page showing the results /// - /// Id of the node to use - /// the wordform being tried + /// Id of the node to use + /// the wordform being tried + /// /// temporary html file showing the results of the first step - public string SetUpWordGrammarDebuggerPage(string sNodeId, string sForm, string sLastURL) + public string SetUpWordGrammarDebuggerPage(string nodeId, string form, string lastUrl) { - m_XmlHtmlStack.Push(new WordGrammarStepPair(null, sLastURL)); - string sInitialAnalysisXml = CreateAnalysisXml(sNodeId, sForm); - string sHtmlPage = CreateWordDebuggerPage(sInitialAnalysisXml); - return sHtmlPage; + m_xmlHtmlStack.Push(new WordGrammarStepPair(null, lastUrl)); + string initialAnalysisFile = CreateTempFile(CreateWordGrammarDebuggerFileName(), "xml"); + using (var writer = XmlWriter.Create(initialAnalysisFile)) + CreateAnalysisXml(writer, nodeId, form); + return CreateWordDebuggerPage(initialAnalysisFile); } + /// /// Perform another step in the word grammar debugging process and /// produce an html page showing the results /// - /// Id of the selected node to use + /// Id of the selected node to use + /// + /// /// temporary html file showing the results of the next step - public string PerformAnotherWordGrammarDebuggerStepPage(string sNodeId, string sForm, string sLastURL) + public string PerformAnotherWordGrammarDebuggerStepPage(string nodeId, string form, string lastUrl) { - m_XmlHtmlStack.Push(new WordGrammarStepPair(m_sWordGrammarDebuggerXmlFile, sLastURL)); - string sNextXml = CreateSelectedWordGrammarXml(sNodeId, sForm); - string sHtmlPage = CreateWordDebuggerPage(sNextXml); - return sHtmlPage; + m_xmlHtmlStack.Push(new WordGrammarStepPair(m_wordGrammarDebuggerXmlFile, lastUrl)); + string nextFile = CreateTempFile("SelectedWordGrammarXml", "xml"); + using (var writer = XmlWriter.Create(nextFile)) + CreateSelectedWordGrammarXml(writer, nodeId, form); + return CreateWordDebuggerPage(nextFile); } + public string PopWordGrammarStack() { - WordGrammarStepPair wgsp; - if (m_XmlHtmlStack.Count > 0) + if (m_xmlHtmlStack.Count > 0) { - wgsp = m_XmlHtmlStack.Pop(); // get the previous one - m_sWordGrammarDebuggerXmlFile = wgsp.XmlFile; + WordGrammarStepPair wgsp = m_xmlHtmlStack.Pop(); + m_wordGrammarDebuggerXmlFile = wgsp.XmlFile; return wgsp.HtmlFile; } return "unknown"; } - protected string CreateAnalysisXml(string sNodeId, string sForm) + + private void CreateAnalysisXml(XmlWriter writer, string nodeId, string form) + { + writer.WriteStartDocument(); + + writer.WriteStartElement("word"); + writer.WriteElementString("form", form); + writer.WriteStartElement("seq"); + + CreateMorphNodes(writer, nodeId); + + writer.WriteEndElement(); + writer.WriteEndElement(); + + writer.WriteEndDocument(); + } + + protected abstract void CreateMorphNodes(XmlWriter writer, string nodeId); + + private void CreateSelectedWordGrammarXml(XmlWriter writer, string nodeId, string form) { - string sResult; - if (m_parseResult != null) + var lastDoc = new XmlDocument(); + lastDoc.Load(m_wordGrammarDebuggerXmlFile); + + writer.WriteStartDocument(); + + writer.WriteStartElement("word"); + writer.WriteElementString("form", form); + + // Find the sNode'th seq node + string sSelect = "//seq[position()='" + nodeId + "']"; + XmlNode selectedSeqNode = lastDoc.SelectSingleNode(sSelect); + // create the "result so far node" + writer.WriteStartElement("resultsSoFar"); + writer.WriteRaw(selectedSeqNode.InnerXml); + writer.WriteEndElement(); + // create the seq node + writer.WriteStartElement("seq"); + writer.WriteRaw(selectedSeqNode.InnerXml); + writer.WriteEndElement(); + } + + protected void CreateMorphXmlElement(XmlWriter writer, XmlNode node) + { + writer.WriteStartElement("morph"); + XmlAttribute alloIdAttr = node.Attributes["alloid"]; + if (alloIdAttr != null) + writer.WriteAttributeString("alloid", alloIdAttr.Value); + XmlAttribute morphnameAttr = node.Attributes["morphname"]; + if (morphnameAttr != null) + writer.WriteAttributeString("morphname", morphnameAttr.Value); + XmlAttribute typeAttr = node.Attributes["type"]; + if (typeAttr != null) + writer.WriteAttributeString("type", typeAttr.Value); + XmlAttribute wordTypeAttr = node.Attributes["wordType"]; + if (wordTypeAttr != null) + writer.WriteAttributeString("wordType", wordTypeAttr.Value); + CreateMorphShortNameXmlElement(writer, node); + XmlNode formNode = node.SelectSingleNode("alloform"); + if (formNode != null) + writer.WriteElementString("alloform", formNode.InnerText); + XmlNode stemNameNode = node.SelectSingleNode("stemName"); + if (stemNameNode != null) { - XmlDocument doc = new XmlDocument(); - XmlNode wordNode = CreateXmlElement(doc, "word", doc); - XmlNode formNode = CreateXmlElement(doc, "form", wordNode); - formNode.InnerXml = sForm; - XmlNode seqNode = CreateXmlElement(doc, "seq", wordNode); - - // following for debugging as needed - sResult = CreateTempFile("ParseResult", "xml"); - m_parseResult.Save(sResult); - CreateMorphNodes(doc, seqNode, sNodeId); - - sResult = CreateTempFile(CreateWordGrammarDebuggerFileName(), "xml"); - doc.Save(sResult); + XmlAttribute idAttr = stemNameNode.Attributes["id"]; + if (idAttr != null) + { + writer.WriteStartElement("stemName"); + writer.WriteAttributeString("id", idAttr.Value); + writer.WriteString(stemNameNode.InnerText); + writer.WriteEndElement(); + } + } + CreateMorphAffixAlloFeatsXmlElement(writer, node); + XmlNode glossNode = node.SelectSingleNode("gloss"); + if (glossNode != null) + writer.WriteElementString("gloss", glossNode.InnerText); + XmlNode citationFormNode = node.SelectSingleNode("citationForm"); + if (citationFormNode != null) + writer.WriteElementString("citationForm", citationFormNode.InnerText); + + if (alloIdAttr != null) + { + int hvo = Convert.ToInt32(alloIdAttr.Value); + ICmObject obj = m_cache.ServiceLocator.GetInstance().GetObject(hvo); + var form = obj as IMoAffixForm; // only for affix forms + if (form != null) + { + if (form.InflectionClassesRC.Count > 0) + { + writer.WriteStartElement("inflClasses"); + CreateInflectionClassesAndSubclassesXmlElement(writer, form.InflectionClassesRC); + } + } + } + if (morphnameAttr != null) + { + ParserXmlGenerator.CreateMsaXmlElement(writer, morphnameAttr.Value, alloIdAttr == null ? null : alloIdAttr.Value, + typeAttr == null ? null : typeAttr.Value, wordTypeAttr == null ? null : wordTypeAttr.Value, m_cache); } - else - sResult = "error!"; - return sResult; } - private string CreateSelectedWordGrammarXml(string sNodeId, string sForm) + + protected abstract void CreateMorphShortNameXmlElement(XmlWriter writer, XmlNode node); + + protected abstract void CreateMorphAffixAlloFeatsXmlElement(XmlWriter writer, XmlNode node); + + private void CreateInflectionClassesAndSubclassesXmlElement(XmlWriter writer, IEnumerable inflectionClasses) { - string sResult; - if (m_sWordGrammarDebuggerXmlFile != null) + foreach (IMoInflClass ic in inflectionClasses) { - XmlDocument lastDoc = new XmlDocument(); - lastDoc.Load(m_sWordGrammarDebuggerXmlFile); - XmlDocument doc = new XmlDocument(); - XmlNode wordNode = CreateXmlElement(doc, "word", doc); - XmlNode formNode = CreateXmlElement(doc, "form", wordNode); - formNode.InnerXml = sForm; - // Find the sNode'th seq node - string sSelect = "//seq[position()='" + sNodeId + "']"; - XmlNode selectedSeqNode = lastDoc.SelectSingleNode(sSelect); - // create the "result so far node" - XmlNode resultSoFarNode = CreateXmlElement(doc, "resultSoFar", wordNode); - resultSoFarNode.InnerXml = selectedSeqNode.InnerXml; - // create the seq node - XmlNode seqNode = CreateXmlElement(doc, "seq", wordNode); - seqNode.InnerXml = selectedSeqNode.InnerXml; - // save result - sResult = CreateTempFile("SelectedWordGrammarXml", "xml"); - doc.Save(sResult); + writer.WriteStartElement("inflClass"); + writer.WriteAttributeString("hvo", ic.Hvo.ToString(CultureInfo.InvariantCulture)); + writer.WriteAttributeString("abbr", ic.Abbreviation.BestAnalysisAlternative.Text); + writer.WriteEndElement(); + CreateInflectionClassesAndSubclassesXmlElement(writer, ic.SubclassesOC); } - else - sResult = "error!"; - return sResult; } private string CreateWordDebuggerPage(string sXmlFile) { // apply word grammar step transform file string sXmlOutput = TransformToXml(sXmlFile); - m_sWordGrammarDebuggerXmlFile = sXmlOutput; + m_wordGrammarDebuggerXmlFile = sXmlOutput; // format the result string sOutput = TransformToHtml(sXmlOutput); return sOutput; @@ -141,8 +206,8 @@ private string CreateWordDebuggerPage(string sXmlFile) private string CreateWordGrammarDebuggerFileName() { - string sDepthLevel = m_XmlHtmlStack.Count.ToString(); - return m_ksWordGrammarDebugger + sDepthLevel; + string sDepthLevel = m_xmlHtmlStack.Count.ToString(); + return "WordGrammarDebugger" + sDepthLevel; } protected string TransformToHtml(string sInputFile) @@ -152,6 +217,7 @@ protected string TransformToHtml(string sInputFile) "FormatXAmpleWordGrammarDebuggerResult.xsl", args); return sOutput; } + private string TransformToXml(string sInputFile) { // Don't overwrite the input file before transforming it! (why +"A" on the next line) diff --git a/Src/LexText/ParserUI/WordGrammarStepPair.cs b/Src/LexText/ParserUI/WordGrammarStepPair.cs new file mode 100644 index 0000000000..bc1f04d3d7 --- /dev/null +++ b/Src/LexText/ParserUI/WordGrammarStepPair.cs @@ -0,0 +1,47 @@ +namespace SIL.FieldWorks.LexText.Controls +{ + public class WordGrammarStepPair + { + protected string m_sXmlFile; + protected string m_sHtmlFile; + /// + /// Constructor + /// + /// Xml file + /// Html file + public WordGrammarStepPair(string sXmlFile, string sHtmlFile) + { + m_sXmlFile = sXmlFile; + m_sHtmlFile = sHtmlFile; + } + /// + /// Gete/set XmlFile + /// + public string XmlFile + { + get + { + return m_sXmlFile; + } + set + { + m_sXmlFile = value; + } + } + /// + /// Gete/set HtmlFile + /// + public string HtmlFile + { + get + { + return m_sHtmlFile; + } + set + { + m_sHtmlFile = value; + } + } + + } +} diff --git a/Src/LexText/ParserUI/XAmpleTrace.cs b/Src/LexText/ParserUI/XAmpleTrace.cs index b13015344d..70238ede16 100644 --- a/Src/LexText/ParserUI/XAmpleTrace.cs +++ b/Src/LexText/ParserUI/XAmpleTrace.cs @@ -23,42 +23,30 @@ namespace SIL.FieldWorks.LexText.Controls /// public class XAmpleTrace : ParserTrace { - - /// - /// Temp File names - /// - const string m_ksXAmpleParse = "XAmpleParse"; - const string m_ksXAmpleTrace = "XAmpleTrace"; - - /// - /// For testing - /// - public XAmpleTrace() - { - } /// /// The real deal /// /// public XAmpleTrace(Mediator mediator) : base(mediator) { - m_sParse = m_ksXAmpleParse; - m_sTrace = m_ksXAmpleTrace; + m_sParse = "XAmpleParse"; + m_sTrace = "XAmpleTrace"; m_sFormatParse = "FormatXAmpleParse.xsl"; m_sFormatTrace = "FormatXAmpleTrace.xsl"; - } + /// /// Initialize what is needed to perform the word grammar debugging and /// produce an html page showing the results /// - /// Id of the node to use - /// the wordform being tried + /// Id of the node to use + /// the wordform being tried + /// /// temporary html file showing the results of the first step - public override string SetUpWordGrammarDebuggerPage(string sNodeId, string sForm, string sLastUrl) + public override string SetUpWordGrammarDebuggerPage(string nodeId, string form, string lastUrl) { m_wordGrammarDebugger = new XAmpleWordGrammarDebugger(m_mediator, m_parseResult); - return m_wordGrammarDebugger.SetUpWordGrammarDebuggerPage(sNodeId, sForm, sLastUrl); + return m_wordGrammarDebugger.SetUpWordGrammarDebuggerPage(nodeId, form, lastUrl); } /// @@ -71,79 +59,13 @@ public override string CreateResultPage(string result) m_parseResult = new XmlDocument(); m_parseResult.LoadXml(result); - string sInput = CreateTempFile(m_ksXAmpleTrace, "xml"); + string sInput = CreateTempFile(m_sTrace, "xml"); m_parseResult.Save(sInput); TransformKind kind = (m_parseResult.DocumentElement.Name == "AmpleTrace" ? TransformKind.kcptTrace : TransformKind.kcptParse); string sOutput = TransformToHtml(sInput, kind); return sOutput; } - - protected override void CreateMorphNodes(XmlDocument doc, XmlNode seqNode, string sNodeId) - { - string s = "//failure[@id=\"" + sNodeId + "\"]/ancestor::parseNode[morph][1]/morph"; - XmlNode node = m_parseResult.SelectSingleNode(s); - if (node != null) - { - CreateMorphNode(doc, seqNode, node); - } - } - private void CreateMorphNode(XmlDocument doc, XmlNode seqNode, XmlNode node) - { - // get the element closest up the chain to node - XmlNode morph = node.SelectSingleNode("../ancestor::parseNode[morph][1]/morph"); - if (morph != null) - { - CreateMorphNode(doc, seqNode, morph); - } - CreateMorphXmlElement(doc, seqNode, node); - } - } - - public class WordGrammarStepPair - { - protected string m_sXmlFile; - protected string m_sHtmlFile; - /// - /// Constructor - /// - /// Xml file - /// Html file - public WordGrammarStepPair(string sXmlFile, string sHtmlFile) - { - m_sXmlFile = sXmlFile; - m_sHtmlFile = sHtmlFile; - } - /// - /// Gete/set XmlFile - /// - public string XmlFile - { - get - { - return m_sXmlFile; - } - set - { - m_sXmlFile = value; - } - } - /// - /// Gete/set HtmlFile - /// - public string HtmlFile - { - get - { - return m_sHtmlFile; - } - set - { - m_sHtmlFile = value; - } - } - } - } /// /// Note for Andy diff --git a/Src/LexText/ParserUI/XAmpleWordGrammarDebugger.cs b/Src/LexText/ParserUI/XAmpleWordGrammarDebugger.cs index 122222bbb0..dd47b096fc 100644 --- a/Src/LexText/ParserUI/XAmpleWordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/XAmpleWordGrammarDebugger.cs @@ -1,42 +1,49 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Xml; +using System.Xml; using XCore; namespace SIL.FieldWorks.LexText.Controls { public class XAmpleWordGrammarDebugger : WordGrammarDebugger { - public XAmpleWordGrammarDebugger() - { } - public XAmpleWordGrammarDebugger(Mediator mediator, XmlDocument parseResult) : base(mediator) { m_parseResult = parseResult; } - protected override void CreateMorphNodes(XmlDocument doc, XmlNode seqNode, string sNodeId) + protected override void CreateMorphNodes(XmlWriter writer, string nodeId) { - string s = "//failure[@id=\"" + sNodeId + "\"]/ancestor::parseNode[morph][1]/morph"; + string s = "//failure[@id=\"" + nodeId + "\"]/ancestor::parseNode[morph][1]/morph"; XmlNode node = m_parseResult.SelectSingleNode(s); if (node != null) - { - CreateMorphNode(doc, seqNode, node); - } + CreateMorphNode(writer, node); } - private void CreateMorphNode(XmlDocument doc, XmlNode seqNode, XmlNode node) + + private void CreateMorphNode(XmlWriter writer, XmlNode node) { // get the element closest up the chain to node XmlNode morph = node.SelectSingleNode("../ancestor::parseNode[morph][1]/morph"); if (morph != null) + CreateMorphNode(writer, morph); + CreateMorphXmlElement(writer, node); + } + + protected override void CreateMorphAffixAlloFeatsXmlElement(XmlWriter writer, XmlNode node) + { + XmlNode affixAlloFeatsNode = node.SelectSingleNode("affixAlloFeats"); + if (affixAlloFeatsNode != null) { - CreateMorphNode(doc, seqNode, morph); + writer.WriteStartElement("affixAlloFeats"); + writer.WriteRaw(affixAlloFeatsNode.InnerXml); + writer.WriteEndElement(); } - CreateMorphXmlElement(doc, seqNode, node); } + protected override void CreateMorphShortNameXmlElement(XmlWriter writer, XmlNode node) + { + XmlNode formNode = node.SelectSingleNode("shortName"); + if (formNode != null) + writer.WriteElementString("shortName", formNode.InnerText); + } } } From 7fd528df47f7e4783a93afc1349f345d295ce8ce Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Wed, 12 Feb 2014 15:56:11 +0700 Subject: [PATCH 073/143] updated ConvertMorphs to use XmlWriter Change-Id: I92c0bed804548d76140053969ef824b112630aeb --- .../ParserCore/ParserXmlGenerator.cs | 229 ++++++++++++++---- 1 file changed, 180 insertions(+), 49 deletions(-) diff --git a/Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs b/Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs index 881634aa34..a15dc3268c 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs @@ -5,8 +5,10 @@ using System.Linq; using System.Text; using System.Xml; +using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.FDO; +using SIL.FieldWorks.FDO.DomainServices; using SIL.Utils; namespace SIL.FieldWorks.WordWorks.Parser @@ -53,7 +55,7 @@ public static void CreateMsaXmlElement(XmlNode node, XmlDocument doc, XmlNode mo { var index = IndexOfLexEntryRef(attr.Value, indexOfPeriod); var lexEntryRef = entry.EntryRefsOS[index]; - var sense = FDO.DomainServices.MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); + var sense = MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); stemMsa = sense.MorphoSyntaxAnalysisRA as IMoStemMsa; CreateStemMsaXmlElement(doc, morphNode, stemMsa, fdoCache); } @@ -78,12 +80,12 @@ public static void CreateMsaXmlElement(XmlWriter writer, string sObjHvo, string throw new ApplicationException(String.Format("Invalid MSA type: {0}.", obj.GetType().Name)); case "MoStemMsa": var stemMsa = obj as IMoStemMsa; - CreateStemMsaXmlElement(writer, stemMsa, fdoCache); + CreateStemMsaXmlElement(writer, stemMsa); break; case "MoInflAffMsa": var inflMsa = obj as IMoInflAffMsa; - CreateInflectionClasses(writer, sAlloId, fdoCache); - CreateInflMsaXmlElement(writer, inflMsa, type, fdoCache); + CreateInflectionClasses(writer, fdoCache, sAlloId); + CreateInflMsaXmlElement(writer, inflMsa, type); break; case "MoDerivAffMsa": var derivMsa = obj as IMoDerivAffMsa; @@ -102,16 +104,16 @@ public static void CreateMsaXmlElement(XmlWriter writer, string sObjHvo, string { var index = IndexOfLexEntryRef(sObjHvo, indexOfPeriod); var lexEntryRef = entry.EntryRefsOS[index]; - var sense = FDO.DomainServices.MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); + var sense = MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); stemMsa = sense.MorphoSyntaxAnalysisRA as IMoStemMsa; - CreateStemMsaXmlElement(writer, stemMsa, fdoCache); + CreateStemMsaXmlElement(writer, stemMsa); } break; case "LexEntryInflType": // This is one of the null allomorphs we create when building the // input for the parser in order to still get the Word Grammar to have something in any // required slots in affix templates. - CreateInflMsaForLexEntryInflType(writer, wordType, obj as ILexEntryInflType, fdoCache); + CreateInflMsaForLexEntryInflType(fdoCache, writer, wordType, obj as ILexEntryInflType); break; } } @@ -182,7 +184,7 @@ private static void CreateStemMsaXmlElement(XmlDocument doc, XmlNode morphNode, CreateFromPOSNodes(doc, stemMsaNode, stemMsa.FromPartsOfSpeechRC, "fromPartsOfSpeech"); } - private static void CreateStemMsaXmlElement(XmlWriter writer, IMoStemMsa stemMsa, FdoCache fdoCache) + private static void CreateStemMsaXmlElement(XmlWriter writer, IMoStemMsa stemMsa) { writer.WriteStartElement("stemMsa"); CreatePOSXmlAttribute(writer, stemMsa.PartOfSpeechRA, "cat"); @@ -198,12 +200,12 @@ private static void CreateStemMsaXmlElement(XmlWriter writer, IMoStemMsa stemMsa inflClassHvo = pos.DefaultInflectionClassRA.Hvo; else { - int clsid = fdoCache.ServiceLocator.GetInstance().GetObject(pos.Owner.Hvo).ClassID; - pos = clsid == PartOfSpeechTags.kClassId ? fdoCache.ServiceLocator.GetInstance().GetObject(pos.Owner.Hvo) : null; + int clsid = stemMsa.Services.GetInstance().GetObject(pos.Owner.Hvo).ClassID; + pos = clsid == PartOfSpeechTags.kClassId ? stemMsa.Services.GetInstance().GetObject(pos.Owner.Hvo) : null; } } if (inflClassHvo != 0) - inflClass = fdoCache.ServiceLocator.GetInstance().GetObject(inflClassHvo); + inflClass = stemMsa.Services.GetInstance().GetObject(inflClassHvo); } CreateInflectionClassXmlAttribute(writer, inflClass, "inflClass"); CreateRequiresInflectionXmlAttribute(writer, stemMsa.PartOfSpeechRA); @@ -233,11 +235,11 @@ private static void CreateInflectionClasses(XmlDocument doc, XmlNode morphNode, } } - private static void CreateInflectionClasses(XmlWriter writer, string sAlloId, FdoCache fdoCache) + private static void CreateInflectionClasses(XmlWriter writer, FdoCache fdoCache, string alloId) { - if (sAlloId == null) + if (alloId == null) return; - int hvoAllomorph = Convert.ToInt32(sAlloId); + int hvoAllomorph = Convert.ToInt32(alloId); // use IMoForm instead of IMoAffixForm or IMoAffixAllomorph because it could be an IMoStemAllomorph IMoForm form = fdoCache.ServiceLocator.GetInstance().GetObject(hvoAllomorph); if (form == null) @@ -263,12 +265,12 @@ private static void CreateInflMsaXmlElement(XmlDocument doc, XmlNode morphNode, CreateProductivityRestrictionNodes(doc, inflMsaNode, inflMsa.FromProdRestrictRC, "fromProductivityRestriction"); } - private static void CreateInflMsaXmlElement(XmlWriter writer, IMoInflAffMsa inflMsa, string type, FdoCache fdoCache) + private static void CreateInflMsaXmlElement(XmlWriter writer, IMoInflAffMsa inflMsa, string type) { writer.WriteStartElement("inflMsa"); CreatePOSXmlAttribute(writer, inflMsa.PartOfSpeechRA, "cat"); // handle any slot - HandleSlotInfoForInflectionalMsa(writer, inflMsa, type, fdoCache); + HandleSlotInfoForInflectionalMsa(writer, inflMsa, type); CreateFeatureStructureNodes(writer, inflMsa.InflFeatsOA, inflMsa.Hvo); CreateProductivityRestrictionNodes(writer, inflMsa.FromProdRestrictRC, "fromProductivityRestriction"); writer.WriteEndElement(); //inflMsa @@ -346,12 +348,12 @@ private static void CreateInflMsaForLexEntryInflType(XmlDocument doc, XmlNode no } } - private static void CreateInflMsaForLexEntryInflType(XmlWriter writer, string wordType, ILexEntryInflType lexEntryInflType, FdoCache fdoCache) + private static void CreateInflMsaForLexEntryInflType(FdoCache cache, XmlWriter writer, string wordType, ILexEntryInflType lexEntryInflType) { IMoInflAffixSlot slot; //var slotId = node.SelectSingleNode("MoForm/@wordType"); if (wordType != null) - slot = fdoCache.ServiceLocator.GetInstance().GetObject(Convert.ToInt32(wordType)); + slot = cache.ServiceLocator.GetInstance().GetObject(Convert.ToInt32(wordType)); else { var slots = lexEntryInflType.SlotsRC; @@ -547,7 +549,7 @@ private static void HandleSlotInfoForInflectionalMsa(IMoInflAffMsa inflMsa, XmlD CreateXmlAttribute(doc, "slotOptional", sSlotOptional, inflMsaNode); } - private static void HandleSlotInfoForInflectionalMsa(XmlWriter writer, IMoInflAffMsa inflMsa, string type, FdoCache fdoCache) + private static void HandleSlotInfoForInflectionalMsa(XmlWriter writer, IMoInflAffMsa inflMsa, string type) { int slotHvo = 0; int iCount = inflMsa.SlotsRC.Count; @@ -570,7 +572,7 @@ private static void HandleSlotInfoForInflectionalMsa(XmlWriter writer, IMoInflAf string sSlotAbbr = "??"; if (Convert.ToInt32(slotHvo) > 0) { - var slot = fdoCache.ServiceLocator.GetInstance().GetObject(Convert.ToInt32(slotHvo)); + var slot = inflMsa.Services.GetInstance().GetObject(Convert.ToInt32(slotHvo)); if (slot != null) { sSlotAbbr = slot.Name.BestAnalysisAlternative.Text; @@ -582,6 +584,93 @@ private static void HandleSlotInfoForInflectionalMsa(XmlWriter writer, IMoInflAf writer.WriteAttributeString("slotOptional", sSlotOptional); } + public static void UpdateMorph(XmlWriter writer, FdoCache cache, int formHvo, string msaId, string wordType, string props) + { + ICmObject obj = cache.ServiceLocator.GetInstance().GetObject(formHvo); + var form = obj as IMoForm; + if (form == null) + { + // This is one of the null allomorphs we create when building the + // input for the parser in order to still get the Word Grammar to have something in any + // required slots in affix templates. + var lexEntryInflType = obj as ILexEntryInflType; + if (lexEntryInflType != null) + { + CreateLexEntryInflTypeElement(cache, writer, wordType, lexEntryInflType); + return; + } + } + string shortName; + string alloform; + string gloss; + string citationForm; + if (form != null) + { + shortName = form.LongName; + int iFirstSpace = shortName.IndexOf(" (", StringComparison.Ordinal); + int iLastSpace = shortName.LastIndexOf("):", StringComparison.Ordinal) + 2; + alloform = shortName.Substring(0, iFirstSpace); + int indexOfPeriod = IndexOfPeriodInMsaHvo(ref msaId); + int hvoMsa = Convert.ToInt32(msaId); + ICmObject msaObj = cache.ServiceLocator.GetObject(hvoMsa); + if (msaObj.ClassID == LexEntryTags.kClassId) + { + var entry = msaObj as ILexEntry; + Debug.Assert(entry != null); + if (entry.EntryRefsOS.Count > 0) + { + int index = IndexOfLexEntryRef(msaId, indexOfPeriod); // the value of the int after the period + ILexEntryRef lexEntryRef = entry.EntryRefsOS[index]; + ITsIncStrBldr sbGlossPrepend; + ITsIncStrBldr sbGlossAppend; + ILexSense sense = MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); + IWritingSystem glossWs = cache.ServiceLocator.WritingSystemManager.Get(cache.DefaultAnalWs); + MorphServices.JoinGlossAffixesOfInflVariantTypes(lexEntryRef.VariantEntryTypesRS, + glossWs, out sbGlossPrepend, out sbGlossAppend); + ITsIncStrBldr sbGloss = sbGlossPrepend; + sbGloss.Append(sense.Gloss.BestAnalysisAlternative.Text); + sbGloss.Append(sbGlossAppend.Text); + gloss = sbGloss.Text; + } + else + { + gloss = ParserCoreStrings.ksUnknownGloss; + } + + } + else + { + var msa = msaObj as IMoMorphSynAnalysis; + gloss = msa != null ? msa.GetGlossOfFirstSense() : shortName.Substring(iFirstSpace, iLastSpace - iFirstSpace).Trim(); + } + citationForm = shortName.Substring(iLastSpace).Trim(); + shortName = String.Format(ParserCoreStrings.ksX_Y_Z, alloform, gloss, citationForm); + } + else + { + alloform = ParserCoreStrings.ksUnknownMorpheme; // in case the user continues... + gloss = ParserCoreStrings.ksUnknownGloss; + citationForm = ParserCoreStrings.ksUnknownCitationForm; + shortName = String.Format(ParserCoreStrings.ksX_Y_Z, alloform, gloss, citationForm); + throw new ApplicationException(shortName); + } + writer.WriteElementString("shortName", shortName); + writer.WriteElementString("alloform", alloform); + switch (form.ClassID) + { + case MoStemAllomorphTags.kClassId: + CreateStemNameElement(writer, form, props); + break; + case MoAffixAllomorphTags.kClassId: + CreateAffixAlloFeatsElement(writer, form, props); + CreateStemNameAffixElement(writer, cache, props); + break; + + } + writer.WriteElementString("gloss", gloss); + writer.WriteElementString("citationForm", citationForm); + } + [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] public static void ConvertMorphs(XmlDocument doc, string sNodeListToFind, bool fIdsInAttribute, FdoCache fdoCache) @@ -635,9 +724,9 @@ public static void ConvertMorphs(XmlDocument doc, string sNodeListToFind, bool f var lexEntryRef = entry.EntryRefsOS[index]; ITsIncStrBldr sbGlossPrepend; ITsIncStrBldr sbGlossAppend; - var sense = FDO.DomainServices.MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); + var sense = MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); var glossWs = fdoCache.ServiceLocator.WritingSystemManager.Get(fdoCache.DefaultAnalWs); - FDO.DomainServices.MorphServices.JoinGlossAffixesOfInflVariantTypes(lexEntryRef.VariantEntryTypesRS, + MorphServices.JoinGlossAffixesOfInflVariantTypes(lexEntryRef.VariantEntryTypesRS, glossWs, out sbGlossPrepend, out sbGlossAppend); ITsIncStrBldr sbGloss = sbGlossPrepend; @@ -711,6 +800,24 @@ private static void ConvertLexEntryInflType(XmlDocument doc, XmlNode node, ILexE CreateInflMsaForLexEntryInflType(doc, node, lexEntryInflType, fdoCache); } + private static void CreateLexEntryInflTypeElement(FdoCache cache, XmlWriter writer, string wordType, ILexEntryInflType lexEntryInflType) + { + writer.WriteElementString("lexEntryInflType", ""); + writer.WriteElementString("alloform", "0"); + string sNullGloss = null; + var sbGloss = new StringBuilder(); + if (string.IsNullOrEmpty(lexEntryInflType.GlossPrepend.BestAnalysisAlternative.Text)) + { + sbGloss.Append(lexEntryInflType.GlossPrepend.BestAnalysisAlternative.Text); + sbGloss.Append("..."); + } + sbGloss.Append(lexEntryInflType.GlossAppend.BestAnalysisAlternative.Text); + writer.WriteElementString("gloss", sbGloss.ToString()); + var sMsg = string.Format(ParserCoreStrings.ksIrregularlyInflectedFormNullAffix, lexEntryInflType.ShortName); + writer.WriteElementString("citationForm", sMsg); + CreateInflMsaForLexEntryInflType(cache, writer, wordType, lexEntryInflType); + } + private static void ConvertStemName(XmlDocument doc, XmlNode node, IMoForm form) { var sallo = form as IMoStemAllomorph; @@ -731,26 +838,26 @@ private static void ConvertStemName(XmlDocument doc, XmlNode node, IMoForm form) } } -// private static void ConvertStemName(XmlWriter writer, IMoForm form) -// { -// var sallo = form as IMoStemAllomorph; -// Debug.Assert(sallo != null); -// IMoStemName sn = sallo.StemNameRA; -// if (sn != null) -// { -// writer.WriteStartElement("stemName"); -// writer.WriteAttributeString("id", sn.Hvo.ToString(CultureInfo.InvariantCulture)); -// writer.WriteString(sn.Name.BestAnalysisAlternative.Text); -// writer.WriteEndElement(); //stemName -// } -// else -// { // There's no overt stem name on this allomorph, but there might be overt stem names -// // on other allomorphs in this lexical entry. This allomorph, then, cannot bear any -// // of the features of these other stem names. If so, there will be a property named -// // NotStemNameddd or NotStemNamedddNotStemNamedddd, etc. -// CreateNotStemNameElement(writer); -// } -// } + private static void CreateStemNameElement(XmlWriter writer, IMoForm form, string props) + { + var sallo = form as IMoStemAllomorph; + Debug.Assert(sallo != null); + IMoStemName sn = sallo.StemNameRA; + if (sn != null) + { + writer.WriteStartElement("stemName"); + writer.WriteAttributeString("id", sn.Hvo.ToString(CultureInfo.InvariantCulture)); + writer.WriteString(sn.Name.BestAnalysisAlternative.Text); + writer.WriteEndElement(); //stemName + } + else + { // There's no overt stem name on this allomorph, but there might be overt stem names + // on other allomorphs in this lexical entry. This allomorph, then, cannot bear any + // of the features of these other stem names. If so, there will be a property named + // NotStemNameddd or NotStemNamedddNotStemNamedddd, etc. + CreateNotStemNameElement(writer, props); + } + } private static void ConvertStemNameAffix(XmlDocument doc, XmlNode node, FdoCache fdoCache) { @@ -777,6 +884,30 @@ private static void ConvertStemNameAffix(XmlDocument doc, XmlNode node, FdoCache } } + private static void CreateStemNameAffixElement(XmlWriter writer, FdoCache cache, string props) + { + if (string.IsNullOrEmpty(props)) + return; + + string[] propsArray = props.Trim().Split(' '); + foreach (string prop in propsArray) + { + int i = prop.IndexOf("StemNameAffix", StringComparison.Ordinal); + if (i > -1) + { + string id = (prop.Substring(i + 13)).Trim(); + IMoStemName sn = cache.ServiceLocator.GetInstance().GetObject(Convert.ToInt32(id)); + if (sn != null) + { + writer.WriteStartElement("stemNameAffix"); + writer.WriteAttributeString("id", id); + writer.WriteString(sn.Name.BestAnalysisAlternative.Text); + writer.WriteEndElement(); + } + } + } + } + private static void CreateNotStemNameElement(XmlDocument doc, XmlNode node) { XmlNode props = node.SelectSingleNode("props"); @@ -831,7 +962,7 @@ private static void ConvertAffixAlloFeats(XmlDocument doc, XmlNode node, IMoForm } } - private static void ConvertAffixAlloFeats(XmlWriter writer, IMoForm form, string propsText, FdoCache fdoCache) + private static void CreateAffixAlloFeatsElement(XmlWriter writer, IMoForm form, string propsText) { var sallo = form as IMoAffixAllomorph; if (sallo == null) @@ -848,7 +979,7 @@ private static void ConvertAffixAlloFeats(XmlWriter writer, IMoForm form, string // on other allomorphs in this lexical entry. This allomorph, then, cannot bear any // of the features of these other stem names. If so, there will be a property named // NotStemNameddd or NotStemNamedddNotStemNamedddd, etc. - CreateNotAffixAlloFeatsElement(writer, propsText, fdoCache); + CreateNotAffixAlloFeatsElement(writer, form.Cache, propsText); } } @@ -890,7 +1021,7 @@ private static void CreateNotAffixAlloFeatsElement(XmlDocument doc, XmlNode node } } - private static void CreateNotAffixAlloFeatsElement(XmlWriter writer, string propsText, FdoCache fdoCache) + private static void CreateNotAffixAlloFeatsElement(XmlWriter writer, FdoCache cache, string propsText) { if (propsText != null) { @@ -912,14 +1043,14 @@ private static void CreateNotAffixAlloFeatsElement(XmlWriter writer, string prop { // there are more sFsHvo = s.Substring(iNot, iNextNot - iNot); - CreateFeatureStructureFromHvoString(writer, sFsHvo, fdoCache); + CreateFeatureStructureFromHvoString(writer, cache, sFsHvo); iNot = iNextNot + 3; } else { // is the last one sFsHvo = s.Substring(iNot); - CreateFeatureStructureFromHvoString(writer, sFsHvo, fdoCache); + CreateFeatureStructureFromHvoString(writer, cache, sFsHvo); iNot = 0; } } @@ -939,10 +1070,10 @@ private static void CreateFeatureStructureFromHvoString(XmlDocument doc, string } } - private static void CreateFeatureStructureFromHvoString(XmlWriter writer, string sFsHvo, FdoCache fdoCache) + private static void CreateFeatureStructureFromHvoString(XmlWriter writer, FdoCache cache, string sFsHvo) { int fsHvo = Convert.ToInt32(sFsHvo); - var fsFeatStruc = (IFsFeatStruc)fdoCache.ServiceLocator.GetInstance().GetObject(fsHvo); + var fsFeatStruc = (IFsFeatStruc) cache.ServiceLocator.GetInstance().GetObject(fsHvo); if (fsFeatStruc != null) CreateFeatureStructureNodes(writer, fsFeatStruc, fsHvo); } From 7c1db23f97c594b84c4086489f177d6fd25232dd Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Wed, 12 Feb 2014 17:24:50 +0700 Subject: [PATCH 074/143] Refactor HCParser to do all XML creation at the same time Change-Id: I00aa75009fc0850254b37178bffb4b89ba220c0e --- .../ParserEngine/ParserCore/HCParser.cs | 292 ++++++++---------- .../ParserEngine/ParserCore/ParserHelper.cs | 13 +- .../ParserCore/ParserXmlGenerator.cs | 27 +- Src/LexText/ParserUI/HCTrace.cs | 8 - Src/LexText/ParserUI/ParserTrace.cs | 28 +- Src/LexText/ParserUI/WordGrammarDebugger.cs | 2 +- 6 files changed, 153 insertions(+), 217 deletions(-) diff --git a/Src/LexText/ParserEngine/ParserCore/HCParser.cs b/Src/LexText/ParserEngine/ParserCore/HCParser.cs index 1f56a2a1fd..2ef7f52508 100644 --- a/Src/LexText/ParserEngine/ParserCore/HCParser.cs +++ b/Src/LexText/ParserEngine/ParserCore/HCParser.cs @@ -266,9 +266,7 @@ private string ParseToXML(string form, bool trace, string[] selectTraceMorphs) writer.WriteStartElement("Wordform"); writer.WriteAttributeString("DbRef", Convert.ToString(0)); writer.WriteAttributeString("Form", form); - var output = new FwXmlOutput(this, writer, trace, - Path.Combine(m_outputDirectory, m_projectName + "patrlex.txt")); - output.MorphAndLookupWord(m_loader.CurrentMorpher, form, true, selectTraceMorphs); + MorphAndLookupWord(writer, m_loader.CurrentMorpher, form, true, selectTraceMorphs, Path.Combine(m_outputDirectory, m_projectName + "patrlex.txt"), trace); AddImpliedDataCheckerInfo(writer); writer.WriteEndElement(); } @@ -330,7 +328,7 @@ private IEnumerable ProcessPatr(IEnumerable synthesis return patrResults; } - private static List GetMorphs(WordSynthesis ws) + private List GetMorphs(WordSynthesis ws) { var ppMorphs = new Dictionary(); var result = new List(); @@ -392,7 +390,7 @@ private static List GetMorphs(WordSynthesis ws) return result; } - private static void WritePcPatrLexiconFile(string path, IEnumerable morphs) + private void WritePcPatrLexiconFile(string path, IEnumerable morphs) { using (var writer = new StreamWriter(path)) { @@ -430,7 +428,7 @@ private static void WritePcPatrLexiconFile(string path, IEnumerable } } - private static string BuildPcPatrInputSentence(IEnumerable morphs) + private string BuildPcPatrInputSentence(IEnumerable morphs) { var sentence = new StringBuilder(); bool firstItem = true; @@ -490,6 +488,92 @@ private string ProcessMorphException(MorphException me) return errorMessage; } + #region Write Xml + private void MorphAndLookupWord(XmlWriter writer, Morpher morpher, string word, bool printTraceInputs, string[] selectTraceMorphs, string patrlexPath, bool doTrace) + { + try + { + ICollection wordGrammarTraces = null; + if (doTrace) + wordGrammarTraces = new HashSet(); + var traceManager = new FwXmlTraceManager(m_cache) { WriteInputs = printTraceInputs, TraceAll = doTrace }; + ICollection synthesisRecs = morpher.MorphAndLookupWord(word, traceManager, selectTraceMorphs); + + IEnumerable patrResults = ProcessPatr(synthesisRecs, patrlexPath, doTrace); + foreach (PatrResult patrResult in patrResults) + { + if (patrResult.PassedPatr) + BuildXmlOutput(writer, patrResult.Morphs); + if (wordGrammarTraces != null) + wordGrammarTraces.Add(patrResult.WordGrammarTrace); + } + + if (doTrace) + { + WriteTrace(writer, traceManager); + ConvertWordGrammarTraceToXml(writer, wordGrammarTraces); + } + traceManager.Reset(); + } + catch (MorphException exc) + { + Write(writer, exc); + } + } + + private void BuildXmlOutput(XmlWriter writer, IEnumerable morphs) + { + writer.WriteStartElement("WfiAnalysis"); + writer.WriteStartElement("Morphs"); + + foreach (PcPatrMorph morph in morphs) + { + writer.WriteStartElement("Morph"); + + writer.WriteStartElement("MoForm"); + writer.WriteAttributeString("DbRef", morph.formId); + writer.WriteAttributeString("Label", morph.form); + writer.WriteAttributeString("wordType", morph.wordType); + writer.WriteEndElement(); + + writer.WriteStartElement("MSI"); + writer.WriteAttributeString("DbRef", morph.msaId); + ParserXmlGenerator.CreateMsaXmlElement(writer, morph.msaId, Convert.ToInt32(morph.formId), null, morph.wordType, m_cache); + writer.WriteEndElement(); + + ParserXmlGenerator.UpdateMorph(writer, m_cache, Convert.ToInt32(morph.formId), morph.msaId, morph.wordType, null); + + writer.WriteEndElement(); + } + + writer.WriteEndElement(); + writer.WriteEndElement(); + } + + private void ConvertWordGrammarTraceToXml(XmlWriter writer, IEnumerable wordGrammarTraces) + { + writer.WriteStartElement("WordGrammarTrace"); + foreach (WordGrammarTrace trace in wordGrammarTraces) + trace.ToXml(writer); + writer.WriteEndElement(); + } + + private void WriteTrace(XmlWriter writer, XmlTraceManager traceManager) + { + writer.WriteStartElement("Trace"); + foreach (XElement trace in traceManager.WordAnalysisTraces) + trace.WriteTo(writer); + writer.WriteEndElement(); + } + + private void Write(XmlWriter writer, MorphException me) + { + writer.WriteStartElement("Error"); + writer.WriteString(ProcessMorphException(me)); + writer.WriteEndElement(); + } + #endregion + private class PatrResult { public List Morphs { get; set; } @@ -503,7 +587,7 @@ private class PatrResult private class ImpliedDataChecker { private readonly FdoCache m_cache; - private List m_mismatches = new List(); + private readonly List m_mismatches = new List(); public ImpliedDataChecker(FdoCache cache) { @@ -566,9 +650,9 @@ public void ToXml(XmlWriter writer) Justification = "All felds are references and are disposed in the parent class")] private class PhonemeBasedNaturalClassMismatch { - private IFsFeatStruc m_impliedPhonologicalFeatures; - private IEnumerable m_predictedPhonemes; - private IPhNCSegments m_natClass; + private readonly IFsFeatStruc m_impliedPhonologicalFeatures; + private readonly IEnumerable m_predictedPhonemes; + private readonly IPhNCSegments m_natClass; public PhonemeBasedNaturalClassMismatch(IFsFeatStruc fs, IEnumerable predictedPhonemes, IPhNCSegments natClass) { @@ -605,132 +689,6 @@ public string ListOfPhonemes(IEnumerable list) } #endregion - #region class FwXmlOutput - [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", - Justification = "m_parser is a reference to the parent class")] - private class FwXmlOutput : XmlOutput - { - private readonly HCParser m_parser; - private readonly bool m_fDotrace; - private readonly string m_patrlexPath; - - public FwXmlOutput(HCParser parser, XmlWriter writer, bool fDotrace, string patrlexPath) - : base(writer, new FwXmlTraceManager()) - { - m_parser = parser; - m_fDotrace = fDotrace; - m_patrlexPath = patrlexPath; - } - - public override void MorphAndLookupWord(Morpher morpher, string word, bool prettyPrint, bool printTraceInputs) - { - MorphAndLookupWord(morpher, word, printTraceInputs, null); - } - - public void MorphAndLookupWord(Morpher morpher, string word, bool printTraceInputs, string[] selectTraceMorphs) - { - try - { - ICollection wordGrammarTraces = null; - if (m_fDotrace) - wordGrammarTraces = new HashSet(); - XmlTraceManager.WriteInputs = printTraceInputs; - TraceManager.TraceAll = m_fDotrace; - ICollection synthesisRecs = morpher.MorphAndLookupWord(word, TraceManager, selectTraceMorphs); - - IEnumerable patrResults = m_parser.ProcessPatr(synthesisRecs, m_patrlexPath, m_fDotrace); - foreach (PatrResult patrResult in patrResults) - { - if (patrResult.PassedPatr) - BuildXmlOutput(patrResult.Morphs); - if (wordGrammarTraces != null) - wordGrammarTraces.Add(patrResult.WordGrammarTrace); - } - - if (m_fDotrace) - { - WriteTrace(); - ConvertWordGrammarTraceToXml(wordGrammarTraces); - } - XmlTraceManager.Reset(); - } - catch (MorphException exc) - { - Write(exc); - } - } - - private void BuildXmlOutput(IEnumerable morphs) - { - XmlWriter.WriteStartElement("WfiAnalysis"); - XmlWriter.WriteStartElement("Morphs"); - - foreach (PcPatrMorph morph in morphs) - { - XmlWriter.WriteStartElement("Morph"); - - XmlWriter.WriteStartElement("MoForm"); - XmlWriter.WriteAttributeString("DbRef", morph.formId); - XmlWriter.WriteAttributeString("Label", morph.form); - XmlWriter.WriteAttributeString("wordType", morph.wordType); - XmlWriter.WriteEndElement(); - - XmlWriter.WriteStartElement("MSI"); - XmlWriter.WriteAttributeString("DbRef", morph.msaId); - XmlWriter.WriteEndElement(); - - XmlWriter.WriteEndElement(); - } - - XmlWriter.WriteEndElement(); - XmlWriter.WriteEndElement(); - } - - private void ConvertWordGrammarTraceToXml(IEnumerable wordGrammarTraces) - { - XmlWriter.WriteStartElement("WordGrammarTrace"); - foreach (WordGrammarTrace trace in wordGrammarTraces) - { - trace.ToXml(XmlWriter); - } - XmlWriter.WriteEndElement(); - } - - public override void Write(LoadException le) - { - XmlWriter.WriteStartElement("Error"); - switch (le.ErrorType) - { - case LoadException.LoadErrorType.INVALID_ENTRY_SHAPE: - var entryShape = le.Data["shape"] as string; - var entryId = le.Data["entry"] as string; - LexEntry entry = le.Loader.CurrentMorpher.Lexicon.GetEntry(entryId); - XmlWriter.WriteString(String.Format(ParserCoreStrings.ksHCInvalidEntryShape, entryShape, entry.Description)); - break; - - case LoadException.LoadErrorType.INVALID_RULE_SHAPE: - var ruleShape = le.Data["shape"] as string; - var ruleId = le.Data["rule"] as string; - MorphologicalRule rule = le.Loader.CurrentMorpher.GetMorphologicalRule(ruleId); - XmlWriter.WriteString(String.Format(ParserCoreStrings.ksHCInvalidRuleShape, ruleShape, rule.Description)); - break; - - default: - XmlWriter.WriteString(String.Format(ParserCoreStrings.ksHCDefaultErrorMsg, le.Message)); - break; - } - XmlWriter.WriteEndElement(); - } - - public override void Write(MorphException me) - { - XmlWriter.WriteStartElement("Error"); - XmlWriter.WriteString(m_parser.ProcessMorphException(me)); - XmlWriter.WriteEndElement(); - } - } - #endregion - #region class WordGrammarTrace [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", Justification = "m_cache is a reference and disposed in the parent class")] @@ -764,9 +722,7 @@ public bool Success public void ToXml(XmlWriter writer) { writer.WriteStartElement("WordGrammarAttempt"); - writer.WriteStartAttribute("success"); - writer.WriteValue(m_fSuccess ? "true" : "false"); - writer.WriteEndAttribute(); + writer.WriteAttributeString("success", m_fSuccess ? "true" : "false"); writer.WriteStartElement("Id"); writer.WriteValue(m_id); writer.WriteEndElement(); @@ -776,30 +732,19 @@ public void ToXml(XmlWriter writer) { writer.WriteStartElement("Morphs"); string sWordType = morph.wordType; - writer.WriteStartAttribute("wordType"); - writer.WriteValue(sWordType); - writer.WriteEndAttribute(); - writer.WriteStartAttribute("type"); + writer.WriteAttributeString("wordType", sWordType); if (sType == "pfx" && sWordType == "root") sType = "root"; else if (sType == "root" && sWordType != "root") sType = "sfx"; - writer.WriteValue(sType); - writer.WriteEndAttribute(); - writer.WriteStartAttribute("alloid"); - writer.WriteValue(morph.formId); - writer.WriteEndAttribute(); - writer.WriteStartAttribute("morphname"); - writer.WriteValue(morph.msaId); - writer.WriteEndAttribute(); - - writer.WriteStartElement("alloform"); - writer.WriteValue(morph.form); - writer.WriteEndElement(); // alloform - //writer.WriteStartElement("Msa"); - //writer.WriteEndElement(); // Msa + writer.WriteAttributeString("type", sType); + writer.WriteAttributeString("alloid", morph.formId); + writer.WriteAttributeString("morphname", morph.msaId); + + writer.WriteElementString("alloform", morph.form); + int hvoForm = Convert.ToInt32(morph.formId); var obj = m_cache.ServiceLocator.GetObject(hvoForm); var stemAllo = obj as IMoStemAllomorph; @@ -816,9 +761,7 @@ public void ToXml(XmlWriter writer) writer.WriteEndElement(); // stemName } } - writer.WriteStartElement("gloss"); - writer.WriteValue(morph.gloss); - writer.WriteEndElement(); // gloss + writer.WriteElementString("gloss", morph.gloss); writer.WriteStartElement("citationForm"); var form = obj as IMoForm; if (form != null) @@ -838,6 +781,13 @@ public void ToXml(XmlWriter writer) #region class FwXmlTraceManager private class FwXmlTraceManager : XmlTraceManager { + private readonly FdoCache m_cache; + + public FwXmlTraceManager(FdoCache fdoCache) : base() + { + m_cache = fdoCache; + } + public override void ReportSuccess(WordSynthesis output) { if (TraceSuccess) @@ -880,7 +830,27 @@ protected override XElement Write(string name, Allomorph allomorph) } if (!String.IsNullOrEmpty(msaId)) - morphElem.Add(new XElement("MSI", new XAttribute("DbRef", msaId))); + { + var msiElement = new XElement("MSI", new XAttribute("DbRef", msaId)); + XElement moFormElement = morphElem.Element("MoForm"); + int formId = 0; + string wordType = null; + if (moFormElement != null) + { + formId = Convert.ToInt32(moFormElement.Attribute("DbRef").Value); + wordType = moFormElement.Attribute("wordType").Value; + } + XElement propsElement = morphElem.Element("props"); + using (XmlWriter writer = msiElement.CreateWriter()) + { + ParserXmlGenerator.CreateMsaXmlElement(writer, msaId, formId, null, wordType, m_cache); + } + morphElem.Add(msiElement); + using (XmlWriter writer = msiElement.CreateWriter()) + { + ParserXmlGenerator.UpdateMorph(writer, m_cache, formId, msaId, wordType, propsElement != null ? propsElement.Value : null); + } + } elem.Add(morphElem); } diff --git a/Src/LexText/ParserEngine/ParserCore/ParserHelper.cs b/Src/LexText/ParserEngine/ParserCore/ParserHelper.cs index 3afa1d9bee..cc4204f1d4 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserHelper.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserHelper.cs @@ -67,9 +67,9 @@ public static bool TryCreateParseMorph(FdoCache cache, string formHvo, string ms } // Irregulary inflected forms can have a combination MSA hvo: the LexEntry hvo, a period, and an index to the LexEntryRef - string[] msaHvoParts = msaHvo.Split('.'); + Tuple msaTuple = ProcessMsaHvo(msaHvo); ICmObject objMsa; - if (!cache.ServiceLocator.GetInstance().TryGetObject(int.Parse(msaHvoParts[0]), out objMsa)) + if (!cache.ServiceLocator.GetInstance().TryGetObject(msaTuple.Item1, out objMsa)) { morph = null; return false; @@ -88,8 +88,7 @@ public static bool TryCreateParseMorph(FdoCache cache, string formHvo, string ms // get the MoStemMsa of its variant if (msaAsLexEntry.EntryRefsOS.Count > 0) { - int index = msaHvoParts.Length == 2 ? int.Parse(msaHvoParts[1]) : 0; - ILexEntryRef lexEntryRef = msaAsLexEntry.EntryRefsOS[index]; + ILexEntryRef lexEntryRef = msaAsLexEntry.EntryRefsOS[msaTuple.Item1]; ILexSense sense = MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); var inflType = (ILexEntryInflType)lexEntryRef.VariantEntryTypesRS[0]; morph = new ParseMorph(form, sense.MorphoSyntaxAnalysisRA, inflType); @@ -102,6 +101,12 @@ public static bool TryCreateParseMorph(FdoCache cache, string formHvo, string ms return true; } + public static Tuple ProcessMsaHvo(string msaHvo) + { + string[] msaHvoParts = msaHvo.Split('.'); + return Tuple.Create(int.Parse(msaHvoParts[0]), msaHvoParts.Length == 2 ? int.Parse(msaHvoParts[1]) : 0); + } + /// /// Convert any characters in the name which are higher than 0x00FF to hex. /// Neither XAmple nor PC-PATR can read a file name containing letters above 0x00FF. diff --git a/Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs b/Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs index a15dc3268c..503d6b5384 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs @@ -69,11 +69,11 @@ public static void CreateMsaXmlElement(XmlNode node, XmlDocument doc, XmlNode mo } } } - public static void CreateMsaXmlElement(XmlWriter writer, string sObjHvo, string sAlloId, string type, string wordType, FdoCache fdoCache) + public static void CreateMsaXmlElement(XmlWriter writer, string msaHvo, int allomorphHvo, string type, string wordType, FdoCache fdoCache) { // Irregulary inflected forms can have a combination MSA hvo: the LexEntry hvo, a period, and an index to the LexEntryRef - var indexOfPeriod = IndexOfPeriodInMsaHvo(ref sObjHvo); - ICmObject obj = fdoCache.ServiceLocator.GetInstance().GetObject(Convert.ToInt32(sObjHvo)); + Tuple msaTuple = ParserHelper.ProcessMsaHvo(msaHvo); + ICmObject obj = fdoCache.ServiceLocator.GetInstance().GetObject(msaTuple.Item1); switch (obj.GetType().Name) { default: @@ -84,7 +84,7 @@ public static void CreateMsaXmlElement(XmlWriter writer, string sObjHvo, string break; case "MoInflAffMsa": var inflMsa = obj as IMoInflAffMsa; - CreateInflectionClasses(writer, fdoCache, sAlloId); + CreateInflectionClasses(writer, fdoCache, allomorphHvo); CreateInflMsaXmlElement(writer, inflMsa, type); break; case "MoDerivAffMsa": @@ -102,8 +102,7 @@ public static void CreateMsaXmlElement(XmlWriter writer, string sObjHvo, string Debug.Assert(entry != null); if (entry.EntryRefsOS.Count > 0) { - var index = IndexOfLexEntryRef(sObjHvo, indexOfPeriod); - var lexEntryRef = entry.EntryRefsOS[index]; + var lexEntryRef = entry.EntryRefsOS[msaTuple.Item2]; var sense = MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); stemMsa = sense.MorphoSyntaxAnalysisRA as IMoStemMsa; CreateStemMsaXmlElement(writer, stemMsa); @@ -235,13 +234,12 @@ private static void CreateInflectionClasses(XmlDocument doc, XmlNode morphNode, } } - private static void CreateInflectionClasses(XmlWriter writer, FdoCache fdoCache, string alloId) + private static void CreateInflectionClasses(XmlWriter writer, FdoCache fdoCache, int allomorphHvo) { - if (alloId == null) + if (allomorphHvo <= 0) return; - int hvoAllomorph = Convert.ToInt32(alloId); // use IMoForm instead of IMoAffixForm or IMoAffixAllomorph because it could be an IMoStemAllomorph - IMoForm form = fdoCache.ServiceLocator.GetInstance().GetObject(hvoAllomorph); + IMoForm form = fdoCache.ServiceLocator.GetInstance().GetObject(allomorphHvo); if (form == null) return; if (!(form is IMoAffixForm)) @@ -351,7 +349,6 @@ private static void CreateInflMsaForLexEntryInflType(XmlDocument doc, XmlNode no private static void CreateInflMsaForLexEntryInflType(FdoCache cache, XmlWriter writer, string wordType, ILexEntryInflType lexEntryInflType) { IMoInflAffixSlot slot; - //var slotId = node.SelectSingleNode("MoForm/@wordType"); if (wordType != null) slot = cache.ServiceLocator.GetInstance().GetObject(Convert.ToInt32(wordType)); else @@ -610,17 +607,15 @@ public static void UpdateMorph(XmlWriter writer, FdoCache cache, int formHvo, st int iFirstSpace = shortName.IndexOf(" (", StringComparison.Ordinal); int iLastSpace = shortName.LastIndexOf("):", StringComparison.Ordinal) + 2; alloform = shortName.Substring(0, iFirstSpace); - int indexOfPeriod = IndexOfPeriodInMsaHvo(ref msaId); - int hvoMsa = Convert.ToInt32(msaId); - ICmObject msaObj = cache.ServiceLocator.GetObject(hvoMsa); + Tuple msaTuple = ParserHelper.ProcessMsaHvo(msaId); + ICmObject msaObj = cache.ServiceLocator.GetObject(msaTuple.Item1); if (msaObj.ClassID == LexEntryTags.kClassId) { var entry = msaObj as ILexEntry; Debug.Assert(entry != null); if (entry.EntryRefsOS.Count > 0) { - int index = IndexOfLexEntryRef(msaId, indexOfPeriod); // the value of the int after the period - ILexEntryRef lexEntryRef = entry.EntryRefsOS[index]; + ILexEntryRef lexEntryRef = entry.EntryRefsOS[msaTuple.Item2]; ITsIncStrBldr sbGlossPrepend; ITsIncStrBldr sbGlossAppend; ILexSense sense = MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); diff --git a/Src/LexText/ParserUI/HCTrace.cs b/Src/LexText/ParserUI/HCTrace.cs index 07bdfca736..052e8712b5 100644 --- a/Src/LexText/ParserUI/HCTrace.cs +++ b/Src/LexText/ParserUI/HCTrace.cs @@ -42,9 +42,6 @@ public override string CreateResultPage(string result) m_parseResult = new XmlDocument(); m_parseResult.LoadXml(result); - ConvertHvosToStrings(fIsTrace); - - AddMsaNodes(false); string sInput = CreateTempFile(m_sTrace, "xml"); m_parseResult.Save(sInput); @@ -54,11 +51,6 @@ public override string CreateResultPage(string result) return sOutput; } - private void ConvertHvosToStrings(bool fIsTrace) - { - ParserXmlGenerator.ConvertMorphs(m_parseResult, fIsTrace ? "//RuleAllomorph/Morph | //RootAllomorph/Morph | //Morphs/Morph" : "//Morphs/Morph", false, m_cache); - } - protected override void AddParserSpecificArguments(List args) { string sLoadErrorFile = Path.Combine(Path.GetTempPath(), m_sDataBaseName + "HCLoadErrors.xml"); diff --git a/Src/LexText/ParserUI/ParserTrace.cs b/Src/LexText/ParserUI/ParserTrace.cs index dc0b7ca613..fd7af2a157 100644 --- a/Src/LexText/ParserUI/ParserTrace.cs +++ b/Src/LexText/ParserUI/ParserTrace.cs @@ -97,37 +97,11 @@ protected string TransformToHtml(string sInputFile, TransformKind kind) private string CreateIconPath() { - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.Append("file:///"); sb.Append(TransformPath.Replace(@"\", "/")); sb.Append("/"); return sb.ToString(); } - - [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", - Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] - protected void AddMsaNodes(bool fIsTrace) - { - string sXPath; - string sAttrXPath; - if (fIsTrace) - { - sXPath = "//morph[@morphname]"; - sAttrXPath = "@morphname"; - } - else - { - sXPath = "//Morph/MSI"; - sAttrXPath = "@DbRef"; - } - XmlNodeList nl = m_parseResult.SelectNodes(sXPath); - if (nl != null) - { - foreach (XmlNode node in nl) - { - ParserXmlGenerator.CreateMsaXmlElement(node, m_parseResult, node, sAttrXPath, m_cache); - } - } - } } } diff --git a/Src/LexText/ParserUI/WordGrammarDebugger.cs b/Src/LexText/ParserUI/WordGrammarDebugger.cs index b4166c8f31..a107bd429e 100644 --- a/Src/LexText/ParserUI/WordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/WordGrammarDebugger.cs @@ -173,7 +173,7 @@ protected void CreateMorphXmlElement(XmlWriter writer, XmlNode node) } if (morphnameAttr != null) { - ParserXmlGenerator.CreateMsaXmlElement(writer, morphnameAttr.Value, alloIdAttr == null ? null : alloIdAttr.Value, + ParserXmlGenerator.CreateMsaXmlElement(writer, morphnameAttr.Value, alloIdAttr == null ? 0 : Convert.ToInt32(alloIdAttr.Value), typeAttr == null ? null : typeAttr.Value, wordTypeAttr == null ? null : wordTypeAttr.Value, m_cache); } } From 26bd0520f46c33356a1ebd3901614e59e1b417f8 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Thu, 13 Feb 2014 10:32:34 +0700 Subject: [PATCH 075/143] Refactor WordGrammarDebugger to use XDocument rather than XmlDocument Change-Id: I5aceaf4faa253579db4bd00dee496d08aa0618c3 --- Src/LexText/ParserUI/HCTrace.cs | 4 +- Src/LexText/ParserUI/HCWordGrammarDebugger.cs | 35 ++++++------ Src/LexText/ParserUI/ParserTraceBase.cs | 4 +- Src/LexText/ParserUI/ParserUI.csproj | 1 + Src/LexText/ParserUI/WordGrammarDebugger.cs | 56 +++++++++++-------- Src/LexText/ParserUI/XAmpleTrace.cs | 6 +- .../ParserUI/XAmpleWordGrammarDebugger.cs | 24 ++++---- 7 files changed, 72 insertions(+), 58 deletions(-) diff --git a/Src/LexText/ParserUI/HCTrace.cs b/Src/LexText/ParserUI/HCTrace.cs index 052e8712b5..071abccb66 100644 --- a/Src/LexText/ParserUI/HCTrace.cs +++ b/Src/LexText/ParserUI/HCTrace.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.IO; using System.Xml; +using System.Xml.Linq; using SIL.FieldWorks.WordWorks.Parser; using SIL.Utils; using XCore; @@ -40,8 +41,7 @@ public override string CreateResultPage(string result) { bool fIsTrace = result.Contains(""); - m_parseResult = new XmlDocument(); - m_parseResult.LoadXml(result); + m_parseResult = XDocument.Parse(result); string sInput = CreateTempFile(m_sTrace, "xml"); m_parseResult.Save(sInput); diff --git a/Src/LexText/ParserUI/HCWordGrammarDebugger.cs b/Src/LexText/ParserUI/HCWordGrammarDebugger.cs index dcfb54d798..3265c14b12 100644 --- a/Src/LexText/ParserUI/HCWordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/HCWordGrammarDebugger.cs @@ -1,12 +1,14 @@ using System.Diagnostics.CodeAnalysis; using System.Xml; +using System.Xml.Linq; +using System.Xml.XPath; using XCore; namespace SIL.FieldWorks.LexText.Controls { public class HCWordGrammarDebugger : WordGrammarDebugger { - public HCWordGrammarDebugger(Mediator mediator, XmlDocument parseResult) + public HCWordGrammarDebugger(Mediator mediator, XDocument parseResult) : base(mediator) { m_parseResult = parseResult; @@ -17,44 +19,43 @@ public HCWordGrammarDebugger(Mediator mediator, XmlDocument parseResult) protected override void CreateMorphNodes(XmlWriter writer, string nodeId) { string s = "//WordGrammarAttempt[Id=\"" + nodeId + "\"]"; - XmlNode node = m_parseResult.SelectSingleNode(s); - if (node != null) + XElement element = m_parseResult.XPathSelectElement(s); + if (element != null) { - XmlNodeList morphs = node.SelectNodes("Morphs"); - foreach (XmlNode morph in morphs) - CreateMorphXmlElement(writer, morph); + foreach (XElement morph in element.Elements("Morphs")) + CreateMorphXElement(writer, morph); } } - protected override void CreateMorphAffixAlloFeatsXmlElement(XmlWriter writer, XmlNode node) + protected override void CreateMorphAffixAlloFeatsXElement(XmlWriter writer, XElement element) { - XmlNode alloid = node.SelectSingleNode("@alloid"); + XElement alloid = element.XPathSelectElement("@alloid"); if (alloid != null) { - XmlNode affixAlloFeatsNode = m_parseResult.SelectSingleNode("//Morph[MoForm/@DbRef='" + alloid.InnerText + "']/affixAlloFeats"); + XElement affixAlloFeatsNode = m_parseResult.XPathSelectElement("//Morph[MoForm/@DbRef='" + alloid.Value + "']/affixAlloFeats"); if (affixAlloFeatsNode != null) { writer.WriteStartElement("affixAlloFeats"); - writer.WriteRaw(affixAlloFeatsNode.InnerXml); + writer.WriteRaw(InnerXml(affixAlloFeatsNode)); writer.WriteEndElement(); } } } - protected override void CreateMorphShortNameXmlElement(XmlWriter writer, XmlNode node) + protected override void CreateMorphShortNameXElement(XmlWriter writer, XElement element) { - XmlNode formNode = node.SelectSingleNode("shortName"); + XElement formNode = element.XPathSelectElement("shortName"); if (formNode != null) { - writer.WriteElementString("shortName", formNode.InnerText); + writer.WriteElementString("shortName", formNode.Value); } else { - XmlNode alloFormNode = node.SelectSingleNode("alloform"); - XmlNode glossNode = node.SelectSingleNode("gloss"); - XmlNode citationFormNode = node.SelectSingleNode("citationForm"); + XElement alloFormNode = element.XPathSelectElement("alloform"); + XElement glossNode = element.XPathSelectElement("gloss"); + XElement citationFormNode = element.XPathSelectElement("citationForm"); if (alloFormNode != null && glossNode != null && citationFormNode != null) - writer.WriteElementString("shortName", string.Format("{0} ({1}): {2}", alloFormNode.InnerText, glossNode.InnerText, citationFormNode.InnerText)); + writer.WriteElementString("shortName", string.Format("{0} ({1}): {2}", alloFormNode.Value, glossNode.Value, citationFormNode.Value)); } } } diff --git a/Src/LexText/ParserUI/ParserTraceBase.cs b/Src/LexText/ParserUI/ParserTraceBase.cs index 847fe5b33b..5f042751d8 100644 --- a/Src/LexText/ParserUI/ParserTraceBase.cs +++ b/Src/LexText/ParserUI/ParserTraceBase.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.IO; -using System.Xml; +using System.Xml.Linq; using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.Common.FwUtils; @@ -23,7 +23,7 @@ public abstract class ParserTraceBase /// /// The parse result xml document /// - protected XmlDocument m_parseResult; + protected XDocument m_parseResult; /// /// The real deal diff --git a/Src/LexText/ParserUI/ParserUI.csproj b/Src/LexText/ParserUI/ParserUI.csproj index 8ac6bd2f34..4a4023bd47 100644 --- a/Src/LexText/ParserUI/ParserUI.csproj +++ b/Src/LexText/ParserUI/ParserUI.csproj @@ -187,6 +187,7 @@ System.XML + Widgets ..\..\..\Output\Debug\Widgets.dll diff --git a/Src/LexText/ParserUI/WordGrammarDebugger.cs b/Src/LexText/ParserUI/WordGrammarDebugger.cs index a107bd429e..7dde107331 100644 --- a/Src/LexText/ParserUI/WordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/WordGrammarDebugger.cs @@ -3,6 +3,8 @@ using System.Globalization; using System.IO; using System.Xml; +using System.Xml.Linq; +using System.Xml.XPath; using SIL.FieldWorks.FDO; using SIL.FieldWorks.WordWorks.Parser; using SIL.Utils; @@ -97,8 +99,7 @@ private void CreateAnalysisXml(XmlWriter writer, string nodeId, string form) private void CreateSelectedWordGrammarXml(XmlWriter writer, string nodeId, string form) { - var lastDoc = new XmlDocument(); - lastDoc.Load(m_wordGrammarDebuggerXmlFile); + var lastDoc = XDocument.Load(m_wordGrammarDebuggerXmlFile); writer.WriteStartDocument(); @@ -107,55 +108,56 @@ private void CreateSelectedWordGrammarXml(XmlWriter writer, string nodeId, strin // Find the sNode'th seq node string sSelect = "//seq[position()='" + nodeId + "']"; - XmlNode selectedSeqNode = lastDoc.SelectSingleNode(sSelect); + XElement selectedSeqNode = lastDoc.XPathSelectElement(sSelect); + string innerXml = InnerXml(selectedSeqNode); // create the "result so far node" writer.WriteStartElement("resultsSoFar"); - writer.WriteRaw(selectedSeqNode.InnerXml); + writer.WriteRaw(innerXml); writer.WriteEndElement(); // create the seq node writer.WriteStartElement("seq"); - writer.WriteRaw(selectedSeqNode.InnerXml); + writer.WriteRaw(innerXml); writer.WriteEndElement(); } - protected void CreateMorphXmlElement(XmlWriter writer, XmlNode node) + protected void CreateMorphXElement(XmlWriter writer, XElement element) { writer.WriteStartElement("morph"); - XmlAttribute alloIdAttr = node.Attributes["alloid"]; + XAttribute alloIdAttr = element.Attribute("alloid"); if (alloIdAttr != null) writer.WriteAttributeString("alloid", alloIdAttr.Value); - XmlAttribute morphnameAttr = node.Attributes["morphname"]; + XAttribute morphnameAttr = element.Attribute("morphname"); if (morphnameAttr != null) writer.WriteAttributeString("morphname", morphnameAttr.Value); - XmlAttribute typeAttr = node.Attributes["type"]; + XAttribute typeAttr = element.Attribute("type"); if (typeAttr != null) writer.WriteAttributeString("type", typeAttr.Value); - XmlAttribute wordTypeAttr = node.Attributes["wordType"]; + XAttribute wordTypeAttr = element.Attribute("wordType"); if (wordTypeAttr != null) writer.WriteAttributeString("wordType", wordTypeAttr.Value); - CreateMorphShortNameXmlElement(writer, node); - XmlNode formNode = node.SelectSingleNode("alloform"); + CreateMorphShortNameXElement(writer, element); + XElement formNode = element.XPathSelectElement("alloform"); if (formNode != null) - writer.WriteElementString("alloform", formNode.InnerText); - XmlNode stemNameNode = node.SelectSingleNode("stemName"); + writer.WriteElementString("alloform", formNode.Value); + XElement stemNameNode = element.XPathSelectElement("stemName"); if (stemNameNode != null) { - XmlAttribute idAttr = stemNameNode.Attributes["id"]; + XAttribute idAttr = stemNameNode.Attribute("id"); if (idAttr != null) { writer.WriteStartElement("stemName"); writer.WriteAttributeString("id", idAttr.Value); - writer.WriteString(stemNameNode.InnerText); + writer.WriteString(stemNameNode.Value); writer.WriteEndElement(); } } - CreateMorphAffixAlloFeatsXmlElement(writer, node); - XmlNode glossNode = node.SelectSingleNode("gloss"); + CreateMorphAffixAlloFeatsXElement(writer, element); + XElement glossNode = element.XPathSelectElement("gloss"); if (glossNode != null) - writer.WriteElementString("gloss", glossNode.InnerText); - XmlNode citationFormNode = node.SelectSingleNode("citationForm"); + writer.WriteElementString("gloss", glossNode.Value); + XElement citationFormNode = element.XPathSelectElement("citationForm"); if (citationFormNode != null) - writer.WriteElementString("citationForm", citationFormNode.InnerText); + writer.WriteElementString("citationForm", citationFormNode.Value); if (alloIdAttr != null) { @@ -176,11 +178,12 @@ protected void CreateMorphXmlElement(XmlWriter writer, XmlNode node) ParserXmlGenerator.CreateMsaXmlElement(writer, morphnameAttr.Value, alloIdAttr == null ? 0 : Convert.ToInt32(alloIdAttr.Value), typeAttr == null ? null : typeAttr.Value, wordTypeAttr == null ? null : wordTypeAttr.Value, m_cache); } + writer.WriteEndElement(); } - protected abstract void CreateMorphShortNameXmlElement(XmlWriter writer, XmlNode node); + protected abstract void CreateMorphShortNameXElement(XmlWriter writer, XElement element); - protected abstract void CreateMorphAffixAlloFeatsXmlElement(XmlWriter writer, XmlNode node); + protected abstract void CreateMorphAffixAlloFeatsXElement(XmlWriter writer, XElement element); private void CreateInflectionClassesAndSubclassesXmlElement(XmlWriter writer, IEnumerable inflectionClasses) { @@ -227,5 +230,12 @@ private string TransformToXml(string sInputFile) XmlUtils.TransformFileToFile(sTransform, new XmlUtils.XSLParameter[0], sInputFile, sOutput); return sOutput; } + + public string InnerXml(XElement element) + { + XmlReader xmlReader = element.CreateReader(); + xmlReader.MoveToContent(); + return xmlReader.ReadInnerXml(); + } } } diff --git a/Src/LexText/ParserUI/XAmpleTrace.cs b/Src/LexText/ParserUI/XAmpleTrace.cs index 70238ede16..a4bd479532 100644 --- a/Src/LexText/ParserUI/XAmpleTrace.cs +++ b/Src/LexText/ParserUI/XAmpleTrace.cs @@ -14,6 +14,7 @@ // using System.Xml; +using System.Xml.Linq; using XCore; namespace SIL.FieldWorks.LexText.Controls @@ -56,12 +57,11 @@ public override string SetUpWordGrammarDebuggerPage(string nodeId, string form, /// URL of the resulting HTML page public override string CreateResultPage(string result) { - m_parseResult = new XmlDocument(); - m_parseResult.LoadXml(result); + m_parseResult = XDocument.Parse(result); string sInput = CreateTempFile(m_sTrace, "xml"); m_parseResult.Save(sInput); - TransformKind kind = (m_parseResult.DocumentElement.Name == "AmpleTrace" ? TransformKind.kcptTrace : TransformKind.kcptParse); + TransformKind kind = (m_parseResult.Root.Name == "AmpleTrace" ? TransformKind.kcptTrace : TransformKind.kcptParse); string sOutput = TransformToHtml(sInput, kind); return sOutput; } diff --git a/Src/LexText/ParserUI/XAmpleWordGrammarDebugger.cs b/Src/LexText/ParserUI/XAmpleWordGrammarDebugger.cs index dd47b096fc..091f1901e8 100644 --- a/Src/LexText/ParserUI/XAmpleWordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/XAmpleWordGrammarDebugger.cs @@ -1,11 +1,13 @@ using System.Xml; +using System.Xml.Linq; +using System.Xml.XPath; using XCore; namespace SIL.FieldWorks.LexText.Controls { public class XAmpleWordGrammarDebugger : WordGrammarDebugger { - public XAmpleWordGrammarDebugger(Mediator mediator, XmlDocument parseResult) + public XAmpleWordGrammarDebugger(Mediator mediator, XDocument parseResult) : base(mediator) { m_parseResult = parseResult; @@ -14,36 +16,36 @@ public XAmpleWordGrammarDebugger(Mediator mediator, XmlDocument parseResult) protected override void CreateMorphNodes(XmlWriter writer, string nodeId) { string s = "//failure[@id=\"" + nodeId + "\"]/ancestor::parseNode[morph][1]/morph"; - XmlNode node = m_parseResult.SelectSingleNode(s); + XElement node = m_parseResult.XPathSelectElement(s); if (node != null) CreateMorphNode(writer, node); } - private void CreateMorphNode(XmlWriter writer, XmlNode node) + private void CreateMorphNode(XmlWriter writer, XElement element) { // get the element closest up the chain to node - XmlNode morph = node.SelectSingleNode("../ancestor::parseNode[morph][1]/morph"); + XElement morph = element.XPathSelectElement("../ancestor::parseNode[morph][1]/morph"); if (morph != null) CreateMorphNode(writer, morph); - CreateMorphXmlElement(writer, node); + CreateMorphXElement(writer, element); } - protected override void CreateMorphAffixAlloFeatsXmlElement(XmlWriter writer, XmlNode node) + protected override void CreateMorphAffixAlloFeatsXElement(XmlWriter writer, XElement element) { - XmlNode affixAlloFeatsNode = node.SelectSingleNode("affixAlloFeats"); + XElement affixAlloFeatsNode = element.XPathSelectElement("affixAlloFeats"); if (affixAlloFeatsNode != null) { writer.WriteStartElement("affixAlloFeats"); - writer.WriteRaw(affixAlloFeatsNode.InnerXml); + writer.WriteRaw(InnerXml(affixAlloFeatsNode)); writer.WriteEndElement(); } } - protected override void CreateMorphShortNameXmlElement(XmlWriter writer, XmlNode node) + protected override void CreateMorphShortNameXElement(XmlWriter writer, XElement element) { - XmlNode formNode = node.SelectSingleNode("shortName"); + XElement formNode = element.XPathSelectElement("shortName"); if (formNode != null) - writer.WriteElementString("shortName", formNode.InnerText); + writer.WriteElementString("shortName", formNode.Value); } } } From 259082b6377a6ebf669b8a0aebcc429ff79c27d3 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Thu, 13 Feb 2014 11:41:08 +0700 Subject: [PATCH 076/143] updated XAmpleParser to generate XDocument Change-Id: I07bceeb1fc4d9613705b062e75ee71d49ea13a6e --- .../ParserEngine/ParserCore/HCParser.cs | 24 +- .../ParserEngine/ParserCore/ParserCore.csproj | 2 +- .../ParserCoreTests/ConvertFailuresTests.cs | 199 --- .../ParserCore/ParserCoreTests}/Failures.xml | 0 .../ParserCoreTests/ParserCoreTests.csproj | 3 +- .../ParserCoreTests/XAmpleParserTests.cs | 89 ++ .../ParserCore/ParserXmlGenerator.cs | 1131 ----------------- .../ParserCore/ParserXmlWriterExtensions.cs | 532 ++++++++ .../ParserEngine/ParserCore/XAmpleParser.cs | 195 ++- Src/LexText/ParserUI/WordGrammarDebugger.cs | 6 +- 10 files changed, 721 insertions(+), 1460 deletions(-) delete mode 100644 Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ConvertFailuresTests.cs rename Src/LexText/{ParserUI/ParserUITests => ParserEngine/ParserCore/ParserCoreTests}/Failures.xml (100%) create mode 100644 Src/LexText/ParserEngine/ParserCore/ParserCoreTests/XAmpleParserTests.cs delete mode 100644 Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs create mode 100644 Src/LexText/ParserEngine/ParserCore/ParserXmlWriterExtensions.cs diff --git a/Src/LexText/ParserEngine/ParserCore/HCParser.cs b/Src/LexText/ParserEngine/ParserCore/HCParser.cs index 2ef7f52508..14dddc46ff 100644 --- a/Src/LexText/ParserEngine/ParserCore/HCParser.cs +++ b/Src/LexText/ParserEngine/ParserCore/HCParser.cs @@ -139,7 +139,7 @@ public string ParseWordXml(string form) { CheckDisposed(); - return ParseToXML(form, false, null); + return ParseToXml(form, false, null); } #endregion @@ -147,7 +147,7 @@ public string TraceWordXml(string form, string[] selectTraceMorphs) { CheckDisposed(); - return ParseToXML(form, true, selectTraceMorphs); + return ParseToXml(form, true, selectTraceMorphs); } protected override void DisposeManagedResources() @@ -251,7 +251,7 @@ private string[] GetArrayFromString(string selectTraceMorphs) return selectTraceMorphIds; } - private string ParseToXML(string form, bool trace, string[] selectTraceMorphs) + private string ParseToXml(string form, bool trace, string[] selectTraceMorphs) { if (!m_loader.IsLoaded) return ParserCoreStrings.ksDidNotParse; @@ -402,7 +402,7 @@ private void WritePcPatrLexiconFile(string path, IEnumerable morphs if (!String.IsNullOrEmpty(morph.featureDescriptors)) { string lastFeatDesc = ""; - string combinedCFPFeatDescs = ""; + string combinedCfpFeatDescs = ""; string[] featDescs = morph.featureDescriptors.Split(' '); if (featDescs.Any()) writer.Write("\\f"); @@ -410,16 +410,16 @@ private void WritePcPatrLexiconFile(string path, IEnumerable morphs { if (featDesc.StartsWith("CFP")) { - combinedCFPFeatDescs += featDesc; + combinedCfpFeatDescs += featDesc; lastFeatDesc = featDesc; continue; } if (lastFeatDesc.StartsWith("CFP")) - writer.Write(" {0}", combinedCFPFeatDescs); + writer.Write(" {0}", combinedCfpFeatDescs); writer.Write(" {0}", featDesc); } if (lastFeatDesc.StartsWith("CFP")) - writer.Write(" {0}", combinedCFPFeatDescs); + writer.Write(" {0}", combinedCfpFeatDescs); } writer.WriteLine(); writer.WriteLine(); @@ -538,10 +538,10 @@ private void BuildXmlOutput(XmlWriter writer, IEnumerable morphs) writer.WriteStartElement("MSI"); writer.WriteAttributeString("DbRef", morph.msaId); - ParserXmlGenerator.CreateMsaXmlElement(writer, morph.msaId, Convert.ToInt32(morph.formId), null, morph.wordType, m_cache); + writer.WriteMsaElement(m_cache, morph.msaId, Convert.ToInt32(morph.formId), null, morph.wordType); writer.WriteEndElement(); - ParserXmlGenerator.UpdateMorph(writer, m_cache, Convert.ToInt32(morph.formId), morph.msaId, morph.wordType, null); + writer.WriteMorphInfoElements(m_cache, Convert.ToInt32(morph.formId), morph.msaId, morph.wordType, null); writer.WriteEndElement(); } @@ -783,7 +783,7 @@ private class FwXmlTraceManager : XmlTraceManager { private readonly FdoCache m_cache; - public FwXmlTraceManager(FdoCache fdoCache) : base() + public FwXmlTraceManager(FdoCache fdoCache) { m_cache = fdoCache; } @@ -843,12 +843,12 @@ protected override XElement Write(string name, Allomorph allomorph) XElement propsElement = morphElem.Element("props"); using (XmlWriter writer = msiElement.CreateWriter()) { - ParserXmlGenerator.CreateMsaXmlElement(writer, msaId, formId, null, wordType, m_cache); + writer.WriteMsaElement(m_cache, msaId, formId, null, wordType); } morphElem.Add(msiElement); using (XmlWriter writer = msiElement.CreateWriter()) { - ParserXmlGenerator.UpdateMorph(writer, m_cache, formId, msaId, wordType, propsElement != null ? propsElement.Value : null); + writer.WriteMorphInfoElements(m_cache, formId, msaId, wordType, propsElement != null ? propsElement.Value : null); } } elem.Add(morphElem); diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj b/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj index 1b7311c32f..4f44efdb33 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj +++ b/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj @@ -215,7 +215,7 @@ Code - + Code diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ConvertFailuresTests.cs b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ConvertFailuresTests.cs deleted file mode 100644 index 422fd00679..0000000000 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ConvertFailuresTests.cs +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (c) 2003-2013 SIL International -// This software is licensed under the LGPL, version 2.1 or later -// (http://www.gnu.org/licenses/lgpl-2.1.html) -// -// File: ConvertFailuresTests.cs -// Responsibility: - -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Xml; -using NUnit.Framework; -using SIL.FieldWorks.Common.FwUtils; -using SIL.FieldWorks.Test.TestUtils; - -namespace SIL.FieldWorks.WordWorks.Parser -{ - /// - /// Summary description for ConvertFailuresTests. - /// - [TestFixture] - public class ConvertFailuresTests : BaseTest - { - private static readonly string[] SaTesting = { "A", "AB", "ABC", "ABCD", "ABCDE", "ABCDEF" }; - - private XmlDocument m_doc; - private int m_testingCount; - - /// - /// Location of simple test FXT files - /// - protected string m_sTestPath; - - [TestFixtureSetUp] - public void FixtureInit() - { - m_sTestPath = Path.Combine(FwDirectoryFinder.SourceDirectory, - "LexText/ParserUI/ParserUITests"); - string sFailureDocPath = Path.Combine(m_sTestPath, "Failures.xml"); - m_doc = new XmlDocument(); - m_doc.Load(sFailureDocPath); - } - - - [TestFixtureTearDown] - public void FixtureCleanUp() - { - } - - private string GetRepresentation(int hvo) - { - if (m_testingCount > 5) - m_testingCount = 0; - return SaTesting[m_testingCount++]; - } - - [Test] - [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", - Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] - public void ConvertANCCFailureStrings() - { - XmlNodeList nl = m_doc.SelectNodes("//failure[contains(@test,'ANCC_FT')]"); - Assert.IsTrue(nl.Count == 2, "Two ANCC failures"); - m_testingCount = 0; - XAmpleParser.ConvertAdHocFailures(m_doc, "ANCC_FT", GetRepresentation); - int i = 1; - foreach (XmlNode node in nl) - { - XmlNode test = node.Attributes.GetNamedItem("test"); - string s = test.InnerText; - switch (i) - { - case 1: - Assert.AreEqual("ANCC_FT: A -/ _ ... AB", s); - break; - case 2: - Assert.AreEqual("ANCC_FT: ABC -/ ABCD ... _ ", s); - break; - } - i++; - } - } - - [Test] - [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", - Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] - public void ConvertMCCFailureStrings() - { - XmlNodeList nl = m_doc.SelectNodes("//failure[contains(@test,'MCC_FT')]"); - Assert.IsTrue(nl.Count == 2, "Two MCC failures"); - m_testingCount = 0; - XAmpleParser.ConvertAdHocFailures(m_doc, "MCC_FT", GetRepresentation); - int i = 1; - foreach (XmlNode node in nl) - { - XmlNode test = node.Attributes.GetNamedItem("test"); - string s = test.InnerText; - switch (i) - { - case 1: - Assert.AreEqual("MCC_FT: A +/ ~_ AB", s); - break; - case 2: - Assert.AreEqual("MCC_FT: ABC +/ ABCD ~_", s); - break; - } - i++; - } - } - - [Test] - [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", - Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] - public void ConvertSECFailureStrings() - { - XmlNodeList nl = m_doc.SelectNodes("//failure[contains(@test,'SEC_ST') and contains(@test,'[')]"); - Assert.IsTrue(nl.Count == 8, "Eight SEC failures with classes"); - m_testingCount = 0; - XAmpleParser.ConvertNaturalClasses(m_doc, "SEC_ST", GetRepresentation); - int i = 1; - foreach (XmlNode node in nl) - { - XmlNode test = node.Attributes.GetNamedItem("test"); - string s = test.InnerText; - switch (i) - { - case 1: - Assert.AreEqual("SEC_ST: dok __ ra / _ [A]", s); - break; - case 2: - Assert.AreEqual("SEC_ST: dok __ ra / _ [AB][ABC]", s); - break; - case 3: - Assert.AreEqual("SEC_ST: migel __ ximura / [ABCD] _", s); - break; - case 4: - Assert.AreEqual("SEC_ST: migel __ ximura / [ABCDE][ABCDEF] _", s); - break; - case 5: - Assert.AreEqual("SEC_ST: migel __ ximura / [A] _ [AB]", s); - break; - case 6: - Assert.AreEqual("SEC_ST: migel __ ximura / [ABC][ABCD] _ [ABCDE]", s); - break; - case 7: - Assert.AreEqual("SEC_ST: migel __ ximura / [ABCDEF] _ [A][AB]", s); - break; - case 8: - Assert.AreEqual("SEC_ST: migel __ ximura / [ABC][ABCD] _ [ABCDE][ABCDEF]", s); - break; - } - i++; - } - } - [Test] - [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", - Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] - public void ConvertInfixEnvironmentFailureStrings() - { - XmlNodeList nl = m_doc.SelectNodes("//failure[contains(@test,'InfixEnvironment') and contains(@test,'[')]"); - Assert.IsTrue(nl.Count == 8, "Eight Infix Environment failures with classes"); - m_testingCount = 0; - XAmpleParser.ConvertNaturalClasses(m_doc, "InfixEnvironment", GetRepresentation); - int i = 1; - foreach (XmlNode node in nl) - { - XmlNode test = node.Attributes.GetNamedItem("test"); - string s = test.InnerText; - switch (i) - { - case 1: - Assert.AreEqual("InfixEnvironment: dok __ ra / _ [A]", s); - break; - case 2: - Assert.AreEqual("InfixEnvironment: dok __ ra / _ [AB][ABC]", s); - break; - case 3: - Assert.AreEqual("InfixEnvironment: migel __ ximura / [ABCD] _", s); - break; - case 4: - Assert.AreEqual("InfixEnvironment: migel __ ximura / [ABCDE][ABCDEF] _", s); - break; - case 5: - Assert.AreEqual("InfixEnvironment: migel __ ximura / [A] _ [AB]", s); - break; - case 6: - Assert.AreEqual("InfixEnvironment: migel __ ximura / [ABC][ABCD] _ [ABCDE]", s); - break; - case 7: - Assert.AreEqual("InfixEnvironment: migel __ ximura / [ABCDEF] _ [A][AB]", s); - break; - case 8: - Assert.AreEqual("InfixEnvironment: migel __ ximura / [ABC][ABCD] _ [ABCDE][ABCDEF]", s); - break; - } - i++; - } - } - } -} diff --git a/Src/LexText/ParserUI/ParserUITests/Failures.xml b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/Failures.xml similarity index 100% rename from Src/LexText/ParserUI/ParserUITests/Failures.xml rename to Src/LexText/ParserEngine/ParserCore/ParserCoreTests/Failures.xml diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParserCoreTests.csproj b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParserCoreTests.csproj index 786b42c57d..d4e352219a 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParserCoreTests.csproj +++ b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParserCoreTests.csproj @@ -132,6 +132,7 @@ System.XML + False ..\..\..\..\..\Output\Debug\TestUtils.dll @@ -146,7 +147,7 @@ AssemblyInfoForTests.cs - + diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/XAmpleParserTests.cs b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/XAmpleParserTests.cs new file mode 100644 index 0000000000..f7181dfa0f --- /dev/null +++ b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/XAmpleParserTests.cs @@ -0,0 +1,89 @@ +// Copyright (c) 2003-2013 SIL International +// This software is licensed under the LGPL, version 2.1 or later +// (http://www.gnu.org/licenses/lgpl-2.1.html) +// +// File: XAmpleParserTests.cs +// Responsibility: + +using System.IO; +using System.Linq; +using System.Xml.Linq; +using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; +using SIL.FieldWorks.FDO; +using SIL.FieldWorks.Test.TestUtils; + +namespace SIL.FieldWorks.WordWorks.Parser +{ + /// + /// Summary description for XAmpleParserTests. + /// + [TestFixture] + public class XAmpleParserTests : BaseTest + { + [Test] + public void ConvertFailures() + { + string testPath = Path.Combine(FwDirectoryFinder.SourceDirectory, "LexText", "ParserEngine", "ParserCore", "ParserCoreTests", "Failures.xml"); + XDocument doc = XDocument.Load(testPath); + + XElement[] failures = doc.Descendants("failure").ToArray(); + XElement[] anccFailures = failures.Where(e => ((string) e.Attribute("test")).StartsWith("ANCC_FT")).ToArray(); + Assert.That(anccFailures.Length, Is.EqualTo(2), "Two ANCC failures"); + XElement[] mccFailures = failures.Where(e => ((string) e.Attribute("test")).StartsWith("MCC_FT")).ToArray(); + Assert.That(mccFailures.Length, Is.EqualTo(2), "Two MCC failures"); + XElement[] secFailures = failures.Where(e => ((string) e.Attribute("test")).StartsWith("SEC_ST") && ((string) e.Attribute("test")).Contains("[")).ToArray(); + Assert.That(secFailures.Length, Is.EqualTo(8), "Eight SEC failures with classes"); + XElement[] infixFailures = failures.Where(e => ((string) e.Attribute("test")).StartsWith("InfixEnvironment") && ((string) e.Attribute("test")).Contains("[")).ToArray(); + Assert.That(infixFailures.Length, Is.EqualTo(8), "Eight Infix Environment failures with classes"); + + XAmpleParser.ConvertFailures(doc, (classID, hvo) => + { + string className = null; + switch (classID) + { + case MoFormTags.kClassId: + className = "Form"; + break; + case MoMorphSynAnalysisTags.kClassId: + className = "MSA"; + break; + case PhNaturalClassTags.kClassId: + className = "NC"; + break; + } + return string.Format("{0}-{1}", className, hvo); + }); + + AssertTestEquals(anccFailures[0], "ANCC_FT: Form-6213 -/ _ ... Form-6279"); + AssertTestEquals(anccFailures[1], "ANCC_FT: Form-6213 -/ Form-6279 ... _ "); + + AssertTestEquals(mccFailures[0], "MCC_FT: MSA-6331 +/ ~_ MSA-6139"); + AssertTestEquals(mccFailures[1], "MCC_FT: MSA-6331 +/ MSA-6139 ~_"); + + AssertTestEquals(secFailures[0], "SEC_ST: dok __ ra / _ [NC-7405]"); + AssertTestEquals(secFailures[1], "SEC_ST: dok __ ra / _ [NC-7405][NC-7405]"); + AssertTestEquals(secFailures[2], "SEC_ST: migel __ ximura / [NC-7405] _"); + AssertTestEquals(secFailures[3], "SEC_ST: migel __ ximura / [NC-7405][NC-7405] _"); + AssertTestEquals(secFailures[4], "SEC_ST: migel __ ximura / [NC-7405] _ [NC-7405]"); + AssertTestEquals(secFailures[5], "SEC_ST: migel __ ximura / [NC-7405][NC-7405] _ [NC-7405]"); + AssertTestEquals(secFailures[6], "SEC_ST: migel __ ximura / [NC-7405] _ [NC-7405][NC-7405]"); + AssertTestEquals(secFailures[7], "SEC_ST: migel __ ximura / [NC-7405][NC-7405] _ [NC-7405][NC-7405]"); + + AssertTestEquals(infixFailures[0], "InfixEnvironment: dok __ ra / _ [NC-7405]"); + AssertTestEquals(infixFailures[1], "InfixEnvironment: dok __ ra / _ [NC-7405][NC-7405]"); + AssertTestEquals(infixFailures[2], "InfixEnvironment: migel __ ximura / [NC-7405] _"); + AssertTestEquals(infixFailures[3], "InfixEnvironment: migel __ ximura / [NC-7405][NC-7405] _"); + AssertTestEquals(infixFailures[4], "InfixEnvironment: migel __ ximura / [NC-7405] _ [NC-7405]"); + AssertTestEquals(infixFailures[5], "InfixEnvironment: migel __ ximura / [NC-7405][NC-7405] _ [NC-7405]"); + AssertTestEquals(infixFailures[6], "InfixEnvironment: migel __ ximura / [NC-7405] _ [NC-7405][NC-7405]"); + AssertTestEquals(infixFailures[7], "InfixEnvironment: migel __ ximura / [NC-7405][NC-7405] _ [NC-7405][NC-7405]"); + } + + private void AssertTestEquals(XElement elem, string expected) + { + var test = (string) elem.Attribute("test"); + Assert.That(test, Is.EqualTo(expected)); + } + } +} diff --git a/Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs b/Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs deleted file mode 100644 index 503d6b5384..0000000000 --- a/Src/LexText/ParserEngine/ParserCore/ParserXmlGenerator.cs +++ /dev/null @@ -1,1131 +0,0 @@ -using System; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Xml; -using SIL.CoreImpl; -using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.FDO; -using SIL.FieldWorks.FDO.DomainServices; -using SIL.Utils; - -namespace SIL.FieldWorks.WordWorks.Parser -{ - public static class ParserXmlGenerator - { - public static void CreateMsaXmlElement(XmlNode node, XmlDocument doc, XmlNode morphNode, string sHvo, FdoCache fdoCache) - { - // morphname contains the hvo of the msa - XmlNode attr = node.SelectSingleNode(sHvo); - if (attr != null) - { - string sObjHvo = attr.Value; - // Irregulary inflected forms can have a combination MSA hvo: the LexEntry hvo, a period, and an index to the LexEntryRef - var indexOfPeriod = IndexOfPeriodInMsaHvo(ref sObjHvo); - ICmObject obj = fdoCache.ServiceLocator.GetInstance().GetObject(Convert.ToInt32(sObjHvo)); - switch (obj.GetType().Name) - { - default: - throw new ApplicationException(String.Format("Invalid MSA type: {0}.", obj.GetType().Name)); - case "MoStemMsa": - var stemMsa = obj as IMoStemMsa; - CreateStemMsaXmlElement(doc, morphNode, stemMsa, fdoCache); - break; - case "MoInflAffMsa": - var inflMsa = obj as IMoInflAffMsa; - CreateInflectionClasses(doc, morphNode, fdoCache); - CreateInflMsaXmlElement(doc, morphNode, inflMsa, fdoCache); - break; - case "MoDerivAffMsa": - var derivMsa = obj as IMoDerivAffMsa; - CreateDerivMsaXmlElement(doc, morphNode, derivMsa); - break; - case "MoUnclassifiedAffixMsa": - var unclassMsa = obj as IMoUnclassifiedAffixMsa; - CreateUnclassifedMsaXmlElement(doc, morphNode, unclassMsa); - break; - case "LexEntry": - // is an irregularly inflected form - // get the MoStemMsa of its variant - var entry = obj as ILexEntry; - Debug.Assert(entry != null); - if (entry.EntryRefsOS.Count > 0) - { - var index = IndexOfLexEntryRef(attr.Value, indexOfPeriod); - var lexEntryRef = entry.EntryRefsOS[index]; - var sense = MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); - stemMsa = sense.MorphoSyntaxAnalysisRA as IMoStemMsa; - CreateStemMsaXmlElement(doc, morphNode, stemMsa, fdoCache); - } - break; - case "LexEntryInflType": - // This is one of the null allomorphs we create when building the - // input for the parser in order to still get the Word Grammar to have something in any - // required slots in affix templates. - CreateInflMsaForLexEntryInflType(doc, morphNode, obj as ILexEntryInflType, fdoCache); - break; - } - } - } - public static void CreateMsaXmlElement(XmlWriter writer, string msaHvo, int allomorphHvo, string type, string wordType, FdoCache fdoCache) - { - // Irregulary inflected forms can have a combination MSA hvo: the LexEntry hvo, a period, and an index to the LexEntryRef - Tuple msaTuple = ParserHelper.ProcessMsaHvo(msaHvo); - ICmObject obj = fdoCache.ServiceLocator.GetInstance().GetObject(msaTuple.Item1); - switch (obj.GetType().Name) - { - default: - throw new ApplicationException(String.Format("Invalid MSA type: {0}.", obj.GetType().Name)); - case "MoStemMsa": - var stemMsa = obj as IMoStemMsa; - CreateStemMsaXmlElement(writer, stemMsa); - break; - case "MoInflAffMsa": - var inflMsa = obj as IMoInflAffMsa; - CreateInflectionClasses(writer, fdoCache, allomorphHvo); - CreateInflMsaXmlElement(writer, inflMsa, type); - break; - case "MoDerivAffMsa": - var derivMsa = obj as IMoDerivAffMsa; - CreateDerivMsaXmlElement(writer, derivMsa); - break; - case "MoUnclassifiedAffixMsa": - var unclassMsa = obj as IMoUnclassifiedAffixMsa; - CreateUnclassifedMsaXmlElement(writer, unclassMsa); - break; - case "LexEntry": - // is an irregularly inflected form - // get the MoStemMsa of its variant - var entry = obj as ILexEntry; - Debug.Assert(entry != null); - if (entry.EntryRefsOS.Count > 0) - { - var lexEntryRef = entry.EntryRefsOS[msaTuple.Item2]; - var sense = MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); - stemMsa = sense.MorphoSyntaxAnalysisRA as IMoStemMsa; - CreateStemMsaXmlElement(writer, stemMsa); - } - break; - case "LexEntryInflType": - // This is one of the null allomorphs we create when building the - // input for the parser in order to still get the Word Grammar to have something in any - // required slots in affix templates. - CreateInflMsaForLexEntryInflType(fdoCache, writer, wordType, obj as ILexEntryInflType); - break; - } - } - - private static int IndexOfLexEntryRef(string sHvo, int indexOfPeriod) - { - int index = 0; - if (indexOfPeriod >= 0) - { - string sIndex = sHvo.Substring(indexOfPeriod + 1); - index = Convert.ToInt32(sIndex); - } - return index; - } - - private static int IndexOfPeriodInMsaHvo(ref string sObjHvo) - { - // Irregulary inflected forms can a combination MSA hvo: the LexEntry hvo, a period, and an index to the LexEntryRef - int indexOfPeriod = sObjHvo.IndexOf('.'); - if (indexOfPeriod >= 0) - { - sObjHvo = sObjHvo.Substring(0, indexOfPeriod); - } - return indexOfPeriod; - } - - /// - /// Determine if a PartOfSpeech requires inflection. - /// If it or any of its parent POSes have a template, it requires inflection. - /// If it is null we default to not requiring inflection. - /// - /// the Part of Speech - /// true if it does, false otherwise - private static bool RequiresInflection(IPartOfSpeech pos) - { - return pos != null && pos.RequiresInflection; - } - - private static void CreateStemMsaXmlElement(XmlDocument doc, XmlNode morphNode, IMoStemMsa stemMsa, FdoCache fdoCache) - { - XmlNode stemMsaNode = CreateXmlElement(doc, "stemMsa", morphNode); - CreatePOSXmlAttribute(doc, stemMsaNode, stemMsa.PartOfSpeechRA, "cat"); - IMoInflClass inflClass = stemMsa.InflectionClassRA; - if (inflClass == null) - { // use default inflection class of the POS or - // the first ancestor POS that has a non-zero default inflection class - int inflClassHvo = 0; - IPartOfSpeech pos = stemMsa.PartOfSpeechRA; - while (pos != null && inflClassHvo == 0) - { - if (pos.DefaultInflectionClassRA != null) - inflClassHvo = pos.DefaultInflectionClassRA.Hvo; - else - { - int clsid = fdoCache.ServiceLocator.GetInstance().GetObject(pos.Owner.Hvo).ClassID; - pos = clsid == PartOfSpeechTags.kClassId ? fdoCache.ServiceLocator.GetInstance().GetObject(pos.Owner.Hvo) : null; - } - } - if (inflClassHvo != 0) - inflClass = fdoCache.ServiceLocator.GetInstance().GetObject(inflClassHvo); - } - CreateInflectionClassXmlAttribute(doc, stemMsaNode, inflClass, "inflClass"); - CreateRequiresInflectionXmlAttribute(doc, - stemMsa.PartOfSpeechRA, - stemMsaNode); - CreateFeatureStructureNodes(doc, stemMsaNode, stemMsa.MsFeaturesOA, stemMsa.Hvo); - CreateProductivityRestrictionNodes(doc, stemMsaNode, stemMsa.ProdRestrictRC, "productivityRestriction"); - CreateFromPOSNodes(doc, stemMsaNode, stemMsa.FromPartsOfSpeechRC, "fromPartsOfSpeech"); - } - - private static void CreateStemMsaXmlElement(XmlWriter writer, IMoStemMsa stemMsa) - { - writer.WriteStartElement("stemMsa"); - CreatePOSXmlAttribute(writer, stemMsa.PartOfSpeechRA, "cat"); - IMoInflClass inflClass = stemMsa.InflectionClassRA; - if (inflClass == null) - { // use default inflection class of the POS or - // the first ancestor POS that has a non-zero default inflection class - int inflClassHvo = 0; - IPartOfSpeech pos = stemMsa.PartOfSpeechRA; - while (pos != null && inflClassHvo == 0) - { - if (pos.DefaultInflectionClassRA != null) - inflClassHvo = pos.DefaultInflectionClassRA.Hvo; - else - { - int clsid = stemMsa.Services.GetInstance().GetObject(pos.Owner.Hvo).ClassID; - pos = clsid == PartOfSpeechTags.kClassId ? stemMsa.Services.GetInstance().GetObject(pos.Owner.Hvo) : null; - } - } - if (inflClassHvo != 0) - inflClass = stemMsa.Services.GetInstance().GetObject(inflClassHvo); - } - CreateInflectionClassXmlAttribute(writer, inflClass, "inflClass"); - CreateRequiresInflectionXmlAttribute(writer, stemMsa.PartOfSpeechRA); - CreateFeatureStructureNodes(writer, stemMsa.MsFeaturesOA, stemMsa.Hvo); - CreateProductivityRestrictionNodes(writer, stemMsa.ProdRestrictRC, "productivityRestriction"); - CreateFromPOSNodes(writer, stemMsa.FromPartsOfSpeechRC, "fromPartsOfSpeech"); - writer.WriteEndElement(); //stemMsa - } - - private static void CreateInflectionClasses(XmlDocument doc, XmlNode morphNode, FdoCache fdoCache) - { - string sAlloId = XmlUtils.GetOptionalAttributeValue(morphNode, "alloid"); - if (sAlloId == null) - return; - int hvoAllomorph = Convert.ToInt32(sAlloId); - // use IMoForm instead of IMoAffixForm or IMoAffixAllomorph because it could be an IMoStemAllomorph - IMoForm form = fdoCache.ServiceLocator.GetInstance().GetObject(hvoAllomorph); - if (form == null) - return; - if (!(form is IMoAffixForm)) - return; - foreach (IMoInflClass ic in ((IMoAffixForm)form).InflectionClassesRC) - { - XmlNode icNode = CreateXmlElement(doc, "inflectionClass", morphNode); - CreateXmlAttribute(doc, "id", ic.Hvo.ToString(CultureInfo.InvariantCulture), icNode); - CreateXmlAttribute(doc, "abbr", ic.Abbreviation.BestAnalysisAlternative.Text, icNode); - } - } - - private static void CreateInflectionClasses(XmlWriter writer, FdoCache fdoCache, int allomorphHvo) - { - if (allomorphHvo <= 0) - return; - // use IMoForm instead of IMoAffixForm or IMoAffixAllomorph because it could be an IMoStemAllomorph - IMoForm form = fdoCache.ServiceLocator.GetInstance().GetObject(allomorphHvo); - if (form == null) - return; - if (!(form is IMoAffixForm)) - return; - foreach (IMoInflClass ic in ((IMoAffixForm)form).InflectionClassesRC) - { - writer.WriteStartElement("inflectionClass"); - writer.WriteAttributeString("id", ic.Hvo.ToString(CultureInfo.InvariantCulture)); - writer.WriteAttributeString("abbr", ic.Abbreviation.BestAnalysisAlternative.Text); - writer.WriteEndElement(); //inflectionClass - } - } - - private static void CreateInflMsaXmlElement(XmlDocument doc, XmlNode morphNode, IMoInflAffMsa inflMsa, FdoCache fdoCache) - { - XmlNode inflMsaNode = CreateXmlElement(doc, "inflMsa", morphNode); - CreatePOSXmlAttribute(doc, inflMsaNode, inflMsa.PartOfSpeechRA, "cat"); - // handle any slot - HandleSlotInfoForInflectionalMsa(inflMsa, doc, inflMsaNode, morphNode, fdoCache); - CreateFeatureStructureNodes(doc, inflMsaNode, inflMsa.InflFeatsOA, inflMsa.Hvo); - CreateProductivityRestrictionNodes(doc, inflMsaNode, inflMsa.FromProdRestrictRC, "fromProductivityRestriction"); - } - - private static void CreateInflMsaXmlElement(XmlWriter writer, IMoInflAffMsa inflMsa, string type) - { - writer.WriteStartElement("inflMsa"); - CreatePOSXmlAttribute(writer, inflMsa.PartOfSpeechRA, "cat"); - // handle any slot - HandleSlotInfoForInflectionalMsa(writer, inflMsa, type); - CreateFeatureStructureNodes(writer, inflMsa.InflFeatsOA, inflMsa.Hvo); - CreateProductivityRestrictionNodes(writer, inflMsa.FromProdRestrictRC, "fromProductivityRestriction"); - writer.WriteEndElement(); //inflMsa - } - - private static void CreateDerivMsaXmlElement(XmlDocument doc, XmlNode morphNode, IMoDerivAffMsa derivMsa) - { - XmlNode derivMsaNode = CreateXmlElement(doc, "derivMsa", morphNode); - CreatePOSXmlAttribute(doc, derivMsaNode, derivMsa.FromPartOfSpeechRA, "fromCat"); - CreatePOSXmlAttribute(doc, derivMsaNode, derivMsa.ToPartOfSpeechRA, "toCat"); - CreateInflectionClassXmlAttribute(doc, derivMsaNode, derivMsa.FromInflectionClassRA, "fromInflClass"); - CreateInflectionClassXmlAttribute(doc, derivMsaNode, derivMsa.ToInflectionClassRA, "toInflClass"); - CreateRequiresInflectionXmlAttribute(doc, derivMsa.ToPartOfSpeechRA, derivMsaNode); - CreateFeatureStructureNodes(doc, derivMsaNode, derivMsa.FromMsFeaturesOA, derivMsa.Hvo, "fromFS"); - CreateFeatureStructureNodes(doc, derivMsaNode, derivMsa.ToMsFeaturesOA, derivMsa.Hvo, "toFS"); - CreateProductivityRestrictionNodes(doc, derivMsaNode, derivMsa.FromProdRestrictRC, "fromProductivityRestriction"); - CreateProductivityRestrictionNodes(doc, derivMsaNode, derivMsa.ToProdRestrictRC, "toProductivityRestriction"); - } - - private static void CreateDerivMsaXmlElement(XmlWriter writer, IMoDerivAffMsa derivMsa) - { - writer.WriteStartElement("derivMsa"); - CreatePOSXmlAttribute(writer, derivMsa.FromPartOfSpeechRA, "fromCat"); - CreatePOSXmlAttribute(writer, derivMsa.ToPartOfSpeechRA, "toCat"); - CreateInflectionClassXmlAttribute(writer, derivMsa.FromInflectionClassRA, "fromInflClass"); - CreateInflectionClassXmlAttribute(writer, derivMsa.ToInflectionClassRA, "toInflClass"); - CreateRequiresInflectionXmlAttribute(writer, derivMsa.ToPartOfSpeechRA); - CreateFeatureStructureNodes(writer, derivMsa.FromMsFeaturesOA, derivMsa.Hvo, "fromFS"); - CreateFeatureStructureNodes(writer, derivMsa.ToMsFeaturesOA, derivMsa.Hvo, "toFS"); - CreateProductivityRestrictionNodes(writer, derivMsa.FromProdRestrictRC, "fromProductivityRestriction"); - CreateProductivityRestrictionNodes(writer, derivMsa.ToProdRestrictRC, "toProductivityRestriction"); - writer.WriteEndElement(); //derivMsa - } - - private static void CreateUnclassifedMsaXmlElement(XmlDocument doc, XmlNode morphNode, IMoUnclassifiedAffixMsa unclassMsa) - { - XmlNode unclassMsaNode = CreateXmlElement(doc, "unclassMsa", morphNode); - CreatePOSXmlAttribute(doc, unclassMsaNode, unclassMsa.PartOfSpeechRA, "fromCat"); - } - - private static void CreateUnclassifedMsaXmlElement(XmlWriter writer, IMoUnclassifiedAffixMsa unclassMsa) - { - writer.WriteStartElement("unclassMsa"); - CreatePOSXmlAttribute(writer, unclassMsa.PartOfSpeechRA, "fromCat"); - writer.WriteEndElement(); //unclassMsa - } - - private static void CreateInflMsaForLexEntryInflType(XmlDocument doc, XmlNode node, ILexEntryInflType lexEntryInflType, FdoCache fdoCache) - { - /*var slots = lexEntryInflType.SlotsRC; - IMoInflAffixSlot firstSlot = null; - foreach (var slot in slots) - { - if (firstSlot == null) - firstSlot = slot; - }*/ - IMoInflAffixSlot slot; - var slotId = node.SelectSingleNode("MoForm/@wordType"); - if (slotId != null) - slot = fdoCache.ServiceLocator.GetInstance().GetObject(Convert.ToInt32(slotId.InnerText)); - else - { - var slots = lexEntryInflType.SlotsRC; - IMoInflAffixSlot firstSlot = slots.FirstOrDefault(); - slot = firstSlot; - } - if (slot != null) - { - XmlNode nullInflMsaNode = CreateXmlElement(doc, "inflMsa", node); - CreatePOSXmlAttribute(doc, nullInflMsaNode, slot.Owner as IPartOfSpeech, "cat"); - CreateXmlAttribute(doc, "slot", slot.Hvo.ToString(CultureInfo.InvariantCulture), nullInflMsaNode); - CreateXmlAttribute(doc, "slotAbbr", slot.Name.BestAnalysisAlternative.Text, nullInflMsaNode); - CreateXmlAttribute(doc, "slotOptional", "false", nullInflMsaNode); - CreateFeatureStructureNodes(doc, nullInflMsaNode, lexEntryInflType.InflFeatsOA, lexEntryInflType.Hvo); - } - } - - private static void CreateInflMsaForLexEntryInflType(FdoCache cache, XmlWriter writer, string wordType, ILexEntryInflType lexEntryInflType) - { - IMoInflAffixSlot slot; - if (wordType != null) - slot = cache.ServiceLocator.GetInstance().GetObject(Convert.ToInt32(wordType)); - else - { - var slots = lexEntryInflType.SlotsRC; - IMoInflAffixSlot firstSlot = slots.FirstOrDefault(); - slot = firstSlot; - } - if (slot != null) - { - writer.WriteStartElement("inflMsa"); - CreatePOSXmlAttribute(writer, slot.Owner as IPartOfSpeech, "cat"); - writer.WriteAttributeString("slot", slot.Hvo.ToString(CultureInfo.InvariantCulture)); - writer.WriteAttributeString("slotAbbr", slot.Name.BestAnalysisAlternative.Text); - writer.WriteAttributeString("slotOptional", "false"); - CreateFeatureStructureNodes(writer, lexEntryInflType.InflFeatsOA, lexEntryInflType.Hvo); - writer.WriteEndElement(); //inflMsa - } - } - - private static void CreateInflectionClassXmlAttribute(XmlDocument doc, XmlNode msaNode, IMoInflClass inflClass, string sInflClass) - { - if (inflClass != null) - { - CreateXmlAttribute(doc, sInflClass, inflClass.Hvo.ToString(CultureInfo.InvariantCulture), msaNode); - string sInflClassAbbr = inflClass.Hvo > 0 ? inflClass.Abbreviation.BestAnalysisAlternative.Text : ""; - CreateXmlAttribute(doc, sInflClass + "Abbr", sInflClassAbbr, msaNode); - } - else - CreateXmlAttribute(doc, sInflClass, "0", msaNode); - } - - private static void CreateInflectionClassXmlAttribute(XmlWriter writer, IMoInflClass inflClass, string sInflClass) - { - if (inflClass != null) - { - writer.WriteAttributeString(sInflClass, inflClass.Hvo.ToString(CultureInfo.InvariantCulture)); - writer.WriteAttributeString(sInflClass + "Abbr", inflClass.Hvo > 0 ? inflClass.Abbreviation.BestAnalysisAlternative.Text : ""); - } - else - writer.WriteAttributeString(sInflClass, "0"); - } - - private static void CreateRequiresInflectionXmlAttribute(XmlDocument doc, IPartOfSpeech pos, XmlNode msaNode) - { - string sPlusMinus = RequiresInflection(pos) ? "+" : "-"; - CreateXmlAttribute(doc, "requiresInfl", sPlusMinus, msaNode); - } - - private static void CreateRequiresInflectionXmlAttribute(XmlWriter writer, IPartOfSpeech pos) - { - writer.WriteAttributeString("requiresInfl", RequiresInflection(pos) ? "+" : "-"); - } - - private static void CreateFeatureStructureNodes(XmlDocument doc, XmlNode msaNode, IFsFeatStruc fs, int id, string sFsName = "fs") - { - if (fs == null) - return; - XmlNode fsNode = CreateXmlElement(doc, sFsName, msaNode); - CreateXmlAttribute(doc, "id", id.ToString(CultureInfo.InvariantCulture), fsNode); - foreach (IFsFeatureSpecification spec in fs.FeatureSpecsOC) - { - XmlNode feature = CreateXmlElement(doc, "feature", fsNode); - XmlNode name = CreateXmlElement(doc, "name", feature); - name.InnerText = spec.FeatureRA.Abbreviation.BestAnalysisAlternative.Text; - XmlNode fvalue = CreateXmlElement(doc, "value", feature); - var cv = spec as IFsClosedValue; - if (cv != null) - fvalue.InnerText = cv.ValueRA.Abbreviation.BestAnalysisAlternative.Text; - else - { - var complex = spec as IFsComplexValue; - if (complex == null) - continue; // skip this one since we're not dealing with it yet - var nestedFs = complex.ValueOA as IFsFeatStruc; - if (nestedFs != null) - CreateFeatureStructureNodes(doc, fvalue, nestedFs, 0); - } - } - } - - private static void CreateFeatureStructureNodes(XmlWriter writer, IFsFeatStruc fs, int id, string sFsName = "fs") - { - if (fs == null) - return; - writer.WriteStartElement(sFsName); - writer.WriteAttributeString("id", id.ToString(CultureInfo.InvariantCulture)); - foreach (IFsFeatureSpecification spec in fs.FeatureSpecsOC) - { - writer.WriteStartElement("feature"); - writer.WriteElementString("name", spec.FeatureRA.Abbreviation.BestAnalysisAlternative.Text); - writer.WriteStartElement("value"); - var cv = spec as IFsClosedValue; - if (cv != null) - writer.WriteString(cv.ValueRA.Abbreviation.BestAnalysisAlternative.Text); - else - { - var complex = spec as IFsComplexValue; - if (complex == null) - continue; // skip this one since we're not dealing with it yet - var nestedFs = complex.ValueOA as IFsFeatStruc; - if (nestedFs != null) - CreateFeatureStructureNodes(writer, nestedFs, 0); - } - writer.WriteEndElement(); //value - writer.WriteEndElement(); //feature - } - writer.WriteEndElement(); //sFsName - } - - private static void CreateProductivityRestrictionNodes(XmlDocument doc, XmlNode msaNode, IFdoReferenceCollection prodRests, string sElementName) - { - if (prodRests == null || prodRests.Count < 1) - return; - foreach (ICmPossibility pr in prodRests) - { - XmlNode prNode = CreateXmlElement(doc, sElementName, msaNode); - CreateXmlAttribute(doc, "id", pr.Hvo.ToString(CultureInfo.InvariantCulture), prNode); - XmlNode prName = CreateXmlElement(doc, "name", prNode); - prName.InnerText = pr.Name.BestAnalysisAlternative.Text; - } - } - - private static void CreateProductivityRestrictionNodes(XmlWriter writer, IFdoReferenceCollection prodRests, string sElementName) - { - if (prodRests == null || prodRests.Count < 1) - return; - foreach (ICmPossibility pr in prodRests) - { - writer.WriteStartElement(sElementName); - writer.WriteAttributeString("id", pr.Hvo.ToString(CultureInfo.InvariantCulture)); - writer.WriteElementString("name", pr.Name.BestAnalysisAlternative.Text); - writer.WriteEndElement(); //sElementName - } - } - - private static void CreateFromPOSNodes(XmlDocument doc, XmlNode msaNode, IFdoReferenceCollection fromPoSes, string sElementName) - { - if (fromPoSes == null || fromPoSes.Count < 1) - return; - foreach (IPartOfSpeech pos in fromPoSes) - { - XmlNode posNode = CreateXmlElement(doc, sElementName, msaNode); - CreateXmlAttribute(doc, "fromCat", pos.Hvo.ToString(CultureInfo.InvariantCulture), posNode); - CreateXmlAttribute(doc, "fromCatAbbr", pos.Abbreviation.BestAnalysisAlternative.Text, posNode); - } - } - - private static void CreateFromPOSNodes(XmlWriter writer, IFdoReferenceCollection fromPoSes, string sElementName) - { - if (fromPoSes == null || fromPoSes.Count < 1) - return; - foreach (IPartOfSpeech pos in fromPoSes) - { - writer.WriteStartElement(sElementName); - writer.WriteAttributeString("fromCat", pos.Hvo.ToString(CultureInfo.InvariantCulture)); - writer.WriteAttributeString("fromCatAbbr", pos.Abbreviation.BestAnalysisAlternative.Text); - writer.WriteEndElement(); //sElementName - } - } - - private static void HandleSlotInfoForInflectionalMsa(IMoInflAffMsa inflMsa, XmlDocument doc, XmlNode inflMsaNode, XmlNode morphNode, FdoCache fdoCache) - { - int slotHvo = 0; - int iCount = inflMsa.SlotsRC.Count; - if (iCount > 0) - { - if (iCount > 1) - { // have a circumfix; assume only two slots and assume that the first is prefix and second is suffix - // TODO: ideally would figure out if the slots are prefix or suffix slots and then align the - // o and 1 indices to the appropriate slot. Will just do this for now (hab 2005.08.04). - XmlNode attrType = morphNode.SelectSingleNode("@type"); - if (attrType != null && attrType.InnerText != "sfx") - slotHvo = inflMsa.SlotsRC.ToHvoArray()[0]; - else - slotHvo = inflMsa.SlotsRC.ToHvoArray()[1]; - } - else - slotHvo = inflMsa.SlotsRC.ToHvoArray()[0]; - } - CreateXmlAttribute(doc, "slot", slotHvo.ToString(CultureInfo.InvariantCulture), inflMsaNode); - string sSlotOptional = "false"; - string sSlotAbbr = "??"; - if (slotHvo > 0) - { - var slot = fdoCache.ServiceLocator.GetInstance().GetObject(slotHvo); - if (slot != null) - { - sSlotAbbr = slot.Name.BestAnalysisAlternative.Text; - if (slot.Optional) - sSlotOptional = "true"; - } - } - CreateXmlAttribute(doc, "slotAbbr", sSlotAbbr, inflMsaNode); - CreateXmlAttribute(doc, "slotOptional", sSlotOptional, inflMsaNode); - } - - private static void HandleSlotInfoForInflectionalMsa(XmlWriter writer, IMoInflAffMsa inflMsa, string type) - { - int slotHvo = 0; - int iCount = inflMsa.SlotsRC.Count; - if (iCount > 0) - { - if (iCount > 1) - { // have a circumfix; assume only two slots and assume that the first is prefix and second is suffix - // TODO: ideally would figure out if the slots are prefix or suffix slots and then align the - // o and 1 indices to the appropriate slot. Will just do this for now (hab 2005.08.04). - if (type != null && type != "sfx") - slotHvo = inflMsa.SlotsRC.ToHvoArray()[0]; - else - slotHvo = inflMsa.SlotsRC.ToHvoArray()[1]; - } - else - slotHvo = inflMsa.SlotsRC.ToHvoArray()[0]; - } - writer.WriteAttributeString("slot", slotHvo.ToString(CultureInfo.InvariantCulture)); - string sSlotOptional = "false"; - string sSlotAbbr = "??"; - if (Convert.ToInt32(slotHvo) > 0) - { - var slot = inflMsa.Services.GetInstance().GetObject(Convert.ToInt32(slotHvo)); - if (slot != null) - { - sSlotAbbr = slot.Name.BestAnalysisAlternative.Text; - if (slot.Optional) - sSlotOptional = "true"; - } - } - writer.WriteAttributeString("slotAbbr", sSlotAbbr); - writer.WriteAttributeString("slotOptional", sSlotOptional); - } - - public static void UpdateMorph(XmlWriter writer, FdoCache cache, int formHvo, string msaId, string wordType, string props) - { - ICmObject obj = cache.ServiceLocator.GetInstance().GetObject(formHvo); - var form = obj as IMoForm; - if (form == null) - { - // This is one of the null allomorphs we create when building the - // input for the parser in order to still get the Word Grammar to have something in any - // required slots in affix templates. - var lexEntryInflType = obj as ILexEntryInflType; - if (lexEntryInflType != null) - { - CreateLexEntryInflTypeElement(cache, writer, wordType, lexEntryInflType); - return; - } - } - string shortName; - string alloform; - string gloss; - string citationForm; - if (form != null) - { - shortName = form.LongName; - int iFirstSpace = shortName.IndexOf(" (", StringComparison.Ordinal); - int iLastSpace = shortName.LastIndexOf("):", StringComparison.Ordinal) + 2; - alloform = shortName.Substring(0, iFirstSpace); - Tuple msaTuple = ParserHelper.ProcessMsaHvo(msaId); - ICmObject msaObj = cache.ServiceLocator.GetObject(msaTuple.Item1); - if (msaObj.ClassID == LexEntryTags.kClassId) - { - var entry = msaObj as ILexEntry; - Debug.Assert(entry != null); - if (entry.EntryRefsOS.Count > 0) - { - ILexEntryRef lexEntryRef = entry.EntryRefsOS[msaTuple.Item2]; - ITsIncStrBldr sbGlossPrepend; - ITsIncStrBldr sbGlossAppend; - ILexSense sense = MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); - IWritingSystem glossWs = cache.ServiceLocator.WritingSystemManager.Get(cache.DefaultAnalWs); - MorphServices.JoinGlossAffixesOfInflVariantTypes(lexEntryRef.VariantEntryTypesRS, - glossWs, out sbGlossPrepend, out sbGlossAppend); - ITsIncStrBldr sbGloss = sbGlossPrepend; - sbGloss.Append(sense.Gloss.BestAnalysisAlternative.Text); - sbGloss.Append(sbGlossAppend.Text); - gloss = sbGloss.Text; - } - else - { - gloss = ParserCoreStrings.ksUnknownGloss; - } - - } - else - { - var msa = msaObj as IMoMorphSynAnalysis; - gloss = msa != null ? msa.GetGlossOfFirstSense() : shortName.Substring(iFirstSpace, iLastSpace - iFirstSpace).Trim(); - } - citationForm = shortName.Substring(iLastSpace).Trim(); - shortName = String.Format(ParserCoreStrings.ksX_Y_Z, alloform, gloss, citationForm); - } - else - { - alloform = ParserCoreStrings.ksUnknownMorpheme; // in case the user continues... - gloss = ParserCoreStrings.ksUnknownGloss; - citationForm = ParserCoreStrings.ksUnknownCitationForm; - shortName = String.Format(ParserCoreStrings.ksX_Y_Z, alloform, gloss, citationForm); - throw new ApplicationException(shortName); - } - writer.WriteElementString("shortName", shortName); - writer.WriteElementString("alloform", alloform); - switch (form.ClassID) - { - case MoStemAllomorphTags.kClassId: - CreateStemNameElement(writer, form, props); - break; - case MoAffixAllomorphTags.kClassId: - CreateAffixAlloFeatsElement(writer, form, props); - CreateStemNameAffixElement(writer, cache, props); - break; - - } - writer.WriteElementString("gloss", gloss); - writer.WriteElementString("citationForm", citationForm); - } - - [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", - Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] - public static void ConvertMorphs(XmlDocument doc, string sNodeListToFind, bool fIdsInAttribute, FdoCache fdoCache) - { - XmlNodeList nl = doc.SelectNodes(sNodeListToFind); - if (nl != null) - { - foreach (XmlNode node in nl) - { - Debug.Assert(node.Attributes != null); - XmlNode alloid = fIdsInAttribute ? node.Attributes.GetNamedItem("alloid") : node.SelectSingleNode("MoForm/@DbRef"); - Debug.Assert(alloid != null); - int hvo = Convert.ToInt32(alloid.InnerText); - var obj = fdoCache.ServiceLocator.GetInstance().GetObject(hvo); - var form = obj as IMoForm; - if (form == null) - { - // This is one of the null allomorphs we create when building the - // input for the parser in order to still get the Word Grammar to have something in any - // required slots in affix templates. - var lexEntryInflType = obj as ILexEntryInflType; - if (lexEntryInflType != null) - { - ConvertLexEntryInflType(doc, node, lexEntryInflType, fdoCache); - continue; - } - } - string sLongName; - string sForm; - string sGloss; - string sCitationForm; - if (form != null) - { - sLongName = form.LongName; - int iFirstSpace = sLongName.IndexOf(" (", StringComparison.Ordinal); - int iLastSpace = sLongName.LastIndexOf("):", StringComparison.Ordinal) + 2; - sForm = sLongName.Substring(0, iFirstSpace); - XmlNode msaid = fIdsInAttribute ? node.Attributes.GetNamedItem("morphname") : node.SelectSingleNode("MSI/@DbRef"); - Debug.Assert(msaid != null); - string sMsaHvo = msaid.InnerText; - var indexOfPeriod = IndexOfPeriodInMsaHvo(ref sMsaHvo); - int hvoMsa = Convert.ToInt32(sMsaHvo); - var msaObj = fdoCache.ServiceLocator.GetObject(hvoMsa); - if (msaObj.ClassID == LexEntryTags.kClassId) - { - var entry = msaObj as ILexEntry; - Debug.Assert(entry != null); - if (entry.EntryRefsOS.Count > 0) - { - var index = IndexOfLexEntryRef(msaid.Value, indexOfPeriod); // the value of the int after the period - var lexEntryRef = entry.EntryRefsOS[index]; - ITsIncStrBldr sbGlossPrepend; - ITsIncStrBldr sbGlossAppend; - var sense = MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); - var glossWs = fdoCache.ServiceLocator.WritingSystemManager.Get(fdoCache.DefaultAnalWs); - MorphServices.JoinGlossAffixesOfInflVariantTypes(lexEntryRef.VariantEntryTypesRS, - glossWs, - out sbGlossPrepend, out sbGlossAppend); - ITsIncStrBldr sbGloss = sbGlossPrepend; - sbGloss.Append(sense.Gloss.BestAnalysisAlternative.Text); - sbGloss.Append(sbGlossAppend.Text); - sGloss = sbGloss.Text; - } - else - { - sGloss = ParserCoreStrings.ksUnknownGloss; - } - - } - else - { - var msa = msaObj as IMoMorphSynAnalysis; - sGloss = msa != null ? msa.GetGlossOfFirstSense() : sLongName.Substring(iFirstSpace, iLastSpace - iFirstSpace).Trim(); - } - sCitationForm = sLongName.Substring(iLastSpace).Trim(); - sLongName = String.Format(ParserCoreStrings.ksX_Y_Z, sForm, sGloss, sCitationForm); - } - else - { - sForm = ParserCoreStrings.ksUnknownMorpheme; // in case the user continues... - sGloss = ParserCoreStrings.ksUnknownGloss; - sCitationForm = ParserCoreStrings.ksUnknownCitationForm; - sLongName = String.Format(ParserCoreStrings.ksX_Y_Z, sForm, sGloss, sCitationForm); - throw new ApplicationException(sLongName); - } - XmlNode tempNode = CreateXmlElement(doc, "shortName", node); - tempNode.InnerXml = CreateEntities(sLongName); - tempNode = CreateXmlElement(doc, "alloform", node); - tempNode.InnerXml = CreateEntities(sForm); - switch (form.ClassID) - { - case MoStemAllomorphTags.kClassId: - ConvertStemName(doc, node, form); - break; - case MoAffixAllomorphTags.kClassId: - ConvertAffixAlloFeats(doc, node, form, fdoCache); - ConvertStemNameAffix(doc, node, fdoCache); - break; - - } - tempNode = CreateXmlElement(doc, "gloss", node); - tempNode.InnerXml = CreateEntities(sGloss); - tempNode = CreateXmlElement(doc, "citationForm", node); - tempNode.InnerXml = CreateEntities(sCitationForm); - } - } - } - - private static void ConvertLexEntryInflType(XmlDocument doc, XmlNode node, ILexEntryInflType lexEntryInflType, FdoCache fdoCache) - { - var lexEntryInflTypeNode = CreateXmlElement(doc, "lexEntryInflType", node); - var nullTempNode = CreateXmlElement(doc, "alloform", node); - nullTempNode.InnerText = "0"; - string sNullGloss = null; - var sbGloss = new StringBuilder(); - if (string.IsNullOrEmpty(lexEntryInflType.GlossPrepend.BestAnalysisAlternative.Text)) - { - sbGloss.Append(lexEntryInflType.GlossPrepend.BestAnalysisAlternative.Text); - sbGloss.Append("..."); - } - sbGloss.Append(lexEntryInflType.GlossAppend.BestAnalysisAlternative.Text); - nullTempNode = CreateXmlElement(doc, "gloss", node); - nullTempNode.InnerXml = CreateEntities(sbGloss.ToString()); - var sMsg = string.Format(ParserCoreStrings.ksIrregularlyInflectedFormNullAffix, lexEntryInflType.ShortName); - nullTempNode = CreateXmlElement(doc, "citationForm", node); - nullTempNode.InnerXml = CreateEntities(sMsg); - CreateInflMsaForLexEntryInflType(doc, node, lexEntryInflType, fdoCache); - } - - private static void CreateLexEntryInflTypeElement(FdoCache cache, XmlWriter writer, string wordType, ILexEntryInflType lexEntryInflType) - { - writer.WriteElementString("lexEntryInflType", ""); - writer.WriteElementString("alloform", "0"); - string sNullGloss = null; - var sbGloss = new StringBuilder(); - if (string.IsNullOrEmpty(lexEntryInflType.GlossPrepend.BestAnalysisAlternative.Text)) - { - sbGloss.Append(lexEntryInflType.GlossPrepend.BestAnalysisAlternative.Text); - sbGloss.Append("..."); - } - sbGloss.Append(lexEntryInflType.GlossAppend.BestAnalysisAlternative.Text); - writer.WriteElementString("gloss", sbGloss.ToString()); - var sMsg = string.Format(ParserCoreStrings.ksIrregularlyInflectedFormNullAffix, lexEntryInflType.ShortName); - writer.WriteElementString("citationForm", sMsg); - CreateInflMsaForLexEntryInflType(cache, writer, wordType, lexEntryInflType); - } - - private static void ConvertStemName(XmlDocument doc, XmlNode node, IMoForm form) - { - var sallo = form as IMoStemAllomorph; - Debug.Assert(sallo != null); - IMoStemName sn = sallo.StemNameRA; - if (sn != null) - { - XmlNode tempNode = CreateXmlElement(doc, "stemName", node); - CreateXmlAttribute(doc, "id", sn.Hvo.ToString(CultureInfo.InvariantCulture), tempNode); - tempNode.InnerXml = CreateEntities(sn.Name.BestAnalysisAlternative.Text); - } - else - { // There's no overt stem name on this allomorph, but there might be overt stem names - // on other allomorphs in this lexical entry. This allomorph, then, cannot bear any - // of the features of these other stem names. If so, there will be a property named - // NotStemNameddd or NotStemNamedddNotStemNamedddd, etc. - CreateNotStemNameElement(doc, node); - } - } - - private static void CreateStemNameElement(XmlWriter writer, IMoForm form, string props) - { - var sallo = form as IMoStemAllomorph; - Debug.Assert(sallo != null); - IMoStemName sn = sallo.StemNameRA; - if (sn != null) - { - writer.WriteStartElement("stemName"); - writer.WriteAttributeString("id", sn.Hvo.ToString(CultureInfo.InvariantCulture)); - writer.WriteString(sn.Name.BestAnalysisAlternative.Text); - writer.WriteEndElement(); //stemName - } - else - { // There's no overt stem name on this allomorph, but there might be overt stem names - // on other allomorphs in this lexical entry. This allomorph, then, cannot bear any - // of the features of these other stem names. If so, there will be a property named - // NotStemNameddd or NotStemNamedddNotStemNamedddd, etc. - CreateNotStemNameElement(writer, props); - } - } - - private static void ConvertStemNameAffix(XmlDocument doc, XmlNode node, FdoCache fdoCache) - { - XmlNode props = node.SelectSingleNode("props"); - if (props != null) - { - string sProps = props.InnerText.Trim(); - string[] saProps = sProps.Split(' '); - foreach (string sProp in saProps) - { - int i = sProp.IndexOf("StemNameAffix", StringComparison.Ordinal); - if (i > -1) - { - string sId = (sProp.Substring(i + 13)).Trim(); - var sn = fdoCache.ServiceLocator.GetInstance().GetObject(Convert.ToInt32(sId)); - if (sn != null) - { - XmlNode tempNode = CreateXmlElement(doc, "stemNameAffix", node); - CreateXmlAttribute(doc, "id", sId, tempNode); - tempNode.InnerXml = CreateEntities(sn.Name.BestAnalysisAlternative.Text); - } - } - } - } - } - - private static void CreateStemNameAffixElement(XmlWriter writer, FdoCache cache, string props) - { - if (string.IsNullOrEmpty(props)) - return; - - string[] propsArray = props.Trim().Split(' '); - foreach (string prop in propsArray) - { - int i = prop.IndexOf("StemNameAffix", StringComparison.Ordinal); - if (i > -1) - { - string id = (prop.Substring(i + 13)).Trim(); - IMoStemName sn = cache.ServiceLocator.GetInstance().GetObject(Convert.ToInt32(id)); - if (sn != null) - { - writer.WriteStartElement("stemNameAffix"); - writer.WriteAttributeString("id", id); - writer.WriteString(sn.Name.BestAnalysisAlternative.Text); - writer.WriteEndElement(); - } - } - } - } - - private static void CreateNotStemNameElement(XmlDocument doc, XmlNode node) - { - XmlNode props = node.SelectSingleNode("props"); - if (props != null) - { - int i = props.InnerText.IndexOf("NotStemName", StringComparison.Ordinal); - if (i > -1) - { - string s = props.InnerText.Substring(i); - int iSpace = s.IndexOf(" ", StringComparison.Ordinal); - string sNotStemName = iSpace > -1 ? s.Substring(0, iSpace - 1) : s; - XmlNode tempNode = CreateXmlElement(doc, "stemName", node); - CreateXmlAttribute(doc, "id", sNotStemName, tempNode); - } - } - } - - private static void CreateNotStemNameElement(XmlWriter writer, string propsText) - { - if (propsText != null) - { - int i = propsText.IndexOf("NotStemName", StringComparison.Ordinal); - if (i > -1) - { - string s = propsText.Substring(i); - int iSpace = s.IndexOf(" ", StringComparison.Ordinal); - string sNotStemName = iSpace > -1 ? s.Substring(0, iSpace - 1) : s; - writer.WriteStartElement("stemName"); - writer.WriteAttributeString("id", sNotStemName); - writer.WriteEndElement(); //stemName - } - } - } - - private static void ConvertAffixAlloFeats(XmlDocument doc, XmlNode node, IMoForm form, FdoCache fdoCache) - { - var sallo = form as IMoAffixAllomorph; - if (sallo == null) - return; // the form could be an IMoAffixProcess in which case there are no MsEnvFeatures. - IFsFeatStruc fsFeatStruc = sallo.MsEnvFeaturesOA; - if (fsFeatStruc != null && !fsFeatStruc.IsEmpty) - { - XmlNode tempNode = CreateXmlElement(doc, "affixAlloFeats", node); - CreateFeatureStructureNodes(doc, tempNode, fsFeatStruc, fsFeatStruc.Hvo); - } - else - { // There's no overt stem name on this allomorph, but there might be overt stem names - // on other allomorphs in this lexical entry. This allomorph, then, cannot bear any - // of the features of these other stem names. If so, there will be a property named - // NotStemNameddd or NotStemNamedddNotStemNamedddd, etc. - CreateNotAffixAlloFeatsElement(doc, node, fdoCache); - } - } - - private static void CreateAffixAlloFeatsElement(XmlWriter writer, IMoForm form, string propsText) - { - var sallo = form as IMoAffixAllomorph; - if (sallo == null) - return; // the form could be an IMoAffixProcess in which case there are no MsEnvFeatures. - IFsFeatStruc fsFeatStruc = sallo.MsEnvFeaturesOA; - if (fsFeatStruc != null && !fsFeatStruc.IsEmpty) - { - writer.WriteStartElement("affixAlloFeats"); - CreateFeatureStructureNodes(writer, fsFeatStruc, fsFeatStruc.Hvo); - writer.WriteEndElement(); //affixAlloFeats - } - else - { // There's no overt stem name on this allomorph, but there might be overt stem names - // on other allomorphs in this lexical entry. This allomorph, then, cannot bear any - // of the features of these other stem names. If so, there will be a property named - // NotStemNameddd or NotStemNamedddNotStemNamedddd, etc. - CreateNotAffixAlloFeatsElement(writer, form.Cache, propsText); - } - } - - private static void CreateNotAffixAlloFeatsElement(XmlDocument doc, XmlNode node, FdoCache fdoCache) - { - XmlNode props = node.SelectSingleNode("props"); - if (props != null) - { - int i = props.InnerText.IndexOf("MSEnvFSNot", StringComparison.Ordinal); - if (i > -1) - { - XmlNode affixAlloFeatsNode = CreateXmlElement(doc, "affixAlloFeats", node); - XmlNode notNode = CreateXmlElement(doc, "not", affixAlloFeatsNode); - string s = props.InnerText.Substring(i); - int j = s.IndexOf(' '); - if (j > 0) - s = props.InnerText.Substring(i, j + 1); - int iNot = s.IndexOf("Not", StringComparison.Ordinal) + 3; - while (iNot > 3) - { - int iNextNot = s.IndexOf("Not", iNot, StringComparison.Ordinal); - string sFsHvo; - if (iNextNot > -1) - { - // there are more - sFsHvo = s.Substring(iNot, iNextNot - iNot); - CreateFeatureStructureFromHvoString(doc, sFsHvo, notNode, fdoCache); - iNot = iNextNot + 3; - } - else - { - // is the last one - sFsHvo = s.Substring(iNot); - CreateFeatureStructureFromHvoString(doc, sFsHvo, notNode, fdoCache); - iNot = 0; - } - } - } - } - } - - private static void CreateNotAffixAlloFeatsElement(XmlWriter writer, FdoCache cache, string propsText) - { - if (propsText != null) - { - int i = propsText.IndexOf("MSEnvFSNot", StringComparison.Ordinal); - if (i > -1) - { - writer.WriteStartElement("affixAlloFeats"); - writer.WriteStartElement("not"); - string s = propsText.Substring(i); - int j = s.IndexOf(' '); - if (j > 0) - s = propsText.Substring(i, j + 1); - int iNot = s.IndexOf("Not", StringComparison.Ordinal) + 3; - while (iNot > 3) - { - int iNextNot = s.IndexOf("Not", iNot, StringComparison.Ordinal); - string sFsHvo; - if (iNextNot > -1) - { - // there are more - sFsHvo = s.Substring(iNot, iNextNot - iNot); - CreateFeatureStructureFromHvoString(writer, cache, sFsHvo); - iNot = iNextNot + 3; - } - else - { - // is the last one - sFsHvo = s.Substring(iNot); - CreateFeatureStructureFromHvoString(writer, cache, sFsHvo); - iNot = 0; - } - } - writer.WriteEndElement(); //not - writer.WriteEndElement(); //affixAlloFeats - } - } - } - - private static void CreateFeatureStructureFromHvoString(XmlDocument doc, string sFsHvo, XmlNode parentNode, FdoCache fdoCache) - { - int fsHvo = Convert.ToInt32(sFsHvo); - var fsFeatStruc = (IFsFeatStruc)fdoCache.ServiceLocator.GetInstance().GetObject(fsHvo); - if (fsFeatStruc != null) - { - CreateFeatureStructureNodes(doc, parentNode, fsFeatStruc, fsHvo); - } - } - - private static void CreateFeatureStructureFromHvoString(XmlWriter writer, FdoCache cache, string sFsHvo) - { - int fsHvo = Convert.ToInt32(sFsHvo); - var fsFeatStruc = (IFsFeatStruc) cache.ServiceLocator.GetInstance().GetObject(fsHvo); - if (fsFeatStruc != null) - CreateFeatureStructureNodes(writer, fsFeatStruc, fsHvo); - } - - public static string CreateEntities(string sInput) - { - if (sInput == null) - return ""; - string sResult1 = sInput.Replace("&", "&"); // N.B. Must be ordered first! - string sResult2 = sResult1.Replace("<", "<"); - return sResult2; - } - - private static void CreatePOSXmlAttribute(XmlDocument doc, XmlNode msaNode, IPartOfSpeech pos, string sCat) - { - if (pos != null) - { - CreateXmlAttribute(doc, sCat, pos.Hvo.ToString(CultureInfo.InvariantCulture), msaNode); - string sPosAbbr = pos.Hvo > 0 ? pos.Abbreviation.BestAnalysisAlternative.Text : "??"; - CreateXmlAttribute(doc, sCat + "Abbr", sPosAbbr, msaNode); - } - else - CreateXmlAttribute(doc, sCat, "0", msaNode); - } - - private static void CreatePOSXmlAttribute(XmlWriter writer, IPartOfSpeech pos, string sCat) - { - if (pos != null) - { - writer.WriteAttributeString(sCat, pos.Hvo.ToString(CultureInfo.InvariantCulture)); - string sPosAbbr = pos.Hvo > 0 ? pos.Abbreviation.BestAnalysisAlternative.Text : "??"; - writer.WriteAttributeString(sCat + "Abbr", sPosAbbr); - } - else - writer.WriteAttributeString(sCat, "0"); - } - - /// - /// Create an xml element and add it to the tree - /// - /// Xml document containing the element - /// name of the element to create - /// owner of the newly created element - /// newly created element node - public static XmlNode CreateXmlElement(XmlDocument doc, string sElementName, XmlNode parentNode) - { - XmlNode node = doc.CreateNode(XmlNodeType.Element, sElementName, null); - parentNode.AppendChild(node); - return node; - } - - public static void CreateXmlAttribute(XmlDocument doc, string sAttrName, string sAttrValue, XmlNode elementNode) - { - XmlNode attr = doc.CreateNode(XmlNodeType.Attribute, sAttrName, null); - attr.Value = sAttrValue; - if (elementNode.Attributes != null) - elementNode.Attributes.SetNamedItem(attr); - } - } -} diff --git a/Src/LexText/ParserEngine/ParserCore/ParserXmlWriterExtensions.cs b/Src/LexText/ParserEngine/ParserCore/ParserXmlWriterExtensions.cs new file mode 100644 index 0000000000..b20c34f51d --- /dev/null +++ b/Src/LexText/ParserEngine/ParserCore/ParserXmlWriterExtensions.cs @@ -0,0 +1,532 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Xml; +using SIL.CoreImpl; +using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.FDO; +using SIL.FieldWorks.FDO.DomainServices; + +namespace SIL.FieldWorks.WordWorks.Parser +{ + public static class ParserXmlWriterExtensions + { + public static void WriteMsaElement(this XmlWriter writer, FdoCache cache, string msaID, int allomorphHvo, string type, string wordType) + { + // Irregulary inflected forms can have a combination MSA hvo: the LexEntry hvo, a period, and an index to the LexEntryRef + Tuple msaTuple = ParserHelper.ProcessMsaHvo(msaID); + ICmObject obj = cache.ServiceLocator.GetInstance().GetObject(msaTuple.Item1); + switch (obj.GetType().Name) + { + default: + throw new ApplicationException(String.Format("Invalid MSA type: {0}.", obj.GetType().Name)); + case "MoStemMsa": + WriteStemMsaXmlElement(writer, (IMoStemMsa) obj); + break; + case "MoInflAffMsa": + WriteInflectionClasses(writer, cache, allomorphHvo); + WriteInflMsaXmlElement(writer, (IMoInflAffMsa) obj, type); + break; + case "MoDerivAffMsa": + WriteDerivMsaXmlElement(writer, (IMoDerivAffMsa) obj); + break; + case "MoUnclassifiedAffixMsa": + WriteUnclassifedMsaXmlElement(writer, (IMoUnclassifiedAffixMsa) obj); + break; + case "LexEntry": + // is an irregularly inflected form + // get the MoStemMsa of its variant + var entry = (ILexEntry) obj; + Debug.Assert(entry != null); + if (entry.EntryRefsOS.Count > 0) + { + var lexEntryRef = entry.EntryRefsOS[msaTuple.Item2]; + var sense = MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); + WriteStemMsaXmlElement(writer, (IMoStemMsa) sense.MorphoSyntaxAnalysisRA); + } + break; + case "LexEntryInflType": + // This is one of the null allomorphs we create when building the + // input for the parser in order to still get the Word Grammar to have something in any + // required slots in affix templates. + WriteInflMsaForLexEntryInflType(writer, wordType, (ILexEntryInflType) obj); + break; + } + } + + /// + /// Determine if a PartOfSpeech requires inflection. + /// If it or any of its parent POSes have a template, it requires inflection. + /// If it is null we default to not requiring inflection. + /// + /// the Part of Speech + /// true if it does, false otherwise + private static bool RequiresInflection(IPartOfSpeech pos) + { + return pos != null && pos.RequiresInflection; + } + + private static void WriteStemMsaXmlElement(XmlWriter writer, IMoStemMsa stemMsa) + { + writer.WriteStartElement("stemMsa"); + WritePosXmlAttribute(writer, stemMsa.PartOfSpeechRA, "cat"); + IMoInflClass inflClass = stemMsa.InflectionClassRA; + if (inflClass == null) + { // use default inflection class of the POS or + // the first ancestor POS that has a non-zero default inflection class + int inflClassHvo = 0; + IPartOfSpeech pos = stemMsa.PartOfSpeechRA; + while (pos != null && inflClassHvo == 0) + { + if (pos.DefaultInflectionClassRA != null) + inflClassHvo = pos.DefaultInflectionClassRA.Hvo; + else + { + int clsid = stemMsa.Services.GetInstance().GetObject(pos.Owner.Hvo).ClassID; + pos = clsid == PartOfSpeechTags.kClassId ? stemMsa.Services.GetInstance().GetObject(pos.Owner.Hvo) : null; + } + } + if (inflClassHvo != 0) + inflClass = stemMsa.Services.GetInstance().GetObject(inflClassHvo); + } + WriteInflectionClassXmlAttribute(writer, inflClass, "inflClass"); + WriteRequiresInflectionXmlAttribute(writer, stemMsa.PartOfSpeechRA); + WriteFeatureStructureNodes(writer, stemMsa.MsFeaturesOA, stemMsa.Hvo); + WriteProductivityRestrictionNodes(writer, stemMsa.ProdRestrictRC, "productivityRestriction"); + WriteFromPosNodes(writer, stemMsa.FromPartsOfSpeechRC, "fromPartsOfSpeech"); + writer.WriteEndElement(); //stemMsa + } + + private static void WriteInflectionClasses(XmlWriter writer, FdoCache fdoCache, int allomorphHvo) + { + if (allomorphHvo <= 0) + return; + // use IMoForm instead of IMoAffixForm or IMoAffixAllomorph because it could be an IMoStemAllomorph + IMoForm form = fdoCache.ServiceLocator.GetInstance().GetObject(allomorphHvo); + if (form == null) + return; + if (!(form is IMoAffixForm)) + return; + foreach (IMoInflClass ic in ((IMoAffixForm)form).InflectionClassesRC) + { + writer.WriteStartElement("inflectionClass"); + writer.WriteAttributeString("id", ic.Hvo.ToString(CultureInfo.InvariantCulture)); + writer.WriteAttributeString("abbr", ic.Abbreviation.BestAnalysisAlternative.Text); + writer.WriteEndElement(); //inflectionClass + } + } + + private static void WriteInflMsaXmlElement(XmlWriter writer, IMoInflAffMsa inflMsa, string type) + { + writer.WriteStartElement("inflMsa"); + WritePosXmlAttribute(writer, inflMsa.PartOfSpeechRA, "cat"); + // handle any slot + HandleSlotInfoForInflectionalMsa(writer, inflMsa, type); + WriteFeatureStructureNodes(writer, inflMsa.InflFeatsOA, inflMsa.Hvo); + WriteProductivityRestrictionNodes(writer, inflMsa.FromProdRestrictRC, "fromProductivityRestriction"); + writer.WriteEndElement(); //inflMsa + } + + private static void WriteDerivMsaXmlElement(XmlWriter writer, IMoDerivAffMsa derivMsa) + { + writer.WriteStartElement("derivMsa"); + WritePosXmlAttribute(writer, derivMsa.FromPartOfSpeechRA, "fromCat"); + WritePosXmlAttribute(writer, derivMsa.ToPartOfSpeechRA, "toCat"); + WriteInflectionClassXmlAttribute(writer, derivMsa.FromInflectionClassRA, "fromInflClass"); + WriteInflectionClassXmlAttribute(writer, derivMsa.ToInflectionClassRA, "toInflClass"); + WriteRequiresInflectionXmlAttribute(writer, derivMsa.ToPartOfSpeechRA); + WriteFeatureStructureNodes(writer, derivMsa.FromMsFeaturesOA, derivMsa.Hvo, "fromFS"); + WriteFeatureStructureNodes(writer, derivMsa.ToMsFeaturesOA, derivMsa.Hvo, "toFS"); + WriteProductivityRestrictionNodes(writer, derivMsa.FromProdRestrictRC, "fromProductivityRestriction"); + WriteProductivityRestrictionNodes(writer, derivMsa.ToProdRestrictRC, "toProductivityRestriction"); + writer.WriteEndElement(); //derivMsa + } + + private static void WriteUnclassifedMsaXmlElement(XmlWriter writer, IMoUnclassifiedAffixMsa unclassMsa) + { + writer.WriteStartElement("unclassMsa"); + WritePosXmlAttribute(writer, unclassMsa.PartOfSpeechRA, "fromCat"); + writer.WriteEndElement(); //unclassMsa + } + + private static void WriteInflMsaForLexEntryInflType(XmlWriter writer, string wordType, ILexEntryInflType lexEntryInflType) + { + IMoInflAffixSlot slot; + if (wordType != null) + { + slot = lexEntryInflType.Services.GetInstance().GetObject(Convert.ToInt32(wordType)); + } + else + { + var slots = lexEntryInflType.SlotsRC; + IMoInflAffixSlot firstSlot = slots.FirstOrDefault(); + slot = firstSlot; + } + + if (slot != null) + { + writer.WriteStartElement("inflMsa"); + WritePosXmlAttribute(writer, slot.Owner as IPartOfSpeech, "cat"); + writer.WriteAttributeString("slot", slot.Hvo.ToString(CultureInfo.InvariantCulture)); + writer.WriteAttributeString("slotAbbr", slot.Name.BestAnalysisAlternative.Text); + writer.WriteAttributeString("slotOptional", "false"); + WriteFeatureStructureNodes(writer, lexEntryInflType.InflFeatsOA, lexEntryInflType.Hvo); + writer.WriteEndElement(); //inflMsa + } + } + + private static void WriteInflectionClassXmlAttribute(XmlWriter writer, IMoInflClass inflClass, string sInflClass) + { + if (inflClass != null) + { + writer.WriteAttributeString(sInflClass, inflClass.Hvo.ToString(CultureInfo.InvariantCulture)); + writer.WriteAttributeString(sInflClass + "Abbr", inflClass.Hvo > 0 ? inflClass.Abbreviation.BestAnalysisAlternative.Text : ""); + } + else + writer.WriteAttributeString(sInflClass, "0"); + } + + private static void WriteRequiresInflectionXmlAttribute(XmlWriter writer, IPartOfSpeech pos) + { + writer.WriteAttributeString("requiresInfl", RequiresInflection(pos) ? "+" : "-"); + } + + private static void WriteFeatureStructureNodes(XmlWriter writer, IFsFeatStruc fs, int id, string sFsName = "fs") + { + if (fs == null) + return; + writer.WriteStartElement(sFsName); + writer.WriteAttributeString("id", id.ToString(CultureInfo.InvariantCulture)); + foreach (IFsFeatureSpecification spec in fs.FeatureSpecsOC) + { + writer.WriteStartElement("feature"); + writer.WriteElementString("name", spec.FeatureRA.Abbreviation.BestAnalysisAlternative.Text); + writer.WriteStartElement("value"); + var cv = spec as IFsClosedValue; + if (cv != null) + writer.WriteString(cv.ValueRA.Abbreviation.BestAnalysisAlternative.Text); + else + { + var complex = spec as IFsComplexValue; + if (complex == null) + continue; // skip this one since we're not dealing with it yet + var nestedFs = complex.ValueOA as IFsFeatStruc; + if (nestedFs != null) + WriteFeatureStructureNodes(writer, nestedFs, 0); + } + writer.WriteEndElement(); //value + writer.WriteEndElement(); //feature + } + writer.WriteEndElement(); //sFsName + } + + private static void WriteProductivityRestrictionNodes(XmlWriter writer, IFdoReferenceCollection prodRests, string sElementName) + { + if (prodRests == null || prodRests.Count < 1) + return; + foreach (ICmPossibility pr in prodRests) + { + writer.WriteStartElement(sElementName); + writer.WriteAttributeString("id", pr.Hvo.ToString(CultureInfo.InvariantCulture)); + writer.WriteElementString("name", pr.Name.BestAnalysisAlternative.Text); + writer.WriteEndElement(); //sElementName + } + } + + private static void WriteFromPosNodes(XmlWriter writer, IFdoReferenceCollection fromPoSes, string sElementName) + { + if (fromPoSes == null || fromPoSes.Count < 1) + return; + foreach (IPartOfSpeech pos in fromPoSes) + { + writer.WriteStartElement(sElementName); + writer.WriteAttributeString("fromCat", pos.Hvo.ToString(CultureInfo.InvariantCulture)); + writer.WriteAttributeString("fromCatAbbr", pos.Abbreviation.BestAnalysisAlternative.Text); + writer.WriteEndElement(); //sElementName + } + } + + private static void HandleSlotInfoForInflectionalMsa(XmlWriter writer, IMoInflAffMsa inflMsa, string type) + { + int slotHvo = 0; + int iCount = inflMsa.SlotsRC.Count; + if (iCount > 0) + { + if (iCount > 1) + { // have a circumfix; assume only two slots and assume that the first is prefix and second is suffix + // TODO: ideally would figure out if the slots are prefix or suffix slots and then align the + // o and 1 indices to the appropriate slot. Will just do this for now (hab 2005.08.04). + if (type != null && type != "sfx") + slotHvo = inflMsa.SlotsRC.ToHvoArray()[0]; + else + slotHvo = inflMsa.SlotsRC.ToHvoArray()[1]; + } + else + slotHvo = inflMsa.SlotsRC.ToHvoArray()[0]; + } + writer.WriteAttributeString("slot", slotHvo.ToString(CultureInfo.InvariantCulture)); + string sSlotOptional = "false"; + string sSlotAbbr = "??"; + if (Convert.ToInt32(slotHvo) > 0) + { + var slot = inflMsa.Services.GetInstance().GetObject(Convert.ToInt32(slotHvo)); + if (slot != null) + { + sSlotAbbr = slot.Name.BestAnalysisAlternative.Text; + if (slot.Optional) + sSlotOptional = "true"; + } + } + writer.WriteAttributeString("slotAbbr", sSlotAbbr); + writer.WriteAttributeString("slotOptional", sSlotOptional); + } + + public static void WriteMorphInfoElements(this XmlWriter writer, FdoCache cache, int formHvo, string msaID, string wordType, string props) + { + ICmObject obj = cache.ServiceLocator.GetInstance().GetObject(formHvo); + var form = obj as IMoForm; + if (form == null) + { + // This is one of the null allomorphs we create when building the + // input for the parser in order to still get the Word Grammar to have something in any + // required slots in affix templates. + var lexEntryInflType = obj as ILexEntryInflType; + if (lexEntryInflType != null) + { + WriteLexEntryInflTypeElement(writer, wordType, lexEntryInflType); + return; + } + } + string shortName; + string alloform; + string gloss; + string citationForm; + if (form != null) + { + shortName = form.LongName; + int iFirstSpace = shortName.IndexOf(" (", StringComparison.Ordinal); + int iLastSpace = shortName.LastIndexOf("):", StringComparison.Ordinal) + 2; + alloform = shortName.Substring(0, iFirstSpace); + Tuple msaTuple = ParserHelper.ProcessMsaHvo(msaID); + ICmObject msaObj = cache.ServiceLocator.GetObject(msaTuple.Item1); + if (msaObj.ClassID == LexEntryTags.kClassId) + { + var entry = msaObj as ILexEntry; + Debug.Assert(entry != null); + if (entry.EntryRefsOS.Count > 0) + { + ILexEntryRef lexEntryRef = entry.EntryRefsOS[msaTuple.Item2]; + ITsIncStrBldr sbGlossPrepend; + ITsIncStrBldr sbGlossAppend; + ILexSense sense = MorphServices.GetMainOrFirstSenseOfVariant(lexEntryRef); + IWritingSystem glossWs = cache.ServiceLocator.WritingSystemManager.Get(cache.DefaultAnalWs); + MorphServices.JoinGlossAffixesOfInflVariantTypes(lexEntryRef.VariantEntryTypesRS, + glossWs, out sbGlossPrepend, out sbGlossAppend); + ITsIncStrBldr sbGloss = sbGlossPrepend; + sbGloss.Append(sense.Gloss.BestAnalysisAlternative.Text); + sbGloss.Append(sbGlossAppend.Text); + gloss = sbGloss.Text; + } + else + { + gloss = ParserCoreStrings.ksUnknownGloss; + } + + } + else + { + var msa = msaObj as IMoMorphSynAnalysis; + gloss = msa != null ? msa.GetGlossOfFirstSense() : shortName.Substring(iFirstSpace, iLastSpace - iFirstSpace).Trim(); + } + citationForm = shortName.Substring(iLastSpace).Trim(); + shortName = String.Format(ParserCoreStrings.ksX_Y_Z, alloform, gloss, citationForm); + } + else + { + alloform = ParserCoreStrings.ksUnknownMorpheme; // in case the user continues... + gloss = ParserCoreStrings.ksUnknownGloss; + citationForm = ParserCoreStrings.ksUnknownCitationForm; + shortName = String.Format(ParserCoreStrings.ksX_Y_Z, alloform, gloss, citationForm); + throw new ApplicationException(shortName); + } + writer.WriteElementString("shortName", shortName); + writer.WriteElementString("alloform", alloform); + switch (form.ClassID) + { + case MoStemAllomorphTags.kClassId: + WriteStemNameElement(writer, form, props); + break; + case MoAffixAllomorphTags.kClassId: + WriteAffixAlloFeatsElement(writer, form, props); + WriteStemNameAffixElement(writer, cache, props); + break; + + } + writer.WriteElementString("gloss", gloss); + writer.WriteElementString("citationForm", citationForm); + } + + private static void WriteLexEntryInflTypeElement(XmlWriter writer, string wordType, ILexEntryInflType lexEntryInflType) + { + writer.WriteStartElement("lexEntryInflType"); + writer.WriteEndElement(); + writer.WriteElementString("alloform", "0"); + string sNullGloss = null; + var sbGloss = new StringBuilder(); + if (string.IsNullOrEmpty(lexEntryInflType.GlossPrepend.BestAnalysisAlternative.Text)) + { + sbGloss.Append(lexEntryInflType.GlossPrepend.BestAnalysisAlternative.Text); + sbGloss.Append("..."); + } + sbGloss.Append(lexEntryInflType.GlossAppend.BestAnalysisAlternative.Text); + writer.WriteElementString("gloss", sbGloss.ToString()); + var sMsg = string.Format(ParserCoreStrings.ksIrregularlyInflectedFormNullAffix, lexEntryInflType.ShortName); + writer.WriteElementString("citationForm", sMsg); + WriteInflMsaForLexEntryInflType(writer, wordType, lexEntryInflType); + } + + private static void WriteStemNameElement(XmlWriter writer, IMoForm form, string props) + { + var sallo = form as IMoStemAllomorph; + Debug.Assert(sallo != null); + IMoStemName sn = sallo.StemNameRA; + if (sn != null) + { + writer.WriteStartElement("stemName"); + writer.WriteAttributeString("id", sn.Hvo.ToString(CultureInfo.InvariantCulture)); + writer.WriteString(sn.Name.BestAnalysisAlternative.Text); + writer.WriteEndElement(); //stemName + } + else + { // There's no overt stem name on this allomorph, but there might be overt stem names + // on other allomorphs in this lexical entry. This allomorph, then, cannot bear any + // of the features of these other stem names. If so, there will be a property named + // NotStemNameddd or NotStemNamedddNotStemNamedddd, etc. + WriteNotStemNameElement(writer, props); + } + } + + private static void WriteStemNameAffixElement(XmlWriter writer, FdoCache cache, string props) + { + if (string.IsNullOrEmpty(props)) + return; + + string[] propsArray = props.Trim().Split(' '); + foreach (string prop in propsArray) + { + int i = prop.IndexOf("StemNameAffix", StringComparison.Ordinal); + if (i > -1) + { + string id = (prop.Substring(i + 13)).Trim(); + IMoStemName sn = cache.ServiceLocator.GetInstance().GetObject(Convert.ToInt32(id)); + if (sn != null) + { + writer.WriteStartElement("stemNameAffix"); + writer.WriteAttributeString("id", id); + writer.WriteString(sn.Name.BestAnalysisAlternative.Text); + writer.WriteEndElement(); + } + } + } + } + + private static void WriteNotStemNameElement(XmlWriter writer, string propsText) + { + if (propsText != null) + { + int i = propsText.IndexOf("NotStemName", StringComparison.Ordinal); + if (i > -1) + { + string s = propsText.Substring(i); + int iSpace = s.IndexOf(" ", StringComparison.Ordinal); + string sNotStemName = iSpace > -1 ? s.Substring(0, iSpace - 1) : s; + writer.WriteStartElement("stemName"); + writer.WriteAttributeString("id", sNotStemName); + writer.WriteEndElement(); //stemName + } + } + } + + private static void WriteAffixAlloFeatsElement(XmlWriter writer, IMoForm form, string propsText) + { + var sallo = form as IMoAffixAllomorph; + if (sallo == null) + return; // the form could be an IMoAffixProcess in which case there are no MsEnvFeatures. + IFsFeatStruc fsFeatStruc = sallo.MsEnvFeaturesOA; + if (fsFeatStruc != null && !fsFeatStruc.IsEmpty) + { + writer.WriteStartElement("affixAlloFeats"); + WriteFeatureStructureNodes(writer, fsFeatStruc, fsFeatStruc.Hvo); + writer.WriteEndElement(); //affixAlloFeats + } + else + { // There's no overt stem name on this allomorph, but there might be overt stem names + // on other allomorphs in this lexical entry. This allomorph, then, cannot bear any + // of the features of these other stem names. If so, there will be a property named + // NotStemNameddd or NotStemNamedddNotStemNamedddd, etc. + WriteNotAffixAlloFeatsElement(writer, form.Cache, propsText); + } + } + + private static void WriteNotAffixAlloFeatsElement(XmlWriter writer, FdoCache cache, string propsText) + { + if (propsText != null) + { + int i = propsText.IndexOf("MSEnvFSNot", StringComparison.Ordinal); + if (i > -1) + { + writer.WriteStartElement("affixAlloFeats"); + writer.WriteStartElement("not"); + string s = propsText.Substring(i); + int j = s.IndexOf(' '); + if (j > 0) + s = propsText.Substring(i, j + 1); + int iNot = s.IndexOf("Not", StringComparison.Ordinal) + 3; + while (iNot > 3) + { + int iNextNot = s.IndexOf("Not", iNot, StringComparison.Ordinal); + string sFsHvo; + if (iNextNot > -1) + { + // there are more + sFsHvo = s.Substring(iNot, iNextNot - iNot); + WriteFeatureStructureFromHvoString(writer, cache, sFsHvo); + iNot = iNextNot + 3; + } + else + { + // is the last one + sFsHvo = s.Substring(iNot); + WriteFeatureStructureFromHvoString(writer, cache, sFsHvo); + iNot = 0; + } + } + writer.WriteEndElement(); //not + writer.WriteEndElement(); //affixAlloFeats + } + } + } + + private static void WriteFeatureStructureFromHvoString(XmlWriter writer, FdoCache cache, string sFsHvo) + { + int fsHvo = Convert.ToInt32(sFsHvo); + var fsFeatStruc = (IFsFeatStruc) cache.ServiceLocator.GetInstance().GetObject(fsHvo); + if (fsFeatStruc != null) + WriteFeatureStructureNodes(writer, fsFeatStruc, fsHvo); + } + + private static void WritePosXmlAttribute(XmlWriter writer, IPartOfSpeech pos, string sCat) + { + if (pos != null) + { + writer.WriteAttributeString(sCat, pos.Hvo.ToString(CultureInfo.InvariantCulture)); + string sPosAbbr = pos.Hvo > 0 ? pos.Abbreviation.BestAnalysisAlternative.Text : "??"; + writer.WriteAttributeString(sCat + "Abbr", sPosAbbr); + } + else + writer.WriteAttributeString(sCat, "0"); + } + } +} diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs b/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs index 04f3121701..2c654d7dfc 100644 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs +++ b/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Text; @@ -139,23 +139,34 @@ public string ParseWordXml(string word) CheckDisposed(); var sb = new StringBuilder(m_xample.ParseWord(word)); - sb.Replace("<...>", "[...]"); sb.Replace("DB_REF_HERE", "'0'"); + sb.Replace("<...>", "[...]"); while (sb[sb.Length - 1] == '\x0') sb.Remove(sb.Length - 1, 1); - var doc = new XmlDocument(); - doc.LoadXml(sb.ToString()); - ParserXmlGenerator.ConvertMorphs(doc, "//Morph", false, m_cache); - - XmlNodeList nl = doc.SelectNodes("//Morph/MSI"); - if (nl != null) + XDocument doc = XDocument.Parse(sb.ToString()); + foreach (XElement morphElem in doc.Descendants("Morph")) { - foreach (XmlNode node in nl) - ParserXmlGenerator.CreateMsaXmlElement(node, doc, node, "@DbRef", m_cache); + var type = (string) morphElem.Attribute("type"); + var props = (string) morphElem.Element("props"); + + XElement formElem = morphElem.Element("MoForm"); + Debug.Assert(formElem != null); + var formHvo = (int) formElem.Attribute("DbRef"); + var wordType = (string) formElem.Attribute("wordType"); + + XElement msaElem = morphElem.Element("MSI"); + Debug.Assert(msaElem != null); + var msaID = (string) msaElem.Attribute("DbRef"); + + using (XmlWriter writer = morphElem.CreateWriter()) + writer.WriteMorphInfoElements(m_cache, formHvo, msaID, wordType, props); + + using (XmlWriter writer = msaElem.CreateWriter()) + writer.WriteMsaElement(m_cache, msaID, formHvo, type, wordType); } - return doc.OuterXml; + return doc.ToString(); } public string TraceWordXml(string word, string selectTraceMorphs) @@ -168,80 +179,37 @@ public string TraceWordXml(string word, string selectTraceMorphs) while (sb[sb.Length - 1] == '\x0') sb.Remove(sb.Length - 1, 1); - var doc = new XmlDocument(); - doc.LoadXml(sb.ToString()); - ParserXmlGenerator.ConvertMorphs(doc, "//morph", true, m_cache); - ConvertFailures(doc); - - XmlNodeList nl = doc.SelectNodes("//morph[@morphname]"); - if (nl != null) + XDocument doc = XDocument.Parse(sb.ToString()); + foreach (XElement morphElem in doc.Descendants("morph")) { - foreach (XmlNode node in nl) - ParserXmlGenerator.CreateMsaXmlElement(node, doc, node, "@morphname", m_cache); - } - - return doc.OuterXml; - } - - private void ConvertFailures(XmlDocument doc) - { - ConvertNaturalClasses(doc, "SEC_ST", GetNCRepresentation); - ConvertNaturalClasses(doc, "InfixEnvironment", GetNCRepresentation); - ConvertAdHocFailures(doc, "ANCC_FT", GetFormRepresentation); - ConvertAdHocFailures(doc, "MCC_FT", GetMsaRepresentation); - ConvertWordGrammarFailures(doc); - } - - private string GetFormRepresentation(int hvo) - { - ICmObject obj = m_cache.ServiceLocator.GetInstance().GetObject(hvo); - var form = obj as IMoForm; - if (form != null) - return form.ShortName; - - throw new ApplicationException(ParserCoreStrings.ksUnknownAllomorph); - } - - private string GetMsaRepresentation(int hvo) - { - ICmObject obj = m_cache.ServiceLocator.GetInstance().GetObject(hvo); - var msa = obj as IMoMorphSynAnalysis; - if (msa != null) - return msa.LongName; + var formHvo = (int) morphElem.Attribute("alloid"); + var msaID = (string) morphElem.Attribute("morphname"); + var type = (string) morphElem.Attribute("type"); + var props = (string) morphElem.Element("props"); + var wordType = (string) morphElem.Attribute("wordType"); - throw new ApplicationException(ParserCoreStrings.ksUnknownMorpheme); - } - - private string GetNCRepresentation(int hvo) - { - ICmObject obj = m_cache.ServiceLocator.GetInstance().GetObject(hvo); - var nc = obj as IPhNCSegments; - if (nc != null) - return nc.Name.BestAnalysisAlternative.Text; + using (XmlWriter writer = morphElem.CreateWriter()) + { + writer.WriteMorphInfoElements(m_cache, formHvo, msaID, wordType, props); + writer.WriteMsaElement(m_cache, msaID, formHvo, type, wordType); + } + } + ConvertFailures(doc, GetStrRep); - throw new ApplicationException(ParserCoreStrings.ksUnknownNaturalClass); + return doc.ToString(); } - [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", - Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] - internal static void ConvertNaturalClasses(XmlDocument doc, string sTestName, Func repSelector) + internal static void ConvertFailures(XDocument doc, Func strRepSelector) { - var sbXPath = new StringBuilder(); - sbXPath.Append("//failure[contains(@test,'"); - sbXPath.Append(sTestName); - sbXPath.Append("') and contains(@test,'[')]"); - XmlNodeList nl = doc.SelectNodes(sbXPath.ToString()); - if (nl != null) + int wordGrammarFailureCount = 1; + foreach (XElement failureElem in doc.Descendants("failure")) { - int testingCount = 0; + var test = (string) failureElem.Attribute("test"); - foreach (XmlNode node in nl) + if ((test.StartsWith("SEC_ST") || test.StartsWith("InfixEnvironment")) && test.Contains("[")) { - XmlNode test = node.Attributes.GetNamedItem("test"); - string s = test.InnerText; - int i = test.InnerText.IndexOf('/'); - string s0 = s.Substring(i); - string[] sa = s0.Split('[', ']'); // split into hunks using brackets + int i = test.IndexOf('/'); + string[] sa = test.Substring(i).Split('[', ']'); // split into hunks using brackets var sb = new StringBuilder(); foreach (string str in sa) // for each hunk { @@ -251,7 +219,7 @@ internal static void ConvertNaturalClasses(XmlDocument doc, string sTestName, Fu sb.Append("["); string sHvo = str; int hvo = Convert.ToInt32(sHvo); - sb.Append(repSelector(hvo)); + sb.Append(strRepSelector(PhNaturalClassTags.kClassId, hvo)); sb.Append("]"); } else @@ -259,27 +227,16 @@ internal static void ConvertNaturalClasses(XmlDocument doc, string sTestName, Fu sb.Append(str); } } - test.InnerText = s.Substring(0, i) + sb; + failureElem.SetAttributeValue("test", test.Substring(0, i) + sb); } - } - } - - [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", - Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] - internal static void ConvertAdHocFailures(XmlDocument doc, string testName, Func repSelector) - { - string sXPath = "//failure[contains(@test,'" + testName + - "') and not(contains(@test,'ExcpFeat')) and not(contains(@test,'StemName')) and not(contains(@test,'IrregInflForm'))]"; - XmlNodeList nl = doc.SelectNodes(sXPath); - if (nl != null) - { - int testingCount = 0; - foreach (XmlNode node in nl) + else if ((test.StartsWith("ANCC_FT") || test.StartsWith("MCC_FT")) && !test.Contains("ExcpFeat") && !test.Contains("StemName") + && !test.Contains("IrregInflForm")) { - XmlNode test = node.Attributes.GetNamedItem("test"); - string s = test.InnerText; - int iStartingPos = s.IndexOf("::", StringComparison.Ordinal) + 2; // skip to the double colon portion - string[] sa = s.Substring(iStartingPos).Split(' '); + int index = test.IndexOf(":", StringComparison.Ordinal); + string testName = test.Substring(0, index); + + int iStartingPos = test.IndexOf("::", StringComparison.Ordinal) + 2; // skip to the double colon portion + string[] sa = test.Substring(iStartingPos).Split(' '); var sb = new StringBuilder(); sb.Append(testName); @@ -289,36 +246,48 @@ internal static void ConvertAdHocFailures(XmlDocument doc, string testName, Func sb.Append(" "); if (str.IndexOfAny(Digits) >= 0) { - string sHvo = str; - int hvo = Convert.ToInt32(sHvo); - sb.Append(repSelector(hvo)); + int hvo = Convert.ToInt32(str); + sb.Append(strRepSelector(testName == "ANCC_FT" ? MoFormTags.kClassId : MoMorphSynAnalysisTags.kClassId, hvo)); } else { sb.Append(str); } } - test.InnerText = sb.ToString(); + failureElem.SetAttributeValue("test", sb.ToString()); + } + else if (test.StartsWith("PC-PATR")) + { + failureElem.Add(new XAttribute("id", wordGrammarFailureCount)); + wordGrammarFailureCount++; } } } - - [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", - Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] - private void ConvertWordGrammarFailures(XmlDocument doc) + private string GetStrRep(int classID, int hvo) { - const string sXPath = "//failure[contains(@test,'PC-PATR')]"; - XmlNodeList nl = doc.SelectNodes(sXPath); - if (nl != null) + ICmObject obj = m_cache.ServiceLocator.GetInstance().GetObject(hvo); + switch (classID) { - int iCount = 1; - foreach (XmlNode node in nl) - { - ParserXmlGenerator.CreateXmlAttribute(doc, "id", iCount.ToString(CultureInfo.InvariantCulture), node); - iCount++; - } + case MoFormTags.kClassId: + var form = obj as IMoForm; + if (form != null) + return form.ShortName; + throw new ApplicationException(ParserCoreStrings.ksUnknownAllomorph); + + case MoMorphSynAnalysisTags.kClassId: + var msa = obj as IMoMorphSynAnalysis; + if (msa != null) + return msa.LongName; + throw new ApplicationException(ParserCoreStrings.ksUnknownMorpheme); + + case PhNaturalClassTags.kClassId: + var nc = obj as IPhNCSegments; + if (nc != null) + return nc.Name.BestAnalysisAlternative.Text; + throw new ApplicationException(ParserCoreStrings.ksUnknownNaturalClass); } + return null; } protected override void DisposeManagedResources() diff --git a/Src/LexText/ParserUI/WordGrammarDebugger.cs b/Src/LexText/ParserUI/WordGrammarDebugger.cs index 7dde107331..ed0533186c 100644 --- a/Src/LexText/ParserUI/WordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/WordGrammarDebugger.cs @@ -175,8 +175,8 @@ protected void CreateMorphXElement(XmlWriter writer, XElement element) } if (morphnameAttr != null) { - ParserXmlGenerator.CreateMsaXmlElement(writer, morphnameAttr.Value, alloIdAttr == null ? 0 : Convert.ToInt32(alloIdAttr.Value), - typeAttr == null ? null : typeAttr.Value, wordTypeAttr == null ? null : wordTypeAttr.Value, m_cache); + writer.WriteMsaElement(m_cache, morphnameAttr.Value, alloIdAttr == null ? 0 : Convert.ToInt32(alloIdAttr.Value), + typeAttr == null ? null : typeAttr.Value, wordTypeAttr == null ? null : wordTypeAttr.Value); } writer.WriteEndElement(); } @@ -209,7 +209,7 @@ private string CreateWordDebuggerPage(string sXmlFile) private string CreateWordGrammarDebuggerFileName() { - string sDepthLevel = m_xmlHtmlStack.Count.ToString(); + string sDepthLevel = m_xmlHtmlStack.Count.ToString(CultureInfo.InvariantCulture); return "WordGrammarDebugger" + sDepthLevel; } From 126bc9d1f3a998c055dfec7cfc6a08c5e774f648 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Thu, 13 Feb 2014 16:54:20 +0700 Subject: [PATCH 077/143] Use XslCompiledTransform and remove some unnecessary IO Change-Id: Iff0847808a3a23b6ea96825fb581de64a62e3afd --- Src/LexText/ParserUI/HCTrace.cs | 11 ++-- Src/LexText/ParserUI/ParserTrace.cs | 17 +++--- Src/LexText/ParserUI/ParserTraceBase.cs | 40 ++++++++----- Src/LexText/ParserUI/WordGrammarDebugger.cs | 56 ++++++++++++------- Src/LexText/ParserUI/XAmpleTrace.cs | 6 +- Src/Utilities/XMLUtils/XMLUtils.csproj | 2 + .../XMLUtils/XslCompiledTransformUtil.cs | 51 +++++++++++++++++ 7 files changed, 125 insertions(+), 58 deletions(-) create mode 100644 Src/Utilities/XMLUtils/XslCompiledTransformUtil.cs diff --git a/Src/LexText/ParserUI/HCTrace.cs b/Src/LexText/ParserUI/HCTrace.cs index 071abccb66..4760fcacf9 100644 --- a/Src/LexText/ParserUI/HCTrace.cs +++ b/Src/LexText/ParserUI/HCTrace.cs @@ -2,6 +2,7 @@ using System.IO; using System.Xml; using System.Xml.Linq; +using System.Xml.Xsl; using SIL.FieldWorks.WordWorks.Parser; using SIL.Utils; using XCore; @@ -43,18 +44,14 @@ public override string CreateResultPage(string result) m_parseResult = XDocument.Parse(result); - string sInput = CreateTempFile(m_sTrace, "xml"); - m_parseResult.Save(sInput); - TransformKind kind = (fIsTrace ? TransformKind.kcptTrace : TransformKind.kcptParse); - string sOutput = TransformToHtml(sInput, kind); - return sOutput; + return TransformToHtml(m_parseResult, kind); } - protected override void AddParserSpecificArguments(List args) + protected override void AddParserSpecificArguments(XsltArgumentList argumentList) { string sLoadErrorFile = Path.Combine(Path.GetTempPath(), m_sDataBaseName + "HCLoadErrors.xml"); - args.Add(new XmlUtils.XSLParameter("prmHCTraceLoadErrorFile", sLoadErrorFile)); + argumentList.AddParam("prmHCTraceLoadErrorFile", "", sLoadErrorFile); } } } diff --git a/Src/LexText/ParserUI/ParserTrace.cs b/Src/LexText/ParserUI/ParserTrace.cs index fd7af2a157..e4010c986f 100644 --- a/Src/LexText/ParserUI/ParserTrace.cs +++ b/Src/LexText/ParserUI/ParserTrace.cs @@ -1,9 +1,6 @@ -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Text; -using System.Xml; -using SIL.FieldWorks.WordWorks.Parser; -using SIL.Utils; +using System.Xml.Linq; +using System.Xml.Xsl; using XCore; namespace SIL.FieldWorks.LexText.Controls @@ -76,20 +73,20 @@ public string PopWordGrammarStack() return m_wordGrammarDebugger.PopWordGrammarStack(); } - protected string TransformToHtml(string sInputFile, TransformKind kind) + protected string TransformToHtml(XDocument xDocument, TransformKind kind) { string sOutput = null; - var args = new List(); + var argumentList = new XsltArgumentList(); switch (kind) { case TransformKind.kcptParse: - sOutput = TransformToHtml(sInputFile, m_sParse, m_sFormatParse, args); + sOutput = TransformToHtml(xDocument, m_sParse, m_sFormatParse, argumentList); break; case TransformKind.kcptTrace: string sIconPath = CreateIconPath(); - args.Add(new XmlUtils.XSLParameter("prmIconPath", sIconPath)); - sOutput = TransformToHtml(sInputFile, m_sTrace, m_sFormatTrace, args); + argumentList.AddParam("prmIconPath", "", sIconPath); + sOutput = TransformToHtml(xDocument, m_sTrace, m_sFormatTrace, argumentList); break; } return sOutput; diff --git a/Src/LexText/ParserUI/ParserTraceBase.cs b/Src/LexText/ParserUI/ParserTraceBase.cs index 5f042751d8..b2de19ad47 100644 --- a/Src/LexText/ParserUI/ParserTraceBase.cs +++ b/Src/LexText/ParserUI/ParserTraceBase.cs @@ -1,6 +1,6 @@ -using System.Collections.Generic; using System.IO; using System.Xml.Linq; +using System.Xml.Xsl; using SIL.CoreImpl; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.Common.FwUtils; @@ -52,39 +52,49 @@ protected string TransformPath get { return FwDirectoryFinder.GetCodeSubDirectory(@"Language Explorer/Configuration/Words/Analyses/TraceParse"); } } - protected string TransformToHtml(string sInputFile, string sTempFileBase, string sTransformFile, List args) + protected string TransformToHtml(string inputPath, string tempFileBase, string transformFile, XsltArgumentList argumentList) { - string sOutput = CreateTempFile(sTempFileBase, "htm"); - string sTransform = Path.Combine(TransformPath, sTransformFile); - SetWritingSystemBasedArguments(args); - AddParserSpecificArguments(args); - XmlUtils.TransformFileToFile(sTransform, args.ToArray(), sInputFile, sOutput); - return sOutput; + string outputPath = CreateTempFile(tempFileBase, "htm"); + string transformPath = Path.Combine(TransformPath, transformFile); + SetWritingSystemBasedArguments(argumentList); + AddParserSpecificArguments(argumentList); + XslCompiledTransformUtil.Instance.TransformFileToFile(transformPath, inputPath, outputPath, argumentList); + return outputPath; } - private void SetWritingSystemBasedArguments(List args) + protected string TransformToHtml(XDocument inputDoc, string tempFileBase, string transformFile, XsltArgumentList argumentList) + { + string outputPath = CreateTempFile(tempFileBase, "htm"); + string transformPath = Path.Combine(TransformPath, transformFile); + SetWritingSystemBasedArguments(argumentList); + AddParserSpecificArguments(argumentList); + XslCompiledTransformUtil.Instance.TransformXDocumentToFile(transformPath, inputDoc, outputPath, argumentList); + return outputPath; + } + + private void SetWritingSystemBasedArguments(XsltArgumentList argumentList) { ILgWritingSystemFactory wsf = m_cache.WritingSystemFactory; IWritingSystemContainer wsContainer = m_cache.ServiceLocator.WritingSystems; IWritingSystem defAnalWs = wsContainer.DefaultAnalysisWritingSystem; using (var myFont = FontHeightAdjuster.GetFontForNormalStyle(defAnalWs.Handle, m_mediator, wsf)) { - args.Add(new XmlUtils.XSLParameter("prmAnalysisFont", myFont.FontFamily.Name)); - args.Add(new XmlUtils.XSLParameter("prmAnalysisFontSize", myFont.Size + "pt")); + argumentList.AddParam("prmAnalysisFont", "", myFont.FontFamily.Name); + argumentList.AddParam("prmAnalysisFontSize", "", myFont.Size + "pt"); } IWritingSystem defVernWs = wsContainer.DefaultVernacularWritingSystem; using (var myFont = FontHeightAdjuster.GetFontForNormalStyle(defVernWs.Handle, m_mediator, wsf)) { - args.Add(new XmlUtils.XSLParameter("prmVernacularFont", myFont.FontFamily.Name)); - args.Add(new XmlUtils.XSLParameter("prmVernacularFontSize", myFont.Size + "pt")); + argumentList.AddParam("prmVernacularFont", "", myFont.FontFamily.Name); + argumentList.AddParam("prmVernacularFontSize", "", myFont.Size + "pt"); } string sRtl = defVernWs.RightToLeftScript ? "Y" : "N"; - args.Add(new XmlUtils.XSLParameter("prmVernacularRTL", sRtl)); + argumentList.AddParam("prmVernacularRTL", "", sRtl); } - protected virtual void AddParserSpecificArguments(List args) + protected virtual void AddParserSpecificArguments(XsltArgumentList argumentList) { // default is to do nothing } diff --git a/Src/LexText/ParserUI/WordGrammarDebugger.cs b/Src/LexText/ParserUI/WordGrammarDebugger.cs index ed0533186c..ed8bf59373 100644 --- a/Src/LexText/ParserUI/WordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/WordGrammarDebugger.cs @@ -5,6 +5,7 @@ using System.Xml; using System.Xml.Linq; using System.Xml.XPath; +using System.Xml.Xsl; using SIL.FieldWorks.FDO; using SIL.FieldWorks.WordWorks.Parser; using SIL.Utils; @@ -45,10 +46,10 @@ protected WordGrammarDebugger(Mediator mediator) public string SetUpWordGrammarDebuggerPage(string nodeId, string form, string lastUrl) { m_xmlHtmlStack.Push(new WordGrammarStepPair(null, lastUrl)); - string initialAnalysisFile = CreateTempFile(CreateWordGrammarDebuggerFileName(), "xml"); - using (var writer = XmlWriter.Create(initialAnalysisFile)) + var doc = new XDocument(); + using (XmlWriter writer = doc.CreateWriter()) CreateAnalysisXml(writer, nodeId, form); - return CreateWordDebuggerPage(initialAnalysisFile); + return CreateWordDebuggerPage(doc); } /// @@ -197,38 +198,51 @@ private void CreateInflectionClassesAndSubclassesXmlElement(XmlWriter writer, IE } } - private string CreateWordDebuggerPage(string sXmlFile) + private string CreateWordDebuggerPage(object xml) { // apply word grammar step transform file - string sXmlOutput = TransformToXml(sXmlFile); - m_wordGrammarDebuggerXmlFile = sXmlOutput; + string xmlOutput = TransformToXml(xml); + m_wordGrammarDebuggerXmlFile = xmlOutput; // format the result - string sOutput = TransformToHtml(sXmlOutput); - return sOutput; + return TransformToHtml(xmlOutput); } private string CreateWordGrammarDebuggerFileName() { - string sDepthLevel = m_xmlHtmlStack.Count.ToString(CultureInfo.InvariantCulture); - return "WordGrammarDebugger" + sDepthLevel; + string depthLevel = m_xmlHtmlStack.Count.ToString(CultureInfo.InvariantCulture); + return "WordGrammarDebugger" + depthLevel; } - protected string TransformToHtml(string sInputFile) + protected string TransformToHtml(string inputPath) { - var args = new List(); - string sOutput = TransformToHtml(sInputFile, CreateWordGrammarDebuggerFileName(), - "FormatXAmpleWordGrammarDebuggerResult.xsl", args); - return sOutput; + return TransformToHtml(inputPath, CreateWordGrammarDebuggerFileName(), + "FormatXAmpleWordGrammarDebuggerResult.xsl", new XsltArgumentList()); } - private string TransformToXml(string sInputFile) + protected string TransformToHtml(XDocument inputDoc) + { + return TransformToHtml(inputDoc, CreateWordGrammarDebuggerFileName(), + "FormatXAmpleWordGrammarDebuggerResult.xsl", new XsltArgumentList()); + } + + private string TransformToXml(string inputPath) + { + // Don't overwrite the input file before transforming it! (why +"A" on the next line) + string outputPath = CreateTempFile(CreateWordGrammarDebuggerFileName() + "A", "xml"); + string xslFileName = m_sDataBaseName + "XAmpleWordGrammarDebugger" + ".xsl"; + string transform = Path.Combine(Path.GetDirectoryName(outputPath), xslFileName); + XslCompiledTransformUtil.Instance.TransformFileToFile(transform, inputPath, outputPath, new XsltArgumentList()); + return outputPath; + } + + private string TransformToXml(XDocument inputDoc) { // Don't overwrite the input file before transforming it! (why +"A" on the next line) - string sOutput = CreateTempFile(CreateWordGrammarDebuggerFileName()+"A", "xml"); - string sName = m_sDataBaseName + "XAmpleWordGrammarDebugger" + ".xsl"; - string sTransform = Path.Combine(Path.GetDirectoryName(sOutput), sName); - XmlUtils.TransformFileToFile(sTransform, new XmlUtils.XSLParameter[0], sInputFile, sOutput); - return sOutput; + string outputPath = CreateTempFile(CreateWordGrammarDebuggerFileName() + "A", "xml"); + string xslFileName = m_sDataBaseName + "XAmpleWordGrammarDebugger" + ".xsl"; + string transform = Path.Combine(Path.GetDirectoryName(outputPath), xslFileName); + XslCompiledTransformUtil.Instance.TransformXDocumentToFile(transform, inputDoc, outputPath, new XsltArgumentList()); + return outputPath; } public string InnerXml(XElement element) diff --git a/Src/LexText/ParserUI/XAmpleTrace.cs b/Src/LexText/ParserUI/XAmpleTrace.cs index a4bd479532..a69b89edf3 100644 --- a/Src/LexText/ParserUI/XAmpleTrace.cs +++ b/Src/LexText/ParserUI/XAmpleTrace.cs @@ -13,7 +13,6 @@ // XAmpleTrace - Deal with results of an XAmple trace // -using System.Xml; using System.Xml.Linq; using XCore; @@ -59,11 +58,8 @@ public override string CreateResultPage(string result) { m_parseResult = XDocument.Parse(result); - string sInput = CreateTempFile(m_sTrace, "xml"); - m_parseResult.Save(sInput); TransformKind kind = (m_parseResult.Root.Name == "AmpleTrace" ? TransformKind.kcptTrace : TransformKind.kcptParse); - string sOutput = TransformToHtml(sInput, kind); - return sOutput; + return TransformToHtml(m_parseResult, kind); } } } diff --git a/Src/Utilities/XMLUtils/XMLUtils.csproj b/Src/Utilities/XMLUtils/XMLUtils.csproj index 2e80695765..93c4f74f48 100644 --- a/Src/Utilities/XMLUtils/XMLUtils.csproj +++ b/Src/Utilities/XMLUtils/XMLUtils.csproj @@ -121,6 +121,7 @@ System.XML + @@ -129,6 +130,7 @@ CommonAssemblyInfo.cs + Code diff --git a/Src/Utilities/XMLUtils/XslCompiledTransformUtil.cs b/Src/Utilities/XMLUtils/XslCompiledTransformUtil.cs new file mode 100644 index 0000000000..7922884d5b --- /dev/null +++ b/Src/Utilities/XMLUtils/XslCompiledTransformUtil.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; +using System.IO; +using System.Xml.Linq; +using System.Xml.Xsl; + +namespace SIL.Utils +{ + public class XslCompiledTransformUtil + { + // Singleton + private static XslCompiledTransformUtil s_instance; + private XslCompiledTransformUtil() {} + public static XslCompiledTransformUtil Instance + { + get { return s_instance ?? (s_instance = new XslCompiledTransformUtil()); } + } + + private readonly Dictionary m_transformCache = new Dictionary(); + + public void TransformXDocumentToFile(string xslPath, XDocument inputDoc, string outputPath, XsltArgumentList argumentList) + { + XslCompiledTransform transform = GetTransform(xslPath); + var fileStream = new FileStream(outputPath, FileMode.Create); + transform.Transform(inputDoc.CreateReader(), argumentList, fileStream); + fileStream.Close(); + } + + public void TransformFileToFile(string xslPath, string inputPath, string outputPath, XsltArgumentList argumentList) + { + XslCompiledTransform transform = GetTransform(xslPath); + var fileStream = new FileStream(outputPath, FileMode.Create); + transform.Transform(inputPath, argumentList, fileStream); + fileStream.Close(); + } + + private XslCompiledTransform GetTransform(string xslPath) + { + lock(m_transformCache) + { + XslCompiledTransform compiledXsl; + if (m_transformCache.TryGetValue(xslPath, out compiledXsl)) + return compiledXsl; + + var transform = new XslCompiledTransform(); + transform.Load(xslPath); + m_transformCache.Add(xslPath, transform); + return transform; + } + } + } +} From 7069d083e1492ae9ef23be8306761331311aa174 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Thu, 13 Feb 2014 17:40:08 +0700 Subject: [PATCH 078/143] Fix Gendarme issues Change-Id: Ie0ca165aa2846ab716558787ce2db228548fb76d --- .../ParserEngine/ParserCore/HCParser.cs | 2 ++ Src/LexText/ParserUI/WordGrammarDebugger.cs | 21 ++++++++++++++----- .../XMLUtils/XslCompiledTransformUtil.cs | 16 ++++++++------ 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/Src/LexText/ParserEngine/ParserCore/HCParser.cs b/Src/LexText/ParserEngine/ParserCore/HCParser.cs index 14dddc46ff..5de124f0a3 100644 --- a/Src/LexText/ParserEngine/ParserCore/HCParser.cs +++ b/Src/LexText/ParserEngine/ParserCore/HCParser.cs @@ -779,6 +779,8 @@ public void ToXml(XmlWriter writer) #endregion #region class FwXmlTraceManager + [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", + Justification = "m_cache is a reference and disposed in the parent class")] private class FwXmlTraceManager : XmlTraceManager { private readonly FdoCache m_cache; diff --git a/Src/LexText/ParserUI/WordGrammarDebugger.cs b/Src/LexText/ParserUI/WordGrammarDebugger.cs index ed8bf59373..d067042f61 100644 --- a/Src/LexText/ParserUI/WordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/WordGrammarDebugger.cs @@ -198,10 +198,19 @@ private void CreateInflectionClassesAndSubclassesXmlElement(XmlWriter writer, IE } } - private string CreateWordDebuggerPage(object xml) + private string CreateWordDebuggerPage(string xmlPath) { // apply word grammar step transform file - string xmlOutput = TransformToXml(xml); + string xmlOutput = TransformToXml(xmlPath); + m_wordGrammarDebuggerXmlFile = xmlOutput; + // format the result + return TransformToHtml(xmlOutput); + } + + private string CreateWordDebuggerPage(XDocument xmlDoc) + { + // apply word grammar step transform file + string xmlOutput = TransformToXml(xmlDoc); m_wordGrammarDebuggerXmlFile = xmlOutput; // format the result return TransformToHtml(xmlOutput); @@ -247,9 +256,11 @@ private string TransformToXml(XDocument inputDoc) public string InnerXml(XElement element) { - XmlReader xmlReader = element.CreateReader(); - xmlReader.MoveToContent(); - return xmlReader.ReadInnerXml(); + using (XmlReader xmlReader = element.CreateReader()) + { + xmlReader.MoveToContent(); + return xmlReader.ReadInnerXml(); + } } } } diff --git a/Src/Utilities/XMLUtils/XslCompiledTransformUtil.cs b/Src/Utilities/XMLUtils/XslCompiledTransformUtil.cs index 7922884d5b..0ba243bc28 100644 --- a/Src/Utilities/XMLUtils/XslCompiledTransformUtil.cs +++ b/Src/Utilities/XMLUtils/XslCompiledTransformUtil.cs @@ -20,17 +20,21 @@ public static XslCompiledTransformUtil Instance public void TransformXDocumentToFile(string xslPath, XDocument inputDoc, string outputPath, XsltArgumentList argumentList) { XslCompiledTransform transform = GetTransform(xslPath); - var fileStream = new FileStream(outputPath, FileMode.Create); - transform.Transform(inputDoc.CreateReader(), argumentList, fileStream); - fileStream.Close(); + using (var fileStream = new FileStream(outputPath, FileMode.Create)) + { + transform.Transform(inputDoc.CreateReader(), argumentList, fileStream); + fileStream.Close(); + } } public void TransformFileToFile(string xslPath, string inputPath, string outputPath, XsltArgumentList argumentList) { XslCompiledTransform transform = GetTransform(xslPath); - var fileStream = new FileStream(outputPath, FileMode.Create); - transform.Transform(inputPath, argumentList, fileStream); - fileStream.Close(); + using (var fileStream = new FileStream(outputPath, FileMode.Create)) + { + transform.Transform(inputPath, argumentList, fileStream); + fileStream.Close(); + } } private XslCompiledTransform GetTransform(string xslPath) From 883a4f9aa7ae13babb48822894039d62bfedf630 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Thu, 13 Feb 2014 16:55:00 +0700 Subject: [PATCH 079/143] Changed parser trace result to be a XDocument Change-Id: I8dbdf07e17ef6907604e3f56aa0328572347fade --- .../ParserEngine/ParserCore/HCParser.cs | 168 +++++------------- .../ParserEngine/ParserCore/IParser.cs | 8 +- .../ParserCore/ParserCoreStrings.Designer.cs | 11 +- .../ParserCore/ParserCoreStrings.resx | 3 - .../ParserEngine/ParserCore/ParserWorker.cs | 3 +- .../ParserEngine/ParserCore/TaskReport.cs | 6 +- .../ParserEngine/ParserCore/XAmpleParser.cs | 64 ++++--- Src/LexText/ParserUI/HCTrace.cs | 12 +- Src/LexText/ParserUI/HCWordGrammarDebugger.cs | 6 +- Src/LexText/ParserUI/ParserConnection.cs | 5 +- Src/LexText/ParserUI/ParserTrace.cs | 5 +- .../ParserUI/ParserUIStrings.Designer.cs | 11 +- Src/LexText/ParserUI/ParserUIStrings.resx | 3 + Src/LexText/ParserUI/TryAWordDlg.cs | 9 +- Src/LexText/ParserUI/WordGrammarDebugger.cs | 47 ++--- Src/LexText/ParserUI/XAmpleTrace.cs | 6 +- .../ParserUI/XAmpleWordGrammarDebugger.cs | 6 +- .../XMLUtils/XslCompiledTransformUtil.cs | 3 +- 18 files changed, 139 insertions(+), 237 deletions(-) diff --git a/Src/LexText/ParserEngine/ParserCore/HCParser.cs b/Src/LexText/ParserEngine/ParserCore/HCParser.cs index 5de124f0a3..056ec2118a 100644 --- a/Src/LexText/ParserEngine/ParserCore/HCParser.cs +++ b/Src/LexText/ParserEngine/ParserCore/HCParser.cs @@ -128,14 +128,14 @@ public ParseResult ParseWord(string word) return result; } - public string TraceWordXml(string form, string selectTraceMorphs) + public XDocument TraceWordXml(string form, string selectTraceMorphs) { CheckDisposed(); return TraceWordXml(form, GetArrayFromString(selectTraceMorphs)); } - public string ParseWordXml(string form) + public XDocument ParseWordXml(string form) { CheckDisposed(); @@ -143,7 +143,7 @@ public string ParseWordXml(string form) } #endregion - public string TraceWordXml(string form, string[] selectTraceMorphs) + public XDocument TraceWordXml(string form, string[] selectTraceMorphs) { CheckDisposed(); @@ -251,34 +251,64 @@ private string[] GetArrayFromString(string selectTraceMorphs) return selectTraceMorphIds; } - private string ParseToXml(string form, bool trace, string[] selectTraceMorphs) + private XDocument ParseToXml(string form, bool trace, string[] selectTraceMorphs) { if (!m_loader.IsLoaded) - return ParserCoreStrings.ksDidNotParse; - - var sb = new StringBuilder(); - var settings = new XmlWriterSettings { OmitXmlDeclaration = true }; + return null; + var doc = new XDocument(); using (new WorkerThreadReadHelper(m_cache.ServiceLocator.GetInstance())) { - using (var writer = XmlWriter.Create(sb, settings)) + using (XmlWriter writer = doc.CreateWriter()) { writer.WriteStartElement("Wordform"); writer.WriteAttributeString("DbRef", Convert.ToString(0)); writer.WriteAttributeString("Form", form); MorphAndLookupWord(writer, m_loader.CurrentMorpher, form, true, selectTraceMorphs, Path.Combine(m_outputDirectory, m_projectName + "patrlex.txt"), trace); - AddImpliedDataCheckerInfo(writer); + WriteDataIssues(writer); writer.WriteEndElement(); } } - return sb.ToString(); + return doc; } - private void AddImpliedDataCheckerInfo(XmlWriter writer) + /// + /// Check integrity of phoneme-based natural classes (PhNCSegments) + /// when there are phonological features + /// + public void WriteDataIssues(XmlWriter writer) { - var impliedDataChecker = new ImpliedDataChecker(m_cache); - impliedDataChecker.CheckPhonemeBasedNaturalClasses(); - impliedDataChecker.ToXml(writer); + if (!m_cache.LangProject.PhFeatureSystemOA.FeaturesOC.Any()) + return; // no phonological features so nothing to check + + writer.WriteStartElement("DataIssues"); + foreach (IPhNCSegments natClass in m_cache.LangProject.PhonologicalDataOA.NaturalClassesOS.OfType()) + { + IFsFeatStruc fs = natClass.GetImpliedPhonologicalFeatures(); + var predictedPhonemes = new HashSet(natClass.GetPredictedPhonemes(fs)); + if (!predictedPhonemes.SetEquals(natClass.SegmentsRC)) + { + writer.WriteStartElement("NatClassPhonemeMismatch"); + writer.WriteStartElement("ClassName"); + writer.WriteString(natClass.Name.BestAnalysisAlternative.Text); + writer.WriteEndElement(); + writer.WriteStartElement("ClassAbbeviation"); + writer.WriteString(natClass.Abbreviation.BestAnalysisAlternative.Text); + writer.WriteEndElement(); + writer.WriteStartElement("ImpliedPhonologicalFeatures"); + writer.WriteString(fs.LongName); + writer.WriteEndElement(); + writer.WriteStartElement("PredictedPhonemes"); + writer.WriteString(string.Join(" ", predictedPhonemes.Select(p => p.Name.BestVernacularAlternative.Text))); + writer.WriteEndElement(); + writer.WriteStartElement("ActualPhonemes"); + writer.WriteString(string.Join(" ", natClass.SegmentsRC.Select(p => p.Name.BestVernacularAlternative.Text))); + writer.WriteEndElement(); + writer.WriteEndElement(); + writer.WriteEndElement(); + } + } + writer.WriteEndElement(); } private IEnumerable ProcessPatr(IEnumerable synthesisRecs, string patrlexPath, bool trace) @@ -574,119 +604,13 @@ private void Write(XmlWriter writer, MorphException me) } #endregion + #region class PatrResult private class PatrResult { public List Morphs { get; set; } public WordGrammarTrace WordGrammarTrace { get; set; } public bool PassedPatr { get; set; } } - - #region class ImpliedDataChecker - [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", - Justification = "m_cache is a reference and disposed in the parent class")] - private class ImpliedDataChecker - { - private readonly FdoCache m_cache; - private readonly List m_mismatches = new List(); - - public ImpliedDataChecker(FdoCache cache) - { - m_cache = cache; - } - - /// - /// Check integrity of phoneme-based natural classes (PhNCSegments) - /// when there are phonological features - /// - public void CheckPhonemeBasedNaturalClasses() - { - var feats = m_cache.LangProject.PhFeatureSystemOA.FeaturesOC; - if (!feats.Any()) - return; // no phonological features so nothing to check - foreach (var natClass in m_cache.LangProject.PhonologicalDataOA.NaturalClassesOS.OfType()) - { - IFsFeatStruc fs = natClass.GetImpliedPhonologicalFeatures(); - IEnumerable predictedPhonemes = natClass.GetPredictedPhonemes(fs).OrderBy(ph => ph.Hvo); - if (!predictedPhonemes.SequenceEqual(natClass.SegmentsRC.OrderBy(ph => ph.Hvo))) - { - var mismatch = new PhonemeBasedNaturalClassMismatch(fs, predictedPhonemes, natClass); - m_mismatches.Add(mismatch); - } - } - } - /// - /// Report information as XML - /// - /// - public void ToXml(XmlWriter writer) - { - if (!m_mismatches.Any()) - return; - writer.WriteStartElement("DataIssues"); - foreach (var mismatch in m_mismatches) - { - writer.WriteStartElement("NatClassPhonemeMismatch"); - writer.WriteStartElement("ClassName"); - writer.WriteString(mismatch.NaturalClass.Name.BestAnalysisAlternative.Text); - writer.WriteEndElement(); - writer.WriteStartElement("ClassAbbeviation"); - writer.WriteString(mismatch.NaturalClass.Abbreviation.BestAnalysisAlternative.Text); - writer.WriteEndElement(); - writer.WriteStartElement("ImpliedPhonologicalFeatures"); - writer.WriteString(mismatch.ImpliedPhonologicalFeatures.LongName); - writer.WriteEndElement(); - writer.WriteStartElement("PredictedPhonemes"); - writer.WriteString(mismatch.ListOfPhonemes(mismatch.PredictedPhonemes)); - writer.WriteEndElement(); - writer.WriteStartElement("ActualPhonemes"); - writer.WriteString(mismatch.ListOfPhonemes(mismatch.NaturalClass.SegmentsRC)); - writer.WriteEndElement(); - writer.WriteEndElement(); - } - writer.WriteEndElement(); - } - - [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", - Justification = "All felds are references and are disposed in the parent class")] - private class PhonemeBasedNaturalClassMismatch - { - private readonly IFsFeatStruc m_impliedPhonologicalFeatures; - private readonly IEnumerable m_predictedPhonemes; - private readonly IPhNCSegments m_natClass; - - public PhonemeBasedNaturalClassMismatch(IFsFeatStruc fs, IEnumerable predictedPhonemes, IPhNCSegments natClass) - { - m_impliedPhonologicalFeatures = fs; - m_predictedPhonemes = predictedPhonemes; - m_natClass = natClass; - } - - public IFsFeatStruc ImpliedPhonologicalFeatures - { - get { return m_impliedPhonologicalFeatures; } - } - - public IEnumerable PredictedPhonemes - { - get { return m_predictedPhonemes; } - } - - public IPhNCSegments NaturalClass - { - get { return m_natClass; } - } - public string ListOfPhonemes(IEnumerable list) - { - var sb = new StringBuilder(); - foreach (var phoneme in list) - { - sb.Append(phoneme.Name.BestVernacularAlternative.Text); - sb.Append(" "); - } - return sb.ToString(); - } - } - } #endregion #region class WordGrammarTrace diff --git a/Src/LexText/ParserEngine/ParserCore/IParser.cs b/Src/LexText/ParserEngine/ParserCore/IParser.cs index 3158b94383..f19ebf0c6d 100644 --- a/Src/LexText/ParserEngine/ParserCore/IParser.cs +++ b/Src/LexText/ParserEngine/ParserCore/IParser.cs @@ -1,4 +1,6 @@ -namespace SIL.FieldWorks.WordWorks.Parser +using System.Xml.Linq; + +namespace SIL.FieldWorks.WordWorks.Parser { public interface IParser { @@ -12,8 +14,8 @@ public interface IParser ParseResult ParseWord(string word); - string ParseWordXml(string word); + XDocument ParseWordXml(string word); - string TraceWordXml(string word, string selectTraceMorphs); + XDocument TraceWordXml(string word, string selectTraceMorphs); } } diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.Designer.cs b/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.Designer.cs index e354272279..99cdecf887 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.Designer.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.18408 +// Runtime Version:4.0.30319.18444 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -69,15 +69,6 @@ internal static string ksCreatingX { } } - /// - /// Looks up a localized string similar to Parse was not attempted because of errors in the lexical data. - /// - internal static string ksDidNotParse { - get { - return ResourceManager.GetString("ksDidNotParse", resourceCulture); - } - } - /// /// Looks up a localized string similar to error encountered. /// diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.resx b/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.resx index 72b5acecfd..67ef65a698 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.resx +++ b/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.resx @@ -120,9 +120,6 @@ Creating {0} - - Parse was not attempted because of errors in the lexical data - error encountered diff --git a/Src/LexText/ParserEngine/ParserCore/ParserWorker.cs b/Src/LexText/ParserEngine/ParserCore/ParserWorker.cs index a19f9442a8..48bc3b8b80 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserWorker.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserWorker.cs @@ -111,8 +111,7 @@ public void TryAWord(string sForm, bool fDoTrace, string sSelectTraceMorphs) using (var task = new TaskReport(string.Format(ParserCoreStrings.ksTraceWordformX, sForm), m_taskUpdateHandler)) { string normForm = Icu.Normalize(sForm, Icu.UNormalizationMode.UNORM_NFD); - var result = fDoTrace ? m_parser.TraceWordXml(normForm, sSelectTraceMorphs) : m_parser.ParseWordXml(normForm); - task.Details = fDoTrace ? result : Icu.Normalize(result, Icu.UNormalizationMode.UNORM_NFD); + task.Details = fDoTrace ? m_parser.TraceWordXml(normForm, sSelectTraceMorphs) : m_parser.ParseWordXml(normForm); } } diff --git a/Src/LexText/ParserEngine/ParserCore/TaskReport.cs b/Src/LexText/ParserEngine/ParserCore/TaskReport.cs index b2d98c7a3e..122e792dbf 100644 --- a/Src/LexText/ParserEngine/ParserCore/TaskReport.cs +++ b/Src/LexText/ParserEngine/ParserCore/TaskReport.cs @@ -12,7 +12,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; - +using System.Xml.Linq; using SIL.Utils; namespace SIL.FieldWorks.WordWorks.Parser @@ -36,7 +36,7 @@ public enum TaskPhase {Started, Working, Finished, ErrorEncountered}; /// /// this was added to hold the results of a trace request /// - private string m_details; + private XDocument m_details; /// ----------------------------------------------------------------------------------- /// @@ -220,7 +220,7 @@ public string Description /// /// this is used to hold the results of a trace request /// - public string Details + public XDocument Details { set { diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs b/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs index 2c654d7dfc..5255115f1f 100644 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs +++ b/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs @@ -134,7 +134,7 @@ public ParseResult ParseWord(string word) return result; } - public string ParseWordXml(string word) + public XDocument ParseWordXml(string word) { CheckDisposed(); @@ -145,31 +145,34 @@ public string ParseWordXml(string word) sb.Remove(sb.Length - 1, 1); XDocument doc = XDocument.Parse(sb.ToString()); - foreach (XElement morphElem in doc.Descendants("Morph")) + using (new WorkerThreadReadHelper(m_cache.ServiceLocator.GetInstance())) { - var type = (string) morphElem.Attribute("type"); - var props = (string) morphElem.Element("props"); + foreach (XElement morphElem in doc.Descendants("Morph")) + { + var type = (string)morphElem.Attribute("type"); + var props = (string)morphElem.Element("props"); - XElement formElem = morphElem.Element("MoForm"); - Debug.Assert(formElem != null); - var formHvo = (int) formElem.Attribute("DbRef"); - var wordType = (string) formElem.Attribute("wordType"); + XElement formElem = morphElem.Element("MoForm"); + Debug.Assert(formElem != null); + var formHvo = (int)formElem.Attribute("DbRef"); + var wordType = (string)formElem.Attribute("wordType"); - XElement msaElem = morphElem.Element("MSI"); - Debug.Assert(msaElem != null); - var msaID = (string) msaElem.Attribute("DbRef"); + XElement msaElem = morphElem.Element("MSI"); + Debug.Assert(msaElem != null); + var msaID = (string)msaElem.Attribute("DbRef"); - using (XmlWriter writer = morphElem.CreateWriter()) - writer.WriteMorphInfoElements(m_cache, formHvo, msaID, wordType, props); + using (XmlWriter writer = morphElem.CreateWriter()) + writer.WriteMorphInfoElements(m_cache, formHvo, msaID, wordType, props); - using (XmlWriter writer = msaElem.CreateWriter()) - writer.WriteMsaElement(m_cache, msaID, formHvo, type, wordType); + using (XmlWriter writer = msaElem.CreateWriter()) + writer.WriteMsaElement(m_cache, msaID, formHvo, type, wordType); + } } - return doc.ToString(); + return doc; } - public string TraceWordXml(string word, string selectTraceMorphs) + public XDocument TraceWordXml(string word, string selectTraceMorphs) { CheckDisposed(); @@ -180,23 +183,26 @@ public string TraceWordXml(string word, string selectTraceMorphs) sb.Remove(sb.Length - 1, 1); XDocument doc = XDocument.Parse(sb.ToString()); - foreach (XElement morphElem in doc.Descendants("morph")) + using (new WorkerThreadReadHelper(m_cache.ServiceLocator.GetInstance())) { - var formHvo = (int) morphElem.Attribute("alloid"); - var msaID = (string) morphElem.Attribute("morphname"); - var type = (string) morphElem.Attribute("type"); - var props = (string) morphElem.Element("props"); - var wordType = (string) morphElem.Attribute("wordType"); - - using (XmlWriter writer = morphElem.CreateWriter()) + foreach (XElement morphElem in doc.Descendants("morph")) { - writer.WriteMorphInfoElements(m_cache, formHvo, msaID, wordType, props); - writer.WriteMsaElement(m_cache, msaID, formHvo, type, wordType); + var formHvo = (int)morphElem.Attribute("alloid"); + var msaID = (string)morphElem.Attribute("morphname"); + var type = (string)morphElem.Attribute("type"); + var props = (string)morphElem.Element("props"); + var wordType = (string)morphElem.Attribute("wordType"); + + using (XmlWriter writer = morphElem.CreateWriter()) + { + writer.WriteMorphInfoElements(m_cache, formHvo, msaID, wordType, props); + writer.WriteMsaElement(m_cache, msaID, formHvo, type, wordType); + } } + ConvertFailures(doc, GetStrRep); } - ConvertFailures(doc, GetStrRep); - return doc.ToString(); + return doc; } internal static void ConvertFailures(XDocument doc, Func strRepSelector) diff --git a/Src/LexText/ParserUI/HCTrace.cs b/Src/LexText/ParserUI/HCTrace.cs index 4760fcacf9..c357922db0 100644 --- a/Src/LexText/ParserUI/HCTrace.cs +++ b/Src/LexText/ParserUI/HCTrace.cs @@ -1,9 +1,8 @@ using System.Collections.Generic; +using System.Diagnostics; using System.IO; -using System.Xml; using System.Xml.Linq; using System.Xml.Xsl; -using SIL.FieldWorks.WordWorks.Parser; using SIL.Utils; using XCore; @@ -38,13 +37,12 @@ public override string SetUpWordGrammarDebuggerPage(string nodeId, string form, return m_wordGrammarDebugger.SetUpWordGrammarDebuggerPage(nodeId, form, lastUrl); } - public override string CreateResultPage(string result) + public override string CreateResultPage(XDocument result) { - bool fIsTrace = result.Contains(""); + m_parseResult = result; - m_parseResult = XDocument.Parse(result); - - TransformKind kind = (fIsTrace ? TransformKind.kcptTrace : TransformKind.kcptParse); + Debug.Assert(m_parseResult.Root != null); + TransformKind kind = (m_parseResult.Root.Element("Trace") != null ? TransformKind.kcptTrace : TransformKind.kcptParse); return TransformToHtml(m_parseResult, kind); } diff --git a/Src/LexText/ParserUI/HCWordGrammarDebugger.cs b/Src/LexText/ParserUI/HCWordGrammarDebugger.cs index 3265c14b12..2099cdaf06 100644 --- a/Src/LexText/ParserUI/HCWordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/HCWordGrammarDebugger.cs @@ -34,11 +34,7 @@ protected override void CreateMorphAffixAlloFeatsXElement(XmlWriter writer, XEle { XElement affixAlloFeatsNode = m_parseResult.XPathSelectElement("//Morph[MoForm/@DbRef='" + alloid.Value + "']/affixAlloFeats"); if (affixAlloFeatsNode != null) - { - writer.WriteStartElement("affixAlloFeats"); - writer.WriteRaw(InnerXml(affixAlloFeatsNode)); - writer.WriteEndElement(); - } + affixAlloFeatsNode.WriteTo(writer); } } diff --git a/Src/LexText/ParserUI/ParserConnection.cs b/Src/LexText/ParserUI/ParserConnection.cs index a580c53712..66af771da5 100644 --- a/Src/LexText/ParserUI/ParserConnection.cs +++ b/Src/LexText/ParserUI/ParserConnection.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.IO; using System.Threading; +using System.Xml.Linq; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.WordWorks.Parser; @@ -25,7 +26,7 @@ public sealed class ParserConnection : FwDisposableBase, IAsyncResult private string m_activity; private string m_notificationMessage; - private string m_traceResult; + private XDocument m_traceResult; private readonly ManualResetEvent m_event = new ManualResetEvent(false); private readonly object m_syncRoot = new object(); @@ -219,7 +220,7 @@ object IAsyncResult.AsyncState { lock (SyncRoot) { - string res = m_traceResult; + XDocument res = m_traceResult; m_traceResult = null; return res; } diff --git a/Src/LexText/ParserUI/ParserTrace.cs b/Src/LexText/ParserUI/ParserTrace.cs index e4010c986f..8a612f1e92 100644 --- a/Src/LexText/ParserUI/ParserTrace.cs +++ b/Src/LexText/ParserUI/ParserTrace.cs @@ -1,6 +1,7 @@ using System.Text; using System.Xml.Linq; using System.Xml.Xsl; +using SIL.Utils; using XCore; namespace SIL.FieldWorks.LexText.Controls @@ -41,9 +42,9 @@ protected ParserTrace(Mediator mediator) /// /// Create an HTML page of the results /// - /// XML string of the XAmple trace output + /// XML of the parse trace output /// URL of the resulting HTML page - public abstract string CreateResultPage(string result); + public abstract string CreateResultPage(XDocument result); /// /// Initialize what is needed to perform the word grammar debugging and diff --git a/Src/LexText/ParserUI/ParserUIStrings.Designer.cs b/Src/LexText/ParserUI/ParserUIStrings.Designer.cs index 8585847ad3..8abdfcd2cc 100644 --- a/Src/LexText/ParserUI/ParserUIStrings.Designer.cs +++ b/Src/LexText/ParserUI/ParserUIStrings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.18408 +// Runtime Version:4.0.30319.18444 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -105,6 +105,15 @@ internal static string ksDash { } } + /// + /// Looks up a localized string similar to Parse was not attempted because of errors in the lexical data. + /// + internal static string ksDidNotParse { + get { + return ResourceManager.GetString("ksDidNotParse", resourceCulture); + } + } + /// /// Looks up a localized string similar to NoDefaultCompounding. /// diff --git a/Src/LexText/ParserUI/ParserUIStrings.resx b/Src/LexText/ParserUI/ParserUIStrings.resx index bcdaf47207..46c4eb1c04 100644 --- a/Src/LexText/ParserUI/ParserUIStrings.resx +++ b/Src/LexText/ParserUI/ParserUIStrings.resx @@ -243,4 +243,7 @@ The Hermit Crab parser cannot currently run, because the morpheme "{0}" has an invalid reduplication environment. The problem is {1}. + + Parse was not attempted because of errors in the lexical data + \ No newline at end of file diff --git a/Src/LexText/ParserUI/TryAWordDlg.cs b/Src/LexText/ParserUI/TryAWordDlg.cs index da85abf9a6..9f205b45ed 100644 --- a/Src/LexText/ParserUI/TryAWordDlg.cs +++ b/Src/LexText/ParserUI/TryAWordDlg.cs @@ -20,6 +20,7 @@ using System.IO; using System.Windows.Forms; using System.Text; +using System.Xml.Linq; using SIL.FieldWorks.Common.RootSites; using SIL.FieldWorks.Common.Widgets; using SIL.FieldWorks.FDO; @@ -548,9 +549,9 @@ private void m_timer_Tick(object sender, EventArgs e) if (m_tryAWordResult != null && m_tryAWordResult.IsCompleted) { - var message = (string) m_tryAWordResult.AsyncState; + var result = (XDocument) m_tryAWordResult.AsyncState; string sOutput; - if (!message.TrimStart().StartsWith("<")) + if (result == null) { // It's an error message. sOutput = Path.GetTempFileName(); @@ -558,7 +559,7 @@ private void m_timer_Tick(object sender, EventArgs e) { writer.WriteLine(""); writer.WriteLine(""); - writer.WriteLine(message); + writer.WriteLine(ParserUIStrings.ksDidNotParse); writer.WriteLine(""); writer.WriteLine(""); writer.Close(); @@ -566,7 +567,7 @@ private void m_timer_Tick(object sender, EventArgs e) } else { - sOutput = m_webPageInteractor.ParserTrace.CreateResultPage(message); + sOutput = m_webPageInteractor.ParserTrace.CreateResultPage(result); } m_htmlControl.URL = sOutput; m_tryAWordResult = null; diff --git a/Src/LexText/ParserUI/WordGrammarDebugger.cs b/Src/LexText/ParserUI/WordGrammarDebugger.cs index d067042f61..f8afcd895e 100644 --- a/Src/LexText/ParserUI/WordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/WordGrammarDebugger.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Xml; @@ -63,10 +64,10 @@ public string SetUpWordGrammarDebuggerPage(string nodeId, string form, string la public string PerformAnotherWordGrammarDebuggerStepPage(string nodeId, string form, string lastUrl) { m_xmlHtmlStack.Push(new WordGrammarStepPair(m_wordGrammarDebuggerXmlFile, lastUrl)); - string nextFile = CreateTempFile("SelectedWordGrammarXml", "xml"); - using (var writer = XmlWriter.Create(nextFile)) + var doc = new XDocument(); + using (XmlWriter writer = doc.CreateWriter()) CreateSelectedWordGrammarXml(writer, nodeId, form); - return CreateWordDebuggerPage(nextFile); + return CreateWordDebuggerPage(doc); } public string PopWordGrammarStack() @@ -110,14 +111,14 @@ private void CreateSelectedWordGrammarXml(XmlWriter writer, string nodeId, strin // Find the sNode'th seq node string sSelect = "//seq[position()='" + nodeId + "']"; XElement selectedSeqNode = lastDoc.XPathSelectElement(sSelect); - string innerXml = InnerXml(selectedSeqNode); // create the "result so far node" - writer.WriteStartElement("resultsSoFar"); - writer.WriteRaw(innerXml); + writer.WriteStartElement("resultSoFar"); + foreach (XElement child in selectedSeqNode.Elements()) + child.WriteTo(writer); writer.WriteEndElement(); // create the seq node + selectedSeqNode.WriteTo(writer); writer.WriteStartElement("seq"); - writer.WriteRaw(innerXml); writer.WriteEndElement(); } @@ -198,15 +199,6 @@ private void CreateInflectionClassesAndSubclassesXmlElement(XmlWriter writer, IE } } - private string CreateWordDebuggerPage(string xmlPath) - { - // apply word grammar step transform file - string xmlOutput = TransformToXml(xmlPath); - m_wordGrammarDebuggerXmlFile = xmlOutput; - // format the result - return TransformToHtml(xmlOutput); - } - private string CreateWordDebuggerPage(XDocument xmlDoc) { // apply word grammar step transform file @@ -234,33 +226,16 @@ protected string TransformToHtml(XDocument inputDoc) "FormatXAmpleWordGrammarDebuggerResult.xsl", new XsltArgumentList()); } - private string TransformToXml(string inputPath) - { - // Don't overwrite the input file before transforming it! (why +"A" on the next line) - string outputPath = CreateTempFile(CreateWordGrammarDebuggerFileName() + "A", "xml"); - string xslFileName = m_sDataBaseName + "XAmpleWordGrammarDebugger" + ".xsl"; - string transform = Path.Combine(Path.GetDirectoryName(outputPath), xslFileName); - XslCompiledTransformUtil.Instance.TransformFileToFile(transform, inputPath, outputPath, new XsltArgumentList()); - return outputPath; - } - private string TransformToXml(XDocument inputDoc) { // Don't overwrite the input file before transforming it! (why +"A" on the next line) string outputPath = CreateTempFile(CreateWordGrammarDebuggerFileName() + "A", "xml"); string xslFileName = m_sDataBaseName + "XAmpleWordGrammarDebugger" + ".xsl"; - string transform = Path.Combine(Path.GetDirectoryName(outputPath), xslFileName); + string dir = Path.GetDirectoryName(outputPath); + Debug.Assert(dir != null); + string transform = Path.Combine(dir, xslFileName); XslCompiledTransformUtil.Instance.TransformXDocumentToFile(transform, inputDoc, outputPath, new XsltArgumentList()); return outputPath; } - - public string InnerXml(XElement element) - { - using (XmlReader xmlReader = element.CreateReader()) - { - xmlReader.MoveToContent(); - return xmlReader.ReadInnerXml(); - } - } } } diff --git a/Src/LexText/ParserUI/XAmpleTrace.cs b/Src/LexText/ParserUI/XAmpleTrace.cs index a69b89edf3..95d2f25d39 100644 --- a/Src/LexText/ParserUI/XAmpleTrace.cs +++ b/Src/LexText/ParserUI/XAmpleTrace.cs @@ -13,6 +13,7 @@ // XAmpleTrace - Deal with results of an XAmple trace // +using System.Diagnostics; using System.Xml.Linq; using XCore; @@ -54,10 +55,11 @@ public override string SetUpWordGrammarDebuggerPage(string nodeId, string form, /// /// XML string of the XAmple trace output /// URL of the resulting HTML page - public override string CreateResultPage(string result) + public override string CreateResultPage(XDocument result) { - m_parseResult = XDocument.Parse(result); + m_parseResult = result; + Debug.Assert(m_parseResult.Root != null); TransformKind kind = (m_parseResult.Root.Name == "AmpleTrace" ? TransformKind.kcptTrace : TransformKind.kcptParse); return TransformToHtml(m_parseResult, kind); } diff --git a/Src/LexText/ParserUI/XAmpleWordGrammarDebugger.cs b/Src/LexText/ParserUI/XAmpleWordGrammarDebugger.cs index 091f1901e8..d067d966ae 100644 --- a/Src/LexText/ParserUI/XAmpleWordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/XAmpleWordGrammarDebugger.cs @@ -34,11 +34,7 @@ protected override void CreateMorphAffixAlloFeatsXElement(XmlWriter writer, XEle { XElement affixAlloFeatsNode = element.XPathSelectElement("affixAlloFeats"); if (affixAlloFeatsNode != null) - { - writer.WriteStartElement("affixAlloFeats"); - writer.WriteRaw(InnerXml(affixAlloFeatsNode)); - writer.WriteEndElement(); - } + affixAlloFeatsNode.WriteTo(writer); } protected override void CreateMorphShortNameXElement(XmlWriter writer, XElement element) diff --git a/Src/Utilities/XMLUtils/XslCompiledTransformUtil.cs b/Src/Utilities/XMLUtils/XslCompiledTransformUtil.cs index 0ba243bc28..79bbdc71bc 100644 --- a/Src/Utilities/XMLUtils/XslCompiledTransformUtil.cs +++ b/Src/Utilities/XMLUtils/XslCompiledTransformUtil.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.IO; +using System.Xml; using System.Xml.Linq; using System.Xml.Xsl; @@ -46,7 +47,7 @@ private XslCompiledTransform GetTransform(string xslPath) return compiledXsl; var transform = new XslCompiledTransform(); - transform.Load(xslPath); + transform.Load(xslPath, new XsltSettings(true, false), new XmlUrlResolver()); m_transformCache.Add(xslPath, transform); return transform; } From 7b4a83b967b3fd0c657b58390a5ff9dad9f6f301 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 14 Feb 2014 13:28:22 +0700 Subject: [PATCH 080/143] simplified WordGrammarDebugger Change-Id: Iebf284500e77e099a16d5971bbb7a857a66e2ae1 --- .../ParserEngine/ParserCore/HCParser.cs | 88 ++++++------------- .../ParserCore/ParserXmlWriterExtensions.cs | 39 ++++++-- .../ParserEngine/ParserCore/XAmpleParser.cs | 29 +++--- Src/LexText/ParserUI/HCTrace.cs | 2 - Src/LexText/ParserUI/HCWordGrammarDebugger.cs | 44 ++-------- Src/LexText/ParserUI/WordGrammarDebugger.cs | 86 +----------------- .../ParserUI/XAmpleWordGrammarDebugger.cs | 42 +++------ 7 files changed, 100 insertions(+), 230 deletions(-) diff --git a/Src/LexText/ParserEngine/ParserCore/HCParser.cs b/Src/LexText/ParserEngine/ParserCore/HCParser.cs index 056ec2118a..7d46c09505 100644 --- a/Src/LexText/ParserEngine/ParserCore/HCParser.cs +++ b/Src/LexText/ParserEngine/ParserCore/HCParser.cs @@ -568,10 +568,10 @@ private void BuildXmlOutput(XmlWriter writer, IEnumerable morphs) writer.WriteStartElement("MSI"); writer.WriteAttributeString("DbRef", morph.msaId); - writer.WriteMsaElement(m_cache, morph.msaId, Convert.ToInt32(morph.formId), null, morph.wordType); + writer.WriteMsaElement(m_cache, morph.formId, morph.msaId, null, morph.wordType); writer.WriteEndElement(); - writer.WriteMorphInfoElements(m_cache, Convert.ToInt32(morph.formId), morph.msaId, morph.wordType, null); + writer.WriteMorphInfoElements(m_cache, morph.formId, morph.msaId, morph.wordType, null); writer.WriteEndElement(); } @@ -651,51 +651,24 @@ public void ToXml(XmlWriter writer) writer.WriteValue(m_id); writer.WriteEndElement(); - string sType = "pfx"; // try to guess morph type based on word type + string type = "pfx"; // try to guess morph type based on word type foreach (PcPatrMorph morph in m_morphs) { - writer.WriteStartElement("Morphs"); + writer.WriteStartElement("morph"); string sWordType = morph.wordType; writer.WriteAttributeString("wordType", sWordType); - if (sType == "pfx" && - sWordType == "root") - sType = "root"; - else if (sType == "root" && - sWordType != "root") - sType = "sfx"; - writer.WriteAttributeString("type", sType); + if (type == "pfx" && sWordType == "root") + type = "root"; + else if (type == "root" && sWordType != "root") + type = "sfx"; + writer.WriteAttributeString("type", type); writer.WriteAttributeString("alloid", morph.formId); writer.WriteAttributeString("morphname", morph.msaId); - writer.WriteElementString("alloform", morph.form); - - int hvoForm = Convert.ToInt32(morph.formId); - var obj = m_cache.ServiceLocator.GetObject(hvoForm); - var stemAllo = obj as IMoStemAllomorph; - if (stemAllo != null) - { - var stemName = stemAllo.StemNameRA; - if (stemName != null) - { - writer.WriteStartElement("stemName"); - writer.WriteStartAttribute("id"); - writer.WriteValue(stemName.Hvo); - writer.WriteEndAttribute(); - writer.WriteValue(stemName.Name.BestAnalysisAlternative.Text); - writer.WriteEndElement(); // stemName - } - } - writer.WriteElementString("gloss", morph.gloss); - writer.WriteStartElement("citationForm"); - var form = obj as IMoForm; - if (form != null) - { - var entry = form.Owner as ILexEntry; - if (entry != null) - writer.WriteValue(entry.HeadWord.Text); - } - writer.WriteEndElement(); // citationForm - writer.WriteEndElement(); // Morphs + writer.WriteMorphInfoElements(m_cache, morph.formId, morph.msaId, morph.wordType, morph.featureDescriptors); + writer.WriteMsaElement(m_cache, morph.formId, morph.msaId, type, morph.wordType); + writer.WriteInflClassesElement(m_cache, morph.formId); + writer.WriteEndElement(); // morph } writer.WriteEndElement(); } @@ -741,42 +714,37 @@ protected override XElement Write(string name, Allomorph allomorph) if (!String.IsNullOrEmpty(formIdsStr) || !String.IsNullOrEmpty(msaId)) { var morphElem = new XElement("Morph"); - + string firstFormId = null; + string firstWordType = null; + string featDesc = allomorph.GetProperty("FeatureDescriptors"); if (!String.IsNullOrEmpty(formIdsStr)) { string[] formIds = formIdsStr.Split(' '); string[] wordTypes = allomorph.GetProperty("WordCategory").Split(' '); for (int i = 0; i < formIds.Length; i++) { - int wordTypeIndex = WordTypeIndex(i, wordTypes.Count()); - morphElem.Add(new XElement("MoForm", new XAttribute("DbRef", formIds[i]), new XAttribute("wordType", wordTypes[wordTypeIndex]))); - string featDesc = allomorph.GetProperty("FeatureDescriptors"); + int wordTypeIndex = WordTypeIndex(i, wordTypes.Length); + string wordType = wordTypes[wordTypeIndex]; + morphElem.Add(new XElement("MoForm", new XAttribute("DbRef", formIds[i]), new XAttribute("wordType", wordType))); morphElem.Add(string.IsNullOrEmpty(featDesc) ? new XElement("props") : new XElement("props", featDesc)); + if (i == 0) + { + firstFormId = formIds[i]; + firstWordType = wordType; + } } } if (!String.IsNullOrEmpty(msaId)) { var msiElement = new XElement("MSI", new XAttribute("DbRef", msaId)); - XElement moFormElement = morphElem.Element("MoForm"); - int formId = 0; - string wordType = null; - if (moFormElement != null) - { - formId = Convert.ToInt32(moFormElement.Attribute("DbRef").Value); - wordType = moFormElement.Attribute("wordType").Value; - } - XElement propsElement = morphElem.Element("props"); using (XmlWriter writer = msiElement.CreateWriter()) - { - writer.WriteMsaElement(m_cache, msaId, formId, null, wordType); - } + writer.WriteMsaElement(m_cache, firstFormId, msaId, null, firstWordType); morphElem.Add(msiElement); - using (XmlWriter writer = msiElement.CreateWriter()) - { - writer.WriteMorphInfoElements(m_cache, formId, msaId, wordType, propsElement != null ? propsElement.Value : null); - } } + + using (XmlWriter writer = morphElem.CreateWriter()) + writer.WriteMorphInfoElements(m_cache, firstFormId, msaId, firstWordType, featDesc); elem.Add(morphElem); } diff --git a/Src/LexText/ParserEngine/ParserCore/ParserXmlWriterExtensions.cs b/Src/LexText/ParserEngine/ParserCore/ParserXmlWriterExtensions.cs index b20c34f51d..bd7d63fc64 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserXmlWriterExtensions.cs +++ b/Src/LexText/ParserEngine/ParserCore/ParserXmlWriterExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; @@ -11,9 +12,9 @@ namespace SIL.FieldWorks.WordWorks.Parser { - public static class ParserXmlWriterExtensions + internal static class ParserXmlWriterExtensions { - public static void WriteMsaElement(this XmlWriter writer, FdoCache cache, string msaID, int allomorphHvo, string type, string wordType) + public static void WriteMsaElement(this XmlWriter writer, FdoCache cache, string formID, string msaID, string type, string wordType) { // Irregulary inflected forms can have a combination MSA hvo: the LexEntry hvo, a period, and an index to the LexEntryRef Tuple msaTuple = ParserHelper.ProcessMsaHvo(msaID); @@ -26,7 +27,7 @@ public static void WriteMsaElement(this XmlWriter writer, FdoCache cache, string WriteStemMsaXmlElement(writer, (IMoStemMsa) obj); break; case "MoInflAffMsa": - WriteInflectionClasses(writer, cache, allomorphHvo); + WriteInflectionClasses(writer, cache, int.Parse(formID, CultureInfo.InvariantCulture)); WriteInflMsaXmlElement(writer, (IMoInflAffMsa) obj, type); break; case "MoDerivAffMsa": @@ -283,9 +284,9 @@ private static void HandleSlotInfoForInflectionalMsa(XmlWriter writer, IMoInflAf writer.WriteAttributeString("slotOptional", sSlotOptional); } - public static void WriteMorphInfoElements(this XmlWriter writer, FdoCache cache, int formHvo, string msaID, string wordType, string props) + public static void WriteMorphInfoElements(this XmlWriter writer, FdoCache cache, string formID, string msaID, string wordType, string props) { - ICmObject obj = cache.ServiceLocator.GetInstance().GetObject(formHvo); + ICmObject obj = cache.ServiceLocator.GetInstance().GetObject(int.Parse(formID, CultureInfo.InvariantCulture)); var form = obj as IMoForm; if (form == null) { @@ -528,5 +529,33 @@ private static void WritePosXmlAttribute(XmlWriter writer, IPartOfSpeech pos, st else writer.WriteAttributeString(sCat, "0"); } + + public static void WriteInflClassesElement(this XmlWriter writer, FdoCache cache, string formID) + { + int hvo = int.Parse(formID, CultureInfo.InvariantCulture); + ICmObject obj = cache.ServiceLocator.GetInstance().GetObject(hvo); + var form = obj as IMoAffixForm; // only for affix forms + if (form != null) + { + if (form.InflectionClassesRC.Count > 0) + { + writer.WriteStartElement("inflClasses"); + WriteInflectionClassesAndSubclassesXmlElement(writer, form.InflectionClassesRC); + writer.WriteEndElement(); + } + } + } + + private static void WriteInflectionClassesAndSubclassesXmlElement(XmlWriter writer, IEnumerable inflectionClasses) + { + foreach (IMoInflClass ic in inflectionClasses) + { + writer.WriteStartElement("inflClass"); + writer.WriteAttributeString("hvo", ic.Hvo.ToString(CultureInfo.InvariantCulture)); + writer.WriteAttributeString("abbr", ic.Abbreviation.BestAnalysisAlternative.Text); + writer.WriteEndElement(); + WriteInflectionClassesAndSubclassesXmlElement(writer, ic.SubclassesOC); + } + } } } diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs b/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs index 5255115f1f..830651aae3 100644 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs +++ b/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs @@ -149,23 +149,23 @@ public XDocument ParseWordXml(string word) { foreach (XElement morphElem in doc.Descendants("Morph")) { - var type = (string)morphElem.Attribute("type"); - var props = (string)morphElem.Element("props"); + var type = (string) morphElem.Attribute("type"); + var props = (string) morphElem.Element("props"); XElement formElem = morphElem.Element("MoForm"); Debug.Assert(formElem != null); - var formHvo = (int)formElem.Attribute("DbRef"); - var wordType = (string)formElem.Attribute("wordType"); + var formID = (string) formElem.Attribute("DbRef"); + var wordType = (string) formElem.Attribute("wordType"); XElement msaElem = morphElem.Element("MSI"); Debug.Assert(msaElem != null); - var msaID = (string)msaElem.Attribute("DbRef"); + var msaID = (string) msaElem.Attribute("DbRef"); using (XmlWriter writer = morphElem.CreateWriter()) - writer.WriteMorphInfoElements(m_cache, formHvo, msaID, wordType, props); + writer.WriteMorphInfoElements(m_cache, formID, msaID, wordType, props); using (XmlWriter writer = msaElem.CreateWriter()) - writer.WriteMsaElement(m_cache, msaID, formHvo, type, wordType); + writer.WriteMsaElement(m_cache, formID, msaID, type, wordType); } } @@ -187,16 +187,17 @@ public XDocument TraceWordXml(string word, string selectTraceMorphs) { foreach (XElement morphElem in doc.Descendants("morph")) { - var formHvo = (int)morphElem.Attribute("alloid"); - var msaID = (string)morphElem.Attribute("morphname"); - var type = (string)morphElem.Attribute("type"); - var props = (string)morphElem.Element("props"); - var wordType = (string)morphElem.Attribute("wordType"); + var formID = (string) morphElem.Attribute("alloid"); + var msaID = (string) morphElem.Attribute("morphname"); + var type = (string) morphElem.Attribute("type"); + var props = (string) morphElem.Element("props"); + var wordType = (string) morphElem.Attribute("wordType"); using (XmlWriter writer = morphElem.CreateWriter()) { - writer.WriteMorphInfoElements(m_cache, formHvo, msaID, wordType, props); - writer.WriteMsaElement(m_cache, msaID, formHvo, type, wordType); + writer.WriteMorphInfoElements(m_cache, formID, msaID, wordType, props); + writer.WriteMsaElement(m_cache, formID, msaID, type, wordType); + writer.WriteInflClassesElement(m_cache, formID); } } ConvertFailures(doc, GetStrRep); diff --git a/Src/LexText/ParserUI/HCTrace.cs b/Src/LexText/ParserUI/HCTrace.cs index c357922db0..1faefe7f5a 100644 --- a/Src/LexText/ParserUI/HCTrace.cs +++ b/Src/LexText/ParserUI/HCTrace.cs @@ -1,9 +1,7 @@ -using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Xml.Linq; using System.Xml.Xsl; -using SIL.Utils; using XCore; namespace SIL.FieldWorks.LexText.Controls diff --git a/Src/LexText/ParserUI/HCWordGrammarDebugger.cs b/Src/LexText/ParserUI/HCWordGrammarDebugger.cs index 2099cdaf06..915d27525a 100644 --- a/Src/LexText/ParserUI/HCWordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/HCWordGrammarDebugger.cs @@ -1,7 +1,7 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics; using System.Xml; using System.Xml.Linq; -using System.Xml.XPath; +using System.Linq; using XCore; namespace SIL.FieldWorks.LexText.Controls @@ -14,44 +14,14 @@ public HCWordGrammarDebugger(Mediator mediator, XDocument parseResult) m_parseResult = parseResult; } - [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", - Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] protected override void CreateMorphNodes(XmlWriter writer, string nodeId) { - string s = "//WordGrammarAttempt[Id=\"" + nodeId + "\"]"; - XElement element = m_parseResult.XPathSelectElement(s); - if (element != null) + Debug.Assert(m_parseResult.Root != null); + XElement wordGrammarAttemptElem = m_parseResult.Root.Elements("WordGrammarTrace").Elements("WordGrammarAttempt").FirstOrDefault(e => ((string) e.Element("Id")) == nodeId); + if (wordGrammarAttemptElem != null) { - foreach (XElement morph in element.Elements("Morphs")) - CreateMorphXElement(writer, morph); - } - } - - protected override void CreateMorphAffixAlloFeatsXElement(XmlWriter writer, XElement element) - { - XElement alloid = element.XPathSelectElement("@alloid"); - if (alloid != null) - { - XElement affixAlloFeatsNode = m_parseResult.XPathSelectElement("//Morph[MoForm/@DbRef='" + alloid.Value + "']/affixAlloFeats"); - if (affixAlloFeatsNode != null) - affixAlloFeatsNode.WriteTo(writer); - } - } - - protected override void CreateMorphShortNameXElement(XmlWriter writer, XElement element) - { - XElement formNode = element.XPathSelectElement("shortName"); - if (formNode != null) - { - writer.WriteElementString("shortName", formNode.Value); - } - else - { - XElement alloFormNode = element.XPathSelectElement("alloform"); - XElement glossNode = element.XPathSelectElement("gloss"); - XElement citationFormNode = element.XPathSelectElement("citationForm"); - if (alloFormNode != null && glossNode != null && citationFormNode != null) - writer.WriteElementString("shortName", string.Format("{0} ({1}): {2}", alloFormNode.Value, glossNode.Value, citationFormNode.Value)); + foreach (XElement morphElem in wordGrammarAttemptElem.Elements("morph")) + morphElem.WriteTo(writer); } } } diff --git a/Src/LexText/ParserUI/WordGrammarDebugger.cs b/Src/LexText/ParserUI/WordGrammarDebugger.cs index f8afcd895e..93d84f296d 100644 --- a/Src/LexText/ParserUI/WordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/WordGrammarDebugger.cs @@ -1,14 +1,11 @@ -using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; +using System.Linq; using System.Xml; using System.Xml.Linq; -using System.Xml.XPath; using System.Xml.Xsl; -using SIL.FieldWorks.FDO; -using SIL.FieldWorks.WordWorks.Parser; using SIL.Utils; using XCore; @@ -109,8 +106,8 @@ private void CreateSelectedWordGrammarXml(XmlWriter writer, string nodeId, strin writer.WriteElementString("form", form); // Find the sNode'th seq node - string sSelect = "//seq[position()='" + nodeId + "']"; - XElement selectedSeqNode = lastDoc.XPathSelectElement(sSelect); + Debug.Assert(lastDoc.Root != null); + XElement selectedSeqNode = lastDoc.Root.Elements("seq").ElementAt(int.Parse(nodeId, CultureInfo.InvariantCulture) - 1); // create the "result so far node" writer.WriteStartElement("resultSoFar"); foreach (XElement child in selectedSeqNode.Elements()) @@ -122,83 +119,6 @@ private void CreateSelectedWordGrammarXml(XmlWriter writer, string nodeId, strin writer.WriteEndElement(); } - protected void CreateMorphXElement(XmlWriter writer, XElement element) - { - writer.WriteStartElement("morph"); - XAttribute alloIdAttr = element.Attribute("alloid"); - if (alloIdAttr != null) - writer.WriteAttributeString("alloid", alloIdAttr.Value); - XAttribute morphnameAttr = element.Attribute("morphname"); - if (morphnameAttr != null) - writer.WriteAttributeString("morphname", morphnameAttr.Value); - XAttribute typeAttr = element.Attribute("type"); - if (typeAttr != null) - writer.WriteAttributeString("type", typeAttr.Value); - XAttribute wordTypeAttr = element.Attribute("wordType"); - if (wordTypeAttr != null) - writer.WriteAttributeString("wordType", wordTypeAttr.Value); - CreateMorphShortNameXElement(writer, element); - XElement formNode = element.XPathSelectElement("alloform"); - if (formNode != null) - writer.WriteElementString("alloform", formNode.Value); - XElement stemNameNode = element.XPathSelectElement("stemName"); - if (stemNameNode != null) - { - XAttribute idAttr = stemNameNode.Attribute("id"); - if (idAttr != null) - { - writer.WriteStartElement("stemName"); - writer.WriteAttributeString("id", idAttr.Value); - writer.WriteString(stemNameNode.Value); - writer.WriteEndElement(); - } - } - CreateMorphAffixAlloFeatsXElement(writer, element); - XElement glossNode = element.XPathSelectElement("gloss"); - if (glossNode != null) - writer.WriteElementString("gloss", glossNode.Value); - XElement citationFormNode = element.XPathSelectElement("citationForm"); - if (citationFormNode != null) - writer.WriteElementString("citationForm", citationFormNode.Value); - - if (alloIdAttr != null) - { - int hvo = Convert.ToInt32(alloIdAttr.Value); - ICmObject obj = m_cache.ServiceLocator.GetInstance().GetObject(hvo); - var form = obj as IMoAffixForm; // only for affix forms - if (form != null) - { - if (form.InflectionClassesRC.Count > 0) - { - writer.WriteStartElement("inflClasses"); - CreateInflectionClassesAndSubclassesXmlElement(writer, form.InflectionClassesRC); - } - } - } - if (morphnameAttr != null) - { - writer.WriteMsaElement(m_cache, morphnameAttr.Value, alloIdAttr == null ? 0 : Convert.ToInt32(alloIdAttr.Value), - typeAttr == null ? null : typeAttr.Value, wordTypeAttr == null ? null : wordTypeAttr.Value); - } - writer.WriteEndElement(); - } - - protected abstract void CreateMorphShortNameXElement(XmlWriter writer, XElement element); - - protected abstract void CreateMorphAffixAlloFeatsXElement(XmlWriter writer, XElement element); - - private void CreateInflectionClassesAndSubclassesXmlElement(XmlWriter writer, IEnumerable inflectionClasses) - { - foreach (IMoInflClass ic in inflectionClasses) - { - writer.WriteStartElement("inflClass"); - writer.WriteAttributeString("hvo", ic.Hvo.ToString(CultureInfo.InvariantCulture)); - writer.WriteAttributeString("abbr", ic.Abbreviation.BestAnalysisAlternative.Text); - writer.WriteEndElement(); - CreateInflectionClassesAndSubclassesXmlElement(writer, ic.SubclassesOC); - } - } - private string CreateWordDebuggerPage(XDocument xmlDoc) { // apply word grammar step transform file diff --git a/Src/LexText/ParserUI/XAmpleWordGrammarDebugger.cs b/Src/LexText/ParserUI/XAmpleWordGrammarDebugger.cs index d067d966ae..2b2cf92335 100644 --- a/Src/LexText/ParserUI/XAmpleWordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/XAmpleWordGrammarDebugger.cs @@ -1,6 +1,7 @@ -using System.Xml; +using System.Diagnostics; +using System.Xml; using System.Xml.Linq; -using System.Xml.XPath; +using System.Linq; using XCore; namespace SIL.FieldWorks.LexText.Controls @@ -15,33 +16,16 @@ public XAmpleWordGrammarDebugger(Mediator mediator, XDocument parseResult) protected override void CreateMorphNodes(XmlWriter writer, string nodeId) { - string s = "//failure[@id=\"" + nodeId + "\"]/ancestor::parseNode[morph][1]/morph"; - XElement node = m_parseResult.XPathSelectElement(s); - if (node != null) - CreateMorphNode(writer, node); - } - - private void CreateMorphNode(XmlWriter writer, XElement element) - { - // get the element closest up the chain to node - XElement morph = element.XPathSelectElement("../ancestor::parseNode[morph][1]/morph"); - if (morph != null) - CreateMorphNode(writer, morph); - CreateMorphXElement(writer, element); - } - - protected override void CreateMorphAffixAlloFeatsXElement(XmlWriter writer, XElement element) - { - XElement affixAlloFeatsNode = element.XPathSelectElement("affixAlloFeats"); - if (affixAlloFeatsNode != null) - affixAlloFeatsNode.WriteTo(writer); - } - - protected override void CreateMorphShortNameXElement(XmlWriter writer, XElement element) - { - XElement formNode = element.XPathSelectElement("shortName"); - if (formNode != null) - writer.WriteElementString("shortName", formNode.Value); + XElement failureElem = m_parseResult.Descendants("failure").FirstOrDefault(e => ((string) e.Attribute("id")) == nodeId); + if (failureElem != null) + { + foreach (XElement parseNodeElem in failureElem.Ancestors("parseNode").Where(e => e.Element("morph") != null).Reverse()) + { + XElement morphElem = parseNodeElem.Element("morph"); + Debug.Assert(morphElem != null); + morphElem.WriteTo(writer); + } + } } } } From d418a36edbded177cd28a69596ec50fae2ac5486 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 14 Feb 2014 16:11:25 +0700 Subject: [PATCH 081/143] refactored parser trace classes Change-Id: Ib2e0f2131abd5fac94b0a00d1513de84cf0ce101 --- Src/LexText/ParserUI/HCTrace.cs | 66 ++++++------ Src/LexText/ParserUI/HCWordGrammarDebugger.cs | 15 +-- Src/LexText/ParserUI/ParserTrace.cs | 98 +++-------------- Src/LexText/ParserUI/ParserTraceBase.cs | 102 ------------------ .../ParserUI/ParserTraceUITransform.cs | 81 ++++++++++++++ Src/LexText/ParserUI/ParserUI.csproj | 3 +- Src/LexText/ParserUI/TryAWordDlg.cs | 3 +- Src/LexText/ParserUI/WebPageInteractor.cs | 6 +- Src/LexText/ParserUI/WordGrammarDebugger.cs | 94 +++++++--------- Src/LexText/ParserUI/WordGrammarStepPair.cs | 47 -------- Src/LexText/ParserUI/XAmpleTrace.cs | 66 ++++++------ .../ParserUI/XAmpleWordGrammarDebugger.cs | 4 +- Src/Utilities/XMLUtils/XMLUtils.csproj | 1 - .../XMLUtils/XslCompiledTransformUtil.cs | 56 ---------- 14 files changed, 214 insertions(+), 428 deletions(-) delete mode 100644 Src/LexText/ParserUI/ParserTraceBase.cs create mode 100644 Src/LexText/ParserUI/ParserTraceUITransform.cs delete mode 100644 Src/LexText/ParserUI/WordGrammarStepPair.cs delete mode 100644 Src/Utilities/XMLUtils/XslCompiledTransformUtil.cs diff --git a/Src/LexText/ParserUI/HCTrace.cs b/Src/LexText/ParserUI/HCTrace.cs index 1faefe7f5a..4d56f191d3 100644 --- a/Src/LexText/ParserUI/HCTrace.cs +++ b/Src/LexText/ParserUI/HCTrace.cs @@ -1,53 +1,55 @@ -using System.Diagnostics; using System.IO; using System.Xml.Linq; using System.Xml.Xsl; +using SIL.FieldWorks.FDO; using XCore; namespace SIL.FieldWorks.LexText.Controls { public class HCTrace : ParserTrace { - /// - /// The real deal - /// - /// - public HCTrace(Mediator mediator) - : base(mediator) + private static ParserTraceUITransform s_traceTransform; + private static ParserTraceUITransform TraceTransform { - m_sParse = "HCParse"; - m_sTrace = "HCTrace"; - m_sFormatParse = "FormatXAmpleParse.xsl"; // the XAmple one works fine with Hermit Crab parse output - m_sFormatTrace = "FormatHCTrace.xsl"; + get + { + if (s_traceTransform == null) + s_traceTransform = new ParserTraceUITransform("FormatHCTrace.xsl"); + return s_traceTransform; + } } + private readonly Mediator m_mediator; + private readonly FdoCache m_cache; + /// - /// Initialize what is needed to perform the word grammar debugging and - /// produce an html page showing the results + /// The real deal /// - /// Id of the node to use - /// the wordform being tried - /// - /// temporary html file showing the results of the first step - public override string SetUpWordGrammarDebuggerPage(string nodeId, string form, string lastUrl) - { - m_wordGrammarDebugger = new HCWordGrammarDebugger(m_mediator, m_parseResult); - return m_wordGrammarDebugger.SetUpWordGrammarDebuggerPage(nodeId, form, lastUrl); - } - - public override string CreateResultPage(XDocument result) + /// + public HCTrace(Mediator mediator) { - m_parseResult = result; - - Debug.Assert(m_parseResult.Root != null); - TransformKind kind = (m_parseResult.Root.Element("Trace") != null ? TransformKind.kcptTrace : TransformKind.kcptParse); - return TransformToHtml(m_parseResult, kind); + m_mediator = mediator; + m_cache = (FdoCache) m_mediator.PropertyTable.GetValue("cache"); } - protected override void AddParserSpecificArguments(XsltArgumentList argumentList) + public override string CreateResultPage(XDocument result, bool isTrace) { - string sLoadErrorFile = Path.Combine(Path.GetTempPath(), m_sDataBaseName + "HCLoadErrors.xml"); - argumentList.AddParam("prmHCTraceLoadErrorFile", "", sLoadErrorFile); + ParserTraceUITransform transform; + string baseName; + if (isTrace) + { + WordGrammarDebugger = new HCWordGrammarDebugger(m_mediator, result); + transform = TraceTransform; + baseName = "HCTrace"; + } + else + { + transform = ParseTransform; + baseName = "HCParse"; + } + var args = new XsltArgumentList(); + args.AddParam("prmHCTraceLoadErrorFile", "", Path.Combine(Path.GetTempPath(), m_cache.ProjectId.Name + "HCLoadErrors.xml")); + return transform.Transform(m_mediator, result, baseName, args); } } } diff --git a/Src/LexText/ParserUI/HCWordGrammarDebugger.cs b/Src/LexText/ParserUI/HCWordGrammarDebugger.cs index 915d27525a..652706905b 100644 --- a/Src/LexText/ParserUI/HCWordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/HCWordGrammarDebugger.cs @@ -1,4 +1,5 @@ -using System.Diagnostics; +using System.Collections.Generic; +using System.Diagnostics; using System.Xml; using System.Xml.Linq; using System.Linq; @@ -8,17 +9,19 @@ namespace SIL.FieldWorks.LexText.Controls { public class HCWordGrammarDebugger : WordGrammarDebugger { + private readonly Dictionary m_attempts; + public HCWordGrammarDebugger(Mediator mediator, XDocument parseResult) : base(mediator) { - m_parseResult = parseResult; + Debug.Assert(parseResult.Root != null); + m_attempts = parseResult.Root.Elements("WordGrammarTrace").Elements("WordGrammarAttempt").ToDictionary(e => (string) e.Element("Id"), e => new XElement(e)); } - protected override void CreateMorphNodes(XmlWriter writer, string nodeId) + protected override void WriteMorphNodes(XmlWriter writer, string nodeId) { - Debug.Assert(m_parseResult.Root != null); - XElement wordGrammarAttemptElem = m_parseResult.Root.Elements("WordGrammarTrace").Elements("WordGrammarAttempt").FirstOrDefault(e => ((string) e.Element("Id")) == nodeId); - if (wordGrammarAttemptElem != null) + XElement wordGrammarAttemptElem; + if (m_attempts.TryGetValue(nodeId, out wordGrammarAttemptElem)) { foreach (XElement morphElem in wordGrammarAttemptElem.Elements("morph")) morphElem.WriteTo(writer); diff --git a/Src/LexText/ParserUI/ParserTrace.cs b/Src/LexText/ParserUI/ParserTrace.cs index 8a612f1e92..c2885338a7 100644 --- a/Src/LexText/ParserUI/ParserTrace.cs +++ b/Src/LexText/ParserUI/ParserTrace.cs @@ -1,105 +1,31 @@ -using System.Text; using System.Xml.Linq; -using System.Xml.Xsl; -using SIL.Utils; -using XCore; namespace SIL.FieldWorks.LexText.Controls { /// /// Base class common to all parser trace processing /// - public abstract class ParserTrace : ParserTraceBase + public abstract class ParserTrace { - protected enum TransformKind + private static ParserTraceUITransform s_traceTransform; + protected static ParserTraceUITransform ParseTransform { - kcptParse = 0, - kcptTrace = 1, - kcptWordGrammarDebugger = 2, + get + { + if (s_traceTransform == null) + s_traceTransform = new ParserTraceUITransform("FormatXAmpleParse.xsl"); + return s_traceTransform; + } } - /// - /// Temp File names - /// - protected string m_sParse; - protected string m_sTrace; - protected WordGrammarDebugger m_wordGrammarDebugger; - /// - /// Transform file names - /// - protected string m_sFormatParse; - protected string m_sFormatTrace; - - /// - /// The real deal - /// - /// - protected ParserTrace(Mediator mediator) - : base(mediator) - { - } + public WordGrammarDebugger WordGrammarDebugger { get; protected set; } /// /// Create an HTML page of the results /// /// XML of the parse trace output + /// /// URL of the resulting HTML page - public abstract string CreateResultPage(XDocument result); - - /// - /// Initialize what is needed to perform the word grammar debugging and - /// produce an html page showing the results - /// - /// Id of the node to use - /// the wordform being tried - /// - /// temporary html file showing the results of the first step - public abstract string SetUpWordGrammarDebuggerPage(string nodeId, string form, string lastUrl); - - /// - /// Perform another step in the word grammar debugging process and - /// produce an html page showing the results - /// - /// Id of the selected node to use - /// - /// - /// temporary html file showing the results of the next step - public string PerformAnotherWordGrammarDebuggerStepPage(string sNodeId, string form, string lastUrl) - { - return m_wordGrammarDebugger.PerformAnotherWordGrammarDebuggerStepPage(sNodeId, form, lastUrl); - } - - public string PopWordGrammarStack() - { - return m_wordGrammarDebugger.PopWordGrammarStack(); - } - - protected string TransformToHtml(XDocument xDocument, TransformKind kind) - { - string sOutput = null; - var argumentList = new XsltArgumentList(); - - switch (kind) - { - case TransformKind.kcptParse: - sOutput = TransformToHtml(xDocument, m_sParse, m_sFormatParse, argumentList); - break; - case TransformKind.kcptTrace: - string sIconPath = CreateIconPath(); - argumentList.AddParam("prmIconPath", "", sIconPath); - sOutput = TransformToHtml(xDocument, m_sTrace, m_sFormatTrace, argumentList); - break; - } - return sOutput; - } - - private string CreateIconPath() - { - var sb = new StringBuilder(); - sb.Append("file:///"); - sb.Append(TransformPath.Replace(@"\", "/")); - sb.Append("/"); - return sb.ToString(); - } + public abstract string CreateResultPage(XDocument result, bool isTrace); } } diff --git a/Src/LexText/ParserUI/ParserTraceBase.cs b/Src/LexText/ParserUI/ParserTraceBase.cs deleted file mode 100644 index b2de19ad47..0000000000 --- a/Src/LexText/ParserUI/ParserTraceBase.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System.IO; -using System.Xml.Linq; -using System.Xml.Xsl; -using SIL.CoreImpl; -using SIL.FieldWorks.Common.COMInterfaces; -using SIL.FieldWorks.Common.FwUtils; -using SIL.FieldWorks.Common.Widgets; -using SIL.FieldWorks.FDO; -using SIL.Utils; -using XCore; - -namespace SIL.FieldWorks.LexText.Controls -{ - public abstract class ParserTraceBase - { - /// - /// xCore Mediator. - /// - protected Mediator m_mediator; - - protected FdoCache m_cache; - protected string m_sDataBaseName = ""; - /// - /// The parse result xml document - /// - protected XDocument m_parseResult; - - /// - /// The real deal - /// - /// - protected ParserTraceBase(Mediator mediator) - { - m_mediator = mediator; - m_cache = (FdoCache)m_mediator.PropertyTable.GetValue("cache"); - m_sDataBaseName = m_cache.ProjectId.Name; - } - - protected string CreateTempFile(string sPrefix, string sExtension) - { - string sTempFileName = Path.Combine(Path.GetTempPath(), m_sDataBaseName + sPrefix) + "." + sExtension; - using (StreamWriter sw = File.CreateText(sTempFileName)) - sw.Close(); - return sTempFileName; - } - - /// - /// Path to transforms - /// - protected string TransformPath - { - get { return FwDirectoryFinder.GetCodeSubDirectory(@"Language Explorer/Configuration/Words/Analyses/TraceParse"); } - } - - protected string TransformToHtml(string inputPath, string tempFileBase, string transformFile, XsltArgumentList argumentList) - { - string outputPath = CreateTempFile(tempFileBase, "htm"); - string transformPath = Path.Combine(TransformPath, transformFile); - SetWritingSystemBasedArguments(argumentList); - AddParserSpecificArguments(argumentList); - XslCompiledTransformUtil.Instance.TransformFileToFile(transformPath, inputPath, outputPath, argumentList); - return outputPath; - } - - protected string TransformToHtml(XDocument inputDoc, string tempFileBase, string transformFile, XsltArgumentList argumentList) - { - string outputPath = CreateTempFile(tempFileBase, "htm"); - string transformPath = Path.Combine(TransformPath, transformFile); - SetWritingSystemBasedArguments(argumentList); - AddParserSpecificArguments(argumentList); - XslCompiledTransformUtil.Instance.TransformXDocumentToFile(transformPath, inputDoc, outputPath, argumentList); - return outputPath; - } - - private void SetWritingSystemBasedArguments(XsltArgumentList argumentList) - { - ILgWritingSystemFactory wsf = m_cache.WritingSystemFactory; - IWritingSystemContainer wsContainer = m_cache.ServiceLocator.WritingSystems; - IWritingSystem defAnalWs = wsContainer.DefaultAnalysisWritingSystem; - using (var myFont = FontHeightAdjuster.GetFontForNormalStyle(defAnalWs.Handle, m_mediator, wsf)) - { - argumentList.AddParam("prmAnalysisFont", "", myFont.FontFamily.Name); - argumentList.AddParam("prmAnalysisFontSize", "", myFont.Size + "pt"); - } - - IWritingSystem defVernWs = wsContainer.DefaultVernacularWritingSystem; - using (var myFont = FontHeightAdjuster.GetFontForNormalStyle(defVernWs.Handle, m_mediator, wsf)) - { - argumentList.AddParam("prmVernacularFont", "", myFont.FontFamily.Name); - argumentList.AddParam("prmVernacularFontSize", "", myFont.Size + "pt"); - } - - string sRtl = defVernWs.RightToLeftScript ? "Y" : "N"; - argumentList.AddParam("prmVernacularRTL", "", sRtl); - } - - protected virtual void AddParserSpecificArguments(XsltArgumentList argumentList) - { - // default is to do nothing - } - } -} diff --git a/Src/LexText/ParserUI/ParserTraceUITransform.cs b/Src/LexText/ParserUI/ParserTraceUITransform.cs new file mode 100644 index 0000000000..c1701eea3c --- /dev/null +++ b/Src/LexText/ParserUI/ParserTraceUITransform.cs @@ -0,0 +1,81 @@ +using System.IO; +using System.Text; +using System.Xml; +using System.Xml.Linq; +using System.Xml.XPath; +using System.Xml.Xsl; +using SIL.CoreImpl; +using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.Common.FwUtils; +using SIL.FieldWorks.Common.Widgets; +using SIL.FieldWorks.FDO; +using XCore; + +namespace SIL.FieldWorks.LexText.Controls +{ + public class ParserTraceUITransform + { + private readonly XslCompiledTransform m_transform; + + public ParserTraceUITransform(string xslFileName) + { + m_transform = new XslCompiledTransform(); + m_transform.Load(Path.Combine(TransformPath, xslFileName), new XsltSettings(true, false), new XmlUrlResolver()); + } + + public string Transform(Mediator mediator, XDocument doc, string baseName) + { + return Transform(mediator, doc, baseName, new XsltArgumentList()); + } + + public string Transform(Mediator mediator, XDocument doc, string baseName, XsltArgumentList args) + { + var cache = (FdoCache) mediator.PropertyTable.GetValue("cache"); + SetWritingSystemBasedArguments(cache, mediator, args); + args.AddParam("prmIconPath", "", IconPath); + string filePath = Path.Combine(Path.GetTempPath(), cache.ProjectId.Name + baseName + ".htm"); + using (var writer = new StreamWriter(filePath)) + m_transform.Transform(doc.CreateNavigator(), args, writer); + return filePath; + } + + private void SetWritingSystemBasedArguments(FdoCache cache, Mediator mediator, XsltArgumentList argumentList) + { + ILgWritingSystemFactory wsf = cache.WritingSystemFactory; + IWritingSystemContainer wsContainer = cache.ServiceLocator.WritingSystems; + IWritingSystem defAnalWs = wsContainer.DefaultAnalysisWritingSystem; + using (var myFont = FontHeightAdjuster.GetFontForNormalStyle(defAnalWs.Handle, mediator, wsf)) + { + argumentList.AddParam("prmAnalysisFont", "", myFont.FontFamily.Name); + argumentList.AddParam("prmAnalysisFontSize", "", myFont.Size + "pt"); + } + + IWritingSystem defVernWs = wsContainer.DefaultVernacularWritingSystem; + using (var myFont = FontHeightAdjuster.GetFontForNormalStyle(defVernWs.Handle, mediator, wsf)) + { + argumentList.AddParam("prmVernacularFont", "", myFont.FontFamily.Name); + argumentList.AddParam("prmVernacularFontSize", "", myFont.Size + "pt"); + } + + string sRtl = defVernWs.RightToLeftScript ? "Y" : "N"; + argumentList.AddParam("prmVernacularRTL", "", sRtl); + } + + private static string TransformPath + { + get { return FwDirectoryFinder.GetCodeSubDirectory(@"Language Explorer/Configuration/Words/Analyses/TraceParse"); } + } + + private static string IconPath + { + get + { + var sb = new StringBuilder(); + sb.Append("file:///"); + sb.Append(TransformPath.Replace(@"\", "/")); + sb.Append("/"); + return sb.ToString(); + } + } + } +} diff --git a/Src/LexText/ParserUI/ParserUI.csproj b/Src/LexText/ParserUI/ParserUI.csproj index 4a4023bd47..b5e6cff137 100644 --- a/Src/LexText/ParserUI/ParserUI.csproj +++ b/Src/LexText/ParserUI/ParserUI.csproj @@ -236,7 +236,7 @@ Form - + True True @@ -253,7 +253,6 @@ - Code diff --git a/Src/LexText/ParserUI/TryAWordDlg.cs b/Src/LexText/ParserUI/TryAWordDlg.cs index 9f205b45ed..0095df0dac 100644 --- a/Src/LexText/ParserUI/TryAWordDlg.cs +++ b/Src/LexText/ParserUI/TryAWordDlg.cs @@ -562,12 +562,11 @@ private void m_timer_Tick(object sender, EventArgs e) writer.WriteLine(ParserUIStrings.ksDidNotParse); writer.WriteLine(""); writer.WriteLine(""); - writer.Close(); } } else { - sOutput = m_webPageInteractor.ParserTrace.CreateResultPage(result); + sOutput = m_webPageInteractor.ParserTrace.CreateResultPage(result, DoTrace); } m_htmlControl.URL = sOutput; m_tryAWordResult = null; diff --git a/Src/LexText/ParserUI/WebPageInteractor.cs b/Src/LexText/ParserUI/WebPageInteractor.cs index 3a85ccd246..8e2dca522c 100644 --- a/Src/LexText/ParserUI/WebPageInteractor.cs +++ b/Src/LexText/ParserUI/WebPageInteractor.cs @@ -178,7 +178,7 @@ public void MouseMove() public void ShowWordGrammarDetail(string sNodeId) { string sForm = AdjustForm(m_tbWordForm.Text); - m_htmlControl.URL = ParserTrace.SetUpWordGrammarDebuggerPage(sNodeId, sForm, m_htmlControl.URL); + m_htmlControl.URL = ParserTrace.WordGrammarDebugger.SetUpWordGrammarDebuggerPage(sNodeId, sForm, m_htmlControl.URL); } /// /// Try another pass in the Word Grammar Debugger @@ -187,7 +187,7 @@ public void ShowWordGrammarDetail(string sNodeId) public void TryWordGrammarAgain(string sNodeId) { string sForm = AdjustForm(m_tbWordForm.Text); - m_htmlControl.URL = ParserTrace.PerformAnotherWordGrammarDebuggerStepPage(sNodeId, sForm, m_htmlControl.URL); + m_htmlControl.URL = ParserTrace.WordGrammarDebugger.PerformAnotherWordGrammarDebuggerStepPage(sNodeId, sForm, m_htmlControl.URL); } /// /// Back up a page in the Word Grammar Debugger @@ -199,7 +199,7 @@ public void TryWordGrammarAgain(string sNodeId) /// public void GoToPreviousWordGrammarPage() { - m_htmlControl.URL = ParserTrace.PopWordGrammarStack(); + m_htmlControl.URL = ParserTrace.WordGrammarDebugger.PopWordGrammarStack(); } /// /// Modify the content of the form to use entities when needed diff --git a/Src/LexText/ParserUI/WordGrammarDebugger.cs b/Src/LexText/ParserUI/WordGrammarDebugger.cs index 93d84f296d..e608298ce6 100644 --- a/Src/LexText/ParserUI/WordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/WordGrammarDebugger.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; @@ -5,32 +6,47 @@ using System.Linq; using System.Xml; using System.Xml.Linq; +using System.Xml.XPath; using System.Xml.Xsl; -using SIL.Utils; +using SIL.FieldWorks.FDO; using XCore; namespace SIL.FieldWorks.LexText.Controls { - public abstract class WordGrammarDebugger : ParserTraceBase + public abstract class WordGrammarDebugger { + private static ParserTraceUITransform s_pageTransform; + private static ParserTraceUITransform PageTransform + { + get + { + if (s_pageTransform == null) + s_pageTransform = new ParserTraceUITransform("FormatXAmpleWordGrammarDebuggerResult.xsl"); + return s_pageTransform; + } + } + /// /// Word Grammar step stack /// - private readonly Stack m_xmlHtmlStack; + private readonly Stack> m_xmlHtmlStack; /// /// the latest word grammar debugging step xml document /// - private string m_wordGrammarDebuggerXmlFile; + private XDocument m_wordGrammarDebuggerXml; + + private readonly XslCompiledTransform m_intermediateTransform; + private readonly Mediator m_mediator; + private readonly FdoCache m_cache; - /// - /// The real deal - /// - /// protected WordGrammarDebugger(Mediator mediator) - : base(mediator) { - m_xmlHtmlStack = new Stack(); + m_mediator = mediator; + m_cache = (FdoCache) m_mediator.PropertyTable.GetValue("cache"); + m_xmlHtmlStack = new Stack>(); + m_intermediateTransform = new XslCompiledTransform(); + m_intermediateTransform.Load(Path.Combine(Path.GetTempPath(), m_cache.ProjectId.Name + "XAmpleWordGrammarDebugger.xsl"), new XsltSettings(true, false), new XmlUrlResolver()); } /// @@ -43,7 +59,7 @@ protected WordGrammarDebugger(Mediator mediator) /// temporary html file showing the results of the first step public string SetUpWordGrammarDebuggerPage(string nodeId, string form, string lastUrl) { - m_xmlHtmlStack.Push(new WordGrammarStepPair(null, lastUrl)); + m_xmlHtmlStack.Push(Tuple.Create((XDocument) null, lastUrl)); var doc = new XDocument(); using (XmlWriter writer = doc.CreateWriter()) CreateAnalysisXml(writer, nodeId, form); @@ -60,7 +76,7 @@ public string SetUpWordGrammarDebuggerPage(string nodeId, string form, string la /// temporary html file showing the results of the next step public string PerformAnotherWordGrammarDebuggerStepPage(string nodeId, string form, string lastUrl) { - m_xmlHtmlStack.Push(new WordGrammarStepPair(m_wordGrammarDebuggerXmlFile, lastUrl)); + m_xmlHtmlStack.Push(Tuple.Create(m_wordGrammarDebuggerXml, lastUrl)); var doc = new XDocument(); using (XmlWriter writer = doc.CreateWriter()) CreateSelectedWordGrammarXml(writer, nodeId, form); @@ -71,9 +87,9 @@ public string PopWordGrammarStack() { if (m_xmlHtmlStack.Count > 0) { - WordGrammarStepPair wgsp = m_xmlHtmlStack.Pop(); - m_wordGrammarDebuggerXmlFile = wgsp.XmlFile; - return wgsp.HtmlFile; + Tuple wgsp = m_xmlHtmlStack.Pop(); + m_wordGrammarDebuggerXml = wgsp.Item1; + return wgsp.Item2; } return "unknown"; } @@ -86,7 +102,7 @@ private void CreateAnalysisXml(XmlWriter writer, string nodeId, string form) writer.WriteElementString("form", form); writer.WriteStartElement("seq"); - CreateMorphNodes(writer, nodeId); + WriteMorphNodes(writer, nodeId); writer.WriteEndElement(); writer.WriteEndElement(); @@ -94,20 +110,18 @@ private void CreateAnalysisXml(XmlWriter writer, string nodeId, string form) writer.WriteEndDocument(); } - protected abstract void CreateMorphNodes(XmlWriter writer, string nodeId); + protected abstract void WriteMorphNodes(XmlWriter writer, string nodeId); private void CreateSelectedWordGrammarXml(XmlWriter writer, string nodeId, string form) { - var lastDoc = XDocument.Load(m_wordGrammarDebuggerXmlFile); - writer.WriteStartDocument(); writer.WriteStartElement("word"); writer.WriteElementString("form", form); // Find the sNode'th seq node - Debug.Assert(lastDoc.Root != null); - XElement selectedSeqNode = lastDoc.Root.Elements("seq").ElementAt(int.Parse(nodeId, CultureInfo.InvariantCulture) - 1); + Debug.Assert(m_wordGrammarDebuggerXml.Root != null); + XElement selectedSeqNode = m_wordGrammarDebuggerXml.Root.Elements("seq").ElementAt(int.Parse(nodeId, CultureInfo.InvariantCulture) - 1); // create the "result so far node" writer.WriteStartElement("resultSoFar"); foreach (XElement child in selectedSeqNode.Elements()) @@ -122,40 +136,12 @@ private void CreateSelectedWordGrammarXml(XmlWriter writer, string nodeId, strin private string CreateWordDebuggerPage(XDocument xmlDoc) { // apply word grammar step transform file - string xmlOutput = TransformToXml(xmlDoc); - m_wordGrammarDebuggerXmlFile = xmlOutput; + var output = new XDocument(); + using (XmlWriter writer = output.CreateWriter()) + m_intermediateTransform.Transform(xmlDoc.CreateNavigator(), writer); + m_wordGrammarDebuggerXml = output; // format the result - return TransformToHtml(xmlOutput); - } - - private string CreateWordGrammarDebuggerFileName() - { - string depthLevel = m_xmlHtmlStack.Count.ToString(CultureInfo.InvariantCulture); - return "WordGrammarDebugger" + depthLevel; - } - - protected string TransformToHtml(string inputPath) - { - return TransformToHtml(inputPath, CreateWordGrammarDebuggerFileName(), - "FormatXAmpleWordGrammarDebuggerResult.xsl", new XsltArgumentList()); - } - - protected string TransformToHtml(XDocument inputDoc) - { - return TransformToHtml(inputDoc, CreateWordGrammarDebuggerFileName(), - "FormatXAmpleWordGrammarDebuggerResult.xsl", new XsltArgumentList()); - } - - private string TransformToXml(XDocument inputDoc) - { - // Don't overwrite the input file before transforming it! (why +"A" on the next line) - string outputPath = CreateTempFile(CreateWordGrammarDebuggerFileName() + "A", "xml"); - string xslFileName = m_sDataBaseName + "XAmpleWordGrammarDebugger" + ".xsl"; - string dir = Path.GetDirectoryName(outputPath); - Debug.Assert(dir != null); - string transform = Path.Combine(dir, xslFileName); - XslCompiledTransformUtil.Instance.TransformXDocumentToFile(transform, inputDoc, outputPath, new XsltArgumentList()); - return outputPath; + return PageTransform.Transform(m_mediator, output, "WordGrammarDebugger" + m_xmlHtmlStack.Count); } } } diff --git a/Src/LexText/ParserUI/WordGrammarStepPair.cs b/Src/LexText/ParserUI/WordGrammarStepPair.cs deleted file mode 100644 index bc1f04d3d7..0000000000 --- a/Src/LexText/ParserUI/WordGrammarStepPair.cs +++ /dev/null @@ -1,47 +0,0 @@ -namespace SIL.FieldWorks.LexText.Controls -{ - public class WordGrammarStepPair - { - protected string m_sXmlFile; - protected string m_sHtmlFile; - /// - /// Constructor - /// - /// Xml file - /// Html file - public WordGrammarStepPair(string sXmlFile, string sHtmlFile) - { - m_sXmlFile = sXmlFile; - m_sHtmlFile = sHtmlFile; - } - /// - /// Gete/set XmlFile - /// - public string XmlFile - { - get - { - return m_sXmlFile; - } - set - { - m_sXmlFile = value; - } - } - /// - /// Gete/set HtmlFile - /// - public string HtmlFile - { - get - { - return m_sHtmlFile; - } - set - { - m_sHtmlFile = value; - } - } - - } -} diff --git a/Src/LexText/ParserUI/XAmpleTrace.cs b/Src/LexText/ParserUI/XAmpleTrace.cs index 95d2f25d39..e2bfc16716 100644 --- a/Src/LexText/ParserUI/XAmpleTrace.cs +++ b/Src/LexText/ParserUI/XAmpleTrace.cs @@ -13,7 +13,6 @@ // XAmpleTrace - Deal with results of an XAmple trace // -using System.Diagnostics; using System.Xml.Linq; using XCore; @@ -24,55 +23,50 @@ namespace SIL.FieldWorks.LexText.Controls /// public class XAmpleTrace : ParserTrace { - /// - /// The real deal - /// - /// - public XAmpleTrace(Mediator mediator) : base(mediator) + private static ParserTraceUITransform s_traceTransform; + private static ParserTraceUITransform TraceTransform { - m_sParse = "XAmpleParse"; - m_sTrace = "XAmpleTrace"; - m_sFormatParse = "FormatXAmpleParse.xsl"; - m_sFormatTrace = "FormatXAmpleTrace.xsl"; + get + { + if (s_traceTransform == null) + s_traceTransform = new ParserTraceUITransform("FormatXAmpleTrace.xsl"); + return s_traceTransform; + } } + private readonly Mediator m_mediator; + /// - /// Initialize what is needed to perform the word grammar debugging and - /// produce an html page showing the results + /// The real deal /// - /// Id of the node to use - /// the wordform being tried - /// - /// temporary html file showing the results of the first step - public override string SetUpWordGrammarDebuggerPage(string nodeId, string form, string lastUrl) + /// + public XAmpleTrace(Mediator mediator) { - m_wordGrammarDebugger = new XAmpleWordGrammarDebugger(m_mediator, m_parseResult); - return m_wordGrammarDebugger.SetUpWordGrammarDebuggerPage(nodeId, form, lastUrl); + m_mediator = mediator; } /// /// Create an HTML page of the results /// /// XML string of the XAmple trace output + /// /// URL of the resulting HTML page - public override string CreateResultPage(XDocument result) + public override string CreateResultPage(XDocument result, bool isTrace) { - m_parseResult = result; - - Debug.Assert(m_parseResult.Root != null); - TransformKind kind = (m_parseResult.Root.Name == "AmpleTrace" ? TransformKind.kcptTrace : TransformKind.kcptParse); - return TransformToHtml(m_parseResult, kind); + ParserTraceUITransform transform; + string baseName; + if (isTrace) + { + WordGrammarDebugger = new XAmpleWordGrammarDebugger(m_mediator, result); + transform = TraceTransform; + baseName = "XAmpleTrace"; + } + else + { + transform = ParseTransform; + baseName = "XAmpleParse"; + } + return transform.Transform(m_mediator, result, baseName); } } } -/// -/// Note for Andy -/// -#if Later -using mshtml; - -IHTMLDocument2 doc; -object boxDoc = m_browser.Document; -doc = (IHTMLDocument2)boxDoc; -string sHtml = doc.body.innerHTML; -#endif diff --git a/Src/LexText/ParserUI/XAmpleWordGrammarDebugger.cs b/Src/LexText/ParserUI/XAmpleWordGrammarDebugger.cs index 2b2cf92335..c6f49a1487 100644 --- a/Src/LexText/ParserUI/XAmpleWordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/XAmpleWordGrammarDebugger.cs @@ -8,13 +8,15 @@ namespace SIL.FieldWorks.LexText.Controls { public class XAmpleWordGrammarDebugger : WordGrammarDebugger { + private readonly XDocument m_parseResult; + public XAmpleWordGrammarDebugger(Mediator mediator, XDocument parseResult) : base(mediator) { m_parseResult = parseResult; } - protected override void CreateMorphNodes(XmlWriter writer, string nodeId) + protected override void WriteMorphNodes(XmlWriter writer, string nodeId) { XElement failureElem = m_parseResult.Descendants("failure").FirstOrDefault(e => ((string) e.Attribute("id")) == nodeId); if (failureElem != null) diff --git a/Src/Utilities/XMLUtils/XMLUtils.csproj b/Src/Utilities/XMLUtils/XMLUtils.csproj index 93c4f74f48..55090e5b31 100644 --- a/Src/Utilities/XMLUtils/XMLUtils.csproj +++ b/Src/Utilities/XMLUtils/XMLUtils.csproj @@ -130,7 +130,6 @@ CommonAssemblyInfo.cs - Code diff --git a/Src/Utilities/XMLUtils/XslCompiledTransformUtil.cs b/Src/Utilities/XMLUtils/XslCompiledTransformUtil.cs deleted file mode 100644 index 79bbdc71bc..0000000000 --- a/Src/Utilities/XMLUtils/XslCompiledTransformUtil.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Xml; -using System.Xml.Linq; -using System.Xml.Xsl; - -namespace SIL.Utils -{ - public class XslCompiledTransformUtil - { - // Singleton - private static XslCompiledTransformUtil s_instance; - private XslCompiledTransformUtil() {} - public static XslCompiledTransformUtil Instance - { - get { return s_instance ?? (s_instance = new XslCompiledTransformUtil()); } - } - - private readonly Dictionary m_transformCache = new Dictionary(); - - public void TransformXDocumentToFile(string xslPath, XDocument inputDoc, string outputPath, XsltArgumentList argumentList) - { - XslCompiledTransform transform = GetTransform(xslPath); - using (var fileStream = new FileStream(outputPath, FileMode.Create)) - { - transform.Transform(inputDoc.CreateReader(), argumentList, fileStream); - fileStream.Close(); - } - } - - public void TransformFileToFile(string xslPath, string inputPath, string outputPath, XsltArgumentList argumentList) - { - XslCompiledTransform transform = GetTransform(xslPath); - using (var fileStream = new FileStream(outputPath, FileMode.Create)) - { - transform.Transform(inputPath, argumentList, fileStream); - fileStream.Close(); - } - } - - private XslCompiledTransform GetTransform(string xslPath) - { - lock(m_transformCache) - { - XslCompiledTransform compiledXsl; - if (m_transformCache.TryGetValue(xslPath, out compiledXsl)) - return compiledXsl; - - var transform = new XslCompiledTransform(); - transform.Load(xslPath, new XsltSettings(true, false), new XmlUrlResolver()); - m_transformCache.Add(xslPath, transform); - return transform; - } - } - } -} From 9abb3681c04a919206bf73c23df419c71628f889 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 14 Feb 2014 17:29:35 +0700 Subject: [PATCH 082/143] removed ParserEngine folder Change-Id: I7b115ebdec5a7753d70108d75938193f94323e37 --- .../ParserCore/AssemblyInfo.cs | 0 .../{ParserEngine => }/ParserCore/HCParser.cs | 0 .../{ParserEngine => }/ParserCore/IParser.cs | 0 ...nvalidReduplicationEnvironmentException.cs | 0 .../ParserCore/M3ModelRetriever.cs | 0 .../ParserCore/M3ToHCTransformer.cs | 0 .../ParserCore/M3ToParserTransformerBase.cs | 0 .../ParserCore/M3ToXAmpleTransformer.cs | 0 .../ParserCore/ParseFiler.cs | 0 .../ParserCore/ParseResult.cs | 0 .../ParserCore/ParserCore.csproj | 32 ++++----- .../ParserCore/ParserCoreStrings.Designer.cs | 0 .../ParserCore/ParserCoreStrings.resx | 0 .../ParserCore/ParserCoreTests/Failures.xml | 0 .../ParserCore/ParserCoreTests/HelperTests.cs | 0 .../M3ToXAmpleTransformerTests.cs | 6 +- .../.gitattributes | 0 .../AffixAlloFeatsAdCtl.txt | 0 .../AffixAlloFeatsLexicon.txt | 0 .../AffixAlloFeatsWordGrammar.txt | 0 .../CircumfixInfixLexicon.txt | 0 .../CircumfixInfixWordGrammar.txt | 0 .../CliticAdCtl.txt | 0 .../CliticEnvsLexicon.txt | 0 .../CliticEnvsParserFxtResult.xml | 0 .../CliticLexicon.txt | 0 .../CliticParserFxtResult.xml | 0 .../CliticWordGrammar.txt | 0 .../ConceptualIntroTestParserFxtResult.xml | 0 .../ConceptualIntroTestlex.txt | 0 .../FullRedupLexicon.txt | 0 .../IndonCircumfixLexicon.txt | 0 .../IndonCircumfixWordGrammar.txt | 0 .../IrregularlyInflectedFormsAdCtl.txt | 0 .../IrregularlyInflectedFormsLexicon.txt | 0 ...regularlyInflectedFormsParserFxtResult.xml | 0 .../LatinAdCtl.txt | 0 .../LatinParserFxtResult.xml | 0 .../LatinWordGrammar.txt | 0 .../M3FXTCircumfixDump.xml | 0 .../M3FXTCircumfixInfixDump.xml | 0 .../M3FXTDump.xml | 0 .../M3FXTFullRedupDump.xml | 0 .../M3FXTStemNameDump.xml | 0 .../OrizabaParserFxtResult.xml | 0 .../Orizabaadctl.txt | 0 .../Orizabagram.txt | 0 .../Orizabalex.txt | 0 .../RootCliticEnvParserFxtResult.xml | 0 .../RootCliticEnvsLexicon.txt | 0 .../StemName3ParserFxtResult.xml | 0 .../StemName3adctl.txt | 0 .../StemName3gram.txt | 0 .../StemName3lex.txt | 0 .../StemNameTestAdCtl.txt | 0 .../StemNameTestlex.txt | 0 .../StemNameWordGrammar.txt | 0 .../TestAdCtl.txt | 0 ...TestAffixAllomorphFeatsParserFxtResult.xml | 0 .../TestLexicon.txt | 0 .../TestWordGrammar.txt | 0 .../ParseFilerProcessingTests.cs | 0 .../ParserCoreTests/ParserCoreTests.csproj | 32 ++++----- .../ParserCoreTests/UpdateParserDataTests.cs | 0 .../ParserCoreTests/XAmpleParserTests.cs | 2 +- .../gendarme-ParserCoreTests.ignore | 0 .../ParserCore/ParserHelper.cs | 0 .../ParserCore/ParserScheduler.cs | 0 .../ParserCore/ParserWorker.cs | 0 .../ParserCore/ParserXmlWriterExtensions.cs | 0 .../PatrParserWrapper/BuildInclude.targets | 2 +- .../PatrParserWrapper/IPatrParser.cs | 0 .../PatrParserWrapper/PatrParser.cs | 0 .../PatrParserWrapper.csproj | 6 +- .../PatrParserWrapper.dll.config | 0 .../PatrParserWrapperTests/Ephtst.ana | 0 .../PatrParserWrapperTests/MyLex.txt | 0 .../PatrParserWrapperTests/PatrParserTests.cs | 2 +- .../PatrParserWrapperTests.csproj | 16 ++--- .../StemNameWordGrammar.txt | 0 .../PatrParserWrapperTests/bears.ana | 0 .../gendarme-PatrParserWrapperTests.ignore | 0 .../Properties/AssemblyInfo.cs | 0 .../gendarme-PatrParserWrapper.ignore | 0 .../ParserCore/TaskReport.cs | 0 .../ParserCore/XAmpleCOMWrapper/ReadMe.txt | 0 .../ParserCore/XAmpleCOMWrapper/Resource.h | 0 .../XAmpleCOMWrapper/XAmpleCOMWrapper.cpp | 0 .../XAmpleCOMWrapper/XAmpleCOMWrapper.rc | 0 .../XAmpleCOMWrapper/XAmpleCOMWrapper.rgs | 0 .../XAmpleCOMWrapper/XAmpleCOMWrapper.vcxproj | 18 ++--- .../XAmpleCOMWrapper.vcxproj.filters | 0 .../XAmpleCOMWrapper/XAmpleCOMWrapperps.def | 0 .../XAmpleCOMWrapper/XAmpleWrapper.cpp | 0 .../XAmpleCOMWrapper/XAmpleWrapperCore.cpp | 0 .../XAmpleCOMWrapper/XAmpleWrapperCore.h | 0 .../ParserCore/XAmpleCOMWrapper/stdafx.cpp | 0 .../ParserCore/XAmpleCOMWrapper/stdafx.h | 0 .../XAmpleCOMWrapper/xamplewrapper.h | 0 .../XAmpleManagedWrapper/AmpleOptions.cs | 0 .../XAmpleManagedWrapper/AssemblyInfo.cs | 0 .../XAmpleManagedWrapper/BuildInclude.targets | 2 +- .../XAmpleManagedWrapper/IXAmpleWrapper.cs | 0 .../XAmpleManagedWrapper/XAmpleDLLWrapper.cs | 0 .../XAmpleManagedWrapper.csproj | 6 +- .../TestXAmpleDLLWrapper.cs | 2 +- .../TestXAmpleWrapper.cs | 2 +- .../XAmpleManagedWrapperTests.csproj | 16 ++--- .../XAmpleManagedWrapper/XAmpleWrapper.cs | 0 .../ParserCore/XAmpleParser.cs | 0 .../ParserCore/gendarme-ParserCore.ignore | 0 .../ParserEngine/Parser Architecture.vsd | Bin 52736 -> 0 bytes .../ParserCore/ParserCoreTests/App.config | 22 ------ .../XAmpleCOMWrapper/XAmpleCOMWrapper.sln | 63 ------------------ .../XAmpleManagedWrapperTests/App.config | 22 ------ Src/LexText/ParserUI/HCTrace.cs | 3 + Src/LexText/ParserUI/WordGrammarDebugger.cs | 3 + Src/LexText/ParserUI/XAmpleTrace.cs | 3 + 118 files changed, 79 insertions(+), 181 deletions(-) rename Src/LexText/{ParserEngine => }/ParserCore/AssemblyInfo.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/HCParser.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/IParser.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/InvalidReduplicationEnvironmentException.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/M3ModelRetriever.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/M3ToHCTransformer.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/M3ToParserTransformerBase.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/M3ToXAmpleTransformer.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParseFiler.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParseResult.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCore.csproj (89%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreStrings.Designer.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreStrings.resx (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/Failures.xml (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/HelperTests.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTests.cs (98%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/.gitattributes (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/AffixAlloFeatsAdCtl.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/AffixAlloFeatsLexicon.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/AffixAlloFeatsWordGrammar.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CircumfixInfixLexicon.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CircumfixInfixWordGrammar.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticAdCtl.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticEnvsLexicon.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticEnvsParserFxtResult.xml (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticLexicon.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticParserFxtResult.xml (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticWordGrammar.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/ConceptualIntroTestParserFxtResult.xml (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/ConceptualIntroTestlex.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/FullRedupLexicon.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IndonCircumfixLexicon.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IndonCircumfixWordGrammar.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IrregularlyInflectedFormsAdCtl.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IrregularlyInflectedFormsLexicon.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IrregularlyInflectedFormsParserFxtResult.xml (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/LatinAdCtl.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/LatinParserFxtResult.xml (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/LatinWordGrammar.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTCircumfixDump.xml (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTCircumfixInfixDump.xml (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTDump.xml (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTFullRedupDump.xml (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTStemNameDump.xml (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/OrizabaParserFxtResult.xml (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/Orizabaadctl.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/Orizabagram.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/Orizabalex.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/RootCliticEnvParserFxtResult.xml (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/RootCliticEnvsLexicon.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemName3ParserFxtResult.xml (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemName3adctl.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemName3gram.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemName3lex.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemNameTestAdCtl.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemNameTestlex.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemNameWordGrammar.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/TestAdCtl.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/TestAffixAllomorphFeatsParserFxtResult.xml (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/TestLexicon.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/TestWordGrammar.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/ParseFilerProcessingTests.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/ParserCoreTests.csproj (85%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/UpdateParserDataTests.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/XAmpleParserTests.cs (98%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserCoreTests/gendarme-ParserCoreTests.ignore (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserHelper.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserScheduler.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserWorker.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/ParserXmlWriterExtensions.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/PatrParserWrapper/BuildInclude.targets (94%) rename Src/LexText/{ParserEngine => }/ParserCore/PatrParserWrapper/IPatrParser.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/PatrParserWrapper/PatrParser.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/PatrParserWrapper/PatrParserWrapper.csproj (95%) rename Src/LexText/{ParserEngine => }/ParserCore/PatrParserWrapper/PatrParserWrapper.dll.config (100%) rename Src/LexText/{ParserEngine => }/ParserCore/PatrParserWrapper/PatrParserWrapperTests/Ephtst.ana (100%) rename Src/LexText/{ParserEngine => }/ParserCore/PatrParserWrapper/PatrParserWrapperTests/MyLex.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/PatrParserWrapper/PatrParserWrapperTests/PatrParserTests.cs (99%) rename Src/LexText/{ParserEngine => }/ParserCore/PatrParserWrapper/PatrParserWrapperTests/PatrParserWrapperTests.csproj (89%) rename Src/LexText/{ParserEngine => }/ParserCore/PatrParserWrapper/PatrParserWrapperTests/StemNameWordGrammar.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/PatrParserWrapper/PatrParserWrapperTests/bears.ana (100%) rename Src/LexText/{ParserEngine => }/ParserCore/PatrParserWrapper/PatrParserWrapperTests/gendarme-PatrParserWrapperTests.ignore (100%) rename Src/LexText/{ParserEngine => }/ParserCore/PatrParserWrapper/Properties/AssemblyInfo.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/PatrParserWrapper/gendarme-PatrParserWrapper.ignore (100%) rename Src/LexText/{ParserEngine => }/ParserCore/TaskReport.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleCOMWrapper/ReadMe.txt (100%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleCOMWrapper/Resource.h (100%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.cpp (100%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.rc (100%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.rgs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.vcxproj (92%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.vcxproj.filters (100%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapperps.def (100%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleCOMWrapper/XAmpleWrapper.cpp (100%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleCOMWrapper/XAmpleWrapperCore.cpp (100%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleCOMWrapper/XAmpleWrapperCore.h (100%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleCOMWrapper/stdafx.cpp (100%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleCOMWrapper/stdafx.h (100%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleCOMWrapper/xamplewrapper.h (100%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleManagedWrapper/AmpleOptions.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleManagedWrapper/AssemblyInfo.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleManagedWrapper/BuildInclude.targets (94%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleManagedWrapper/IXAmpleWrapper.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleManagedWrapper/XAmpleDLLWrapper.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapper.csproj (95%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleDLLWrapper.cs (94%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleWrapper.cs (93%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/XAmpleManagedWrapperTests.csproj (84%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleManagedWrapper/XAmpleWrapper.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/XAmpleParser.cs (100%) rename Src/LexText/{ParserEngine => }/ParserCore/gendarme-ParserCore.ignore (100%) delete mode 100644 Src/LexText/ParserEngine/Parser Architecture.vsd delete mode 100644 Src/LexText/ParserEngine/ParserCore/ParserCoreTests/App.config delete mode 100644 Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.sln delete mode 100644 Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/App.config diff --git a/Src/LexText/ParserEngine/ParserCore/AssemblyInfo.cs b/Src/LexText/ParserCore/AssemblyInfo.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/AssemblyInfo.cs rename to Src/LexText/ParserCore/AssemblyInfo.cs diff --git a/Src/LexText/ParserEngine/ParserCore/HCParser.cs b/Src/LexText/ParserCore/HCParser.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/HCParser.cs rename to Src/LexText/ParserCore/HCParser.cs diff --git a/Src/LexText/ParserEngine/ParserCore/IParser.cs b/Src/LexText/ParserCore/IParser.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/IParser.cs rename to Src/LexText/ParserCore/IParser.cs diff --git a/Src/LexText/ParserEngine/ParserCore/InvalidReduplicationEnvironmentException.cs b/Src/LexText/ParserCore/InvalidReduplicationEnvironmentException.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/InvalidReduplicationEnvironmentException.cs rename to Src/LexText/ParserCore/InvalidReduplicationEnvironmentException.cs diff --git a/Src/LexText/ParserEngine/ParserCore/M3ModelRetriever.cs b/Src/LexText/ParserCore/M3ModelRetriever.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/M3ModelRetriever.cs rename to Src/LexText/ParserCore/M3ModelRetriever.cs diff --git a/Src/LexText/ParserEngine/ParserCore/M3ToHCTransformer.cs b/Src/LexText/ParserCore/M3ToHCTransformer.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/M3ToHCTransformer.cs rename to Src/LexText/ParserCore/M3ToHCTransformer.cs diff --git a/Src/LexText/ParserEngine/ParserCore/M3ToParserTransformerBase.cs b/Src/LexText/ParserCore/M3ToParserTransformerBase.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/M3ToParserTransformerBase.cs rename to Src/LexText/ParserCore/M3ToParserTransformerBase.cs diff --git a/Src/LexText/ParserEngine/ParserCore/M3ToXAmpleTransformer.cs b/Src/LexText/ParserCore/M3ToXAmpleTransformer.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/M3ToXAmpleTransformer.cs rename to Src/LexText/ParserCore/M3ToXAmpleTransformer.cs diff --git a/Src/LexText/ParserEngine/ParserCore/ParseFiler.cs b/Src/LexText/ParserCore/ParseFiler.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParseFiler.cs rename to Src/LexText/ParserCore/ParseFiler.cs diff --git a/Src/LexText/ParserEngine/ParserCore/ParseResult.cs b/Src/LexText/ParserCore/ParseResult.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParseResult.cs rename to Src/LexText/ParserCore/ParseResult.cs diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj b/Src/LexText/ParserCore/ParserCore.csproj similarity index 89% rename from Src/LexText/ParserEngine/ParserCore/ParserCore.csproj rename to Src/LexText/ParserCore/ParserCore.csproj index 4f44efdb33..011551a1a7 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCore.csproj +++ b/Src/LexText/ParserCore/ParserCore.csproj @@ -32,7 +32,7 @@ - ..\..\..\..\Output\Debug\ + ..\..\..\Output\Debug\ false 285212672 false @@ -56,7 +56,7 @@ x86 - ..\..\..\..\Output\Release\ + ..\..\..\Output\Release\ false 285212672 false @@ -88,7 +88,7 @@ 168,169,219,414,649,1635,1702,1701 full x86 - ..\..\..\..\Output\Debug\ParserCore.dll.CodeAnalysisLog.xml + ..\..\..\Output\Debug\ParserCore.dll.CodeAnalysisLog.xml true GlobalSuppressions.cs prompt @@ -108,7 +108,7 @@ 168,169,219,414,649,1635,1702,1701 full x86 - ..\..\..\..\Output\Release\ParserCore.dll.CodeAnalysisLog.xml + ..\..\..\Output\Release\ParserCore.dll.CodeAnalysisLog.xml true GlobalSuppressions.cs prompt @@ -122,36 +122,36 @@ False - ..\..\..\..\Output\Debug\BasicUtils.dll + ..\..\..\Output\Debug\BasicUtils.dll False - ..\..\..\..\Output\Debug\COMInterfaces.dll + ..\..\..\Output\Debug\COMInterfaces.dll False - ..\..\..\..\Output\Debug\CoreImpl.dll + ..\..\..\Output\Debug\CoreImpl.dll FDO - ..\..\..\..\Output\Debug\FDO.dll + ..\..\..\Output\Debug\FDO.dll GAFAWSAnalysis False - ..\..\..\..\DistFiles\GAFAWSAnalysis.dll + ..\..\..\DistFiles\GAFAWSAnalysis.dll False - ..\..\..\..\Lib\debug\HermitCrab.dll + ..\..\..\Lib\debug\HermitCrab.dll False - ..\..\..\..\DistFiles\Microsoft.Practices.ServiceLocation.dll + ..\..\..\DistFiles\Microsoft.Practices.ServiceLocation.dll False - ..\..\..\..\Output\Debug\PhonEnvValidator.dll + ..\..\..\Output\Debug\PhonEnvValidator.dll False @@ -173,22 +173,22 @@ False - ..\..\..\..\Output\Debug\XAmpleManagedWrapper.dll + ..\..\..\Output\Debug\XAmpleManagedWrapper.dll XMLUtils - ..\..\..\..\Output\Debug\XMLUtils.dll + ..\..\..\Output\Debug\XMLUtils.dll PatrParserWrapper - ..\..\..\..\Output\Debug\PatrParserWrapper.dll + ..\..\..\Output\Debug\PatrParserWrapper.dll Code - + CommonAssemblyInfo.cs diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.Designer.cs b/Src/LexText/ParserCore/ParserCoreStrings.Designer.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.Designer.cs rename to Src/LexText/ParserCore/ParserCoreStrings.Designer.cs diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.resx b/Src/LexText/ParserCore/ParserCoreStrings.resx similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreStrings.resx rename to Src/LexText/ParserCore/ParserCoreStrings.resx diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/Failures.xml b/Src/LexText/ParserCore/ParserCoreTests/Failures.xml similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/Failures.xml rename to Src/LexText/ParserCore/ParserCoreTests/Failures.xml diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/HelperTests.cs b/Src/LexText/ParserCore/ParserCoreTests/HelperTests.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/HelperTests.cs rename to Src/LexText/ParserCore/ParserCoreTests/HelperTests.cs diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTests.cs b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTests.cs similarity index 98% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTests.cs rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTests.cs index de0de401b6..1131cd6343 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTests.cs +++ b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTests.cs @@ -70,11 +70,7 @@ public override void FixtureSetup() { base.FixtureSetup(); - m_sTestPath = Path.Combine(FwDirectoryFinder.SourceDirectory, - Path.Combine("LexText", - Path.Combine("ParserEngine", - Path.Combine("ParserCore", - Path.Combine("ParserCoreTests", "M3ToXAmpleTransformerTestsDataFiles"))))); + m_sTestPath = Path.Combine(FwDirectoryFinder.SourceDirectory, "LexText", "ParserCore", "ParserCoreTests", "M3ToXAmpleTransformerTestsDataFiles"); m_sTransformPath = Path.Combine(FwDirectoryFinder.FlexFolder, "Transforms"); SetUpXAmpleTransforms(); diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/.gitattributes b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/.gitattributes similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/.gitattributes rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/.gitattributes diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/AffixAlloFeatsAdCtl.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/AffixAlloFeatsAdCtl.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/AffixAlloFeatsAdCtl.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/AffixAlloFeatsAdCtl.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/AffixAlloFeatsLexicon.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/AffixAlloFeatsLexicon.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/AffixAlloFeatsLexicon.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/AffixAlloFeatsLexicon.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/AffixAlloFeatsWordGrammar.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/AffixAlloFeatsWordGrammar.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/AffixAlloFeatsWordGrammar.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/AffixAlloFeatsWordGrammar.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CircumfixInfixLexicon.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CircumfixInfixLexicon.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CircumfixInfixLexicon.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CircumfixInfixLexicon.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CircumfixInfixWordGrammar.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CircumfixInfixWordGrammar.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CircumfixInfixWordGrammar.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CircumfixInfixWordGrammar.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticAdCtl.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticAdCtl.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticAdCtl.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticAdCtl.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticEnvsLexicon.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticEnvsLexicon.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticEnvsLexicon.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticEnvsLexicon.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticEnvsParserFxtResult.xml b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticEnvsParserFxtResult.xml similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticEnvsParserFxtResult.xml rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticEnvsParserFxtResult.xml diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticLexicon.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticLexicon.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticLexicon.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticLexicon.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticParserFxtResult.xml b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticParserFxtResult.xml similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticParserFxtResult.xml rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticParserFxtResult.xml diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticWordGrammar.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticWordGrammar.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticWordGrammar.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/CliticWordGrammar.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/ConceptualIntroTestParserFxtResult.xml b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/ConceptualIntroTestParserFxtResult.xml similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/ConceptualIntroTestParserFxtResult.xml rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/ConceptualIntroTestParserFxtResult.xml diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/ConceptualIntroTestlex.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/ConceptualIntroTestlex.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/ConceptualIntroTestlex.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/ConceptualIntroTestlex.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/FullRedupLexicon.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/FullRedupLexicon.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/FullRedupLexicon.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/FullRedupLexicon.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IndonCircumfixLexicon.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IndonCircumfixLexicon.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IndonCircumfixLexicon.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IndonCircumfixLexicon.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IndonCircumfixWordGrammar.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IndonCircumfixWordGrammar.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IndonCircumfixWordGrammar.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IndonCircumfixWordGrammar.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IrregularlyInflectedFormsAdCtl.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IrregularlyInflectedFormsAdCtl.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IrregularlyInflectedFormsAdCtl.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IrregularlyInflectedFormsAdCtl.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IrregularlyInflectedFormsLexicon.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IrregularlyInflectedFormsLexicon.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IrregularlyInflectedFormsLexicon.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IrregularlyInflectedFormsLexicon.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IrregularlyInflectedFormsParserFxtResult.xml b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IrregularlyInflectedFormsParserFxtResult.xml similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IrregularlyInflectedFormsParserFxtResult.xml rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/IrregularlyInflectedFormsParserFxtResult.xml diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/LatinAdCtl.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/LatinAdCtl.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/LatinAdCtl.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/LatinAdCtl.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/LatinParserFxtResult.xml b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/LatinParserFxtResult.xml similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/LatinParserFxtResult.xml rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/LatinParserFxtResult.xml diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/LatinWordGrammar.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/LatinWordGrammar.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/LatinWordGrammar.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/LatinWordGrammar.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTCircumfixDump.xml b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTCircumfixDump.xml similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTCircumfixDump.xml rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTCircumfixDump.xml diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTCircumfixInfixDump.xml b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTCircumfixInfixDump.xml similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTCircumfixInfixDump.xml rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTCircumfixInfixDump.xml diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTDump.xml b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTDump.xml similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTDump.xml rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTDump.xml diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTFullRedupDump.xml b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTFullRedupDump.xml similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTFullRedupDump.xml rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTFullRedupDump.xml diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTStemNameDump.xml b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTStemNameDump.xml similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTStemNameDump.xml rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/M3FXTStemNameDump.xml diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/OrizabaParserFxtResult.xml b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/OrizabaParserFxtResult.xml similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/OrizabaParserFxtResult.xml rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/OrizabaParserFxtResult.xml diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/Orizabaadctl.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/Orizabaadctl.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/Orizabaadctl.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/Orizabaadctl.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/Orizabagram.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/Orizabagram.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/Orizabagram.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/Orizabagram.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/Orizabalex.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/Orizabalex.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/Orizabalex.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/Orizabalex.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/RootCliticEnvParserFxtResult.xml b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/RootCliticEnvParserFxtResult.xml similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/RootCliticEnvParserFxtResult.xml rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/RootCliticEnvParserFxtResult.xml diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/RootCliticEnvsLexicon.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/RootCliticEnvsLexicon.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/RootCliticEnvsLexicon.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/RootCliticEnvsLexicon.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemName3ParserFxtResult.xml b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemName3ParserFxtResult.xml similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemName3ParserFxtResult.xml rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemName3ParserFxtResult.xml diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemName3adctl.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemName3adctl.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemName3adctl.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemName3adctl.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemName3gram.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemName3gram.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemName3gram.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemName3gram.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemName3lex.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemName3lex.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemName3lex.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemName3lex.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemNameTestAdCtl.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemNameTestAdCtl.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemNameTestAdCtl.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemNameTestAdCtl.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemNameTestlex.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemNameTestlex.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemNameTestlex.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemNameTestlex.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemNameWordGrammar.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemNameWordGrammar.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemNameWordGrammar.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/StemNameWordGrammar.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/TestAdCtl.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/TestAdCtl.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/TestAdCtl.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/TestAdCtl.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/TestAffixAllomorphFeatsParserFxtResult.xml b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/TestAffixAllomorphFeatsParserFxtResult.xml similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/TestAffixAllomorphFeatsParserFxtResult.xml rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/TestAffixAllomorphFeatsParserFxtResult.xml diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/TestLexicon.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/TestLexicon.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/TestLexicon.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/TestLexicon.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/TestWordGrammar.txt b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/TestWordGrammar.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/TestWordGrammar.txt rename to Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles/TestWordGrammar.txt diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParseFilerProcessingTests.cs b/Src/LexText/ParserCore/ParserCoreTests/ParseFilerProcessingTests.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParseFilerProcessingTests.cs rename to Src/LexText/ParserCore/ParserCoreTests/ParseFilerProcessingTests.cs diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParserCoreTests.csproj b/Src/LexText/ParserCore/ParserCoreTests/ParserCoreTests.csproj similarity index 85% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParserCoreTests.csproj rename to Src/LexText/ParserCore/ParserCoreTests/ParserCoreTests.csproj index d4e352219a..723d0f77ed 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/ParserCoreTests.csproj +++ b/Src/LexText/ParserCore/ParserCoreTests/ParserCoreTests.csproj @@ -32,7 +32,7 @@ - ..\..\..\..\..\Output\Debug\ + ..\..\..\..\Output\Debug\ false 285212672 false @@ -56,7 +56,7 @@ x86 - ..\..\..\..\..\Output\Release\ + ..\..\..\..\Output\Release\ false 285212672 false @@ -82,47 +82,47 @@ False - ..\..\..\..\..\Output\Debug\BasicUtils.dll + ..\..\..\..\Output\Debug\BasicUtils.dll False - ..\..\..\..\..\Output\Debug\BasicUtilsTests.dll + ..\..\..\..\Output\Debug\BasicUtilsTests.dll False - ..\..\..\..\..\Output\Debug\COMInterfaces.dll + ..\..\..\..\Output\Debug\COMInterfaces.dll False - ..\..\..\..\..\Output\Debug\COMInterfacesTests.dll + ..\..\..\..\Output\Debug\COMInterfacesTests.dll False - ..\..\..\..\..\Output\Debug\CoreImpl.dll + ..\..\..\..\Output\Debug\CoreImpl.dll FDO - ..\..\..\..\..\Output\Debug\FDO.dll + ..\..\..\..\Output\Debug\FDO.dll FDOTests - ..\..\..\..\..\Output\Debug\FDOTests.dll + ..\..\..\..\Output\Debug\FDOTests.dll False - ..\..\..\..\..\Output\Debug\FwUtils.dll + ..\..\..\..\Output\Debug\FwUtils.dll False - ..\..\..\..\..\DistFiles\Microsoft.Practices.ServiceLocation.dll + ..\..\..\..\DistFiles\Microsoft.Practices.ServiceLocation.dll nunit.framework - ..\..\..\..\..\Bin\NUnit\bin\nunit.framework.dll + ..\..\..\..\Bin\NUnit\bin\nunit.framework.dll ParserCore - ..\..\..\..\..\Output\Debug\ParserCore.dll + ..\..\..\..\Output\Debug\ParserCore.dll System @@ -135,16 +135,16 @@ False - ..\..\..\..\..\Output\Debug\TestUtils.dll + ..\..\..\..\Output\Debug\TestUtils.dll XMLUtils - ..\..\..\..\..\Output\Debug\XMLUtils.dll + ..\..\..\..\Output\Debug\XMLUtils.dll - + AssemblyInfoForTests.cs diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/UpdateParserDataTests.cs b/Src/LexText/ParserCore/ParserCoreTests/UpdateParserDataTests.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/UpdateParserDataTests.cs rename to Src/LexText/ParserCore/ParserCoreTests/UpdateParserDataTests.cs diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/XAmpleParserTests.cs b/Src/LexText/ParserCore/ParserCoreTests/XAmpleParserTests.cs similarity index 98% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/XAmpleParserTests.cs rename to Src/LexText/ParserCore/ParserCoreTests/XAmpleParserTests.cs index f7181dfa0f..608662c269 100644 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/XAmpleParserTests.cs +++ b/Src/LexText/ParserCore/ParserCoreTests/XAmpleParserTests.cs @@ -24,7 +24,7 @@ public class XAmpleParserTests : BaseTest [Test] public void ConvertFailures() { - string testPath = Path.Combine(FwDirectoryFinder.SourceDirectory, "LexText", "ParserEngine", "ParserCore", "ParserCoreTests", "Failures.xml"); + string testPath = Path.Combine(FwDirectoryFinder.SourceDirectory, "LexText", "ParserCore", "ParserCoreTests", "Failures.xml"); XDocument doc = XDocument.Load(testPath); XElement[] failures = doc.Descendants("failure").ToArray(); diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/gendarme-ParserCoreTests.ignore b/Src/LexText/ParserCore/ParserCoreTests/gendarme-ParserCoreTests.ignore similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserCoreTests/gendarme-ParserCoreTests.ignore rename to Src/LexText/ParserCore/ParserCoreTests/gendarme-ParserCoreTests.ignore diff --git a/Src/LexText/ParserEngine/ParserCore/ParserHelper.cs b/Src/LexText/ParserCore/ParserHelper.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserHelper.cs rename to Src/LexText/ParserCore/ParserHelper.cs diff --git a/Src/LexText/ParserEngine/ParserCore/ParserScheduler.cs b/Src/LexText/ParserCore/ParserScheduler.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserScheduler.cs rename to Src/LexText/ParserCore/ParserScheduler.cs diff --git a/Src/LexText/ParserEngine/ParserCore/ParserWorker.cs b/Src/LexText/ParserCore/ParserWorker.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserWorker.cs rename to Src/LexText/ParserCore/ParserWorker.cs diff --git a/Src/LexText/ParserEngine/ParserCore/ParserXmlWriterExtensions.cs b/Src/LexText/ParserCore/ParserXmlWriterExtensions.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/ParserXmlWriterExtensions.cs rename to Src/LexText/ParserCore/ParserXmlWriterExtensions.cs diff --git a/Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/BuildInclude.targets b/Src/LexText/ParserCore/PatrParserWrapper/BuildInclude.targets similarity index 94% rename from Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/BuildInclude.targets rename to Src/LexText/ParserCore/PatrParserWrapper/BuildInclude.targets index 613ca38b95..0b2e62114e 100644 --- a/Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/BuildInclude.targets +++ b/Src/LexText/ParserCore/PatrParserWrapper/BuildInclude.targets @@ -1,7 +1,7 @@ - ../../../../.. + ../../../.. diff --git a/Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/IPatrParser.cs b/Src/LexText/ParserCore/PatrParserWrapper/IPatrParser.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/IPatrParser.cs rename to Src/LexText/ParserCore/PatrParserWrapper/IPatrParser.cs diff --git a/Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParser.cs b/Src/LexText/ParserCore/PatrParserWrapper/PatrParser.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParser.cs rename to Src/LexText/ParserCore/PatrParserWrapper/PatrParser.cs diff --git a/Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapper.csproj b/Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapper.csproj similarity index 95% rename from Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapper.csproj rename to Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapper.csproj index e81b9f095d..bd2d4025b7 100644 --- a/Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapper.csproj +++ b/Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapper.csproj @@ -37,7 +37,7 @@ true full false - ..\..\..\..\..\Output\Debug\ + ..\..\..\..\Output\Debug\ DEBUG;TRACE prompt 4 @@ -49,7 +49,7 @@ pdbonly true - ..\..\..\..\..\Output\Release\ + ..\..\..\..\Output\Release\ TRACE prompt 4 @@ -67,7 +67,7 @@ - + CommonAssemblyInfo.cs diff --git a/Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapper.dll.config b/Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapper.dll.config similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapper.dll.config rename to Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapper.dll.config diff --git a/Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapperTests/Ephtst.ana b/Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapperTests/Ephtst.ana similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapperTests/Ephtst.ana rename to Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapperTests/Ephtst.ana diff --git a/Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapperTests/MyLex.txt b/Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapperTests/MyLex.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapperTests/MyLex.txt rename to Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapperTests/MyLex.txt diff --git a/Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapperTests/PatrParserTests.cs b/Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapperTests/PatrParserTests.cs similarity index 99% rename from Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapperTests/PatrParserTests.cs rename to Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapperTests/PatrParserTests.cs index 990fe3dc1a..e38eb29541 100644 --- a/Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapperTests/PatrParserTests.cs +++ b/Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapperTests/PatrParserTests.cs @@ -11,7 +11,7 @@ namespace PatrParserWrapperTest public class PatrParserInteropTests { protected const string LocationToSrcDirFromOutputDebug = - "../../Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapperTests/"; + "../../Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapperTests/"; protected const string GrammarFileName = LocationToSrcDirFromOutputDebug + "StemNameWordGrammar.txt"; diff --git a/Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapperTests/PatrParserWrapperTests.csproj b/Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapperTests/PatrParserWrapperTests.csproj similarity index 89% rename from Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapperTests/PatrParserWrapperTests.csproj rename to Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapperTests/PatrParserWrapperTests.csproj index cf64d656cc..b23abe6c54 100644 --- a/Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapperTests/PatrParserWrapperTests.csproj +++ b/Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapperTests/PatrParserWrapperTests.csproj @@ -39,7 +39,7 @@ true full false - ..\..\..\..\..\..\Output\Debug\ + ..\..\..\..\..\Output\Debug\ DEBUG;TRACE prompt 4 @@ -49,7 +49,7 @@ pdbonly true - ..\..\..\..\..\..\Output\Release\ + ..\..\..\..\..\Output\Release\ TRACE prompt 4 @@ -59,29 +59,29 @@ False - ..\..\..\..\..\..\Output\Debug\BasicUtilsTests.dll + ..\..\..\..\..\Output\Debug\BasicUtilsTests.dll False - ..\..\..\..\..\..\Output\Debug\COMInterfacesTests.dll + ..\..\..\..\..\Output\Debug\COMInterfacesTests.dll False - ..\..\..\..\..\..\Bin\NUnit\bin\nunit.framework.dll + ..\..\..\..\..\Bin\NUnit\bin\nunit.framework.dll False - ..\..\..\..\..\..\Output\Debug\Patr100Interop.dll + ..\..\..\..\..\Output\Debug\Patr100Interop.dll PatrParserWrapper - ..\..\..\..\..\..\Output\Debug\PatrParserWrapper.dll + ..\..\..\..\..\Output\Debug\PatrParserWrapper.dll - + AssemblyInfoForTests.cs diff --git a/Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapperTests/StemNameWordGrammar.txt b/Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapperTests/StemNameWordGrammar.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapperTests/StemNameWordGrammar.txt rename to Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapperTests/StemNameWordGrammar.txt diff --git a/Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapperTests/bears.ana b/Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapperTests/bears.ana similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapperTests/bears.ana rename to Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapperTests/bears.ana diff --git a/Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapperTests/gendarme-PatrParserWrapperTests.ignore b/Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapperTests/gendarme-PatrParserWrapperTests.ignore similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/PatrParserWrapperTests/gendarme-PatrParserWrapperTests.ignore rename to Src/LexText/ParserCore/PatrParserWrapper/PatrParserWrapperTests/gendarme-PatrParserWrapperTests.ignore diff --git a/Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/Properties/AssemblyInfo.cs b/Src/LexText/ParserCore/PatrParserWrapper/Properties/AssemblyInfo.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/Properties/AssemblyInfo.cs rename to Src/LexText/ParserCore/PatrParserWrapper/Properties/AssemblyInfo.cs diff --git a/Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/gendarme-PatrParserWrapper.ignore b/Src/LexText/ParserCore/PatrParserWrapper/gendarme-PatrParserWrapper.ignore similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/PatrParserWrapper/gendarme-PatrParserWrapper.ignore rename to Src/LexText/ParserCore/PatrParserWrapper/gendarme-PatrParserWrapper.ignore diff --git a/Src/LexText/ParserEngine/ParserCore/TaskReport.cs b/Src/LexText/ParserCore/TaskReport.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/TaskReport.cs rename to Src/LexText/ParserCore/TaskReport.cs diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/ReadMe.txt b/Src/LexText/ParserCore/XAmpleCOMWrapper/ReadMe.txt similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/ReadMe.txt rename to Src/LexText/ParserCore/XAmpleCOMWrapper/ReadMe.txt diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/Resource.h b/Src/LexText/ParserCore/XAmpleCOMWrapper/Resource.h similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/Resource.h rename to Src/LexText/ParserCore/XAmpleCOMWrapper/Resource.h diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.cpp b/Src/LexText/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.cpp similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.cpp rename to Src/LexText/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.cpp diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.rc b/Src/LexText/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.rc similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.rc rename to Src/LexText/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.rc diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.rgs b/Src/LexText/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.rgs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.rgs rename to Src/LexText/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.rgs diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.vcxproj b/Src/LexText/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.vcxproj similarity index 92% rename from Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.vcxproj rename to Src/LexText/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.vcxproj index 72585850c2..d8ea98386a 100644 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.vcxproj +++ b/Src/LexText/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.vcxproj @@ -53,15 +53,15 @@ <_ProjectFileVersion>10.0.30319.1 - ..\..\..\..\..\Lib\$(Configuration)\ + ..\..\..\..\Lib\$(Configuration)\ Debug\Obj\ true true - ..\..\..\..\..\Lib\$(Configuration)\ + ..\..\..\..\Lib\$(Configuration)\ Release\Obj\ true false - ..\..\..\..\..\Lib\$(Configuration)\ + ..\..\..\..\Lib\$(Configuration)\ Bounds\ true true @@ -81,7 +81,7 @@ Disabled - ..\..\..\..\..\Include;%(AdditionalIncludeDirectories) + ..\..\..\..\Include;%(AdditionalIncludeDirectories) WIN32;_WINDOWS;_DEBUG;_USRDLL;_ATL_ATTRIBUTES;%(PreprocessorDefinitions) true EnableFastChecks @@ -99,7 +99,7 @@ icudt.lib;icuind.lib;icuucd.lib;%(AdditionalDependencies) $(OutDir)XAmpleCOMWrapper.dll - ..\..\..\..\..\Lib;..\..\..\..\..\Lib\$(Configuration);%(AdditionalLibraryDirectories) + ..\..\..\..\Lib;..\..\..\..\Lib\$(Configuration);%(AdditionalLibraryDirectories) _XAmpleCOMWrapper.idl true Windows @@ -122,7 +122,7 @@ OnlyExplicitInline - ..\..\..\..\..\Include;%(AdditionalIncludeDirectories) + ..\..\..\..\Include;%(AdditionalIncludeDirectories) WIN32;_WINDOWS;NDEBUG;_USRDLL;_ATL_ATTRIBUTES;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -139,7 +139,7 @@ icudt.lib;icuin.lib;icuuc.lib;%(AdditionalDependencies) $(OutDir)XAmpleCOMWrapper.dll - ..\..\..\..\..\Lib;..\..\..\..\..\Lib\$(Configuration);%(AdditionalLibraryDirectories) + ..\..\..\..\Lib;..\..\..\..\Lib\$(Configuration);%(AdditionalLibraryDirectories) _XAmpleCOMWrapper.idl true Windows @@ -174,7 +174,7 @@ Disabled - ..\..\..\..\..\Include;%(AdditionalIncludeDirectories) + ..\..\..\..\Include;%(AdditionalIncludeDirectories) WIN32;_WINDOWS;_DEBUG;_USRDLL;_ATL_ATTRIBUTES;%(PreprocessorDefinitions) true EnableFastChecks @@ -191,7 +191,7 @@ icudt.lib;icuind.lib;icuucd.lib;%(AdditionalDependencies) $(OutDir)XAmpleCOMWrapper.dll - ..\..\..\..\..\Lib;..\..\..\..\..\Lib\$(Configuration);%(AdditionalLibraryDirectories) + ..\..\..\..\Lib;..\..\..\..\Lib\$(Configuration);%(AdditionalLibraryDirectories) _XAmpleCOMWrapper.idl true Windows diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.vcxproj.filters b/Src/LexText/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.vcxproj.filters similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.vcxproj.filters rename to Src/LexText/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.vcxproj.filters diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapperps.def b/Src/LexText/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapperps.def similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapperps.def rename to Src/LexText/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapperps.def diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleWrapper.cpp b/Src/LexText/ParserCore/XAmpleCOMWrapper/XAmpleWrapper.cpp similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleWrapper.cpp rename to Src/LexText/ParserCore/XAmpleCOMWrapper/XAmpleWrapper.cpp diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleWrapperCore.cpp b/Src/LexText/ParserCore/XAmpleCOMWrapper/XAmpleWrapperCore.cpp similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleWrapperCore.cpp rename to Src/LexText/ParserCore/XAmpleCOMWrapper/XAmpleWrapperCore.cpp diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleWrapperCore.h b/Src/LexText/ParserCore/XAmpleCOMWrapper/XAmpleWrapperCore.h similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleWrapperCore.h rename to Src/LexText/ParserCore/XAmpleCOMWrapper/XAmpleWrapperCore.h diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/stdafx.cpp b/Src/LexText/ParserCore/XAmpleCOMWrapper/stdafx.cpp similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/stdafx.cpp rename to Src/LexText/ParserCore/XAmpleCOMWrapper/stdafx.cpp diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/stdafx.h b/Src/LexText/ParserCore/XAmpleCOMWrapper/stdafx.h similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/stdafx.h rename to Src/LexText/ParserCore/XAmpleCOMWrapper/stdafx.h diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/xamplewrapper.h b/Src/LexText/ParserCore/XAmpleCOMWrapper/xamplewrapper.h similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/xamplewrapper.h rename to Src/LexText/ParserCore/XAmpleCOMWrapper/xamplewrapper.h diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/AmpleOptions.cs b/Src/LexText/ParserCore/XAmpleManagedWrapper/AmpleOptions.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/AmpleOptions.cs rename to Src/LexText/ParserCore/XAmpleManagedWrapper/AmpleOptions.cs diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/AssemblyInfo.cs b/Src/LexText/ParserCore/XAmpleManagedWrapper/AssemblyInfo.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/AssemblyInfo.cs rename to Src/LexText/ParserCore/XAmpleManagedWrapper/AssemblyInfo.cs diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/BuildInclude.targets b/Src/LexText/ParserCore/XAmpleManagedWrapper/BuildInclude.targets similarity index 94% rename from Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/BuildInclude.targets rename to Src/LexText/ParserCore/XAmpleManagedWrapper/BuildInclude.targets index c103de774a..9191714c52 100644 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/BuildInclude.targets +++ b/Src/LexText/ParserCore/XAmpleManagedWrapper/BuildInclude.targets @@ -1,7 +1,7 @@ - ../../../../.. + ../../../.. diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/IXAmpleWrapper.cs b/Src/LexText/ParserCore/XAmpleManagedWrapper/IXAmpleWrapper.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/IXAmpleWrapper.cs rename to Src/LexText/ParserCore/XAmpleManagedWrapper/IXAmpleWrapper.cs diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleDLLWrapper.cs b/Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleDLLWrapper.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleDLLWrapper.cs rename to Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleDLLWrapper.cs diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapper.csproj b/Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapper.csproj similarity index 95% rename from Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapper.csproj rename to Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapper.csproj index fe59ec6175..6a5cbb8e8a 100644 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapper.csproj +++ b/Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapper.csproj @@ -36,7 +36,7 @@ full false 168,169,219,414,649,1635,1702,1701 - ..\..\..\..\..\Output\Debug + ..\..\..\..\Output\Debug DEBUG prompt 4 @@ -48,7 +48,7 @@ none false 168,169,219,414,649,1635,1702,1701 - ..\..\..\..\..\Output\Release + ..\..\..\..\Output\Release prompt 4 false @@ -59,7 +59,7 @@ - + CommonAssemblyInfo.cs diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleDLLWrapper.cs b/Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleDLLWrapper.cs similarity index 94% rename from Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleDLLWrapper.cs rename to Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleDLLWrapper.cs index d0e787a32c..0f3031c09f 100644 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleDLLWrapper.cs +++ b/Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleDLLWrapper.cs @@ -17,7 +17,7 @@ protected XAmpleDLLWrapper CreateXAmpleDllWrapper() protected void LoadFilesHelper(XAmpleDLLWrapper wrapper) { - string tempPath = "../../Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles"; + string tempPath = "../../Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles"; // TODO: use DirectoryFinder.FWCodeDirectory string xPath = "../../DistFiles/" + "/Language Explorer/Configuration/Grammar"; wrapper.LoadFiles(xPath, tempPath, "StemName3"); diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleWrapper.cs b/Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleWrapper.cs similarity index 93% rename from Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleWrapper.cs rename to Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleWrapper.cs index 6e21046768..db35efdc9b 100644 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleWrapper.cs +++ b/Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/TestXAmpleWrapper.cs @@ -15,7 +15,7 @@ protected XAmpleWrapper InitHelper() protected void LoadFilesHelper(XAmpleWrapper wrapper) { - var tempPath = "../../Src/LexText/ParserEngine/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles"; + var tempPath = "../../Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTestsDataFiles"; // TODO: use DirectoryFinder.FWCodeDirectory var xPath = "../../DistFiles/" + "/Language Explorer/Configuration/Grammar"; wrapper.LoadFiles(xPath, tempPath, "StemName3"); diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/XAmpleManagedWrapperTests.csproj b/Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/XAmpleManagedWrapperTests.csproj similarity index 84% rename from Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/XAmpleManagedWrapperTests.csproj rename to Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/XAmpleManagedWrapperTests.csproj index f324842988..56a9c78866 100644 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/XAmpleManagedWrapperTests.csproj +++ b/Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/XAmpleManagedWrapperTests.csproj @@ -21,7 +21,7 @@ full false 168,169,219,414,649,1635,1702,1701 - ..\..\..\..\..\..\Output\Debug + ..\..\..\..\..\Output\Debug DEBUG prompt 4 @@ -37,7 +37,7 @@ none false 168,169,219,414,649,1635,1702,1701 - ..\..\..\..\..\..\Output\Release + ..\..\..\..\..\Output\Release prompt 4 AllRules.ruleset @@ -46,29 +46,29 @@ False - ..\..\..\..\..\..\Output\Debug\BasicUtilsTests.dll + ..\..\..\..\..\Output\Debug\BasicUtilsTests.dll False - ..\..\..\..\..\..\Output\Debug\COMInterfacesTests.dll + ..\..\..\..\..\Output\Debug\COMInterfacesTests.dll False - ..\..\..\..\..\..\Bin\NUnit\bin\nunit.framework.dll + ..\..\..\..\..\Bin\NUnit\bin\nunit.framework.dll False - ..\..\..\..\..\..\Output\Debug\XAmpleManagedWrapper.dll + ..\..\..\..\..\Output\Debug\XAmpleManagedWrapper.dll TestUtils False - ..\..\..\..\..\..\Output\Debug\TestUtils.dll + ..\..\..\..\..\Output\Debug\TestUtils.dll - + AssemblyInfoForTests.cs diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleWrapper.cs b/Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleWrapper.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleWrapper.cs rename to Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleWrapper.cs diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs b/Src/LexText/ParserCore/XAmpleParser.cs similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/XAmpleParser.cs rename to Src/LexText/ParserCore/XAmpleParser.cs diff --git a/Src/LexText/ParserEngine/ParserCore/gendarme-ParserCore.ignore b/Src/LexText/ParserCore/gendarme-ParserCore.ignore similarity index 100% rename from Src/LexText/ParserEngine/ParserCore/gendarme-ParserCore.ignore rename to Src/LexText/ParserCore/gendarme-ParserCore.ignore diff --git a/Src/LexText/ParserEngine/Parser Architecture.vsd b/Src/LexText/ParserEngine/Parser Architecture.vsd deleted file mode 100644 index 0ed72aa9ac6f747978133c7326774a493f879be5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52736 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 z 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 OADHE%Ci|ZZ|Nj8n+VtN5 diff --git a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/App.config b/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/App.config deleted file mode 100644 index 8d329647ba..0000000000 --- a/Src/LexText/ParserEngine/ParserCore/ParserCoreTests/App.config +++ /dev/null @@ -1,22 +0,0 @@ - - - - -
- - - - - - - - - - - - - - - - - diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.sln b/Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.sln deleted file mode 100644 index a0b770cfa0..0000000000 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleCOMWrapper/XAmpleCOMWrapper.sln +++ /dev/null @@ -1,63 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XAmpleCOMWrapper", "XAmpleCOMWrapper.vcproj", "{D841AF80-C339-4523-9919-1E645F41D08E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParserCore", "..\ParserCore.csproj", "{116BE16A-B3A0-408C-A5CD-25BCBBDBE327}" -EndProject -Global - GlobalSection(SourceCodeControl) = preSolution - SccNumberOfProjects = 3 - SccProjectName0 = Perforce\u0020Project - SccLocalPath0 = . - SccProvider0 = MSSCCI:Perforce\u0020SCM - CanCheckoutShared = true - SccProjectUniqueName1 = XAmpleCOMWrapper.vcproj - SccLocalPath1 = . - CanCheckoutShared = true - SccProjectUniqueName2 = ..\\ParserCore.csproj - SccLocalPath2 = .. - CanCheckoutShared = true - EndGlobalSection - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Bounds|Any CPU = Bounds|Any CPU - Bounds|Mixed Platforms = Bounds|Mixed Platforms - Bounds|Win32 = Bounds|Win32 - Debug|Any CPU = Debug|Any CPU - Debug|Mixed Platforms = Debug|Mixed Platforms - Debug|Win32 = Debug|Win32 - Release|Any CPU = Release|Any CPU - Release|Mixed Platforms = Release|Mixed Platforms - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D841AF80-C339-4523-9919-1E645F41D08E}.Bounds|Any CPU.ActiveCfg = Bounds|Win32 - {D841AF80-C339-4523-9919-1E645F41D08E}.Bounds|Mixed Platforms.ActiveCfg = Bounds|Win32 - {D841AF80-C339-4523-9919-1E645F41D08E}.Bounds|Mixed Platforms.Build.0 = Bounds|Win32 - {D841AF80-C339-4523-9919-1E645F41D08E}.Bounds|Win32.ActiveCfg = Bounds|Win32 - {D841AF80-C339-4523-9919-1E645F41D08E}.Bounds|Win32.Build.0 = Bounds|Win32 - {D841AF80-C339-4523-9919-1E645F41D08E}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {D841AF80-C339-4523-9919-1E645F41D08E}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {D841AF80-C339-4523-9919-1E645F41D08E}.Debug|Win32.ActiveCfg = Debug|Win32 - {D841AF80-C339-4523-9919-1E645F41D08E}.Debug|Win32.Build.0 = Debug|Win32 - {D841AF80-C339-4523-9919-1E645F41D08E}.Release|Any CPU.ActiveCfg = Release|Win32 - {D841AF80-C339-4523-9919-1E645F41D08E}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {D841AF80-C339-4523-9919-1E645F41D08E}.Release|Win32.ActiveCfg = Release|Win32 - {D841AF80-C339-4523-9919-1E645F41D08E}.Release|Win32.Build.0 = Release|Win32 - {116BE16A-B3A0-408C-A5CD-25BCBBDBE327}.Bounds|Any CPU.ActiveCfg = Release|Any CPU - {116BE16A-B3A0-408C-A5CD-25BCBBDBE327}.Bounds|Any CPU.Build.0 = Release|Any CPU - {116BE16A-B3A0-408C-A5CD-25BCBBDBE327}.Bounds|Mixed Platforms.ActiveCfg = Release|Any CPU - {116BE16A-B3A0-408C-A5CD-25BCBBDBE327}.Bounds|Mixed Platforms.Build.0 = Release|Any CPU - {116BE16A-B3A0-408C-A5CD-25BCBBDBE327}.Bounds|Win32.ActiveCfg = Release|Any CPU - {116BE16A-B3A0-408C-A5CD-25BCBBDBE327}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {116BE16A-B3A0-408C-A5CD-25BCBBDBE327}.Debug|Any CPU.Build.0 = Debug|Any CPU - {116BE16A-B3A0-408C-A5CD-25BCBBDBE327}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {116BE16A-B3A0-408C-A5CD-25BCBBDBE327}.Debug|Win32.ActiveCfg = Debug|Any CPU - {116BE16A-B3A0-408C-A5CD-25BCBBDBE327}.Release|Any CPU.ActiveCfg = Release|Any CPU - {116BE16A-B3A0-408C-A5CD-25BCBBDBE327}.Release|Any CPU.Build.0 = Release|Any CPU - {116BE16A-B3A0-408C-A5CD-25BCBBDBE327}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {116BE16A-B3A0-408C-A5CD-25BCBBDBE327}.Release|Win32.ActiveCfg = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/App.config b/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/App.config deleted file mode 100644 index 8d329647ba..0000000000 --- a/Src/LexText/ParserEngine/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/App.config +++ /dev/null @@ -1,22 +0,0 @@ - - - - -
- - - - - - - - - - - - - - - - - diff --git a/Src/LexText/ParserUI/HCTrace.cs b/Src/LexText/ParserUI/HCTrace.cs index 4d56f191d3..7edc181ed2 100644 --- a/Src/LexText/ParserUI/HCTrace.cs +++ b/Src/LexText/ParserUI/HCTrace.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Xml.Linq; using System.Xml.Xsl; @@ -6,6 +7,8 @@ namespace SIL.FieldWorks.LexText.Controls { + [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", + Justification="m_cache and m_mediator are references")] public class HCTrace : ParserTrace { private static ParserTraceUITransform s_traceTransform; diff --git a/Src/LexText/ParserUI/WordGrammarDebugger.cs b/Src/LexText/ParserUI/WordGrammarDebugger.cs index e608298ce6..a6dd52fb08 100644 --- a/Src/LexText/ParserUI/WordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/WordGrammarDebugger.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; @@ -13,6 +14,8 @@ namespace SIL.FieldWorks.LexText.Controls { + [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", + Justification="m_cache and m_mediator are references")] public abstract class WordGrammarDebugger { private static ParserTraceUITransform s_pageTransform; diff --git a/Src/LexText/ParserUI/XAmpleTrace.cs b/Src/LexText/ParserUI/XAmpleTrace.cs index e2bfc16716..16e2e79b27 100644 --- a/Src/LexText/ParserUI/XAmpleTrace.cs +++ b/Src/LexText/ParserUI/XAmpleTrace.cs @@ -13,6 +13,7 @@ // XAmpleTrace - Deal with results of an XAmple trace // +using System.Diagnostics.CodeAnalysis; using System.Xml.Linq; using XCore; @@ -21,6 +22,8 @@ namespace SIL.FieldWorks.LexText.Controls /// /// Summary description for XAmpleTrace. /// + [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", + Justification="m_mediator is a reference")] public class XAmpleTrace : ParserTrace { private static ParserTraceUITransform s_traceTransform; From 8445cf537b51e9316ac920cdfdc0723c3adbb50a Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Mon, 17 Feb 2014 16:38:59 +0700 Subject: [PATCH 083/143] refactored parser loading to use XDocument Change-Id: Id0e0fac80003c1742bcf979989141cb3bce786d5 --- .../DomainServices/M3ModelExportServices.cs | 24 +- Src/LexText/ParserCore/HCParser.cs | 24 +- Src/LexText/ParserCore/M3ModelRetriever.cs | 212 ++++++++---------- Src/LexText/ParserCore/M3ToHCTransformer.cs | 32 ++- .../ParserCore/M3ToParserTransformerBase.cs | 43 +++- .../ParserCore/M3ToXAmpleTransformer.cs | 135 ++++++----- Src/LexText/ParserCore/ParserCore.csproj | 7 +- .../ParserCoreTests/ParserCoreTests.csproj | 1 - .../ParserCoreTests/UpdateParserDataTests.cs | 4 +- .../XAmpleManagedWrapperTests.csproj | 1 - Src/LexText/ParserCore/XAmpleParser.cs | 28 +-- 11 files changed, 271 insertions(+), 240 deletions(-) diff --git a/Src/FDO/DomainServices/M3ModelExportServices.cs b/Src/FDO/DomainServices/M3ModelExportServices.cs index dba93406f6..0d774a88f4 100644 --- a/Src/FDO/DomainServices/M3ModelExportServices.cs +++ b/Src/FDO/DomainServices/M3ModelExportServices.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Xml.Linq; using Microsoft.Practices.ServiceLocation; @@ -51,9 +50,8 @@ public static void ExportGrammarSketch(string outputPath, ILangProject languageP /// /// Export the grammar and lexicon. /// - public static void ExportGrammarAndLexicon(string outputPath, ILangProject languageProject) + public static XDocument ExportGrammarAndLexicon(ILangProject languageProject) { - if (string.IsNullOrEmpty(outputPath)) throw new ArgumentNullException("outputPath"); if (languageProject == null) throw new ArgumentNullException("languageProject"); var servLoc = languageProject.Cache.ServiceLocator; @@ -76,7 +74,7 @@ public static void ExportGrammarAndLexicon(string outputPath, ILangProject langu ExportFeatureSystem(languageProject.PhFeatureSystemOA, "PhFeatureSystem", mode) ) ); - doc.Save(outputPath); + return doc; } private static XElement ExportLanguageProject(ILangProject languageProject, Icu.UNormalizationMode mode) @@ -127,12 +125,12 @@ static bool IsValidTemplate(IMoInflAffixTemplate template) return (from affixSlot in template.PrefixSlotsRS.Concat(template.SuffixSlotsRS) where IsValidSlot(affixSlot) - select affixSlot).Take(1).Count() > 0; + select affixSlot).Take(1).Any(); } private static bool IsValidSlot(IMoInflAffixSlot affixSlot) { - return affixSlot.Affixes.Take(1).Count() > 0; + return affixSlot.Affixes.Take(1).Any(); } @@ -316,7 +314,7 @@ private static XElement ExportLexiconFull(IServiceLocator servLoc, Icu.UNormaliz { return new XElement("Lexicon", ExportEntries(servLoc.GetInstance()), - ExportMSAs(servLoc), + ExportMsas(servLoc), ExportSenses(servLoc.GetInstance(), mode), ExportAllomorphs(servLoc, mode)); } @@ -346,7 +344,7 @@ from lexEntryInflType in lexEntryRef.VariantEntryTypesRS select ExportItemAsReference(lexEntryInflType, "LexEntryInflType")))); } - private static XElement ExportMSAs(IServiceLocator servLoc) + private static XElement ExportMsas(IServiceLocator servLoc) { return new XElement("MorphoSyntaxAnalyses", from stemMsa in servLoc.GetInstance().AllInstances() @@ -503,9 +501,9 @@ private static XElement ExportPhonRuleFeat(IPhPhonRuleFeat phonRuleFeat, Icu.UNo private static XElement ExportPhonRule(IPhSegmentRule phonRule, Icu.UNormalizationMode mode) { - XElement retVal = null; if (phonRule.Disabled) - return retVal; + return null; + XElement retVal = null; switch (phonRule.ClassName) { case "PhMetathesisRule": @@ -930,10 +928,8 @@ from insertContent in insertPhones.ContentRS /// /// Export everything needed by parsers for GAFAWS data. /// - public static void ExportGafaws(string outputFolder, string databaseName, ICollection partsOfSpeech) + public static XDocument ExportGafaws(IEnumerable partsOfSpeech) { - if (string.IsNullOrEmpty(outputFolder)) throw new ArgumentNullException("outputFolder"); - if (string.IsNullOrEmpty(databaseName)) throw new ArgumentNullException("databaseName"); if (partsOfSpeech == null) throw new ArgumentNullException("partsOfSpeech"); var doc = new XDocument( @@ -942,7 +938,7 @@ public static void ExportGafaws(string outputFolder, string databaseName, IColle new XElement("PartsOfSpeech", from IPartOfSpeech pos in partsOfSpeech select ExportPartOfSpeechGafaws("PartOfSpeech", pos)))); - doc.Save(Path.Combine(outputFolder, databaseName + "GAFAWSFxtResult.xml")); + return doc; } /// diff --git a/Src/LexText/ParserCore/HCParser.cs b/Src/LexText/ParserCore/HCParser.cs index 7d46c09505..e64abd1b29 100644 --- a/Src/LexText/ParserCore/HCParser.cs +++ b/Src/LexText/ParserCore/HCParser.cs @@ -27,17 +27,16 @@ public class HCParser : FwDisposableBase, IParser private PatrParser m_patr; private readonly Loader m_loader; private M3ParserModelRetriever m_retriever; - private readonly string m_dataDir; private readonly string m_outputDirectory; // m_projectName here is only used to create temporary files for the parser to load. // We convert the name to use strictly ANSI characters so that the patr parsers (which is // a legacy C program) can read the file names. private readonly string m_projectName; + private readonly M3ToHCTransformer m_transformer; public HCParser(FdoCache cache, string dataDir) { m_cache = cache; - m_dataDir = dataDir; m_retriever = new M3ParserModelRetriever(m_cache); m_patr = new PatrParser @@ -53,24 +52,24 @@ public HCParser(FdoCache cache, string dataDir) m_outputDirectory = Path.GetTempPath(); m_projectName = ParserHelper.ConvertNameToUseAnsiCharacters(cache.ProjectId.Name); + m_transformer = new M3ToHCTransformer(m_projectName, dataDir); } #region IParser implementation public bool IsUpToDate() { - return m_retriever.Loaded; + return !m_retriever.Updated; } public void Update() { CheckDisposed(); - if (!m_retriever.RetrieveModel()) + XDocument model; + if (!m_retriever.RetrieveModel(out model)) return; - XmlDocument fxtResult = m_retriever.ModelDom; - XmlDocument gafawsFxtResult = m_retriever.TemplateDom; - LoadParser(ref fxtResult); + LoadParser(model); } public void Reset() @@ -166,7 +165,7 @@ protected override void DisposeManagedResources() } #region Load - private void LoadParser(ref XmlDocument model) + private void LoadParser(XDocument model) { string hcPath = HcInputPath; File.Delete(hcPath); // In case we don't produce one successfully, don't keep an old one. @@ -191,16 +190,15 @@ private void LoadParser(ref XmlDocument model) } } - var transformer = new M3ToHCTransformer(m_projectName, m_dataDir); - transformer.MakeHCFiles(ref model); + m_transformer.MakeHCFiles(model); m_patr.LoadGrammarFile(HcGrammarPath); LoadHCInfo(hcPath); - XmlNode delReappsNode = model.SelectSingleNode("/M3Dump/ParserParameters/HC/DelReapps"); - if (delReappsNode != null) - m_loader.CurrentMorpher.DelReapplications = Convert.ToInt32(delReappsNode.InnerText); + XElement delReappsElem = model.Elements("M3Dump").Elements("ParserParameters").Elements("HC").Elements("DelReapps").FirstOrDefault(); + if (delReappsElem != null) + m_loader.CurrentMorpher.DelReapplications = (int) delReappsElem; } private void LoadHCInfo(string hcPath) diff --git a/Src/LexText/ParserCore/M3ModelRetriever.cs b/Src/LexText/ParserCore/M3ModelRetriever.cs index f623fa02f4..4589a22c96 100644 --- a/Src/LexText/ParserCore/M3ModelRetriever.cs +++ b/Src/LexText/ParserCore/M3ModelRetriever.cs @@ -10,10 +10,7 @@ // using System; -using System.Diagnostics; -using System.IO; -using System.Xml; - +using System.Xml.Linq; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices; @@ -28,16 +25,9 @@ namespace SIL.FieldWorks.WordWorks.Parser /// Is public for testing purposes public class M3ParserModelRetriever : FwDisposableBase, IVwNotifyChange { - public bool Loaded { get; private set; } - private readonly FdoCache m_cache; - private readonly string m_modelPath; - private readonly string m_templatePath; - private readonly string m_outputDirectory; - private XmlDocument m_modelDom; - private XmlDocument m_templateDom; - private readonly object m_syncRoot = new object(); + private bool m_updated; /// ----------------------------------------------------------------------------------- /// @@ -50,10 +40,7 @@ public M3ParserModelRetriever(FdoCache cache) m_cache = cache; m_cache.DomainDataByFlid.AddNotification(this); - - m_outputDirectory = Path.GetTempPath(); - m_modelPath = Path.Combine(m_outputDirectory, m_cache.ProjectId.Name + "ParserFxtResult.xml"); - m_templatePath = Path.Combine(m_outputDirectory, m_cache.ProjectId.Name + "GAFAWSFxtResult.xml"); + m_updated = true; } protected override void DisposeManagedResources() @@ -61,16 +48,29 @@ protected override void DisposeManagedResources() m_cache.DomainDataByFlid.RemoveNotification(this); } + public bool Updated + { + get + { + lock (m_syncRoot) + return m_updated; + } + } + /// /// /// - public bool RetrieveModel() + public bool RetrieveModel(out XDocument model, out XDocument template) { lock (m_syncRoot) { - if (Loaded) + if (!m_updated) + { + model = null; + template = null; return false; - Loaded = true; + } + m_updated = false; } // According to the fxt template files, GAFAWS is NFC, all others are NFD. @@ -78,125 +78,105 @@ public bool RetrieveModel() { ILangProject lp = m_cache.LanguageProject; // 1. Export lexicon and/or grammar. - m_modelDom = null; - M3ModelExportServices.ExportGrammarAndLexicon(m_modelPath, lp); + model = M3ModelExportServices.ExportGrammarAndLexicon(lp); // 2. Export GAFAWS data. - m_templateDom = null; - M3ModelExportServices.ExportGafaws(m_outputDirectory, m_cache.ProjectId.Name, - lp.PartsOfSpeechOA.PossibilitiesOS); + template = M3ModelExportServices.ExportGafaws(lp.PartsOfSpeechOA.PossibilitiesOS); } return true; } - public void Reset() + public bool RetrieveModel(out XDocument model) { lock (m_syncRoot) - Loaded = false; - m_modelDom = null; - m_templateDom = null; - } - - /// - /// Get the model (FXT result) DOM - /// - /// Is public for testing only - public XmlDocument ModelDom - { - get { - Debug.Assert(m_modelPath != null); - Debug.Assert(File.Exists(m_modelPath)); - if (m_modelDom == null) + if (!m_updated) { - m_modelDom = new XmlDocument(); - m_modelDom.Load(m_modelPath); + model = null; + return false; } - return m_modelDom; + m_updated = false; } - } - internal XmlDocument TemplateDom - { - get + // According to the fxt template files, GAFAWS is NFC, all others are NFD. + using (new WorkerThreadReadHelper(m_cache.ServiceLocator.GetInstance())) { - if (m_templateDom == null) - { - Debug.Assert(m_templatePath != null); - Debug.Assert(File.Exists(m_templatePath)); - m_templateDom = new XmlDocument(); - m_templateDom.Load(m_templatePath); - } - return m_templateDom; - + ILangProject lp = m_cache.LanguageProject; + // 1. Export lexicon and/or grammar. + model = M3ModelExportServices.ExportGrammarAndLexicon(lp); } + return true; + } + + public void Reset() + { + lock (m_syncRoot) + m_updated = true; } #region Implementation of IVwNotifyChange void IVwNotifyChange.PropChanged(int hvo, int tag, int ivMin, int cvIns, int cvDel) { - lock (m_syncRoot) + int clsid = m_cache.ServiceLocator.GetObject(hvo).ClassID; + switch (clsid) { - int clsid = m_cache.ServiceLocator.GetObject(hvo).ClassID; - switch (clsid) - { - case LexDbTags.kClassId: - case LexEntryTags.kClassId: - case LexSenseTags.kClassId: - - case FsClosedValueTags.kClassId: - case FsComplexValueTags.kClassId: - case FsFeatStrucTags.kClassId: - case FsFeatStrucTypeTags.kClassId: - case FsClosedFeatureTags.kClassId: - case FsComplexFeatureTags.kClassId: - case FsFeatureSystemTags.kClassId: - case FsSymFeatValTags.kClassId: - - case MoMorphTypeTags.kClassId: - case MoAdhocProhibGrTags.kClassId: - case MoAlloAdhocProhibTags.kClassId: - case MoMorphAdhocProhibTags.kClassId: - case MoEndoCompoundTags.kClassId: - case MoExoCompoundTags.kClassId: - case MoInflAffixSlotTags.kClassId: - case MoInflAffixTemplateTags.kClassId: - case MoInflClassTags.kClassId: - case MoAffixAllomorphTags.kClassId: - case MoStemAllomorphTags.kClassId: - case MoAffixProcessTags.kClassId: - case MoCopyFromInputTags.kClassId: - case MoInsertPhonesTags.kClassId: - case MoInsertNCTags.kClassId: - case MoModifyFromInputTags.kClassId: - case MoDerivAffMsaTags.kClassId: - case MoInflAffMsaTags.kClassId: - case MoUnclassifiedAffixMsaTags.kClassId: - case MoStemMsaTags.kClassId: - case MoMorphDataTags.kClassId: - - case PhCodeTags.kClassId: - case PhIterationContextTags.kClassId: - case PhMetathesisRuleTags.kClassId: - case PhRegularRuleTags.kClassId: - case PhSegRuleRHSTags.kClassId: - case PhPhonemeSetTags.kClassId: - case PartOfSpeechTags.kClassId: - case PhFeatureConstraintTags.kClassId: - case PhNCFeaturesTags.kClassId: - case PhNCSegmentsTags.kClassId: - case PhPhonDataTags.kClassId: - case PhPhonemeTags.kClassId: - case PhSequenceContextTags.kClassId: - case PhSimpleContextBdryTags.kClassId: - case PhSimpleContextNCTags.kClassId: - case PhSimpleContextSegTags.kClassId: - case PhVariableTags.kClassId: - case PhEnvironmentTags.kClassId: - Loaded = false; - break; - } + case LexDbTags.kClassId: + case LexEntryTags.kClassId: + case LexSenseTags.kClassId: + + case FsClosedValueTags.kClassId: + case FsComplexValueTags.kClassId: + case FsFeatStrucTags.kClassId: + case FsFeatStrucTypeTags.kClassId: + case FsClosedFeatureTags.kClassId: + case FsComplexFeatureTags.kClassId: + case FsFeatureSystemTags.kClassId: + case FsSymFeatValTags.kClassId: + + case MoMorphTypeTags.kClassId: + case MoAdhocProhibGrTags.kClassId: + case MoAlloAdhocProhibTags.kClassId: + case MoMorphAdhocProhibTags.kClassId: + case MoEndoCompoundTags.kClassId: + case MoExoCompoundTags.kClassId: + case MoInflAffixSlotTags.kClassId: + case MoInflAffixTemplateTags.kClassId: + case MoInflClassTags.kClassId: + case MoAffixAllomorphTags.kClassId: + case MoStemAllomorphTags.kClassId: + case MoAffixProcessTags.kClassId: + case MoCopyFromInputTags.kClassId: + case MoInsertPhonesTags.kClassId: + case MoInsertNCTags.kClassId: + case MoModifyFromInputTags.kClassId: + case MoDerivAffMsaTags.kClassId: + case MoInflAffMsaTags.kClassId: + case MoUnclassifiedAffixMsaTags.kClassId: + case MoStemMsaTags.kClassId: + case MoMorphDataTags.kClassId: + + case PhCodeTags.kClassId: + case PhIterationContextTags.kClassId: + case PhMetathesisRuleTags.kClassId: + case PhRegularRuleTags.kClassId: + case PhSegRuleRHSTags.kClassId: + case PhPhonemeSetTags.kClassId: + case PartOfSpeechTags.kClassId: + case PhFeatureConstraintTags.kClassId: + case PhNCFeaturesTags.kClassId: + case PhNCSegmentsTags.kClassId: + case PhPhonDataTags.kClassId: + case PhPhonemeTags.kClassId: + case PhSequenceContextTags.kClassId: + case PhSimpleContextBdryTags.kClassId: + case PhSimpleContextNCTags.kClassId: + case PhSimpleContextSegTags.kClassId: + case PhVariableTags.kClassId: + case PhEnvironmentTags.kClassId: + lock (m_syncRoot) + m_updated = true; + break; } } diff --git a/Src/LexText/ParserCore/M3ToHCTransformer.cs b/Src/LexText/ParserCore/M3ToHCTransformer.cs index 1a5902da5e..8596b76d7e 100644 --- a/Src/LexText/ParserCore/M3ToHCTransformer.cs +++ b/Src/LexText/ParserCore/M3ToHCTransformer.cs @@ -6,7 +6,10 @@ // File: M3ParserTransformer.cs // Responsibility: John Hatton -using System.Xml; +using System.IO; +using System.Xml.Linq; +using System.Xml.XPath; +using System.Xml.Xsl; namespace SIL.FieldWorks.WordWorks.Parser { @@ -16,6 +19,8 @@ namespace SIL.FieldWorks.WordWorks.Parser /// internal class M3ToHCTransformer : M3ToParserTransformerBase { + private XslCompiledTransform m_inputTransform; + private readonly string m_database; /// ----------------------------------------------------------------------------------- /// @@ -23,22 +28,35 @@ internal class M3ToHCTransformer : M3ToParserTransformerBase /// /// ----------------------------------------------------------------------------------- public M3ToHCTransformer(string database, string dataDir) - : base(database, dataDir) + : base(dataDir) { + m_database = database; } - public void MakeHCFiles(ref XmlDocument model) + private XslCompiledTransform InputTransform { - TransformDomToFile("FxtM3ParserToHCInput.xsl", model, m_database + "HCInput.xml"); + get + { + if (m_inputTransform == null) + m_inputTransform = CreateTransform("FxtM3ParserToHCInput.xsl"); + return m_inputTransform; + } + } + + public void MakeHCFiles(XDocument model) + { + using (var writer = new StreamWriter(Path.Combine(Path.GetTempPath(), m_database + "HCInput.xml"))) + InputTransform.Transform(model.CreateNavigator(), null, writer); - TransformDomToFile("FxtM3ParserToToXAmpleGrammar.xsl", model, m_database + "gram.txt"); + using (var writer = new StreamWriter(Path.Combine(Path.GetTempPath(), m_database + "gram.txt"))) + GrammarTransform.Transform(model.CreateNavigator(), null, writer); // TODO: Putting this here is not necessarily efficient because it happens every time // the parser is run. It would be more efficient to run this only when the user // is trying a word. But we need the "model" to apply this transform and it is // available here, so we're doing this for now. - string sName = m_database + "XAmpleWordGrammarDebugger.xsl"; - TransformDomToFile("FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl", model, sName); + using (var writer = new StreamWriter(Path.Combine(Path.GetTempPath(), m_database + "XAmpleWordGrammarDebugger.xsl"))) + GrammarDebuggingTransform.Transform(model.CreateNavigator(), null, writer); } } } diff --git a/Src/LexText/ParserCore/M3ToParserTransformerBase.cs b/Src/LexText/ParserCore/M3ToParserTransformerBase.cs index 8a683c7b29..d0d89fd41a 100644 --- a/Src/LexText/ParserCore/M3ToParserTransformerBase.cs +++ b/Src/LexText/ParserCore/M3ToParserTransformerBase.cs @@ -1,34 +1,53 @@ using System.IO; -using System.Xml; -using SIL.Utils; +using System.Xml.Xsl; namespace SIL.FieldWorks.WordWorks.Parser { /// /// Base class for transforming an M3 model to files needed by a parser /// - abstract internal class M3ToParserTransformerBase + internal abstract class M3ToParserTransformerBase { - protected string m_outputDirectory; - protected string m_database; - protected readonly string m_dataDir; + private readonly string m_dataDir; + + private XslCompiledTransform m_grammarTransform; + private XslCompiledTransform m_grammarDebuggingTransform; /// ----------------------------------------------------------------------------------- /// /// Initializes a new instance of the class. /// /// ----------------------------------------------------------------------------------- - public M3ToParserTransformerBase(string database, string dataDir) + protected M3ToParserTransformerBase(string dataDir) { - m_database = database; m_dataDir = dataDir; - m_outputDirectory = Path.GetTempPath(); } - protected void TransformDomToFile(string transformName, XmlDocument inputDom, string outputName) + protected XslCompiledTransform GrammarTransform + { + get + { + if (m_grammarTransform == null) + m_grammarTransform = CreateTransform("FxtM3ParserToToXAmpleGrammar.xsl"); + return m_grammarTransform; + } + } + + protected XslCompiledTransform GrammarDebuggingTransform + { + get + { + if (m_grammarDebuggingTransform == null) + m_grammarDebuggingTransform = CreateTransform("FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl"); + return m_grammarDebuggingTransform; + } + } + + protected XslCompiledTransform CreateTransform(string fileName) { - XmlUtils.TransformDomToFile(Path.Combine(m_dataDir + "/Transforms/", transformName), - inputDom, Path.Combine(m_outputDirectory, outputName)); + var transform = new XslCompiledTransform(); + transform.Load(Path.Combine(m_dataDir, "Transforms", fileName)); + return transform; } } } diff --git a/Src/LexText/ParserCore/M3ToXAmpleTransformer.cs b/Src/LexText/ParserCore/M3ToXAmpleTransformer.cs index 3288b8b721..621d6b8370 100644 --- a/Src/LexText/ParserCore/M3ToXAmpleTransformer.cs +++ b/Src/LexText/ParserCore/M3ToXAmpleTransformer.cs @@ -7,10 +7,12 @@ // Responsibility: John Hatton using System; -using System.Diagnostics.CodeAnalysis; -using System.Text; -using System.Xml; +using System.Diagnostics; using System.IO; +using System.Xml.Linq; +using System.Xml.XPath; +using System.Xml.Xsl; +using System.Linq; using SIL.WordWorks.GAFAWS.PositionAnalysis; namespace SIL.FieldWorks.WordWorks.Parser @@ -21,98 +23,119 @@ namespace SIL.FieldWorks.WordWorks.Parser /// internal class M3ToXAmpleTransformer : M3ToParserTransformerBase { + private XslCompiledTransform m_gafawsTransform; + private XslCompiledTransform m_adctlTransform; + private XslCompiledTransform m_lexTransform; + private readonly string m_database; + /// ----------------------------------------------------------------------------------- /// /// Initializes a new instance of the class. /// /// ----------------------------------------------------------------------------------- - public M3ToXAmpleTransformer(string database, string dataDir) - : base(database, dataDir) + public M3ToXAmpleTransformer(string dataDir, string database) + : base(dataDir) + { + m_database = database; + } + + private XslCompiledTransform AdctlTransform { + get + { + if (m_adctlTransform == null) + m_adctlTransform = CreateTransform("FxtM3ParserToXAmpleADCtl.xsl"); + return m_adctlTransform; + } + } + + private XslCompiledTransform GafawsTransform + { + get + { + if (m_gafawsTransform == null) + m_gafawsTransform = CreateTransform("FxtM3ParserToGAFAWS.xsl"); + return m_gafawsTransform; + } } - [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", - Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] - internal void PrepareTemplatesForXAmpleFiles(ref XmlDocument domModel, XmlDocument domTemplate) + private XslCompiledTransform LexTransform { + get + { + if (m_lexTransform == null) + m_lexTransform = CreateTransform("FxtM3ParserToXAmpleLex.xsl"); + return m_lexTransform; + } + } + + public void PrepareTemplatesForXAmpleFiles(XDocument domModel, XDocument domTemplate) + { + Debug.Assert(domTemplate.Root != null); // get top level POS that has at least one template with slots - XmlNodeList templateNodeList = domTemplate.SelectNodes("//PartsOfSpeech/PartOfSpeech[descendant-or-self::MoInflAffixTemplate[PrefixSlots or SuffixSlots]]"); - foreach (XmlNode templateNode in templateNodeList) + foreach (XElement templateElem in domTemplate.Root.Elements("PartsOfSpeech").Elements("PartOfSpeech") + .Where(pe => pe.Elements("AffixTemplates").Elements("MoInflAffixTemplate").Any(te => te.Element("PrefixSlots") != null || te.Element("SuffixSlots") != null))) { // transform the POS that has templates to GAFAWS format - string sGafawsFile = m_database + "gafawsData.xml"; - TransformPosInfoToGafawsInputFormat(templateNode, sGafawsFile); - string sResultFile = ApplyGafawsAlgorithm(sGafawsFile); + string gafawsFile = m_database + "gafawsData.xml"; + TransformPosInfoToGafawsInputFormat(templateElem, gafawsFile); + string resultFile = ApplyGafawsAlgorithm(gafawsFile); //based on results of GAFAWS, modify the model dom by inserting orderclass in slots - InsertOrderclassInfo(ref domModel, sResultFile); + InsertOrderclassInfo(domModel, resultFile); } } - [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", - Justification = "In .NET 4.5 XmlNodeList implements IDisposable, but not in 4.0.")] - protected void InsertOrderclassInfo(ref XmlDocument domModel, string sResultFile) + private void InsertOrderclassInfo(XDocument domModel, string resultFile) { // Check for a valid filename (see LT-6472). - if (String.IsNullOrEmpty(sResultFile)) + if (String.IsNullOrEmpty(resultFile)) return; - var dom = new XmlDocument(); - dom.Load(sResultFile); - XmlNodeList gafawsNodeList = dom.SelectNodes("//Morpheme"); - foreach (XmlNode gafawsNode in gafawsNodeList) + XDocument dom = XDocument.Load(resultFile); + foreach (XElement gafawsElem in dom.Elements("GAFAWSData").Elements("Morphemes").Elements("Morpheme")) { - string sMorphemeId = gafawsNode.Attributes.GetNamedItem("MID").InnerText; - if (sMorphemeId == "R") + var morphemeID = (string) gafawsElem.Attribute("MID"); + if (morphemeID == "R") continue; // skip the stem/root node - string sXpathToMorphemeId = "//MoInflAffixSlot[@Id='" + sMorphemeId + "']"; - XmlNode modelNode = domModel.SelectSingleNode(sXpathToMorphemeId); - StringBuilder sb; - BuildOrderclassElementsString(out sb, gafawsNode); - XmlElement orderclassNode = domModel.CreateElement("orderclass"); - orderclassNode.InnerXml = sb.ToString(); - modelNode.AppendChild(orderclassNode); + XElement modelElem = domModel.Descendants("MoInflAffixSlot").First(e => ((string) e.Attribute("Id")) == morphemeID); + modelElem.Add(new XElement("orderclass", + new XElement("minValue", (string) gafawsElem.Attribute("StartCLIDREF")), + new XElement("maxValue", (string) gafawsElem.Attribute("EndCLIDREF")))); } } - private static void BuildOrderclassElementsString(out StringBuilder sb, XmlNode gafawsNode) - { - sb = new StringBuilder(); - sb.Append(""); - sb.Append(gafawsNode.Attributes.GetNamedItem("StartCLIDREF").InnerText); - sb.Append(" "); - sb.Append(gafawsNode.Attributes.GetNamedItem("EndCLIDREF").InnerText); - sb.Append(""); - } - - protected string ApplyGafawsAlgorithm(string sGafawsFile) + private string ApplyGafawsAlgorithm(string gafawsFile) { var pa = new PositionAnalyzer(); - string sGafawsInputFile = Path.Combine(m_outputDirectory, sGafawsFile); - return pa.Process(sGafawsInputFile); + string gafawsInputFile = Path.Combine(Path.GetTempPath(), gafawsFile); + return pa.Process(gafawsInputFile); } /// /// transform the POS that has templates to GAFAWS format /// - protected void TransformPosInfoToGafawsInputFormat(XmlNode templateNode, string sGafawsFile) + private void TransformPosInfoToGafawsInputFormat(XElement templateElem, string gafawsFile) { - var dom = new XmlDocument(); - dom.CreateElement("GAFAWSData"); // create root element - dom.InnerXml = templateNode.OuterXml; // copy in POS elements - TransformDomToFile("FxtM3ParserToGAFAWS.xsl", dom, sGafawsFile); + var dom = new XDocument(new XElement(templateElem)); + using (var writer = new StreamWriter(Path.Combine(Path.GetTempPath(), gafawsFile))) + GafawsTransform.Transform(dom.CreateNavigator(), null, writer); } - internal void MakeAmpleFiles(XmlDocument model) + public void MakeAmpleFiles(XDocument model) { - DateTime startTime = DateTime.Now; - TransformDomToFile("FxtM3ParserToXAmpleADCtl.xsl", model, m_database + "adctl.txt"); - TransformDomToFile("FxtM3ParserToToXAmpleGrammar.xsl", model, m_database + "gram.txt"); + using (var writer = new StreamWriter(Path.Combine(Path.GetTempPath(), m_database + "adctl.txt"))) + AdctlTransform.Transform(model.CreateNavigator(), null, writer); + + using (var writer = new StreamWriter(Path.Combine(Path.GetTempPath(), m_database + "gram.txt"))) + GrammarTransform.Transform(model.CreateNavigator(), null, writer); + // TODO: Putting this here is not necessarily efficient because it happens every time // the parser is run. It would be more efficient to run this only when the user // is trying a word. But we need the "model" to apply this transform an it is // available here, so we're doing this for now. - string sName = m_database + "XAmpleWordGrammarDebugger.xsl"; - TransformDomToFile("FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl", model, sName); + using (var writer = new StreamWriter(Path.Combine(Path.GetTempPath(), m_database + "XAmpleWordGrammarDebugger.xsl"))) + GrammarDebuggingTransform.Transform(model.CreateNavigator(), null, writer); - TransformDomToFile("FxtM3ParserToXAmpleLex.xsl", model, m_database + "lex.txt"); + using (var writer = new StreamWriter(Path.Combine(Path.GetTempPath(), m_database + "lex.txt"))) + LexTransform.Transform(model.CreateNavigator(), null, writer); } } } diff --git a/Src/LexText/ParserCore/ParserCore.csproj b/Src/LexText/ParserCore/ParserCore.csproj index 011551a1a7..92d7c94cb9 100644 --- a/Src/LexText/ParserCore/ParserCore.csproj +++ b/Src/LexText/ParserCore/ParserCore.csproj @@ -81,7 +81,7 @@ true - bin\x86\Debug\ + ..\..\..\Output\Debug\ DEBUG;TRACE 285212672 4096 @@ -100,7 +100,7 @@ true - bin\x86\Release\ + ..\..\..\Output\Release\ TRACE 285212672 true @@ -153,9 +153,6 @@ False ..\..\..\Output\Debug\PhonEnvValidator.dll - - False - System diff --git a/Src/LexText/ParserCore/ParserCoreTests/ParserCoreTests.csproj b/Src/LexText/ParserCore/ParserCoreTests/ParserCoreTests.csproj index 723d0f77ed..9554d4d3b8 100644 --- a/Src/LexText/ParserCore/ParserCoreTests/ParserCoreTests.csproj +++ b/Src/LexText/ParserCore/ParserCoreTests/ParserCoreTests.csproj @@ -143,7 +143,6 @@ - AssemblyInfoForTests.cs diff --git a/Src/LexText/ParserCore/ParserCoreTests/UpdateParserDataTests.cs b/Src/LexText/ParserCore/ParserCoreTests/UpdateParserDataTests.cs index 05e2c70b55..cff845b504 100644 --- a/Src/LexText/ParserCore/ParserCoreTests/UpdateParserDataTests.cs +++ b/Src/LexText/ParserCore/ParserCoreTests/UpdateParserDataTests.cs @@ -10,6 +10,7 @@ // Implements the UpdateParserDataTests unit tests. // +using System.Xml.Linq; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.FDOTests; @@ -46,7 +47,8 @@ public override void FixtureTeardown() [Test] public void EmptyLexicon() { - Assert.IsTrue(m_retriever.RetrieveModel()); + XDocument model; + Assert.IsTrue(m_retriever.RetrieveModel(out model)); } } diff --git a/Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/XAmpleManagedWrapperTests.csproj b/Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/XAmpleManagedWrapperTests.csproj index 56a9c78866..2f6f50e913 100644 --- a/Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/XAmpleManagedWrapperTests.csproj +++ b/Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleManagedWrapperTests/XAmpleManagedWrapperTests.csproj @@ -73,7 +73,6 @@ - \ No newline at end of file diff --git a/Src/LexText/ParserCore/XAmpleParser.cs b/Src/LexText/ParserCore/XAmpleParser.cs index 830651aae3..e9ff45e9f0 100644 --- a/Src/LexText/ParserCore/XAmpleParser.cs +++ b/Src/LexText/ParserCore/XAmpleParser.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Globalization; using System.IO; +using System.Linq; using System.Text; using System.Xml; using System.Xml.Linq; @@ -21,6 +22,8 @@ public class XAmpleParser : FwDisposableBase, IParser private readonly string m_dataDir; private readonly FdoCache m_cache; private M3ParserModelRetriever m_retriever; + private readonly M3ToXAmpleTransformer m_transformer; + private readonly string m_database; public XAmpleParser(FdoCache cache, string dataDir) { @@ -29,43 +32,40 @@ public XAmpleParser(FdoCache cache, string dataDir) m_xample.Init(); m_dataDir = dataDir; m_retriever = new M3ParserModelRetriever(m_cache); + m_database = ParserHelper.ConvertNameToUseAnsiCharacters(m_cache.ProjectId.Name); + m_transformer = new M3ToXAmpleTransformer(dataDir, m_database); } public bool IsUpToDate() { - return m_retriever.Loaded; + return !m_retriever.Updated; } public void Update() { CheckDisposed(); - if (!m_retriever.RetrieveModel()) + XDocument model, template; + if (!m_retriever.RetrieveModel(out model, out template)) return; - XmlDocument fxtResult = m_retriever.ModelDom; - XmlDocument gafawsFxtResult = m_retriever.TemplateDom; - string projectName = ParserHelper.ConvertNameToUseAnsiCharacters(m_cache.ProjectId.Name); - - var transformer = new M3ToXAmpleTransformer(projectName, m_dataDir); // PrepareTemplatesForXAmpleFiles adds orderclass elements to MoInflAffixSlot elements - transformer.PrepareTemplatesForXAmpleFiles(ref fxtResult, gafawsFxtResult); + m_transformer.PrepareTemplatesForXAmpleFiles(model, template); - transformer.MakeAmpleFiles(fxtResult); + m_transformer.MakeAmpleFiles(model); int maxAnalCount = 20; - XmlNode maxAnalCountNode = fxtResult.SelectSingleNode("/M3Dump/ParserParameters/XAmple/MaxAnalysesToReturn"); - if (maxAnalCountNode != null) + XElement maxAnalCountElem = model.Elements("M3Dump").Elements("ParserParameters").Elements("XAmple").Elements("MaxAnalysesToReturn").FirstOrDefault(); + if (maxAnalCountElem != null) { - maxAnalCount = Convert.ToInt16(maxAnalCountNode.FirstChild.Value); + maxAnalCount = (int) maxAnalCountElem; if (maxAnalCount < 1) maxAnalCount = -1; } m_xample.SetParameter("MaxAnalysesToReturn", maxAnalCount.ToString(CultureInfo.InvariantCulture)); - string tempPath = Path.GetTempPath(); - m_xample.LoadFiles(m_dataDir + @"/Configuration/Grammar", tempPath, projectName); + m_xample.LoadFiles(Path.Combine(m_dataDir, "Configuration", "Grammar"), Path.GetTempPath(), m_database); } public void Reset() From 87e96189767dc0aeef7a78f0bdc3efdef0ae1757 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Tue, 18 Feb 2014 09:34:55 +0700 Subject: [PATCH 084/143] Precompile XSL files and merge into ParserUI assembly Change-Id: Ic2e487df6c4f44dcd1b446d7e4ae7f4663b3860d --- .../LexText/ParserUI}/FormatCommon.xsl | 0 .../LexText/ParserUI}/FormatHCTrace.xsl | 0 .../LexText/ParserUI}/FormatXAmpleParse.xsl | 0 .../LexText/ParserUI}/FormatXAmpleTrace.xsl | 0 .../FormatXAmpleWordGrammarDebuggerResult.xsl | 0 Src/LexText/ParserUI/HCTrace.cs | 2 +- Src/LexText/ParserUI/ParserTrace.cs | 2 +- .../ParserUI/ParserTraceUITransform.cs | 9 +++--- Src/LexText/ParserUI/ParserUI.csproj | 32 +++++++++++++++++++ Src/LexText/ParserUI/WordGrammarDebugger.cs | 2 +- Src/LexText/ParserUI/XAmpleTrace.cs | 2 +- Src/LexText/ParserUI/gendarme-ParserUI.ignore | 9 ++++++ 12 files changed, 50 insertions(+), 8 deletions(-) rename {DistFiles/Language Explorer/Configuration/Words/Analyses/TraceParse => Src/LexText/ParserUI}/FormatCommon.xsl (100%) rename {DistFiles/Language Explorer/Configuration/Words/Analyses/TraceParse => Src/LexText/ParserUI}/FormatHCTrace.xsl (100%) rename {DistFiles/Language Explorer/Configuration/Words/Analyses/TraceParse => Src/LexText/ParserUI}/FormatXAmpleParse.xsl (100%) rename {DistFiles/Language Explorer/Configuration/Words/Analyses/TraceParse => Src/LexText/ParserUI}/FormatXAmpleTrace.xsl (100%) rename {DistFiles/Language Explorer/Configuration/Words/Analyses/TraceParse => Src/LexText/ParserUI}/FormatXAmpleWordGrammarDebuggerResult.xsl (100%) diff --git a/DistFiles/Language Explorer/Configuration/Words/Analyses/TraceParse/FormatCommon.xsl b/Src/LexText/ParserUI/FormatCommon.xsl similarity index 100% rename from DistFiles/Language Explorer/Configuration/Words/Analyses/TraceParse/FormatCommon.xsl rename to Src/LexText/ParserUI/FormatCommon.xsl diff --git a/DistFiles/Language Explorer/Configuration/Words/Analyses/TraceParse/FormatHCTrace.xsl b/Src/LexText/ParserUI/FormatHCTrace.xsl similarity index 100% rename from DistFiles/Language Explorer/Configuration/Words/Analyses/TraceParse/FormatHCTrace.xsl rename to Src/LexText/ParserUI/FormatHCTrace.xsl diff --git a/DistFiles/Language Explorer/Configuration/Words/Analyses/TraceParse/FormatXAmpleParse.xsl b/Src/LexText/ParserUI/FormatXAmpleParse.xsl similarity index 100% rename from DistFiles/Language Explorer/Configuration/Words/Analyses/TraceParse/FormatXAmpleParse.xsl rename to Src/LexText/ParserUI/FormatXAmpleParse.xsl diff --git a/DistFiles/Language Explorer/Configuration/Words/Analyses/TraceParse/FormatXAmpleTrace.xsl b/Src/LexText/ParserUI/FormatXAmpleTrace.xsl similarity index 100% rename from DistFiles/Language Explorer/Configuration/Words/Analyses/TraceParse/FormatXAmpleTrace.xsl rename to Src/LexText/ParserUI/FormatXAmpleTrace.xsl diff --git a/DistFiles/Language Explorer/Configuration/Words/Analyses/TraceParse/FormatXAmpleWordGrammarDebuggerResult.xsl b/Src/LexText/ParserUI/FormatXAmpleWordGrammarDebuggerResult.xsl similarity index 100% rename from DistFiles/Language Explorer/Configuration/Words/Analyses/TraceParse/FormatXAmpleWordGrammarDebuggerResult.xsl rename to Src/LexText/ParserUI/FormatXAmpleWordGrammarDebuggerResult.xsl diff --git a/Src/LexText/ParserUI/HCTrace.cs b/Src/LexText/ParserUI/HCTrace.cs index 7edc181ed2..4ba70cb2f2 100644 --- a/Src/LexText/ParserUI/HCTrace.cs +++ b/Src/LexText/ParserUI/HCTrace.cs @@ -17,7 +17,7 @@ private static ParserTraceUITransform TraceTransform get { if (s_traceTransform == null) - s_traceTransform = new ParserTraceUITransform("FormatHCTrace.xsl"); + s_traceTransform = new ParserTraceUITransform("FormatHCTrace"); return s_traceTransform; } } diff --git a/Src/LexText/ParserUI/ParserTrace.cs b/Src/LexText/ParserUI/ParserTrace.cs index c2885338a7..bc50668e35 100644 --- a/Src/LexText/ParserUI/ParserTrace.cs +++ b/Src/LexText/ParserUI/ParserTrace.cs @@ -13,7 +13,7 @@ protected static ParserTraceUITransform ParseTransform get { if (s_traceTransform == null) - s_traceTransform = new ParserTraceUITransform("FormatXAmpleParse.xsl"); + s_traceTransform = new ParserTraceUITransform("FormatXAmpleParse"); return s_traceTransform; } } diff --git a/Src/LexText/ParserUI/ParserTraceUITransform.cs b/Src/LexText/ParserUI/ParserTraceUITransform.cs index c1701eea3c..fa9b52cfa1 100644 --- a/Src/LexText/ParserUI/ParserTraceUITransform.cs +++ b/Src/LexText/ParserUI/ParserTraceUITransform.cs @@ -1,6 +1,6 @@ -using System.IO; +using System; +using System.IO; using System.Text; -using System.Xml; using System.Xml.Linq; using System.Xml.XPath; using System.Xml.Xsl; @@ -17,10 +17,11 @@ public class ParserTraceUITransform { private readonly XslCompiledTransform m_transform; - public ParserTraceUITransform(string xslFileName) + public ParserTraceUITransform(string fullTypeName) { + // Assumes the XSL has been precompiled. fullTypeName is the fully qualified name of the precompiled class m_transform = new XslCompiledTransform(); - m_transform.Load(Path.Combine(TransformPath, xslFileName), new XsltSettings(true, false), new XmlUrlResolver()); + m_transform.Load(Type.GetType(fullTypeName)); } public string Transform(Mediator mediator, XDocument doc, string baseName) diff --git a/Src/LexText/ParserUI/ParserUI.csproj b/Src/LexText/ParserUI/ParserUI.csproj index b5e6cff137..abc4ee3b74 100644 --- a/Src/LexText/ParserUI/ParserUI.csproj +++ b/Src/LexText/ParserUI/ParserUI.csproj @@ -304,4 +304,36 @@ + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin + $(OutputPath)\ParserUInew.dll + + + + + + + + + + + + \ No newline at end of file diff --git a/Src/LexText/ParserUI/WordGrammarDebugger.cs b/Src/LexText/ParserUI/WordGrammarDebugger.cs index a6dd52fb08..798f1e0f44 100644 --- a/Src/LexText/ParserUI/WordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/WordGrammarDebugger.cs @@ -24,7 +24,7 @@ private static ParserTraceUITransform PageTransform get { if (s_pageTransform == null) - s_pageTransform = new ParserTraceUITransform("FormatXAmpleWordGrammarDebuggerResult.xsl"); + s_pageTransform = new ParserTraceUITransform("FormatXAmpleWordGrammarDebuggerResult"); return s_pageTransform; } } diff --git a/Src/LexText/ParserUI/XAmpleTrace.cs b/Src/LexText/ParserUI/XAmpleTrace.cs index 16e2e79b27..fbad4bd907 100644 --- a/Src/LexText/ParserUI/XAmpleTrace.cs +++ b/Src/LexText/ParserUI/XAmpleTrace.cs @@ -32,7 +32,7 @@ private static ParserTraceUITransform TraceTransform get { if (s_traceTransform == null) - s_traceTransform = new ParserTraceUITransform("FormatXAmpleTrace.xsl"); + s_traceTransform = new ParserTraceUITransform("FormatXAmpleTrace"); return s_traceTransform; } } diff --git a/Src/LexText/ParserUI/gendarme-ParserUI.ignore b/Src/LexText/ParserUI/gendarme-ParserUI.ignore index 4bd1fb685b..213be44e65 100644 --- a/Src/LexText/ParserUI/gendarme-ParserUI.ignore +++ b/Src/LexText/ParserUI/gendarme-ParserUI.ignore @@ -22,3 +22,12 @@ R: Gendarme.Rules.Design.TypesWithDisposableFieldsShouldBeDisposableRule T: SIL.FieldWorks.LexText.Controls.ParserTraceBase T: SIL.FieldWorks.LexText.Controls.WebPageInteractor T: SIL.FieldWorks.LexText.Controls.WordImporter + +#----------------------------------------------------------------------------------------------- +R: Gendarme.Rules.Portability.NewLineLiteralRule + +#generated code +T: FormatHCTrace +T: FormatXAmpleParse +T: FormatXAmpleTrace +T: FormatXAmpleWordGrammarDebuggerResult \ No newline at end of file From 9c62644ab4491d089bedc79c8e27beb1caa80fa2 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Wed, 19 Feb 2014 09:52:53 +0700 Subject: [PATCH 085/143] Precompile XSLs for ParserCore and ParserUI Change-Id: I87b791ed4052594f4f9a26dbef0ae2638202c507 --- Build/Windows.targets | 10 ++- .../Grammar/Edit/toolConfiguration.xml | 4 +- Src/LexText/ParserCore/M3ToHCTransformer.cs | 2 +- .../ParserCore/M3ToParserTransformerBase.cs | 12 ++- .../ParserCore/M3ToXAmpleTransformer.cs | 6 +- Src/LexText/ParserCore/ParserCore.csproj | 4 + .../ParserUI/ParserTraceUITransform.cs | 10 +-- Src/LexText/ParserUI/ParserUI.csproj | 36 +------- .../Application}/BoundaryMarkerGuids.xsl | 0 ...CalculateStemNamesUsedInLexicalEntries.xsl | 0 .../Application}/FxtM3MorphologySketch.xsl | 0 .../Application}/FxtM3ParserCommon.xsl | 0 .../Application}/FxtM3ParserToGAFAWS.xsl | 0 .../Application}/FxtM3ParserToHCInput.xsl | 2 +- .../FxtM3ParserToToXAmpleGrammar.xsl | 0 .../Application}/FxtM3ParserToXAmpleADCtl.xsl | 0 .../Application}/FxtM3ParserToXAmpleLex.xsl | 0 ...ParserToXAmpleWordGrammarDebuggingXSLT.xsl | 0 .../Application}/MorphTypeGuids.xsl | 0 .../UnifyTwoFeatureStructures.xsl | 0 .../Application}/XAmpleTemplateVariables.xsl | 0 .../Presentation}/FormatCommon.xsl | 0 .../Presentation}/FormatHCTrace.xsl | 0 .../Presentation}/FormatXAmpleParse.xsl | 0 .../Presentation}/FormatXAmpleTrace.xsl | 0 .../FormatXAmpleWordGrammarDebuggerResult.xsl | 0 .../Transforms/Presentation}/XLingPap1.xsl | 0 .../Presentation}/XLingPaperForXXE.xsl | 0 Src/Utilities/XMLUtils/XmlUtils.cs | 16 ++++ Src/xWorks/GeneratedHtmlViewer.cs | 83 ++++++++++++------- 30 files changed, 100 insertions(+), 85 deletions(-) rename {DistFiles/Language Explorer/Transforms => Src/Transforms/Application}/BoundaryMarkerGuids.xsl (100%) rename {DistFiles/Language Explorer/Transforms => Src/Transforms/Application}/CalculateStemNamesUsedInLexicalEntries.xsl (100%) rename {DistFiles/Language Explorer/Transforms => Src/Transforms/Application}/FxtM3MorphologySketch.xsl (100%) rename {DistFiles/Language Explorer/Transforms => Src/Transforms/Application}/FxtM3ParserCommon.xsl (100%) rename {DistFiles/Language Explorer/Transforms => Src/Transforms/Application}/FxtM3ParserToGAFAWS.xsl (100%) rename {DistFiles/Language Explorer/Transforms => Src/Transforms/Application}/FxtM3ParserToHCInput.xsl (99%) rename {DistFiles/Language Explorer/Transforms => Src/Transforms/Application}/FxtM3ParserToToXAmpleGrammar.xsl (100%) rename {DistFiles/Language Explorer/Transforms => Src/Transforms/Application}/FxtM3ParserToXAmpleADCtl.xsl (100%) rename {DistFiles/Language Explorer/Transforms => Src/Transforms/Application}/FxtM3ParserToXAmpleLex.xsl (100%) rename {DistFiles/Language Explorer/Transforms => Src/Transforms/Application}/FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl (100%) rename {DistFiles/Language Explorer/Transforms => Src/Transforms/Application}/MorphTypeGuids.xsl (100%) rename {DistFiles/Language Explorer/Transforms => Src/Transforms/Application}/UnifyTwoFeatureStructures.xsl (100%) rename {DistFiles/Language Explorer/Transforms => Src/Transforms/Application}/XAmpleTemplateVariables.xsl (100%) rename Src/{LexText/ParserUI => Transforms/Presentation}/FormatCommon.xsl (100%) rename Src/{LexText/ParserUI => Transforms/Presentation}/FormatHCTrace.xsl (100%) rename Src/{LexText/ParserUI => Transforms/Presentation}/FormatXAmpleParse.xsl (100%) rename Src/{LexText/ParserUI => Transforms/Presentation}/FormatXAmpleTrace.xsl (100%) rename Src/{LexText/ParserUI => Transforms/Presentation}/FormatXAmpleWordGrammarDebuggerResult.xsl (100%) rename {DistFiles/Language Explorer/Transforms => Src/Transforms/Presentation}/XLingPap1.xsl (100%) rename {DistFiles/Language Explorer/Transforms => Src/Transforms/Presentation}/XLingPaperForXXE.xsl (100%) diff --git a/Build/Windows.targets b/Build/Windows.targets index 9950cebe76..44de165760 100644 --- a/Build/Windows.targets +++ b/Build/Windows.targets @@ -6,7 +6,7 @@ + DependsOnTargets="Initialize;EncConvertersDlls;CopyOtherDlls;BuildXslAssemblies"> @@ -105,4 +105,12 @@ + + ..\Src\Transforms\Application + ..\Src\Transforms\Presentation + + + + + diff --git a/DistFiles/Language Explorer/Configuration/Grammar/Edit/toolConfiguration.xml b/DistFiles/Language Explorer/Configuration/Grammar/Edit/toolConfiguration.xml index 826d54ddeb..3e80dac5a3 100644 --- a/DistFiles/Language Explorer/Configuration/Grammar/Edit/toolConfiguration.xml +++ b/DistFiles/Language Explorer/Configuration/Grammar/Edit/toolConfiguration.xml @@ -401,7 +401,7 @@ - + @@ -419,7 +419,7 @@ - + diff --git a/Src/LexText/ParserCore/M3ToHCTransformer.cs b/Src/LexText/ParserCore/M3ToHCTransformer.cs index 8596b76d7e..b660259b47 100644 --- a/Src/LexText/ParserCore/M3ToHCTransformer.cs +++ b/Src/LexText/ParserCore/M3ToHCTransformer.cs @@ -38,7 +38,7 @@ private XslCompiledTransform InputTransform get { if (m_inputTransform == null) - m_inputTransform = CreateTransform("FxtM3ParserToHCInput.xsl"); + m_inputTransform = CreateTransform("FxtM3ParserToHCInput"); return m_inputTransform; } } diff --git a/Src/LexText/ParserCore/M3ToParserTransformerBase.cs b/Src/LexText/ParserCore/M3ToParserTransformerBase.cs index d0d89fd41a..e269a96607 100644 --- a/Src/LexText/ParserCore/M3ToParserTransformerBase.cs +++ b/Src/LexText/ParserCore/M3ToParserTransformerBase.cs @@ -1,5 +1,5 @@ -using System.IO; using System.Xml.Xsl; +using SIL.Utils; namespace SIL.FieldWorks.WordWorks.Parser { @@ -28,7 +28,7 @@ protected XslCompiledTransform GrammarTransform get { if (m_grammarTransform == null) - m_grammarTransform = CreateTransform("FxtM3ParserToToXAmpleGrammar.xsl"); + m_grammarTransform = CreateTransform("FxtM3ParserToToXAmpleGrammar"); return m_grammarTransform; } } @@ -38,16 +38,14 @@ protected XslCompiledTransform GrammarDebuggingTransform get { if (m_grammarDebuggingTransform == null) - m_grammarDebuggingTransform = CreateTransform("FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl"); + m_grammarDebuggingTransform = CreateTransform("FxtM3ParserToXAmpleWordGrammarDebuggingXSLT"); return m_grammarDebuggingTransform; } } - protected XslCompiledTransform CreateTransform(string fileName) + protected XslCompiledTransform CreateTransform(string xslName) { - var transform = new XslCompiledTransform(); - transform.Load(Path.Combine(m_dataDir, "Transforms", fileName)); - return transform; + return XmlUtils.CreateTransform(xslName, "ApplicationTransforms"); } } } diff --git a/Src/LexText/ParserCore/M3ToXAmpleTransformer.cs b/Src/LexText/ParserCore/M3ToXAmpleTransformer.cs index 621d6b8370..4f45a63c5b 100644 --- a/Src/LexText/ParserCore/M3ToXAmpleTransformer.cs +++ b/Src/LexText/ParserCore/M3ToXAmpleTransformer.cs @@ -44,7 +44,7 @@ private XslCompiledTransform AdctlTransform get { if (m_adctlTransform == null) - m_adctlTransform = CreateTransform("FxtM3ParserToXAmpleADCtl.xsl"); + m_adctlTransform = CreateTransform("FxtM3ParserToXAmpleADCtl"); return m_adctlTransform; } } @@ -54,7 +54,7 @@ private XslCompiledTransform GafawsTransform get { if (m_gafawsTransform == null) - m_gafawsTransform = CreateTransform("FxtM3ParserToGAFAWS.xsl"); + m_gafawsTransform = CreateTransform("FxtM3ParserToGAFAWS"); return m_gafawsTransform; } } @@ -64,7 +64,7 @@ private XslCompiledTransform LexTransform get { if (m_lexTransform == null) - m_lexTransform = CreateTransform("FxtM3ParserToXAmpleLex.xsl"); + m_lexTransform = CreateTransform("FxtM3ParserToXAmpleLex"); return m_lexTransform; } } diff --git a/Src/LexText/ParserCore/ParserCore.csproj b/Src/LexText/ParserCore/ParserCore.csproj index 92d7c94cb9..1998c836d5 100644 --- a/Src/LexText/ParserCore/ParserCore.csproj +++ b/Src/LexText/ParserCore/ParserCore.csproj @@ -120,6 +120,10 @@ false + + False + ..\..\..\Output\Debug\ApplicationTransforms.dll + False ..\..\..\Output\Debug\BasicUtils.dll diff --git a/Src/LexText/ParserUI/ParserTraceUITransform.cs b/Src/LexText/ParserUI/ParserTraceUITransform.cs index fa9b52cfa1..9e9806fbc0 100644 --- a/Src/LexText/ParserUI/ParserTraceUITransform.cs +++ b/Src/LexText/ParserUI/ParserTraceUITransform.cs @@ -1,5 +1,4 @@ -using System; -using System.IO; +using System.IO; using System.Text; using System.Xml.Linq; using System.Xml.XPath; @@ -9,6 +8,7 @@ using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Common.Widgets; using SIL.FieldWorks.FDO; +using SIL.Utils; using XCore; namespace SIL.FieldWorks.LexText.Controls @@ -17,11 +17,9 @@ public class ParserTraceUITransform { private readonly XslCompiledTransform m_transform; - public ParserTraceUITransform(string fullTypeName) + public ParserTraceUITransform(string xslName) { - // Assumes the XSL has been precompiled. fullTypeName is the fully qualified name of the precompiled class - m_transform = new XslCompiledTransform(); - m_transform.Load(Type.GetType(fullTypeName)); + m_transform = XmlUtils.CreateTransform(xslName, "PresentationTransforms"); } public string Transform(Mediator mediator, XDocument doc, string baseName) diff --git a/Src/LexText/ParserUI/ParserUI.csproj b/Src/LexText/ParserUI/ParserUI.csproj index abc4ee3b74..d6db6a4d1f 100644 --- a/Src/LexText/ParserUI/ParserUI.csproj +++ b/Src/LexText/ParserUI/ParserUI.csproj @@ -149,6 +149,10 @@ ParserCore ..\..\..\Output\Debug\ParserCore.dll + + False + ..\..\..\Output\Debug\PresentationTransforms.dll + ..\..\..\Output\Debug\Reporting.dll False @@ -304,36 +308,4 @@ - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - - C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin - $(OutputPath)\ParserUInew.dll - - - - - - - - - - - - \ No newline at end of file diff --git a/DistFiles/Language Explorer/Transforms/BoundaryMarkerGuids.xsl b/Src/Transforms/Application/BoundaryMarkerGuids.xsl similarity index 100% rename from DistFiles/Language Explorer/Transforms/BoundaryMarkerGuids.xsl rename to Src/Transforms/Application/BoundaryMarkerGuids.xsl diff --git a/DistFiles/Language Explorer/Transforms/CalculateStemNamesUsedInLexicalEntries.xsl b/Src/Transforms/Application/CalculateStemNamesUsedInLexicalEntries.xsl similarity index 100% rename from DistFiles/Language Explorer/Transforms/CalculateStemNamesUsedInLexicalEntries.xsl rename to Src/Transforms/Application/CalculateStemNamesUsedInLexicalEntries.xsl diff --git a/DistFiles/Language Explorer/Transforms/FxtM3MorphologySketch.xsl b/Src/Transforms/Application/FxtM3MorphologySketch.xsl similarity index 100% rename from DistFiles/Language Explorer/Transforms/FxtM3MorphologySketch.xsl rename to Src/Transforms/Application/FxtM3MorphologySketch.xsl diff --git a/DistFiles/Language Explorer/Transforms/FxtM3ParserCommon.xsl b/Src/Transforms/Application/FxtM3ParserCommon.xsl similarity index 100% rename from DistFiles/Language Explorer/Transforms/FxtM3ParserCommon.xsl rename to Src/Transforms/Application/FxtM3ParserCommon.xsl diff --git a/DistFiles/Language Explorer/Transforms/FxtM3ParserToGAFAWS.xsl b/Src/Transforms/Application/FxtM3ParserToGAFAWS.xsl similarity index 100% rename from DistFiles/Language Explorer/Transforms/FxtM3ParserToGAFAWS.xsl rename to Src/Transforms/Application/FxtM3ParserToGAFAWS.xsl diff --git a/DistFiles/Language Explorer/Transforms/FxtM3ParserToHCInput.xsl b/Src/Transforms/Application/FxtM3ParserToHCInput.xsl similarity index 99% rename from DistFiles/Language Explorer/Transforms/FxtM3ParserToHCInput.xsl rename to Src/Transforms/Application/FxtM3ParserToHCInput.xsl index 1baa1e9f60..e7562f5b0c 100644 --- a/DistFiles/Language Explorer/Transforms/FxtM3ParserToHCInput.xsl +++ b/Src/Transforms/Application/FxtM3ParserToHCInput.xsl @@ -24,7 +24,7 @@ - + diff --git a/DistFiles/Language Explorer/Transforms/FxtM3ParserToToXAmpleGrammar.xsl b/Src/Transforms/Application/FxtM3ParserToToXAmpleGrammar.xsl similarity index 100% rename from DistFiles/Language Explorer/Transforms/FxtM3ParserToToXAmpleGrammar.xsl rename to Src/Transforms/Application/FxtM3ParserToToXAmpleGrammar.xsl diff --git a/DistFiles/Language Explorer/Transforms/FxtM3ParserToXAmpleADCtl.xsl b/Src/Transforms/Application/FxtM3ParserToXAmpleADCtl.xsl similarity index 100% rename from DistFiles/Language Explorer/Transforms/FxtM3ParserToXAmpleADCtl.xsl rename to Src/Transforms/Application/FxtM3ParserToXAmpleADCtl.xsl diff --git a/DistFiles/Language Explorer/Transforms/FxtM3ParserToXAmpleLex.xsl b/Src/Transforms/Application/FxtM3ParserToXAmpleLex.xsl similarity index 100% rename from DistFiles/Language Explorer/Transforms/FxtM3ParserToXAmpleLex.xsl rename to Src/Transforms/Application/FxtM3ParserToXAmpleLex.xsl diff --git a/DistFiles/Language Explorer/Transforms/FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl b/Src/Transforms/Application/FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl similarity index 100% rename from DistFiles/Language Explorer/Transforms/FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl rename to Src/Transforms/Application/FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl diff --git a/DistFiles/Language Explorer/Transforms/MorphTypeGuids.xsl b/Src/Transforms/Application/MorphTypeGuids.xsl similarity index 100% rename from DistFiles/Language Explorer/Transforms/MorphTypeGuids.xsl rename to Src/Transforms/Application/MorphTypeGuids.xsl diff --git a/DistFiles/Language Explorer/Transforms/UnifyTwoFeatureStructures.xsl b/Src/Transforms/Application/UnifyTwoFeatureStructures.xsl similarity index 100% rename from DistFiles/Language Explorer/Transforms/UnifyTwoFeatureStructures.xsl rename to Src/Transforms/Application/UnifyTwoFeatureStructures.xsl diff --git a/DistFiles/Language Explorer/Transforms/XAmpleTemplateVariables.xsl b/Src/Transforms/Application/XAmpleTemplateVariables.xsl similarity index 100% rename from DistFiles/Language Explorer/Transforms/XAmpleTemplateVariables.xsl rename to Src/Transforms/Application/XAmpleTemplateVariables.xsl diff --git a/Src/LexText/ParserUI/FormatCommon.xsl b/Src/Transforms/Presentation/FormatCommon.xsl similarity index 100% rename from Src/LexText/ParserUI/FormatCommon.xsl rename to Src/Transforms/Presentation/FormatCommon.xsl diff --git a/Src/LexText/ParserUI/FormatHCTrace.xsl b/Src/Transforms/Presentation/FormatHCTrace.xsl similarity index 100% rename from Src/LexText/ParserUI/FormatHCTrace.xsl rename to Src/Transforms/Presentation/FormatHCTrace.xsl diff --git a/Src/LexText/ParserUI/FormatXAmpleParse.xsl b/Src/Transforms/Presentation/FormatXAmpleParse.xsl similarity index 100% rename from Src/LexText/ParserUI/FormatXAmpleParse.xsl rename to Src/Transforms/Presentation/FormatXAmpleParse.xsl diff --git a/Src/LexText/ParserUI/FormatXAmpleTrace.xsl b/Src/Transforms/Presentation/FormatXAmpleTrace.xsl similarity index 100% rename from Src/LexText/ParserUI/FormatXAmpleTrace.xsl rename to Src/Transforms/Presentation/FormatXAmpleTrace.xsl diff --git a/Src/LexText/ParserUI/FormatXAmpleWordGrammarDebuggerResult.xsl b/Src/Transforms/Presentation/FormatXAmpleWordGrammarDebuggerResult.xsl similarity index 100% rename from Src/LexText/ParserUI/FormatXAmpleWordGrammarDebuggerResult.xsl rename to Src/Transforms/Presentation/FormatXAmpleWordGrammarDebuggerResult.xsl diff --git a/DistFiles/Language Explorer/Transforms/XLingPap1.xsl b/Src/Transforms/Presentation/XLingPap1.xsl similarity index 100% rename from DistFiles/Language Explorer/Transforms/XLingPap1.xsl rename to Src/Transforms/Presentation/XLingPap1.xsl diff --git a/DistFiles/Language Explorer/Transforms/XLingPaperForXXE.xsl b/Src/Transforms/Presentation/XLingPaperForXXE.xsl similarity index 100% rename from DistFiles/Language Explorer/Transforms/XLingPaperForXXE.xsl rename to Src/Transforms/Presentation/XLingPaperForXXE.xsl diff --git a/Src/Utilities/XMLUtils/XmlUtils.cs b/Src/Utilities/XMLUtils/XmlUtils.cs index 402b01c669..73db56e544 100644 --- a/Src/Utilities/XMLUtils/XmlUtils.cs +++ b/Src/Utilities/XMLUtils/XmlUtils.cs @@ -25,6 +25,8 @@ using System.Globalization; using System.Xml.Serialization; using System.Windows.Forms; +using System.Xml.Xsl; + #if __MonoCS__ using System.Xml.Xsl; #endif @@ -1088,6 +1090,20 @@ public static bool VisitAttributes(XmlNode input, IAttributeVisitor visitor) } return fSuccessfulVisit; } + + public static XslCompiledTransform CreateTransform(string xslName, string assemblyName) + { + var transform = new XslCompiledTransform(); +#if !__MonoCS__ + // Assumes the XSL has been precompiled. xslName is the name of the precompiled class + Type type = Type.GetType(xslName + "," + assemblyName); + Debug.Assert(type != null); + transform.Load(type); +#else + transform.Load(Path.Combine(TransformPath, xslName + ".xls"), new XsltSettings(true, false), new XmlUrlResolver()); +#endif + return transform; + } } /// diff --git a/Src/xWorks/GeneratedHtmlViewer.cs b/Src/xWorks/GeneratedHtmlViewer.cs index 9360d00613..ecf0cf7243 100644 --- a/Src/xWorks/GeneratedHtmlViewer.cs +++ b/Src/xWorks/GeneratedHtmlViewer.cs @@ -21,6 +21,7 @@ using System.IO; using System.Resources; using System.Text; +using System.Xml.Xsl; using Microsoft.Win32; using SIL.FieldWorks.FDO.DomainServices; using XCore; @@ -125,6 +126,8 @@ public class GeneratedHtmlViewer : UserControl, IxCoreContentControl, IFWDisposa private const string m_ksHtmlFilePath = "HtmlFilePath"; private const string m_ksAlsoSaveFilePath = "AlsoSaveFilePath"; + private readonly Dictionary transforms = new Dictionary(); + #endregion // Data Members #region Properties @@ -594,31 +597,48 @@ private void PerformTransformations(string sLastFile, ProgressDialogWorkingOn dl m_sHtmlFileName = sLastFile; } - private string ApplyTransform(string sInputFile, XmlNode node, ProgressDialogWorkingOn dlg) + private string ApplyTransform(string inputFile, XmlNode node, ProgressDialogWorkingOn dlg) { - string sProgressPrompt = XmlUtils.GetManditoryAttributeValue(node, "progressPrompt"); - UpdateProgress(sProgressPrompt, dlg); - string sXslt = XmlUtils.GetManditoryAttributeValue(node, "file"); - string sOutputFile = Path.Combine(m_outputDirectory, Cache.ProjectId.Name + sXslt + "Result." + GetExtensionFromNode(node)); + string progressPrompt = XmlUtils.GetManditoryAttributeValue(node, "progressPrompt"); + UpdateProgress(progressPrompt, dlg); + string stylesheetName = XmlUtils.GetManditoryAttributeValue(node, "stylesheetName"); + string stylesheetAssembly = XmlUtils.GetManditoryAttributeValue(node, "stylesheetAssembly"); + string outputFile = Path.Combine(m_outputDirectory, Cache.ProjectId.Name + stylesheetName + "Result." + GetExtensionFromNode(node)); - XmlUtils.XSLParameter[] parameterList = CreateParameterList(node); + XsltArgumentList argumentList = CreateParameterList(node); IWritingSystemContainer wsContainer = Cache.ServiceLocator.WritingSystems; - if (parameterList != null) + + if (argumentList.GetParam("prmVernacularFontSize", "") != null) { - foreach (XmlUtils.XSLParameter param in parameterList) - { - if (param.Name == "prmVernacularFontSize") - { - param.Value = GetNormalStyleFontSize(wsContainer.DefaultVernacularWritingSystem.Handle); - } - if (param.Name == "prmGlossFontSize") - { - param.Value = GetNormalStyleFontSize(wsContainer.DefaultAnalysisWritingSystem.Handle); - } - } + argumentList.RemoveParam("prmVernacularFontSize", ""); + argumentList.AddParam("prmVernacularFontSize", "", GetNormalStyleFontSize(wsContainer.DefaultVernacularWritingSystem.Handle)); + } + if (argumentList.GetParam("prmGlossFontSize", "") != null) + { + argumentList.RemoveParam("prmGlossFontSize", ""); + argumentList.AddParam("prmGlossFontSize", "", GetNormalStyleFontSize(wsContainer.DefaultAnalysisWritingSystem.Handle)); + } + + var xmlReaderSettings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Parse }; + using (var writer = new StreamWriter(outputFile)) + using (var reader = XmlReader.Create(new XmlTextReader(inputFile), xmlReaderSettings)) + GetTransform(stylesheetName, stylesheetAssembly).Transform(reader, argumentList, writer); + return outputFile; + } + + private XslCompiledTransform GetTransform(string xslName, string xslAssembly) + { + lock(transforms) + { + XslCompiledTransform transform; + transforms.TryGetValue(xslName, out transform); + if (transform != null) + return transform; + + transform = XmlUtils.CreateTransform(xslName, xslAssembly); + transforms.Add(xslName, transform); + return transform; } - XmlUtils.TransformFileToFile(Path.Combine(TransformPath, sXslt), parameterList, sInputFile, sOutputFile); - return sOutputFile; } private string GetNormalStyleFontSize(int ws) @@ -628,9 +648,9 @@ private string GetNormalStyleFontSize(int ws) return myFont.Size + "pt"; } - private static XmlUtils.XSLParameter[] CreateParameterList(XmlNode node) + private static XsltArgumentList CreateParameterList(XmlNode node) { - XmlUtils.XSLParameter[] parameterList = null; + XsltArgumentList parameterList = new XsltArgumentList(); foreach (XmlNode rNode in node.ChildNodes) { if (rNode.Name == "xsltParameters") @@ -638,29 +658,28 @@ private static XmlUtils.XSLParameter[] CreateParameterList(XmlNode node) int cParams = CountParams(rNode); if (cParams > 0) { - parameterList = GetParameters(cParams, rNode); + parameterList = GetParameters(rNode); + break; } } } return parameterList; } - private static XmlUtils.XSLParameter[] GetParameters(int cParams, XmlNode rNode) + private static XsltArgumentList GetParameters(XmlNode rNode) { - var parameterList = new XmlUtils.XSLParameter[cParams]; - int i = 0; + var parameterList = new XsltArgumentList(); foreach (XmlNode rParamNode in rNode.ChildNodes) { if (rParamNode.Name == "param") { - string sName = XmlUtils.GetManditoryAttributeValue(rParamNode, "name"); - string sValue = XmlUtils.GetManditoryAttributeValue(rParamNode, "value"); - if (sValue == "TransformDirectory") + string name = XmlUtils.GetManditoryAttributeValue(rParamNode, "name"); + string value = XmlUtils.GetManditoryAttributeValue(rParamNode, "value"); + if (value == "TransformDirectory") { - sValue = TransformPath.Replace("\\", "/"); + value = TransformPath.Replace("\\", "/"); } - parameterList[i] = new XmlUtils.XSLParameter(sName, sValue); - i++; + parameterList.AddParam(name, "", value); } } return parameterList; From bb40f3aa97feae310fbe86ec9ca65bf9d77b2d9c Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Wed, 19 Feb 2014 10:08:20 +0700 Subject: [PATCH 086/143] Fixing duplicate using directive for linux in previous commit Change-Id: If217b781b3a191132297d89c1564e715f9372e65 --- Src/Utilities/XMLUtils/XmlUtils.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Src/Utilities/XMLUtils/XmlUtils.cs b/Src/Utilities/XMLUtils/XmlUtils.cs index 73db56e544..b01fbc5afa 100644 --- a/Src/Utilities/XMLUtils/XmlUtils.cs +++ b/Src/Utilities/XMLUtils/XmlUtils.cs @@ -27,10 +27,6 @@ using System.Windows.Forms; using System.Xml.Xsl; -#if __MonoCS__ -using System.Xml.Xsl; -#endif - namespace SIL.Utils { /// From 40511fb14e2364b51f0a23d0a175388969ff46f6 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Wed, 19 Feb 2014 15:49:32 +0700 Subject: [PATCH 087/143] Fix unit tests from previous commit Change-Id: I5e4459d83159db72dd70e78aca0fe75658f4e77a --- .../M3ToXAmpleTransformerTests.cs | 22 ++-- .../ParserUITests/ParserUITests.csproj | 4 + .../ParserUITests/TestUnificationViaXSLT.xsl | 2 +- .../TLPSameSlotTwiceWordGrammarDebugger.xsl | 108 +++++++++--------- .../fpfptovAffixAlloFeatsStep00.xml | 4 +- .../fpfptovAffixAlloFeatsStep00Result.xml | 16 +-- .../fpfptovAffixAlloFeatsStep01.xml | 12 +- .../fpfptovAffixAlloFeatsStep01Result.xml | 18 +-- .../fpfptovAffixAlloFeatsStep02.xml | 12 +- .../fpfptovAffixAlloFeatsStep02Result.xml | 4 +- .../fpfstovAffixAlloFeatsStep00.xml | 4 +- .../fpfstovAffixAlloFeatsStep00Result.xml | 16 +-- .../fpfstovAffixAlloFeatsStep01.xml | 12 +- .../fpfstovAffixAlloFeatsStep01Result.xml | 2 +- .../fsfptovAffixAlloFeatsStep00.xml | 4 +- .../fsfptovAffixAlloFeatsStep00Result.xml | 16 +-- .../fsfptovAffixAlloFeatsStep01.xml | 12 +- .../fsfptovAffixAlloFeatsStep01Result.xml | 2 +- .../fsfstovAffixAlloFeatsStep00.xml | 4 +- .../fsfstovAffixAlloFeatsStep00Result.xml | 16 +-- .../fsfstovAffixAlloFeatsStep01.xml | 12 +- .../fsfstovAffixAlloFeatsStep01Result.xml | 18 +-- .../fsfstovAffixAlloFeatsStep02.xml | 12 +- .../fsfstovAffixAlloFeatsStep02Result.xml | 4 +- .../fsinflAffixAlloFeatsStep00.xml | 4 +- .../fsinflAffixAlloFeatsStep00Result.xml | 14 +-- .../fsinflAffixAlloFeatsStep01.xml | 10 +- .../fsinflAffixAlloFeatsStep01Result.xml | 4 +- .../fsinflAffixAlloFeatsStep02.xml | 2 +- .../fsinflAffixAlloFeatsStep02Result.xml | 2 +- .../mpmsAffixAlloFeatsStep00.xml | 4 +- .../mpmsAffixAlloFeatsStep00Result.xml | 14 +-- .../mpmsAffixAlloFeatsStep01.xml | 10 +- .../mpmsAffixAlloFeatsStep01Result.xml | 2 +- .../msinflAffixAlloFeatsStep00.xml | 4 +- .../msinflAffixAlloFeatsStep00Result.xml | 14 +-- .../msinflAffixAlloFeatsStep01.xml | 10 +- .../msinflAffixAlloFeatsStep01Result.xml | 2 +- .../msmsAffixAlloFeatsStep00.xml | 4 +- .../msmsAffixAlloFeatsStep00Result.xml | 14 +-- .../msmsAffixAlloFeatsStep01.xml | 10 +- .../msmsAffixAlloFeatsStep01Result.xml | 4 +- .../msmsAffixAlloFeatsStep02.xml | 2 +- .../msmsAffixAlloFeatsStep02Result.xml | 2 +- .../niyuhohwusaStemNameNotSetFailStep00.xml | 4 +- ...uhohwusaStemNameNotSetFailStep00Result.xml | 16 +-- ...uhohwusaStemNameNotSetFailStep01Result.xml | 16 +-- ...uhohwusaStemNameNotSetFailStep02Result.xml | 14 +-- .../niyumamwupeStemNameSetNoFsStep00.xml | 4 +- ...niyumamwupeStemNameSetNoFsStep00Result.xml | 16 +-- ...niyumamwupeStemNameSetNoFsStep01Result.xml | 16 +-- ...niyumamwupeStemNameSetNoFsStep02Result.xml | 14 +-- ...yuwowwukoStemNameNotSetMultiFailStep00.xml | 4 +- ...ukoStemNameNotSetMultiFailStep00Result.xml | 16 +-- ...ukoStemNameNotSetMultiFailStep01Result.xml | 16 +-- ...ukoStemNameNotSetMultiFailStep02Result.xml | 14 +-- .../niyuwowwupeStemNameNotSetStep00.xml | 4 +- .../niyuwowwupeStemNameNotSetStep00Result.xml | 16 +-- .../niyuwowwupeStemNameNotSetStep01Result.xml | 16 +-- .../niyuwowwupeStemNameNotSetStep02Result.xml | 14 +-- .../niyuyiywupeStemNameFailStep00.xml | 4 +- .../niyuyiywupeStemNameFailStep00Result.xml | 16 +-- .../niyuyiywupeStemNameFailStep01Result.xml | 16 +-- .../niyuyiywupeStemNameFailStep02Result.xml | 14 +-- .../niyuyiywusaStemNameSetStep00.xml | 4 +- .../niyuyiywusaStemNameSetStep00Result.xml | 16 +-- .../niyuyiywusaStemNameSetStep01Result.xml | 16 +-- .../niyuyiywusaStemNameSetStep02Result.xml | 14 +-- ...muwupeStemNameNotSetCompoundFailStep00.xml | 8 +- ...StemNameNotSetCompoundFailStep00Result.xml | 18 +-- ...StemNameNotSetCompoundFailStep01Result.xml | 4 +- ...StemNameNotSetCompoundFailStep02Result.xml | 16 +-- ...StemNameNotSetCompoundFailStep03Result.xml | 16 +-- ...StemNameNotSetCompoundFailStep04Result.xml | 14 +-- ...yuyiyximuwusaStemNameSetCompoundStep00.xml | 8 +- ...imuwusaStemNameSetCompoundStep00Result.xml | 18 +-- ...imuwusaStemNameSetCompoundStep01Result.xml | 4 +- ...imuwusaStemNameSetCompoundStep02Result.xml | 16 +-- ...imuwusaStemNameSetCompoundStep03Result.xml | 16 +-- ...imuwusaStemNameSetCompoundStep04Result.xml | 14 +-- ...imikikwupeStemNameSetMultiFsFailStep00.xml | 4 +- ...wupeStemNameSetMultiFsFailStep00Result.xml | 16 +-- ...wupeStemNameSetMultiFsFailStep01Result.xml | 16 +-- ...wupeStemNameSetMultiFsFailStep02Result.xml | 14 +-- .../timikikwusaStemNameSetMultiFsStep00.xml | 4 +- ...ikikwusaStemNameSetMultiFsStep00Result.xml | 16 +-- ...ikikwusaStemNameSetMultiFsStep01Result.xml | 16 +-- ...ikikwusaStemNameSetMultiFsStep02Result.xml | 14 +-- .../yalotetuStep01.xml | 4 +- .../WordGrammarDebuggingTests.cs | 101 +++++----------- ...ParserToXAmpleWordGrammarDebuggingXSLT.xsl | 88 ++++++-------- Src/Utilities/XMLUtils/XmlUtils.cs | 2 +- 92 files changed, 578 insertions(+), 637 deletions(-) diff --git a/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTests.cs b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTests.cs index 1131cd6343..8ef2fa4e8f 100644 --- a/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTests.cs +++ b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTests.cs @@ -136,25 +136,23 @@ private void SetUpM3FXTDump() private void SetupXmlDocument(string filepath) { - XPathDocument xdoc = new XPathDocument(filepath); + var xdoc = new XPathDocument(filepath); m_mapXmlDocs.Add(filepath, xdoc); } private void SetUpXAmpleTransforms() { - SetUpTransform(ref m_adTransform, "FxtM3ParserToXAmpleADCtl.xsl"); - SetUpTransform(ref m_lexTransform, "FxtM3ParserToXAmpleLex.xsl"); - SetUpTransform(ref m_gramTransform, "FxtM3ParserToToXAmpleGrammar.xsl"); + SetUpTransform(out m_adTransform, "FxtM3ParserToXAmpleADCtl"); + SetUpTransform(out m_lexTransform, "FxtM3ParserToXAmpleLex"); + SetUpTransform(out m_gramTransform, "FxtM3ParserToToXAmpleGrammar"); } - private void SetUpTransform(ref XslCompiledTransform transform, string sName) + private void SetUpTransform(out XslCompiledTransform transform, string name) { - string sTransformPath = Path.Combine(m_sTransformPath, sName); - transform = new XslCompiledTransform(); - transform.Load(sTransformPath); + transform = XmlUtils.CreateTransform(name, "ApplicationTransforms"); } - private void SetUpTransform(ref IntPtr transform, string sName) + private void SetUpTransform(ref IntPtr transform, string name) { - string sTransformPath = Path.Combine(m_sTransformPath, sName); + string sTransformPath = Path.Combine(m_sTransformPath, name); transform = LibXslt.CompileTransform(sTransformPath); } @@ -215,7 +213,7 @@ private void ApplyTransform(string sInput, XslCompiledTransform transform, strin { XPathDocument fxtDump = m_mapXmlDocs[sInput]; string sOutput = FileUtils.GetTempFile("txt"); - using (StreamWriter result = new StreamWriter(sOutput)) + using (var result = new StreamWriter(sOutput)) { transform.Transform(fxtDump, null, result); result.Close(); @@ -228,7 +226,7 @@ private void ApplyTransform(string sInput, XslCompiledTransform transform, strin private void ApplyTransform(string sInput, IntPtr transform, string sExpectedOutput) { string sOutput = FileUtils.GetTempFile("txt"); - SIL.Utils.LibXslt.TransformFileToFile(transform, sInput, sOutput); + LibXslt.TransformFileToFile(transform, sInput, sOutput); string sExpectedResult = Path.Combine(m_sTestPath, sExpectedOutput); CheckOutputEquals(sExpectedResult, sOutput); // by deleting it here instead of a finally block, when it fails, we can see what the result is. diff --git a/Src/LexText/ParserUI/ParserUITests/ParserUITests.csproj b/Src/LexText/ParserUI/ParserUITests/ParserUITests.csproj index 56cee34718..8394d5f6d1 100644 --- a/Src/LexText/ParserUI/ParserUITests/ParserUITests.csproj +++ b/Src/LexText/ParserUI/ParserUITests/ParserUITests.csproj @@ -81,6 +81,10 @@ x86 + + False + ..\..\..\..\Output\Debug\ApplicationTransforms.dll + False ..\..\..\..\Output\Debug\BasicUtils.dll diff --git a/Src/LexText/ParserUI/ParserUITests/TestUnificationViaXSLT.xsl b/Src/LexText/ParserUI/ParserUITests/TestUnificationViaXSLT.xsl index f9188448ae..bec93ee9f3 100644 --- a/Src/LexText/ParserUI/ParserUITests/TestUnificationViaXSLT.xsl +++ b/Src/LexText/ParserUI/ParserUITests/TestUnificationViaXSLT.xsl @@ -13,7 +13,7 @@ Revision History is at the end of this file. Preamble - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - + - + - + @@ -2103,9 +2103,9 @@ InflectionalTemplate102 - - - + + + The inflectional template named 'Possessed noun' for category 'noun' @@ -2125,7 +2125,7 @@ InflectionalTemplate102 - + The inflectional template named 'Possessed noun' for category 'noun' @@ -2136,17 +2136,17 @@ InflectionalTemplate102 - + - + - - + + The inflectional template named 'Possessed noun' for category 'noun' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. @@ -2890,9 +2890,9 @@ InflectionalTemplate156 - - - + + + The inflectional template named 'Intransitive verb' for category 'intransitive verb' @@ -2912,7 +2912,7 @@ InflectionalTemplate156 - + The inflectional template named 'Intransitive verb' for category 'intransitive verb' @@ -2923,17 +2923,17 @@ InflectionalTemplate156 - + - + - - + + The inflectional template named 'Intransitive verb' for category 'intransitive verb' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. @@ -3341,9 +3341,9 @@ InflectionalTemplate166 - - - + + + The inflectional template named 'Stative verb' for category 'stative' @@ -3363,7 +3363,7 @@ InflectionalTemplate166 - + The inflectional template named 'Stative verb' for category 'stative' @@ -3374,17 +3374,17 @@ InflectionalTemplate166 - + - + - - + + The inflectional template named 'Stative verb' for category 'stative' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. @@ -3792,9 +3792,9 @@ InflectionalTemplate171 - - - + + + The inflectional template named 'Transitive verb' for category 'transitive verb' @@ -3814,7 +3814,7 @@ InflectionalTemplate171 - + The inflectional template named 'Transitive verb' for category 'transitive verb' @@ -3825,17 +3825,17 @@ InflectionalTemplate171 - + - + - - + + The inflectional template named 'Transitive verb' for category 'transitive verb' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. @@ -4307,9 +4307,9 @@ InflectionalTemplate175 - - - + + + The inflectional template named 'Bitransitive verb' for category 'bitransitive verb' @@ -4329,7 +4329,7 @@ InflectionalTemplate175 - + The inflectional template named 'Bitransitive verb' for category 'bitransitive verb' @@ -4340,17 +4340,17 @@ InflectionalTemplate175 - + - + - - + + The inflectional template named 'Bitransitive verb' for category 'bitransitive verb' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. @@ -5515,7 +5515,7 @@ UnifyPrefixSlots - + @@ -5561,7 +5561,7 @@ UnifySuffixSlots - + @@ -5608,14 +5608,14 @@ UnifyTwoFeatureStructures - + Empty and - + Empty @@ -5624,16 +5624,16 @@ UnifyTwoFeatureStructures - + - + - + @@ -5723,13 +5723,13 @@ XSubsumesY N - + - - + + diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep00.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep00.xml index 2599af0a5d..d82483730f 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep00.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep00.xml @@ -1,7 +1,7 @@ fpfptov - + @@ -82,7 +82,7 @@ - + A root can only be a "Partial" when its category is unknown, but the category here is 'n'. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep00Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep00Result.xml index 49705eee58..7104af0209 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep00Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep00Result.xml @@ -1,7 +1,7 @@
fpfptov
- + @@ -101,7 +101,7 @@
- + @@ -184,7 +184,7 @@ - + The category (N) of the inflectional template "Possessed noun" is incompatible with the category (n) of the stem. @@ -240,7 +240,7 @@ - + The category (comm) of the inflectional template "test stem name features" is incompatible with the category (n) of the stem. @@ -296,7 +296,7 @@ - + The category (intrans) of the inflectional template "Intransitive verb" is incompatible with the category (n) of the stem. @@ -398,7 +398,7 @@ - + The category (sta) of the inflectional template "Stative verb" is incompatible with the category (n) of the stem. @@ -500,7 +500,7 @@ - + The category (trans) of the inflectional template "Transitive verb" is incompatible with the category (n) of the stem. @@ -603,7 +603,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (n) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep01.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep01.xml index 586c79bfe9..f07bc4d4ca 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep01.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep01.xml @@ -82,7 +82,7 @@ - + @@ -182,7 +182,7 @@ - + @@ -265,7 +265,7 @@ - + @@ -320,7 +320,7 @@ - + @@ -420,7 +420,7 @@ - + The category (v) of the inflectional template "Tense/Aspect" is incompatible with the category (n) of the stem. @@ -521,7 +521,7 @@ - + The category (v) of the inflectional template "Non-final" is incompatible with the category (n) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep01Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep01Result.xml index 3ccc0b8e69..c5cc71303d 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep01Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep01Result.xml @@ -82,7 +82,7 @@ - + In attaching a derivational suffix: The from category (n) of the derivational suffix "-0 (ForWGD): 0" is incompatible with the category (v) of the stem. @@ -185,7 +185,7 @@ - + @@ -287,7 +287,7 @@ - + The category (N) of the inflectional template "Possessed noun" is incompatible with the category (v) of the stem. @@ -315,7 +315,7 @@ - + The category (comm) of the inflectional template "test stem name features" is incompatible with the category (v) of the stem. @@ -343,7 +343,7 @@ - + The category (intrans) of the inflectional template "Intransitive verb" is incompatible with the category (v) of the stem. @@ -464,7 +464,7 @@ - + The category (sta) of the inflectional template "Stative verb" is incompatible with the category (v) of the stem. @@ -585,7 +585,7 @@ - + The category (trans) of the inflectional template "Transitive verb" is incompatible with the category (v) of the stem. @@ -707,7 +707,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (v) of the stem. @@ -829,7 +829,7 @@ - + The category 'n' requires inflection, but there was no inflection. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep02.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep02.xml index 0b57a4b424..3d8cced89b 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep02.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep02.xml @@ -101,7 +101,7 @@ - + In attaching a derivational suffix: The from category (n) of the derivational suffix "-0 (ForWGD): 0" is incompatible with the category (v) of the stem. @@ -204,7 +204,7 @@ - + @@ -306,7 +306,7 @@ - + The category (n) of the inflectional template "template for test" is incompatible with the category (v) of the stem. @@ -334,7 +334,7 @@ - + The category (n) of the inflectional template "possessed" is incompatible with the category (v) of the stem. @@ -454,7 +454,7 @@ - + @@ -573,7 +573,7 @@ - + diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep02Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep02Result.xml index 22de9e7c59..2aabdb6a8d 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep02Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfptovAffixAlloFeatsStep02Result.xml @@ -101,7 +101,7 @@ - + The category 'v' requires inflection, but there was no inflection. @@ -206,7 +206,7 @@ - + diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfstovAffixAlloFeatsStep00.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfstovAffixAlloFeatsStep00.xml index 62c13a5a1b..a83487dc9d 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfstovAffixAlloFeatsStep00.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfstovAffixAlloFeatsStep00.xml @@ -1,7 +1,7 @@
fpfstov
- + @@ -73,7 +73,7 @@ - + A root can only be a "Partial" when its category is unknown, but the category here is 'n'. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfstovAffixAlloFeatsStep00Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfstovAffixAlloFeatsStep00Result.xml index c65b64d6f8..373a59092a 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfstovAffixAlloFeatsStep00Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfstovAffixAlloFeatsStep00Result.xml @@ -1,7 +1,7 @@
fpfstov
- + @@ -93,7 +93,7 @@
- + @@ -167,7 +167,7 @@ - + The category (N) of the inflectional template "Possessed noun" is incompatible with the category (n) of the stem. @@ -214,7 +214,7 @@ - + The category (comm) of the inflectional template "test stem name features" is incompatible with the category (n) of the stem. @@ -261,7 +261,7 @@ - + The category (intrans) of the inflectional template "Intransitive verb" is incompatible with the category (n) of the stem. @@ -354,7 +354,7 @@ - + The category (sta) of the inflectional template "Stative verb" is incompatible with the category (n) of the stem. @@ -447,7 +447,7 @@ - + The category (trans) of the inflectional template "Transitive verb" is incompatible with the category (n) of the stem. @@ -541,7 +541,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (n) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfstovAffixAlloFeatsStep01.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfstovAffixAlloFeatsStep01.xml index f0766fb9bb..f8564d3643 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfstovAffixAlloFeatsStep01.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfstovAffixAlloFeatsStep01.xml @@ -73,7 +73,7 @@ - + @@ -165,7 +165,7 @@ - + @@ -239,7 +239,7 @@ - + @@ -285,7 +285,7 @@ - + @@ -376,7 +376,7 @@ - + The category (v) of the inflectional template "Tense/Aspect" is incompatible with the category (n) of the stem. @@ -468,7 +468,7 @@ - + The category (v) of the inflectional template "Non-final" is incompatible with the category (n) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfstovAffixAlloFeatsStep01Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfstovAffixAlloFeatsStep01Result.xml index cf2ac16e7f..a05399038d 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfstovAffixAlloFeatsStep01Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fpfstovAffixAlloFeatsStep01Result.xml @@ -73,7 +73,7 @@ - + The category 'n' requires inflection, but there was no inflection. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfptovAffixAlloFeatsStep00.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfptovAffixAlloFeatsStep00.xml index 7d53ecf7b7..8eca3f7b4c 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfptovAffixAlloFeatsStep00.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfptovAffixAlloFeatsStep00.xml @@ -1,7 +1,7 @@
fsfptov
- + @@ -75,7 +75,7 @@ - + A root can only be a "Partial" when its category is unknown, but the category here is 'n'. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfptovAffixAlloFeatsStep00Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfptovAffixAlloFeatsStep00Result.xml index 53a6348445..b0a39b418c 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfptovAffixAlloFeatsStep00Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfptovAffixAlloFeatsStep00Result.xml @@ -1,7 +1,7 @@
fsfptov
- + @@ -95,7 +95,7 @@
- + @@ -171,7 +171,7 @@ - + The category (N) of the inflectional template "Possessed noun" is incompatible with the category (n) of the stem. @@ -220,7 +220,7 @@ - + The category (comm) of the inflectional template "test stem name features" is incompatible with the category (n) of the stem. @@ -269,7 +269,7 @@ - + The category (intrans) of the inflectional template "Intransitive verb" is incompatible with the category (n) of the stem. @@ -364,7 +364,7 @@ - + The category (sta) of the inflectional template "Stative verb" is incompatible with the category (n) of the stem. @@ -459,7 +459,7 @@ - + The category (trans) of the inflectional template "Transitive verb" is incompatible with the category (n) of the stem. @@ -555,7 +555,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (n) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfptovAffixAlloFeatsStep01.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfptovAffixAlloFeatsStep01.xml index eab3ba6f73..759d4acc40 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfptovAffixAlloFeatsStep01.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfptovAffixAlloFeatsStep01.xml @@ -75,7 +75,7 @@ - + @@ -169,7 +169,7 @@ - + @@ -245,7 +245,7 @@ - + @@ -293,7 +293,7 @@ - + @@ -386,7 +386,7 @@ - + The category (v) of the inflectional template "Tense/Aspect" is incompatible with the category (n) of the stem. @@ -480,7 +480,7 @@ - + The category (v) of the inflectional template "Non-final" is incompatible with the category (n) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfptovAffixAlloFeatsStep01Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfptovAffixAlloFeatsStep01Result.xml index f38b3b20b8..458ca152cc 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfptovAffixAlloFeatsStep01Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfptovAffixAlloFeatsStep01Result.xml @@ -75,7 +75,7 @@ - + The category 'n' requires inflection, but there was no inflection. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep00.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep00.xml index 4561dd13e0..38775cf9ca 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep00.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep00.xml @@ -1,7 +1,7 @@
fsfstov
- + @@ -80,7 +80,7 @@ - + A root can only be a "Partial" when its category is unknown, but the category here is 'n'. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep00Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep00Result.xml index 9c0799f0bf..09585023b5 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep00Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep00Result.xml @@ -1,7 +1,7 @@
fsfstov
- + @@ -99,7 +99,7 @@
- + @@ -180,7 +180,7 @@ - + The category (N) of the inflectional template "Possessed noun" is incompatible with the category (n) of the stem. @@ -234,7 +234,7 @@ - + The category (comm) of the inflectional template "test stem name features" is incompatible with the category (n) of the stem. @@ -288,7 +288,7 @@ - + The category (intrans) of the inflectional template "Intransitive verb" is incompatible with the category (n) of the stem. @@ -388,7 +388,7 @@ - + The category (sta) of the inflectional template "Stative verb" is incompatible with the category (n) of the stem. @@ -488,7 +488,7 @@ - + The category (trans) of the inflectional template "Transitive verb" is incompatible with the category (n) of the stem. @@ -589,7 +589,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (n) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep01.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep01.xml index 9854242f23..33ac9617fd 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep01.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep01.xml @@ -80,7 +80,7 @@ - + @@ -178,7 +178,7 @@ - + @@ -259,7 +259,7 @@ - + @@ -312,7 +312,7 @@ - + @@ -410,7 +410,7 @@ - + The category (v) of the inflectional template "Tense/Aspect" is incompatible with the category (n) of the stem. @@ -509,7 +509,7 @@ - + The category (v) of the inflectional template "Non-final" is incompatible with the category (n) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep01Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep01Result.xml index 8b37b60497..16b98f89c4 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep01Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep01Result.xml @@ -80,7 +80,7 @@ - + In attaching a derivational suffix: The from category (n) of the derivational suffix "-0 (ForWGD): 0" is incompatible with the category (v) of the stem. @@ -181,7 +181,7 @@ - + @@ -281,7 +281,7 @@ - + The category (N) of the inflectional template "Possessed noun" is incompatible with the category (v) of the stem. @@ -309,7 +309,7 @@ - + The category (comm) of the inflectional template "test stem name features" is incompatible with the category (v) of the stem. @@ -337,7 +337,7 @@ - + The category (intrans) of the inflectional template "Intransitive verb" is incompatible with the category (v) of the stem. @@ -456,7 +456,7 @@ - + The category (sta) of the inflectional template "Stative verb" is incompatible with the category (v) of the stem. @@ -575,7 +575,7 @@ - + The category (trans) of the inflectional template "Transitive verb" is incompatible with the category (v) of the stem. @@ -695,7 +695,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (v) of the stem. @@ -815,7 +815,7 @@ - + The category 'n' requires inflection, but there was no inflection. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep02.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep02.xml index 754cd075f7..d545cae9cc 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep02.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep02.xml @@ -99,7 +99,7 @@ - + In attaching a derivational suffix: The from category (n) of the derivational suffix "-0 (ForWGD): 0" is incompatible with the category (v) of the stem. @@ -200,7 +200,7 @@ - + @@ -300,7 +300,7 @@ - + The category (n) of the inflectional template "template for test" is incompatible with the category (v) of the stem. @@ -328,7 +328,7 @@ - + The category (n) of the inflectional template "possessed" is incompatible with the category (v) of the stem. @@ -446,7 +446,7 @@ - + @@ -563,7 +563,7 @@ - + diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep02Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep02Result.xml index fb06d0cd31..9340aa4f43 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep02Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsfstovAffixAlloFeatsStep02Result.xml @@ -99,7 +99,7 @@ - + The category 'v' requires inflection, but there was no inflection. @@ -202,7 +202,7 @@ - + diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep00.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep00.xml index 6a9f260491..97572ed3f0 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep00.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep00.xml @@ -1,7 +1,7 @@
fsinfl
- + @@ -99,7 +99,7 @@ - + A root can only be a "Partial" when its category is unknown, but the category here is 'n'. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep00Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep00Result.xml index f58bc3a110..1e8aabe3c8 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep00Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep00Result.xml @@ -1,7 +1,7 @@
fsinfl
- + @@ -101,7 +101,7 @@
- + The category (N) of the inflectional template "Possessed noun" is incompatible with the category (n) of the stem. @@ -174,7 +174,7 @@ - + The category (comm) of the inflectional template "test stem name features" is incompatible with the category (n) of the stem. @@ -247,7 +247,7 @@ - + The category (intrans) of the inflectional template "Intransitive verb" is incompatible with the category (n) of the stem. @@ -366,7 +366,7 @@ - + The category (sta) of the inflectional template "Stative verb" is incompatible with the category (n) of the stem. @@ -485,7 +485,7 @@ - + The category (trans) of the inflectional template "Transitive verb" is incompatible with the category (n) of the stem. @@ -605,7 +605,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (n) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep01.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep01.xml index c8c3902742..38ccd0c991 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep01.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep01.xml @@ -99,7 +99,7 @@ - + @@ -199,7 +199,7 @@ - + @@ -226,7 +226,7 @@ - + @@ -343,7 +343,7 @@ - + The category (v) of the inflectional template "Tense/Aspect" is incompatible with the category (n) of the stem. @@ -461,7 +461,7 @@ - + The category (v) of the inflectional template "Non-final" is incompatible with the category (n) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep01Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep01Result.xml index cab7c078c2..d024a2da71 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep01Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep01Result.xml @@ -99,7 +99,7 @@ - + The category 'n' requires inflection, but there was no inflection. @@ -202,7 +202,7 @@ - + diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep02.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep02.xml index 517a541794..24928710fc 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep02.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep02.xml @@ -118,7 +118,7 @@ - + diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep02Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep02Result.xml index 337fdf39ea..f760929806 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep02Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/fsinflAffixAlloFeatsStep02Result.xml @@ -118,7 +118,7 @@ - + diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/mpmsAffixAlloFeatsStep00.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/mpmsAffixAlloFeatsStep00.xml index 0a51aa2ab0..261bf88c44 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/mpmsAffixAlloFeatsStep00.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/mpmsAffixAlloFeatsStep00.xml @@ -1,7 +1,7 @@
mpms
- + @@ -73,7 +73,7 @@ - + A root can only be a "Partial" when its category is unknown, but the category here is 'n'. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/mpmsAffixAlloFeatsStep00Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/mpmsAffixAlloFeatsStep00Result.xml index 4cfb0f3859..20d54d73d3 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/mpmsAffixAlloFeatsStep00Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/mpmsAffixAlloFeatsStep00Result.xml @@ -1,7 +1,7 @@
mpms
- + @@ -75,7 +75,7 @@
- + The category (N) of the inflectional template "Possessed noun" is incompatible with the category (n) of the stem. @@ -122,7 +122,7 @@ - + The category (comm) of the inflectional template "test stem name features" is incompatible with the category (n) of the stem. @@ -169,7 +169,7 @@ - + The category (intrans) of the inflectional template "Intransitive verb" is incompatible with the category (n) of the stem. @@ -262,7 +262,7 @@ - + The category (sta) of the inflectional template "Stative verb" is incompatible with the category (n) of the stem. @@ -355,7 +355,7 @@ - + The category (trans) of the inflectional template "Transitive verb" is incompatible with the category (n) of the stem. @@ -449,7 +449,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (n) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/mpmsAffixAlloFeatsStep01.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/mpmsAffixAlloFeatsStep01.xml index 83da6ac6e3..9c7cef13d3 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/mpmsAffixAlloFeatsStep01.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/mpmsAffixAlloFeatsStep01.xml @@ -73,7 +73,7 @@ - + @@ -147,7 +147,7 @@ - + The inflectional affix allomorph '-ms (INFL): infl' is conditioned to only occur when the inflected form it attaches to has certain features, but the inflected form does not have them. The required features the affix must be inflected for are: [nagr:[gen:m num:sg]]. The inflected features for this inflected form are: [nagr:[gen:m num:pl]]. @@ -168,7 +168,7 @@
nagrgenmnumplmp (masc.pl): mpmpmasc.plmpnagrgenmnumpl-ms (INFL): infl-msnagrgenmnumsgINFLinfl
- + @@ -259,7 +259,7 @@ - + The category (v) of the inflectional template "Tense/Aspect" is incompatible with the category (n) of the stem. @@ -351,7 +351,7 @@ - + The category (v) of the inflectional template "Non-final" is incompatible with the category (n) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/mpmsAffixAlloFeatsStep01Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/mpmsAffixAlloFeatsStep01Result.xml index c47a6e6b0a..af058db4a3 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/mpmsAffixAlloFeatsStep01Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/mpmsAffixAlloFeatsStep01Result.xml @@ -73,7 +73,7 @@ - + The category 'n' requires inflection, but there was no inflection. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msinflAffixAlloFeatsStep00.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msinflAffixAlloFeatsStep00.xml index d6da6ee1b8..5c0b4acc31 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msinflAffixAlloFeatsStep00.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msinflAffixAlloFeatsStep00.xml @@ -1,7 +1,7 @@
msinfl
- + @@ -92,7 +92,7 @@ - + A root can only be a "Partial" when its category is unknown, but the category here is 'n'. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msinflAffixAlloFeatsStep00Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msinflAffixAlloFeatsStep00Result.xml index 31a5986954..1c18db29c3 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msinflAffixAlloFeatsStep00Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msinflAffixAlloFeatsStep00Result.xml @@ -1,7 +1,7 @@
msinfl
- + @@ -94,7 +94,7 @@
- + The category (N) of the inflectional template "Possessed noun" is incompatible with the category (n) of the stem. @@ -160,7 +160,7 @@ - + The category (comm) of the inflectional template "test stem name features" is incompatible with the category (n) of the stem. @@ -226,7 +226,7 @@ - + The category (intrans) of the inflectional template "Intransitive verb" is incompatible with the category (n) of the stem. @@ -338,7 +338,7 @@ - + The category (sta) of the inflectional template "Stative verb" is incompatible with the category (n) of the stem. @@ -450,7 +450,7 @@ - + The category (trans) of the inflectional template "Transitive verb" is incompatible with the category (n) of the stem. @@ -563,7 +563,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (n) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msinflAffixAlloFeatsStep01.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msinflAffixAlloFeatsStep01.xml index 8b119bd8ed..8999becc6c 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msinflAffixAlloFeatsStep01.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msinflAffixAlloFeatsStep01.xml @@ -92,7 +92,7 @@ - + @@ -185,7 +185,7 @@ - + While the inflectional affix allomorph '-infl (INFL): infl' is not conditioned to occur when the inflected form it attaches to has certain features, there are other allomorphs in the entry that are so conditioned. Thus, the inflected form must not be inflected for certain features, but it is. The features the affix must not be inflected for are: [nagr:[gen:m num:pl]] and also [nagr:[gen:m num:sg]]. The inflected features for this inflected form are: [nagr:[gen:m num:sg]]. @@ -206,7 +206,7 @@ nagrgenmnumsgms (masc.sing): msmsmasc.singmsnagrgenmnumsg-infl (INFL): infl-inflnagrgenmnumplnagrgenmnumsgINFLinfl - + @@ -316,7 +316,7 @@ - + The category (v) of the inflectional template "Tense/Aspect" is incompatible with the category (n) of the stem. @@ -427,7 +427,7 @@ - + The category (v) of the inflectional template "Non-final" is incompatible with the category (n) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msinflAffixAlloFeatsStep01Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msinflAffixAlloFeatsStep01Result.xml index 52177fc9b5..35b162a5be 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msinflAffixAlloFeatsStep01Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msinflAffixAlloFeatsStep01Result.xml @@ -92,7 +92,7 @@ - + The category 'n' requires inflection, but there was no inflection. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep00.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep00.xml index c5ea54ed9a..eb1a4a6604 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep00.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep00.xml @@ -1,7 +1,7 @@
msms
- + @@ -80,7 +80,7 @@ - + A root can only be a "Partial" when its category is unknown, but the category here is 'n'. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep00Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep00Result.xml index 1da162d660..40e18485a1 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep00Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep00Result.xml @@ -1,7 +1,7 @@
msms
- + @@ -82,7 +82,7 @@
- + The category (N) of the inflectional template "Possessed noun" is incompatible with the category (n) of the stem. @@ -136,7 +136,7 @@ - + The category (comm) of the inflectional template "test stem name features" is incompatible with the category (n) of the stem. @@ -190,7 +190,7 @@ - + The category (intrans) of the inflectional template "Intransitive verb" is incompatible with the category (n) of the stem. @@ -290,7 +290,7 @@ - + The category (sta) of the inflectional template "Stative verb" is incompatible with the category (n) of the stem. @@ -390,7 +390,7 @@ - + The category (trans) of the inflectional template "Transitive verb" is incompatible with the category (n) of the stem. @@ -491,7 +491,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (n) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep01.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep01.xml index 6a449e8825..a2d3b43e73 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep01.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep01.xml @@ -80,7 +80,7 @@ - + @@ -161,7 +161,7 @@ - + @@ -188,7 +188,7 @@ - + @@ -286,7 +286,7 @@ - + The category (v) of the inflectional template "Tense/Aspect" is incompatible with the category (n) of the stem. @@ -385,7 +385,7 @@ - + The category (v) of the inflectional template "Non-final" is incompatible with the category (n) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep01Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep01Result.xml index 4da1e89333..3c8a3b878d 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep01Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep01Result.xml @@ -80,7 +80,7 @@ - + The category 'n' requires inflection, but there was no inflection. @@ -164,7 +164,7 @@ - + diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep02.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep02.xml index 29d0f89b45..8a1fde48b4 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep02.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep02.xml @@ -99,7 +99,7 @@ - + diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep02Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep02Result.xml index 526d1066c3..cc6423c161 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep02Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/msmsAffixAlloFeatsStep02Result.xml @@ -99,7 +99,7 @@ - + diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuhohwusaStemNameNotSetFailStep00.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuhohwusaStemNameNotSetFailStep00.xml index f8a6a7b660..11642c363b 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuhohwusaStemNameNotSetFailStep00.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuhohwusaStemNameNotSetFailStep00.xml @@ -1,7 +1,7 @@
niyuhohwusa
- + ni- (1SgSubj): ni ni- @@ -51,7 +51,7 @@
- + ni- (1SgSubj): ni ni- diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuhohwusaStemNameNotSetFailStep00Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuhohwusaStemNameNotSetFailStep00Result.xml index 948fb40a4e..2b00a4f765 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuhohwusaStemNameNotSetFailStep00Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuhohwusaStemNameNotSetFailStep00Result.xml @@ -1,7 +1,7 @@
niyuhohwusa
- + ni- (1SgSubj): ni ni- @@ -54,7 +54,7 @@
- + ni- (1SgSubj): ni ni- @@ -106,7 +106,7 @@
- + ni- (1SgSubj): ni ni- @@ -148,7 +148,7 @@ - + ni- (1SgSubj): ni ni- @@ -190,7 +190,7 @@ - + ni- (1SgSubj): ni ni- @@ -244,7 +244,7 @@ - + ni- (1SgSubj): ni ni- @@ -298,7 +298,7 @@ - + ni- (1SgSubj): ni @@ -351,7 +351,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuhohwusaStemNameNotSetFailStep01Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuhohwusaStemNameNotSetFailStep01Result.xml index fc1676a55b..cc1b3fd2bb 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuhohwusaStemNameNotSetFailStep01Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuhohwusaStemNameNotSetFailStep01Result.xml @@ -51,7 +51,7 @@ - + ni- (1SgSubj): ni ni- @@ -104,7 +104,7 @@ - + ni- (1SgSubj): ni ni- @@ -156,7 +156,7 @@ - + ni- (1SgSubj): ni ni- @@ -198,7 +198,7 @@ - + ni- (1SgSubj): ni ni- @@ -240,7 +240,7 @@ - + ni- (1SgSubj): ni ni- @@ -294,7 +294,7 @@ - + ni- (1SgSubj): ni ni- @@ -348,7 +348,7 @@ - + ni- (1SgSubj): ni @@ -401,7 +401,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuhohwusaStemNameNotSetFailStep02Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuhohwusaStemNameNotSetFailStep02Result.xml index 08977395fa..d5b334a097 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuhohwusaStemNameNotSetFailStep02Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuhohwusaStemNameNotSetFailStep02Result.xml @@ -54,7 +54,7 @@ - + ni- (1SgSubj): ni ni- @@ -109,7 +109,7 @@ - + ni- (1SgSubj): ni ni- @@ -144,7 +144,7 @@ - + ni- (1SgSubj): ni ni- @@ -179,7 +179,7 @@ - + ni- (1SgSubj): ni ni- @@ -241,7 +241,7 @@ - + ni- (1SgSubj): ni ni- @@ -298,7 +298,7 @@ - + @@ -360,7 +360,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyumamwupeStemNameSetNoFsStep00.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyumamwupeStemNameSetNoFsStep00.xml index 5001eba92b..40026135e9 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyumamwupeStemNameSetNoFsStep00.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyumamwupeStemNameSetNoFsStep00.xml @@ -1,7 +1,7 @@
niyumamwupe
- + ni- (1SgSubj): ni ni- @@ -58,7 +58,7 @@ - + ni- (1SgSubj): ni ni- diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyumamwupeStemNameSetNoFsStep00Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyumamwupeStemNameSetNoFsStep00Result.xml index 2859183ae0..76522383f2 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyumamwupeStemNameSetNoFsStep00Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyumamwupeStemNameSetNoFsStep00Result.xml @@ -1,7 +1,7 @@
niyumamwupe
- + ni- (1SgSubj): ni ni- @@ -61,7 +61,7 @@ - + ni- (1SgSubj): ni ni- @@ -120,7 +120,7 @@ - + ni- (1SgSubj): ni ni- @@ -169,7 +169,7 @@ - + ni- (1SgSubj): ni ni- @@ -218,7 +218,7 @@ - + ni- (1SgSubj): ni ni- @@ -279,7 +279,7 @@ - + ni- (1SgSubj): ni ni- @@ -340,7 +340,7 @@ - + ni- (1SgSubj): ni @@ -400,7 +400,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyumamwupeStemNameSetNoFsStep01Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyumamwupeStemNameSetNoFsStep01Result.xml index 22436d078b..27f1241040 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyumamwupeStemNameSetNoFsStep01Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyumamwupeStemNameSetNoFsStep01Result.xml @@ -58,7 +58,7 @@ - + ni- (1SgSubj): ni ni- @@ -118,7 +118,7 @@ - + ni- (1SgSubj): ni ni- @@ -177,7 +177,7 @@ - + ni- (1SgSubj): ni ni- @@ -226,7 +226,7 @@ - + ni- (1SgSubj): ni ni- @@ -275,7 +275,7 @@ - + ni- (1SgSubj): ni ni- @@ -336,7 +336,7 @@ - + ni- (1SgSubj): ni ni- @@ -397,7 +397,7 @@ - + ni- (1SgSubj): ni @@ -457,7 +457,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyumamwupeStemNameSetNoFsStep02Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyumamwupeStemNameSetNoFsStep02Result.xml index c7f4f6074c..1d10055ad8 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyumamwupeStemNameSetNoFsStep02Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyumamwupeStemNameSetNoFsStep02Result.xml @@ -61,7 +61,7 @@ - + ni- (1SgSubj): ni ni- @@ -123,7 +123,7 @@ - + ni- (1SgSubj): ni ni- @@ -165,7 +165,7 @@ - + ni- (1SgSubj): ni ni- @@ -207,7 +207,7 @@ - + ni- (1SgSubj): ni ni- @@ -276,7 +276,7 @@ - + ni- (1SgSubj): ni ni- @@ -340,7 +340,7 @@ - + @@ -408,7 +408,7 @@
- + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwukoStemNameNotSetMultiFailStep00.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwukoStemNameNotSetMultiFailStep00.xml index b8ad270fd5..9dabfa1daf 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwukoStemNameNotSetMultiFailStep00.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwukoStemNameNotSetMultiFailStep00.xml @@ -1,7 +1,7 @@
niyuwowwuko
- + ni- (1SgSubj): ni ni- @@ -51,7 +51,7 @@ - + ni- (1SgSubj): ni ni- diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwukoStemNameNotSetMultiFailStep00Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwukoStemNameNotSetMultiFailStep00Result.xml index f5b4e8712a..febea2bef6 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwukoStemNameNotSetMultiFailStep00Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwukoStemNameNotSetMultiFailStep00Result.xml @@ -1,7 +1,7 @@
niyuwowwuko
- + ni- (1SgSubj): ni ni- @@ -54,7 +54,7 @@ - + ni- (1SgSubj): ni ni- @@ -106,7 +106,7 @@ - + ni- (1SgSubj): ni ni- @@ -148,7 +148,7 @@ - + ni- (1SgSubj): ni ni- @@ -190,7 +190,7 @@ - + ni- (1SgSubj): ni ni- @@ -244,7 +244,7 @@ - + ni- (1SgSubj): ni ni- @@ -298,7 +298,7 @@ - + ni- (1SgSubj): ni @@ -351,7 +351,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwukoStemNameNotSetMultiFailStep01Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwukoStemNameNotSetMultiFailStep01Result.xml index c775c26f7e..821bbfb23e 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwukoStemNameNotSetMultiFailStep01Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwukoStemNameNotSetMultiFailStep01Result.xml @@ -51,7 +51,7 @@ - + ni- (1SgSubj): ni ni- @@ -104,7 +104,7 @@ - + ni- (1SgSubj): ni ni- @@ -156,7 +156,7 @@ - + ni- (1SgSubj): ni ni- @@ -198,7 +198,7 @@ - + ni- (1SgSubj): ni ni- @@ -240,7 +240,7 @@ - + ni- (1SgSubj): ni ni- @@ -294,7 +294,7 @@ - + ni- (1SgSubj): ni ni- @@ -348,7 +348,7 @@ - + ni- (1SgSubj): ni @@ -401,7 +401,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwukoStemNameNotSetMultiFailStep02Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwukoStemNameNotSetMultiFailStep02Result.xml index ab0a0529d3..c744994084 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwukoStemNameNotSetMultiFailStep02Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwukoStemNameNotSetMultiFailStep02Result.xml @@ -54,7 +54,7 @@ - + ni- (1SgSubj): ni ni- @@ -109,7 +109,7 @@ - + ni- (1SgSubj): ni ni- @@ -144,7 +144,7 @@ - + ni- (1SgSubj): ni ni- @@ -179,7 +179,7 @@ - + ni- (1SgSubj): ni ni- @@ -241,7 +241,7 @@ - + ni- (1SgSubj): ni ni- @@ -298,7 +298,7 @@ - + @@ -360,7 +360,7 @@
- + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwupeStemNameNotSetStep00.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwupeStemNameNotSetStep00.xml index e036ed2907..f4596d829c 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwupeStemNameNotSetStep00.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwupeStemNameNotSetStep00.xml @@ -1,7 +1,7 @@
niyuwowwupe
- + ni- (1SgSubj): ni ni- @@ -51,7 +51,7 @@ - + ni- (1SgSubj): ni ni- diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwupeStemNameNotSetStep00Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwupeStemNameNotSetStep00Result.xml index 04f070d93b..55df344e2e 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwupeStemNameNotSetStep00Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwupeStemNameNotSetStep00Result.xml @@ -1,7 +1,7 @@
niyuwowwupe
- + ni- (1SgSubj): ni ni- @@ -54,7 +54,7 @@ - + ni- (1SgSubj): ni ni- @@ -106,7 +106,7 @@ - + ni- (1SgSubj): ni ni- @@ -148,7 +148,7 @@ - + ni- (1SgSubj): ni ni- @@ -190,7 +190,7 @@ - + ni- (1SgSubj): ni ni- @@ -244,7 +244,7 @@ - + ni- (1SgSubj): ni ni- @@ -298,7 +298,7 @@ - + ni- (1SgSubj): ni @@ -351,7 +351,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwupeStemNameNotSetStep01Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwupeStemNameNotSetStep01Result.xml index afe0657162..1f8eb903d1 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwupeStemNameNotSetStep01Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwupeStemNameNotSetStep01Result.xml @@ -51,7 +51,7 @@ - + ni- (1SgSubj): ni ni- @@ -104,7 +104,7 @@ - + ni- (1SgSubj): ni ni- @@ -156,7 +156,7 @@ - + ni- (1SgSubj): ni ni- @@ -198,7 +198,7 @@ - + ni- (1SgSubj): ni ni- @@ -240,7 +240,7 @@ - + ni- (1SgSubj): ni ni- @@ -294,7 +294,7 @@ - + ni- (1SgSubj): ni ni- @@ -348,7 +348,7 @@ - + ni- (1SgSubj): ni @@ -401,7 +401,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwupeStemNameNotSetStep02Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwupeStemNameNotSetStep02Result.xml index 0a23118f92..972a8bd8c6 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwupeStemNameNotSetStep02Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuwowwupeStemNameNotSetStep02Result.xml @@ -54,7 +54,7 @@ - + ni- (1SgSubj): ni ni- @@ -109,7 +109,7 @@ - + ni- (1SgSubj): ni ni- @@ -144,7 +144,7 @@ - + ni- (1SgSubj): ni ni- @@ -179,7 +179,7 @@ - + ni- (1SgSubj): ni ni- @@ -235,7 +235,7 @@ - + ni- (1SgSubj): ni ni- @@ -292,7 +292,7 @@ - + ni- (1SgSubj): ni @@ -347,7 +347,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywupeStemNameFailStep00.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywupeStemNameFailStep00.xml index 4a221692be..061efbf2b2 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywupeStemNameFailStep00.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywupeStemNameFailStep00.xml @@ -1,7 +1,7 @@
niyuyiywupe
- + ni- (1SgSubj): ni ni- @@ -44,7 +44,7 @@ - + ni- (1SgSubj): ni ni- diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywupeStemNameFailStep00Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywupeStemNameFailStep00Result.xml index 66658380d7..9915047072 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywupeStemNameFailStep00Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywupeStemNameFailStep00Result.xml @@ -1,7 +1,7 @@
niyuyiywupe
- + ni- (1SgSubj): ni ni- @@ -47,7 +47,7 @@ - + ni- (1SgSubj): ni ni- @@ -92,7 +92,7 @@ - + ni- (1SgSubj): ni ni- @@ -127,7 +127,7 @@ - + ni- (1SgSubj): ni ni- @@ -162,7 +162,7 @@ - + ni- (1SgSubj): ni ni- @@ -209,7 +209,7 @@ - + ni- (1SgSubj): ni ni- @@ -256,7 +256,7 @@ - + ni- (1SgSubj): ni @@ -302,7 +302,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywupeStemNameFailStep01Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywupeStemNameFailStep01Result.xml index 40cce4affb..3427e1bcde 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywupeStemNameFailStep01Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywupeStemNameFailStep01Result.xml @@ -44,7 +44,7 @@ - + ni- (1SgSubj): ni ni- @@ -90,7 +90,7 @@ - + ni- (1SgSubj): ni ni- @@ -135,7 +135,7 @@ - + ni- (1SgSubj): ni ni- @@ -170,7 +170,7 @@ - + ni- (1SgSubj): ni ni- @@ -205,7 +205,7 @@ - + ni- (1SgSubj): ni ni- @@ -252,7 +252,7 @@ - + ni- (1SgSubj): ni ni- @@ -299,7 +299,7 @@ - + ni- (1SgSubj): ni @@ -345,7 +345,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywupeStemNameFailStep02Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywupeStemNameFailStep02Result.xml index 2d20502bbe..b8eaa8456d 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywupeStemNameFailStep02Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywupeStemNameFailStep02Result.xml @@ -54,7 +54,7 @@ - + ni- (1SgSubj): ni ni- @@ -109,7 +109,7 @@ - + ni- (1SgSubj): ni ni- @@ -144,7 +144,7 @@ - + ni- (1SgSubj): ni ni- @@ -179,7 +179,7 @@ - + ni- (1SgSubj): ni ni- @@ -241,7 +241,7 @@ - + ni- (1SgSubj): ni ni- @@ -298,7 +298,7 @@ - + @@ -360,7 +360,7 @@
- + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywusaStemNameSetStep00.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywusaStemNameSetStep00.xml index fd121c0938..55fab4b21e 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywusaStemNameSetStep00.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywusaStemNameSetStep00.xml @@ -1,7 +1,7 @@
niyuyiywusa
- + ni- (1SgSubj): ni ni- @@ -58,7 +58,7 @@ - + ni- (1SgSubj): ni ni- diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywusaStemNameSetStep00Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywusaStemNameSetStep00Result.xml index d184b6de3c..fa9eeb9e91 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywusaStemNameSetStep00Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywusaStemNameSetStep00Result.xml @@ -1,7 +1,7 @@
niyuyiywusa
- + ni- (1SgSubj): ni ni- @@ -61,7 +61,7 @@ - + ni- (1SgSubj): ni ni- @@ -120,7 +120,7 @@ - + ni- (1SgSubj): ni ni- @@ -169,7 +169,7 @@ - + ni- (1SgSubj): ni ni- @@ -218,7 +218,7 @@ - + ni- (1SgSubj): ni ni- @@ -279,7 +279,7 @@ - + ni- (1SgSubj): ni ni- @@ -340,7 +340,7 @@ - + ni- (1SgSubj): ni @@ -400,7 +400,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywusaStemNameSetStep01Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywusaStemNameSetStep01Result.xml index b976173b30..a486e9fd4d 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywusaStemNameSetStep01Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywusaStemNameSetStep01Result.xml @@ -58,7 +58,7 @@ - + ni- (1SgSubj): ni ni- @@ -118,7 +118,7 @@ - + ni- (1SgSubj): ni ni- @@ -177,7 +177,7 @@ - + ni- (1SgSubj): ni ni- @@ -226,7 +226,7 @@ - + ni- (1SgSubj): ni ni- @@ -275,7 +275,7 @@ - + ni- (1SgSubj): ni ni- @@ -336,7 +336,7 @@ - + ni- (1SgSubj): ni ni- @@ -397,7 +397,7 @@ - + ni- (1SgSubj): ni @@ -457,7 +457,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywusaStemNameSetStep02Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywusaStemNameSetStep02Result.xml index 7a46f60c0f..6b348fd9f4 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywusaStemNameSetStep02Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiywusaStemNameSetStep02Result.xml @@ -61,7 +61,7 @@ - + ni- (1SgSubj): ni ni- @@ -123,7 +123,7 @@ - + ni- (1SgSubj): ni ni- @@ -165,7 +165,7 @@ - + ni- (1SgSubj): ni ni- @@ -207,7 +207,7 @@ - + ni- (1SgSubj): ni ni- @@ -276,7 +276,7 @@ - + ni- (1SgSubj): ni ni- @@ -340,7 +340,7 @@ - + @@ -408,7 +408,7 @@
- + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep00.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep00.xml index 2087bee027..72f6100a28 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep00.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep00.xml @@ -1,7 +1,7 @@
niyuyiyximuwupe
- + ni- (1SgSubj): ni ni- @@ -58,7 +58,7 @@ - + ni- (1SgSubj): ni ni- @@ -116,7 +116,7 @@ - + ni- (1SgSubj): ni ni- @@ -173,7 +173,7 @@ - + ni- (1SgSubj): ni ni- diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep00Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep00Result.xml index 76b4b0a16a..442e6e0af0 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep00Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep00Result.xml @@ -1,7 +1,7 @@
niyuyiyximuwupe
- + ni- (1SgSubj): ni ni- @@ -60,7 +60,7 @@ - + ni- (1SgSubj): ni ni- @@ -120,7 +120,7 @@ - + ni- (1SgSubj): ni ni- @@ -180,7 +180,7 @@ - + ni- (1SgSubj): ni ni- @@ -241,7 +241,7 @@ - + ni- (1SgSubj): ni ni- @@ -301,7 +301,7 @@ - + ni- (1SgSubj): ni ni- @@ -361,7 +361,7 @@ - + ni- (1SgSubj): ni ni- @@ -421,7 +421,7 @@ - + ni- (1SgSubj): ni ni- @@ -482,7 +482,7 @@ - + ni- (1SgSubj): ni ni- diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep01Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep01Result.xml index 040b345214..c82f66ecb6 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep01Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep01Result.xml @@ -58,7 +58,7 @@ - + ni- (1SgSubj): ni ni- @@ -117,7 +117,7 @@ - + ni- (1SgSubj): ni ni- diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep02Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep02Result.xml index d14ff67608..b3fc4f534d 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep02Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep02Result.xml @@ -60,7 +60,7 @@ - + ni- (1SgSubj): ni ni- @@ -120,7 +120,7 @@ - + ni- (1SgSubj): ni ni- @@ -194,7 +194,7 @@ - + ni- (1SgSubj): ni ni- @@ -280,7 +280,7 @@ - + ni- (1SgSubj): ni ni- @@ -366,7 +366,7 @@ - + ni- (1SgSubj): ni ni- @@ -428,7 +428,7 @@ - + ni- (1SgSubj): ni ni- @@ -514,7 +514,7 @@ - + ni- (1SgSubj): ni ni- @@ -600,7 +600,7 @@ - + ni- (1SgSubj): ni ni- diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep03Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep03Result.xml index df58d177cb..5094cd5e1d 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep03Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep03Result.xml @@ -63,7 +63,7 @@ - + ni- (1SgSubj): ni ni- @@ -128,7 +128,7 @@ - + ni- (1SgSubj): ni ni- @@ -192,7 +192,7 @@ - + ni- (1SgSubj): ni ni- @@ -234,7 +234,7 @@ - + ni- (1SgSubj): ni ni- @@ -276,7 +276,7 @@ - + ni- (1SgSubj): ni ni- @@ -342,7 +342,7 @@ - + ni- (1SgSubj): ni ni- @@ -408,7 +408,7 @@ - + A stem allomorph belongs to Stem Name 'Present tense or 2nd Person' so the word must be inflected for certain features, but it is not. The possible feature sets it must be inflected for are: [absolute tense:present tense] or [subject agreement:[person:second person]]. The inflected features for this word are: (none). @@ -474,7 +474,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep04Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep04Result.xml index 4501025379..6f3a6e4734 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep04Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwupeStemNameNotSetCompoundFailStep04Result.xml @@ -66,7 +66,7 @@ - + ni- (1SgSubj): ni ni- @@ -133,7 +133,7 @@ - + ni- (1SgSubj): ni ni- @@ -168,7 +168,7 @@ - + ni- (1SgSubj): ni ni- @@ -203,7 +203,7 @@ - + ni- (1SgSubj): ni ni- @@ -277,7 +277,7 @@ - + ni- (1SgSubj): ni ni- @@ -346,7 +346,7 @@ - + @@ -420,7 +420,7 @@
- + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep00.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep00.xml index 907d5d3cae..2c9e693d9a 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep00.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep00.xml @@ -1,7 +1,7 @@
niyuyiyximuwusa
- + ni- (1SgSubj): ni ni- @@ -65,7 +65,7 @@ - + ni- (1SgSubj): ni ni- @@ -130,7 +130,7 @@ - + ni- (1SgSubj): ni ni- @@ -194,7 +194,7 @@ - + ni- (1SgSubj): ni ni- diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep00Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep00Result.xml index 15b6f4fda4..a7d5881c56 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep00Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep00Result.xml @@ -1,7 +1,7 @@
niyuyiyximuwusa
- + ni- (1SgSubj): ni ni- @@ -67,7 +67,7 @@ - + ni- (1SgSubj): ni ni- @@ -134,7 +134,7 @@ - + ni- (1SgSubj): ni ni- @@ -201,7 +201,7 @@ - + ni- (1SgSubj): ni ni- @@ -269,7 +269,7 @@ - + ni- (1SgSubj): ni ni- @@ -336,7 +336,7 @@ - + ni- (1SgSubj): ni ni- @@ -403,7 +403,7 @@ - + ni- (1SgSubj): ni ni- @@ -470,7 +470,7 @@ - + ni- (1SgSubj): ni ni- @@ -538,7 +538,7 @@ - + ni- (1SgSubj): ni ni- diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep01Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep01Result.xml index f714690124..a8a9de49bf 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep01Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep01Result.xml @@ -65,7 +65,7 @@ - + ni- (1SgSubj): ni ni- @@ -131,7 +131,7 @@ - + ni- (1SgSubj): ni ni- diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep02Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep02Result.xml index 21f34e46cb..60e6def4fa 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep02Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep02Result.xml @@ -67,7 +67,7 @@ - + ni- (1SgSubj): ni ni- @@ -134,7 +134,7 @@ - + ni- (1SgSubj): ni ni- @@ -215,7 +215,7 @@ - + ni- (1SgSubj): ni ni- @@ -308,7 +308,7 @@ - + ni- (1SgSubj): ni ni- @@ -401,7 +401,7 @@ - + ni- (1SgSubj): ni ni- @@ -470,7 +470,7 @@ - + ni- (1SgSubj): ni ni- @@ -563,7 +563,7 @@ - + ni- (1SgSubj): ni ni- @@ -656,7 +656,7 @@ - + ni- (1SgSubj): ni ni- diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep03Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep03Result.xml index 8c8c470d02..663436b0b4 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep03Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep03Result.xml @@ -70,7 +70,7 @@ - + ni- (1SgSubj): ni ni- @@ -142,7 +142,7 @@ - + ni- (1SgSubj): ni ni- @@ -213,7 +213,7 @@ - + ni- (1SgSubj): ni ni- @@ -262,7 +262,7 @@ - + ni- (1SgSubj): ni ni- @@ -311,7 +311,7 @@ - + ni- (1SgSubj): ni ni- @@ -384,7 +384,7 @@ - + ni- (1SgSubj): ni ni- @@ -457,7 +457,7 @@ - + A stem allomorph belongs to Stem Name 'Present tense or 2nd Person' so the word must be inflected for certain features, but it is not. The possible feature sets it must be inflected for are: [absolute tense:present tense] or [subject agreement:[person:second person]]. The inflected features for this word are: (none). @@ -530,7 +530,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep04Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep04Result.xml index a82e3d4fcd..09832e1310 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep04Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/niyuyiyximuwusaStemNameSetCompoundStep04Result.xml @@ -73,7 +73,7 @@ - + ni- (1SgSubj): ni ni- @@ -147,7 +147,7 @@ - + ni- (1SgSubj): ni ni- @@ -189,7 +189,7 @@ - + ni- (1SgSubj): ni ni- @@ -231,7 +231,7 @@ - + ni- (1SgSubj): ni ni- @@ -312,7 +312,7 @@ - + ni- (1SgSubj): ni ni- @@ -388,7 +388,7 @@ - + @@ -468,7 +468,7 @@
- + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwupeStemNameSetMultiFsFailStep00.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwupeStemNameSetMultiFsFailStep00.xml index 297c84fee8..8b155c7394 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwupeStemNameSetMultiFsFailStep00.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwupeStemNameSetMultiFsFailStep00.xml @@ -1,7 +1,7 @@
timikikwupe
- + ti- (2SgSubj): ti ti- @@ -51,7 +51,7 @@ - + ti- (2SgSubj): ti ti- diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwupeStemNameSetMultiFsFailStep00Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwupeStemNameSetMultiFsFailStep00Result.xml index eba840ed4a..a032ae27b3 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwupeStemNameSetMultiFsFailStep00Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwupeStemNameSetMultiFsFailStep00Result.xml @@ -1,7 +1,7 @@
timikikwupe
- + ti- (2SgSubj): ti ti- @@ -54,7 +54,7 @@ - + ti- (2SgSubj): ti ti- @@ -106,7 +106,7 @@ - + ti- (2SgSubj): ti ti- @@ -148,7 +148,7 @@ - + ti- (2SgSubj): ti ti- @@ -190,7 +190,7 @@ - + ti- (2SgSubj): ti ti- @@ -244,7 +244,7 @@ - + ti- (2SgSubj): ti ti- @@ -298,7 +298,7 @@ - + ti- (2SgSubj): ti @@ -351,7 +351,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwupeStemNameSetMultiFsFailStep01Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwupeStemNameSetMultiFsFailStep01Result.xml index 831c3b180b..f191b6bbe3 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwupeStemNameSetMultiFsFailStep01Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwupeStemNameSetMultiFsFailStep01Result.xml @@ -51,7 +51,7 @@ - + ti- (2SgSubj): ti ti- @@ -104,7 +104,7 @@ - + ti- (2SgSubj): ti ti- @@ -156,7 +156,7 @@ - + ti- (2SgSubj): ti ti- @@ -198,7 +198,7 @@ - + ti- (2SgSubj): ti ti- @@ -240,7 +240,7 @@ - + ti- (2SgSubj): ti ti- @@ -294,7 +294,7 @@ - + ti- (2SgSubj): ti ti- @@ -348,7 +348,7 @@ - + ti- (2SgSubj): ti @@ -401,7 +401,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwupeStemNameSetMultiFsFailStep02Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwupeStemNameSetMultiFsFailStep02Result.xml index bbd16a76f9..58fb8c9f82 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwupeStemNameSetMultiFsFailStep02Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwupeStemNameSetMultiFsFailStep02Result.xml @@ -54,7 +54,7 @@ - + ti- (2SgSubj): ti ti- @@ -109,7 +109,7 @@ - + ti- (2SgSubj): ti ti- @@ -144,7 +144,7 @@ - + ti- (2SgSubj): ti ti- @@ -179,7 +179,7 @@ - + ti- (2SgSubj): ti ti- @@ -241,7 +241,7 @@ - + ti- (2SgSubj): ti ti- @@ -298,7 +298,7 @@ - + @@ -360,7 +360,7 @@
- + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwusaStemNameSetMultiFsStep00.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwusaStemNameSetMultiFsStep00.xml index 5738f1f3df..e52ceeffd3 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwusaStemNameSetMultiFsStep00.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwusaStemNameSetMultiFsStep00.xml @@ -1,7 +1,7 @@
timikikwusa
- + ti- (2SgSubj): ti ti- @@ -58,7 +58,7 @@ - + ti- (2SgSubj): ti ti- diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwusaStemNameSetMultiFsStep00Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwusaStemNameSetMultiFsStep00Result.xml index b412a0325d..4b44f9c07e 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwusaStemNameSetMultiFsStep00Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwusaStemNameSetMultiFsStep00Result.xml @@ -1,7 +1,7 @@
timikikwusa
- + ti- (2SgSubj): ti ti- @@ -61,7 +61,7 @@ - + ti- (2SgSubj): ti ti- @@ -120,7 +120,7 @@ - + ti- (2SgSubj): ti ti- @@ -169,7 +169,7 @@ - + ti- (2SgSubj): ti ti- @@ -218,7 +218,7 @@ - + ti- (2SgSubj): ti ti- @@ -279,7 +279,7 @@ - + ti- (2SgSubj): ti ti- @@ -340,7 +340,7 @@ - + ti- (2SgSubj): ti @@ -400,7 +400,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwusaStemNameSetMultiFsStep01Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwusaStemNameSetMultiFsStep01Result.xml index 494d4bd474..0fbd0dad7e 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwusaStemNameSetMultiFsStep01Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwusaStemNameSetMultiFsStep01Result.xml @@ -58,7 +58,7 @@ - + ti- (2SgSubj): ti ti- @@ -118,7 +118,7 @@ - + ti- (2SgSubj): ti ti- @@ -177,7 +177,7 @@ - + ti- (2SgSubj): ti ti- @@ -226,7 +226,7 @@ - + ti- (2SgSubj): ti ti- @@ -275,7 +275,7 @@ - + ti- (2SgSubj): ti ti- @@ -336,7 +336,7 @@ - + ti- (2SgSubj): ti ti- @@ -397,7 +397,7 @@ - + ti- (2SgSubj): ti @@ -457,7 +457,7 @@ - + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwusaStemNameSetMultiFsStep02Result.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwusaStemNameSetMultiFsStep02Result.xml index fb2f16ca1f..0745c95fad 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwusaStemNameSetMultiFsStep02Result.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/timikikwusaStemNameSetMultiFsStep02Result.xml @@ -61,7 +61,7 @@ - + ti- (2SgSubj): ti ti- @@ -123,7 +123,7 @@ - + ti- (2SgSubj): ti ti- @@ -165,7 +165,7 @@ - + ti- (2SgSubj): ti ti- @@ -207,7 +207,7 @@ - + ti- (2SgSubj): ti ti- @@ -276,7 +276,7 @@ - + ti- (2SgSubj): ti ti- @@ -340,7 +340,7 @@ - + @@ -408,7 +408,7 @@
- + The category (bitrans) of the inflectional template "Bitransitive verb" is incompatible with the category (trans) of the stem. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/yalotetuStep01.xml b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/yalotetuStep01.xml index af66f92841..94fa55e02f 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/yalotetuStep01.xml +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/yalotetuStep01.xml @@ -1,7 +1,7 @@
yalotetu
- + yalo (mat): yalo @@ -41,7 +41,7 @@ - + A root can only be a "Partial" when its category is unknown, but the category here is 'N'. diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingTests.cs b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingTests.cs index 54d3133f0a..2ff2489bc7 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingTests.cs +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingTests.cs @@ -6,12 +6,10 @@ // Responsibility: using System; -using System.Collections.Generic; -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.IO; using System.Text; -using System.Xml; #if __MonoCS__ using System.Xml.Linq; #endif @@ -60,10 +58,6 @@ public class WordGrammarDebuggingTests : BaseTest ///
protected string m_sTestPath; /// - protected string m_sTransformPath; - /// - protected string m_sMasterTransform; - /// protected string m_sResultTransform; /// protected string m_sResultTransformNoCompoundRules; @@ -80,9 +74,9 @@ public class WordGrammarDebuggingTests : BaseTest /// protected string m_sM3FXTDumpAffixAlloFeats; /// Set to true to be able to debug into stylesheets - private bool m_fDebug; + private readonly bool m_fDebug; /// path to the standard directory for temporary files. - private string m_sTempPath; + private readonly string m_sTempPath; /// ------------------------------------------------------------------------------------ /// /// Initializes a new instance of the class. @@ -110,19 +104,17 @@ public override void FixtureSetup() base.FixtureSetup(); m_sTestPath = Path.Combine(FwDirectoryFinder.SourceDirectory, "LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults"); - m_sTransformPath = Path.Combine(FwDirectoryFinder.CodeDirectory, - "Language Explorer/Transforms"); SetUpMasterTransform(); - CreateResultTransform("M3FXTDump.xml", ref m_sResultTransform); + CreateResultTransform("M3FXTDump.xml", out m_sResultTransform); SetUpResultTransform(m_sResultTransform, out m_resultTransform); SetUpUnificationViaXsltTransform(); SetUpSameSlotTwiceTransform(); - CreateResultTransform("M3FXTDumpNoCompoundRules.xml", ref m_sResultTransformNoCompoundRules); + CreateResultTransform("M3FXTDumpNoCompoundRules.xml", out m_sResultTransformNoCompoundRules); SetUpResultTransform(m_sResultTransformNoCompoundRules, out m_resultTransformNoCompoundRules); - CreateResultTransform("M3FXTDumpStemNames.xml", ref m_sResultTransformStemNames); + CreateResultTransform("M3FXTDumpStemNames.xml", out m_sResultTransformStemNames); SetUpResultTransform(m_sResultTransformStemNames, out m_resultTransformStemNames); - CreateResultTransform("M3FXTDumpAffixAlloFeats.xml", ref m_sResultTransformAffixAlloFeats); + CreateResultTransform("M3FXTDumpAffixAlloFeats.xml", out m_sResultTransformAffixAlloFeats); SetUpResultTransform(m_sResultTransformAffixAlloFeats, out m_resultTransformAffixAlloFeats); } @@ -258,12 +250,12 @@ private void SetUpSameSlotTwiceTransform() /// Creates a result transform. /// /// ------------------------------------------------------------------------------------ - private void CreateResultTransform(string sFXTDumpFile, ref string sResultTransform) + private void CreateResultTransform(string fxtDumpFile, out string resultTransform) { - sResultTransform = FileUtils.GetTempFile("xsl"); - string sFXTDump = Path.Combine(m_sTestPath, sFXTDumpFile); - SIL.Utils.XmlUtils.TransformFileToFile(m_sMasterTransform, sFXTDump, - sResultTransform); + resultTransform = FileUtils.GetTempFile("xsl"); + string fxtDump = Path.Combine(m_sTestPath, fxtDumpFile); + using (var writer = new StreamWriter(resultTransform)) + m_masterTransform.Transform(fxtDump, null, writer); } /// ------------------------------------------------------------------------------------ @@ -273,14 +265,7 @@ private void CreateResultTransform(string sFXTDumpFile, ref string sResultTransf /// ------------------------------------------------------------------------------------ private void SetUpMasterTransform() { - m_sMasterTransform = Path.Combine(m_sTransformPath, - "FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl"); -#if __MonoCS__ - m_masterTransform = SIL.Utils.LibXslt.CompileTransform(m_sMasterTransform); -#else - m_masterTransform = new XslCompiledTransform(); - m_masterTransform.Load(m_sMasterTransform); -#endif + m_masterTransform = XmlUtils.CreateTransform("FxtM3ParserToXAmpleWordGrammarDebuggingXSLT", "ApplicationTransforms"); } #endregion @@ -305,50 +290,28 @@ private void ApplyTransform(string sInputFile, string sExpectedOutput) /// The expected output filename. /// The transform. /// ------------------------------------------------------------------------------------ - private void ApplyTransform(string sInputFile, string sExpectedOutput, - XslCompiledTransform transform) - { - ApplyTransform(sInputFile, sExpectedOutput, transform, true); - } - private void ApplyTransform(string sInputFile, string sExpectedOutput, - IntPtr transform) - { - ApplyTransform(sInputFile, sExpectedOutput, transform, true); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Applies the transform. - /// - /// The input file filename. - /// The expected output filename. - /// The transform. - /// remove Msxsl namespace - /// ------------------------------------------------------------------------------------ - private void ApplyTransform(string sInputFile, string sExpectedOutput, - XslCompiledTransform transform, bool fFixMsxslNameSpace) + private void ApplyTransform(string sInputFile, string sExpectedOutput, XslCompiledTransform transform) { string sInput = Path.Combine(m_sTestPath, sInputFile); m_doc = new XPathDocument(sInput); string sOutput = FileUtils.GetTempFile("xml"); - using (StreamWriter result = new StreamWriter(sOutput)) + using (var result = new StreamWriter(sOutput)) { transform.Transform(m_doc, null, result); result.Close(); string sExpectedResult = Path.Combine(m_sTestPath, sExpectedOutput); - CheckXmlEquals(sExpectedResult, sOutput, fFixMsxslNameSpace); + CheckXmlEquals(sExpectedResult, sOutput); // by deleting it here instead of a finally block, when it fails, we can see what the result is. File.Delete(sOutput); } } - private void ApplyTransform(string sInputFile, string sExpectedOutput, - IntPtr transform, bool fFixMsxslNameSpace) + private void ApplyTransform(string sInputFile, string sExpectedOutput, IntPtr transform) { string sInput = Path.Combine(m_sTestPath, sInputFile); string sOutput = FileUtils.GetTempFile("xml"); SIL.Utils.LibXslt.TransformFileToFile(transform, sInput, sOutput); string sExpectedResult = Path.Combine(m_sTestPath, sExpectedOutput); - CheckXmlEquals(sExpectedResult, sOutput, fFixMsxslNameSpace); + CheckXmlEquals(sExpectedResult, sOutput); // by deleting it here instead of a finally block, when it fails, we can see what the result is. File.Delete(sOutput); } @@ -359,39 +322,27 @@ private void ApplyTransform(string sInputFile, string sExpectedOutput, ///
/// The expected result filename. /// The actual result filename. - /// remove Msxsl namespace /// ------------------------------------------------------------------------------------ - private void CheckXmlEquals(string sExpectedResultFile, string sActualResultFile, bool fFixMsxslNameSpace) + private void CheckXmlEquals(string sExpectedResultFile, string sActualResultFile) { string sExpected, sActual; - using (StreamReader expected = new StreamReader(sExpectedResultFile)) + using (var expected = new StreamReader(sExpectedResultFile)) sExpected = expected.ReadToEnd(); - using (StreamReader actual = new StreamReader(sActualResultFile)) + using (var actual = new StreamReader(sActualResultFile)) sActual = actual.ReadToEnd(); - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.Append("Expected file was "); sb.AppendLine(sExpectedResultFile); sb.Append("Actual file was "); sb.AppendLine(sActualResultFile); #if __MonoCS__ // REVIEW: Perhaps we should always use the fancy compare method using XElement objects? - if (fFixMsxslNameSpace) - sActual = sActual.Replace(" xmlns:auto-ns1=\"urn:schemas-microsoft-com:xslt\"", ""); XElement xeActual = XElement.Parse(sActual, LoadOptions.None); XElement xeExpected = XElement.Parse(sExpected, LoadOptions.None); bool ok = XmlHelper.EqualXml(xeExpected, xeActual, sb); Assert.IsTrue(ok, sb.ToString()); #else - if (fFixMsxslNameSpace) - { - string sFixMsxslNameSpace = - sActual.Replace(" xmlns:auto-ns1=\"urn:schemas-microsoft-com:xslt\"", ""); - Assert.AreEqual(sExpected, sFixMsxslNameSpace, sb.ToString()); - } - else - { - Assert.AreEqual(sExpected, sActual, sb.ToString()); - } + Assert.AreEqual(sExpected, sActual, sb.ToString()); #endif } #endregion @@ -713,7 +664,7 @@ public void StemNames() private void DoWordGrammarDebuggerSteps(string sName, int count, XslCompiledTransform transform) { for (int i = 0; i < count; i++) - ApplyTransform(sName + "Step0" + i.ToString() + ".xml", sName + "Step0" + i.ToString() + "Result.xml", m_resultTransformStemNames, false); + ApplyTransform(sName + "Step0" + i.ToString(CultureInfo.InvariantCulture) + ".xml", sName + "Step0" + i.ToString(CultureInfo.InvariantCulture) + "Result.xml", m_resultTransformStemNames); } private void DoWordGrammarDebuggerSteps(string sName, int count, IntPtr transform) { @@ -721,7 +672,7 @@ private void DoWordGrammarDebuggerSteps(string sName, int count, IntPtr transfor { var inputName = String.Format("{0}Step0{1}.xml", sName, i); var outputName = String.Format("{0}Step0{1}Result.xml", sName, i); - ApplyTransform(inputName, outputName, m_resultTransformStemNames, false); + ApplyTransform(inputName, outputName, m_resultTransformStemNames); } } @@ -731,7 +682,7 @@ private void DoWordGrammarDebuggerSteps(string sName, int count, IntPtr transfor ///
/// ------------------------------------------------------------------------------------ [Test] - public void UnificationViaXSLT() + public void UnificationViaXslt() { ApplyTransform("TestFeatureStructureUnification.xml", "TestFeatureStructureUnification.xml", m_UnificationViaXsltTransform); diff --git a/Src/Transforms/Application/FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl b/Src/Transforms/Application/FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl index 709433e8d8..18122f6147 100644 --- a/Src/Transforms/Application/FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl +++ b/Src/Transforms/Application/FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl @@ -1,9 +1,6 @@ + xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="exsl"> 1.0 - - - - - - - - - - - + + exsl xml 1.0 @@ -1346,16 +1334,16 @@ Ignore text template loop through the features of both feature structures at same time, sorted by name - + get name of this feature get this feature if it's in the first feature structure - + get this feature if it's in the second feature structure - + both feature1 and feature2 have this feature name @@ -1436,14 +1424,14 @@ Ignore text template - + Empty and - + Empty @@ -1452,16 +1440,16 @@ Ignore text template loop through the features of both feature structures at same time, sorted by name - + get name of this feature get this feature if it's in the first feature structure - + get this feature if it's in the second feature structure - + both feature1 and feature2 have this feature name @@ -1594,7 +1582,7 @@ Ignore text template - + @@ -1642,7 +1630,7 @@ Ignore text template - + @@ -1812,8 +1800,8 @@ Ignore text template - - + + @@ -1844,7 +1832,7 @@ Ignore text template . The inflected features for this word are: - + @@ -2762,15 +2750,15 @@ Ignore text template - - + + - - + + @@ -2801,7 +2789,7 @@ Ignore text template . The inflected features for this are: - + @@ -2832,7 +2820,7 @@ Ignore text template . The inflected features for this are: - + @@ -2868,18 +2856,18 @@ Ignore text template - + Override those unified features with deriv to features - + - + @@ -3842,7 +3830,7 @@ OutputElsewhereChecksForStemNamesUsedInLexicalEntries . The inflected features for this word are: - + @@ -4025,8 +4013,8 @@ OutputMultipleStemNameRegionsSubsumptionChecks - - + + @@ -4349,9 +4337,9 @@ ProcessInflectionalTemplatePercolationAndConstraints - - - + + + @@ -4375,7 +4363,7 @@ ProcessInflectionalTemplatePercolationAndConstraints - + @@ -4402,7 +4390,7 @@ ProcessInflectionalTemplatePercolationAndConstraints - + @@ -4417,11 +4405,11 @@ ProcessInflectionalTemplatePercolationAndConstraints - + - + diff --git a/Src/Utilities/XMLUtils/XmlUtils.cs b/Src/Utilities/XMLUtils/XmlUtils.cs index b01fbc5afa..578652dd28 100644 --- a/Src/Utilities/XMLUtils/XmlUtils.cs +++ b/Src/Utilities/XMLUtils/XmlUtils.cs @@ -1096,7 +1096,7 @@ public static XslCompiledTransform CreateTransform(string xslName, string assemb Debug.Assert(type != null); transform.Load(type); #else - transform.Load(Path.Combine(TransformPath, xslName + ".xls"), new XsltSettings(true, false), new XmlUrlResolver()); + //transform.Load(Path.Combine(TransformPath, xslName + ".xls"), new XsltSettings(true, false), new XmlUrlResolver()); #endif return transform; } From 0d020ca7a1be886545441a31f3ac686473cd3fd3 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Thu, 20 Feb 2014 11:51:50 +0700 Subject: [PATCH 088/143] Fixing export of XLing Paper Change-Id: Ib9e94498d2af6626885a6dae5e3352d1c251b51b --- .../Export Templates}/XLingPaperForXXE.xsl | 0 .../XMLUtils/XMLUtilsTests/XmlUtilsTest.cs | 72 ---------- Src/Utilities/XMLUtils/XmlUtils.cs | 128 ------------------ Src/xWorks/GeneratedHtmlViewer.cs | 66 ++++++--- 4 files changed, 46 insertions(+), 220 deletions(-) rename {Src/Transforms/Presentation => DistFiles/Language Explorer/Export Templates}/XLingPaperForXXE.xsl (100%) diff --git a/Src/Transforms/Presentation/XLingPaperForXXE.xsl b/DistFiles/Language Explorer/Export Templates/XLingPaperForXXE.xsl similarity index 100% rename from Src/Transforms/Presentation/XLingPaperForXXE.xsl rename to DistFiles/Language Explorer/Export Templates/XLingPaperForXXE.xsl diff --git a/Src/Utilities/XMLUtils/XMLUtilsTests/XmlUtilsTest.cs b/Src/Utilities/XMLUtils/XMLUtilsTests/XmlUtilsTest.cs index 2f633e4235..e848cafdf1 100644 --- a/Src/Utilities/XMLUtils/XMLUtilsTests/XmlUtilsTest.cs +++ b/Src/Utilities/XMLUtils/XMLUtilsTests/XmlUtilsTest.cs @@ -9,12 +9,7 @@ // // -using System; -using System.IO; -using System.Xml; -using System.Text; using NUnit.Framework; -using SIL.Utils; namespace SIL.Utils { @@ -58,73 +53,6 @@ public void GetBooleanAttributeValueTest() Assert.IsTrue(XmlUtils.GetBooleanAttributeValue("Yes"), "'Yes' returns true"); Assert.IsTrue(XmlUtils.GetBooleanAttributeValue("yes"), "'yes' returns true"); } - [Test] - public void TransformFileToFileWithParametersTest() - { - // set up transform (use local copy so don't have to keep it in sync with the real one) - string sTransform = Path.Combine(m_sTestPath, "Test.xsl"); - // build parameter list - XmlUtils.XSLParameter[] parameterList = new XmlUtils.XSLParameter[2]; - parameterList[0] = new XmlUtils.XSLParameter("prmiNumber", "10"); - parameterList[1] = new XmlUtils.XSLParameter("prmsNumber", "ten"); - // use local input file - string sInput = Path.Combine(m_sTestPath, "Test.xml"); - // create temp output file - string sResult = FileUtils.GetTempFile("xml"); - // do transform - XmlUtils.TransformFileToFile(sTransform, parameterList, sInput, sResult); - // check results - string sExpected; - if (XmlUtils.UsingDotNetTransforms()) - sExpected = "ResultWithParams.xml"; - else - sExpected = "ResultWithParamsMSXML2.xml"; - if (Environment.OSVersion.Platform == PlatformID.Unix) // Mono puts a newline in a different place - sExpected = "ResultWithParams-Linux.xml"; - CheckXmlEquals(Path.Combine(m_sTestPath, sExpected), sResult); - if (File.Exists(sResult)) - File.Delete(sResult); - } - [Test] - public void TransformFileToFileNoParametersTest() - { - // set up transform (use local copy so don't have to keep it in sync with the real one) - string sTransform = Path.Combine(m_sTestPath, "Test.xsl"); - // use local input file - string sInput = Path.Combine(m_sTestPath, "Test.xml"); - // create temp output file - string sResult = FileUtils.GetTempFile("xml"); - // do transform - SIL.Utils.XmlUtils.TransformFileToFile(sTransform, sInput, sResult); - // check results - string sExpected; - if (SIL.Utils.XmlUtils.UsingDotNetTransforms()) - sExpected = "ResultNoParams.xml"; - else if (SIL.Utils.XmlUtils.UsingMSXML2Transforms()) - sExpected = "ResultNoParamsMSXML2.xml"; - else - sExpected = "ResultNoParams-Linux.xml"; - CheckXmlEquals(Path.Combine(m_sTestPath, sExpected), sResult); - if (File.Exists(sResult)) - File.Delete(sResult); - } - private void CheckXmlEquals(string sExpectedResultFile, string sActualResultFile) - { - using (var expected = new StreamReader(sExpectedResultFile)) - { - using (var actual = new StreamReader(sActualResultFile)) - { - string sExpected = expected.ReadToEnd(); - string sActual = actual.ReadToEnd(); - StringBuilder sb = new StringBuilder(); - sb.Append("Expected file was "); - sb.Append(sExpectedResultFile); - Assert.AreEqual(sExpected, sActual, sb.ToString()); - expected.Close(); - actual.Close(); - } - } - } [Test] public void MakeSafeXmlAttributeTest() diff --git a/Src/Utilities/XMLUtils/XmlUtils.cs b/Src/Utilities/XMLUtils/XmlUtils.cs index 578652dd28..4a15edc42b 100644 --- a/Src/Utilities/XMLUtils/XmlUtils.cs +++ b/Src/Utilities/XMLUtils/XmlUtils.cs @@ -24,7 +24,6 @@ using System.Xml; using System.Globalization; using System.Xml.Serialization; -using System.Windows.Forms; using System.Xml.Xsl; namespace SIL.Utils @@ -429,36 +428,6 @@ public static XmlNode GetFirstNonCommentChild(XmlNode node) return child; return null; } - /// - /// Apply an XSLT transform on a DOM to produce a resulting file - /// - /// full path name of the XSLT transform - /// XmlDocument DOM containing input to be transformed - /// full path of the resulting output file - public static void TransformDomToFile(string sTransformName, XmlDocument inputDOM, string sOutputName) - { - string sTempInput = FileUtils.GetTempFile("xml"); - try - { - inputDOM.Save(sTempInput); - TransformFileToFile(sTransformName, sTempInput, sOutputName); - } - finally - { - if (File.Exists(sTempInput)) - File.Delete(sTempInput); - } - } - /// - /// Apply an XSLT transform on a file to produce a resulting file - /// - /// full path name of the XSLT transform - /// full path of the input file - /// full path of the resulting output file - public static void TransformFileToFile(string sTransformName, string sInputPath, string sOutputName) - { - TransformFileToFile(sTransformName, null, sInputPath, sOutputName); - } /// /// Convert an encoded string (safe XML) into plain text. @@ -829,103 +798,6 @@ static protected string MakeGetStaticMethodErrorMessage(string sMainMsg, string return sResult; } - /// - /// Apply an XSLT transform on a file to produce a resulting file - /// - /// full path name of the XSLT transform - /// list of parameters to pass to the transform - /// full path of the input file - /// full path of the resulting output file - public static void TransformFileToFile(string sTransformName, XSLParameter[] parameterList, string sInputPath, string sOutputName) - { -#if DEBUG - Debug.WriteLine("Transform: " + sTransformName + " input file: " + sInputPath); - DateTime start = DateTime.Now; - Debug.WriteLine("\tStarting at: " + start.TimeOfDay.ToString()); -#endif -#if UsingDotNetTransforms - // set up transform - XslCompiledTransform transformer = new XslCompiledTransform(); - transformer.Load(sTransformName); - - // add any parameters - XsltArgumentList args; - AddParameters(out args, parameterList); - - // setup output file - using (var writer = File.CreateText(sOutputName)) - { - // load input file - using (var reader = new XmlTextReader(sInputPath)) - { -#if !__MonoCS__ - reader.DtdProcessing = DtdProcessing.Parse; -#else - reader.ProhibitDtd = false; -#endif - reader.EntityHandling = EntityHandling.ExpandEntities; - - // Apply transform - transformer.Transform(reader, args, writer); - } - } -#else // not UsingDotNetTransforms -#if __MonoCS__ - if (parameterList != null) - { - foreach(XSLParameter rParam in parameterList) - { - // Following is a specially recognized parameter name - if (rParam.Name == "prmSDateTime") - { - rParam.Value = GetCurrentDateTime(); - } - } - } - SIL.Utils.LibXslt.TransformFileToFile(sTransformName, parameterList, sInputPath, sOutputName); -#else - //.Net framework XML transform is still slower than something like MSXML2 - // (this is so especially for transforms using xsl:key). - MSXML2.XSLTemplate60Class xslt = new MSXML2.XSLTemplate60Class(); - MSXML2.FreeThreadedDOMDocument60Class xslDoc = new - MSXML2.FreeThreadedDOMDocument60Class(); - MSXML2.DOMDocument60Class xmlDoc = new MSXML2.DOMDocument60Class(); - MSXML2.IXSLProcessor xslProc; - - xslDoc.async = false; - xslDoc.setProperty("ResolveExternals", true); - xslDoc.setProperty("ProhibitDTD", false); - xslDoc.setProperty("AllowDocumentFunction", true); // MSXSL 6 defaults to false - xslDoc.load(sTransformName); - xslt.stylesheet = xslDoc; - xmlDoc.setProperty("ResolveExternals", true); - xmlDoc.setProperty("ProhibitDTD", false); - xmlDoc.async = false; - var fOk = xmlDoc.load(sInputPath); - if (!fOk) - { - var msg = String.Format(XmlUtilsStrings.ksXmlFileIsInvalid, sInputPath); - MessageBox.Show(msg, XmlUtilsStrings.ksWarning, MessageBoxButtons.OK, MessageBoxIcon.Warning); - } - xslProc = xslt.createProcessor(); - xslProc.input = xmlDoc; - AddParameters(parameterList, xslProc); - xslProc.transform(); - using (StreamWriter sr = File.CreateText(sOutputName)) - { - sr.Write(xslProc.output); - sr.Close(); - } -#endif // __MonoCS__ -#endif // UsingDotNetTransforms -#if DEBUG - DateTime end = DateTime.Now; - Debug.WriteLine("\tEnding at: " + end.TimeOfDay.ToString()); - System.TimeSpan diff = end.Subtract(start); - Debug.WriteLine("\tProcess took: " + diff.ToString() + " " + sOutputName); -#endif - } - #if UsingDotNetTransforms static private void AddParameters(out XsltArgumentList args, XSLParameter[] parameterList) { diff --git a/Src/xWorks/GeneratedHtmlViewer.cs b/Src/xWorks/GeneratedHtmlViewer.cs index ecf0cf7243..bd9939ed8c 100644 --- a/Src/xWorks/GeneratedHtmlViewer.cs +++ b/Src/xWorks/GeneratedHtmlViewer.cs @@ -126,7 +126,7 @@ public class GeneratedHtmlViewer : UserControl, IxCoreContentControl, IFWDisposa private const string m_ksHtmlFilePath = "HtmlFilePath"; private const string m_ksAlsoSaveFilePath = "AlsoSaveFilePath"; - private readonly Dictionary transforms = new Dictionary(); + private readonly Dictionary m_transforms = new Dictionary(); #endregion // Data Members @@ -139,6 +139,15 @@ private static string TransformPath { get { return Path.Combine(FwDirectoryFinder.FlexFolder, "Transforms"); } } + + /// + /// Path to Export Templates + /// + private static string ExportTemplatePath + { + get { return Path.Combine(FwDirectoryFinder.FlexFolder, "Export Templates"); } + } + /// /// Path to utility html files /// @@ -350,7 +359,7 @@ public bool OnSaveAsWebpage(object parameterObj) return false; // we sure can't handle it; should we throw? string whatToSave = param.Item1; string outPath = param.Item2; - string sXsltFiles = param.Item3; + string xsltFiles = param.Item3; string directory = Path.GetDirectoryName(outPath); if (!Directory.Exists(directory)) { @@ -362,23 +371,25 @@ public bool OnSaveAsWebpage(object parameterObj) case "GrammarSketchXLingPaper": if (File.Exists(m_sAlsoSaveFileName)) { - string sInputFile = m_sAlsoSaveFileName; - if (!string.IsNullOrEmpty(sXsltFiles)) + string inputFile = m_sAlsoSaveFileName; + if (!string.IsNullOrEmpty(xsltFiles)) { - string sNewFileName = Path.GetFileNameWithoutExtension(outPath); - string sTempFileName = Path.Combine(Path.GetTempPath(), sNewFileName); - string sOutputFile = sTempFileName; - XmlUtils.XSLParameter[] parameterList = null; - string[] rgsXslts = sXsltFiles.Split(new[] { ';' }); + string newFileName = Path.GetFileNameWithoutExtension(outPath); + string tempFileName = Path.Combine(Path.GetTempPath(), newFileName); + string outputFile = tempFileName; + string[] rgsXslts = xsltFiles.Split(new[] { ';' }); int cXslts = rgsXslts.GetLength(0); - for (int ix = 0; ix < cXslts; ++ix) + for (int i = 0; i < cXslts; ++i) { - sOutputFile = sOutputFile + (ix + 1); - XmlUtils.TransformFileToFile(Path.Combine(TransformPath, rgsXslts[ix]), parameterList, sInputFile, sOutputFile + ".xml"); - sInputFile = sOutputFile + ".xml"; + outputFile = outputFile + (i + 1); + var transform = GetTransformFromFile(Path.Combine(ExportTemplatePath, rgsXslts[i])); + using (var writer = new StreamWriter(outputFile + ".xml")) + using (var reader = XmlReader.Create(new XmlTextReader(inputFile), new XmlReaderSettings { DtdProcessing = DtdProcessing.Parse })) + transform.Transform(reader, null, writer); + inputFile = outputFile + ".xml"; } } - CopyFile(sInputFile, outPath); + CopyFile(inputFile, outPath); return true; } break; @@ -619,24 +630,39 @@ private string ApplyTransform(string inputFile, XmlNode node, ProgressDialogWork argumentList.AddParam("prmGlossFontSize", "", GetNormalStyleFontSize(wsContainer.DefaultAnalysisWritingSystem.Handle)); } - var xmlReaderSettings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Parse }; using (var writer = new StreamWriter(outputFile)) - using (var reader = XmlReader.Create(new XmlTextReader(inputFile), xmlReaderSettings)) - GetTransform(stylesheetName, stylesheetAssembly).Transform(reader, argumentList, writer); + using (var reader = XmlReader.Create(new XmlTextReader(inputFile), new XmlReaderSettings { DtdProcessing = DtdProcessing.Parse })) + GetTransform(stylesheetName, stylesheetAssembly).Transform(reader, argumentList, writer); return outputFile; } private XslCompiledTransform GetTransform(string xslName, string xslAssembly) { - lock(transforms) + lock (m_transforms) { XslCompiledTransform transform; - transforms.TryGetValue(xslName, out transform); + m_transforms.TryGetValue(xslName, out transform); if (transform != null) return transform; transform = XmlUtils.CreateTransform(xslName, xslAssembly); - transforms.Add(xslName, transform); + m_transforms.Add(xslName, transform); + return transform; + } + } + + private XslCompiledTransform GetTransformFromFile(string xslPath) + { + lock (m_transforms) + { + XslCompiledTransform transform; + m_transforms.TryGetValue(xslPath, out transform); + if (transform != null) + return transform; + + transform = new XslCompiledTransform(); + transform.Load(xslPath); + m_transforms.Add(xslPath, transform); return transform; } } From 59aaa08510b324b89e619c7f902cb6b39c8b77a8 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Thu, 20 Feb 2014 14:38:45 +0700 Subject: [PATCH 089/143] Remove LibXslt.cs Change-Id: I3c9da5a37d6c469936987cca568edb1078ebd472 --- .../M3ToXAmpleTransformerTests.cs | 50 +- .../ParserUITests/ParserUITests.csproj | 2 +- .../TestUnificationViaXSLT-Linux.xsl | 54 - ...SameSlotTwiceWordGrammarDebugger-Linux.xsl | 5759 ----------------- .../WordGrammarDebuggingTests.cs | 145 +- Src/Utilities/XMLUtils/LibXslt.cs | 337 - Src/Utilities/XMLUtils/XMLUtils.csproj | 3 - Src/Utilities/XMLUtils/XmlUtils.cs | 53 - 8 files changed, 30 insertions(+), 6373 deletions(-) delete mode 100644 Src/LexText/ParserUI/ParserUITests/TestUnificationViaXSLT-Linux.xsl delete mode 100644 Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/TLPSameSlotTwiceWordGrammarDebugger-Linux.xsl delete mode 100644 Src/Utilities/XMLUtils/LibXslt.cs diff --git a/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTests.cs b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTests.cs index 8ef2fa4e8f..d067ecb877 100644 --- a/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTests.cs +++ b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTests.cs @@ -44,16 +44,12 @@ public class M3ToXAmpleTransformerTests : BaseTest string m_sM3FXTAffixAlloFeatsDump; string m_sM3FXTLatinDump; string m_sM3FXTIrregularlyInflectedFormsDump; - Dictionary m_mapXmlDocs = new Dictionary(); -#if __MonoCS__ - IntPtr m_adTransform; - IntPtr m_lexTransform; - IntPtr m_gramTransform; -#else + readonly Dictionary m_mapXmlDocs = new Dictionary(); + XslCompiledTransform m_adTransform; XslCompiledTransform m_lexTransform; XslCompiledTransform m_gramTransform; -#endif + bool m_fResultMatchesExpected = true; /// @@ -80,23 +76,6 @@ public override void FixtureSetup() [TestFixtureTearDown] public override void FixtureTeardown() { -#if __MonoCS__ - if (m_adTransform != IntPtr.Zero) - { - LibXslt.FreeCompiledTransform(m_adTransform); - m_adTransform = IntPtr.Zero; - } - if (m_lexTransform != IntPtr.Zero) - { - LibXslt.FreeCompiledTransform(m_lexTransform); - m_lexTransform = IntPtr.Zero; - } - if (m_gramTransform != IntPtr.Zero) - { - LibXslt.FreeCompiledTransform(m_gramTransform); - m_gramTransform = IntPtr.Zero; - } -#endif base.FixtureTeardown(); } @@ -116,7 +95,7 @@ private void SetUpM3FXTDump() m_sM3FXTAffixAlloFeatsDump = Path.Combine(m_sTestPath, "TestAffixAllomorphFeatsParserFxtResult.xml"); m_sM3FXTLatinDump = Path.Combine(m_sTestPath, "LatinParserFxtResult.xml"); m_sM3FXTIrregularlyInflectedFormsDump = Path.Combine(m_sTestPath, "IrregularlyInflectedFormsParserFxtResult.xml"); -#if !__MonoCS__ + SetupXmlDocument(m_sM3FXTDump); SetupXmlDocument(m_sM3FXTCircumfixDump); SetupXmlDocument(m_sM3FXTCircumfixInfixDump); @@ -131,7 +110,6 @@ private void SetUpM3FXTDump() SetupXmlDocument(m_sM3FXTAffixAlloFeatsDump); SetupXmlDocument(m_sM3FXTLatinDump); SetupXmlDocument(m_sM3FXTIrregularlyInflectedFormsDump); -#endif } private void SetupXmlDocument(string filepath) @@ -150,11 +128,6 @@ private void SetUpTransform(out XslCompiledTransform transform, string name) { transform = XmlUtils.CreateTransform(name, "ApplicationTransforms"); } - private void SetUpTransform(ref IntPtr transform, string name) - { - string sTransformPath = Path.Combine(m_sTransformPath, name); - transform = LibXslt.CompileTransform(sTransformPath); - } /// /// Test creating the AD Control file @@ -223,27 +196,18 @@ private void ApplyTransform(string sInput, XslCompiledTransform transform, strin // by deleting it here instead of a finally block, when it fails, we can see what the result is. File.Delete(sOutput); } - private void ApplyTransform(string sInput, IntPtr transform, string sExpectedOutput) - { - string sOutput = FileUtils.GetTempFile("txt"); - LibXslt.TransformFileToFile(transform, sInput, sOutput); - string sExpectedResult = Path.Combine(m_sTestPath, sExpectedOutput); - CheckOutputEquals(sExpectedResult, sOutput); - // by deleting it here instead of a finally block, when it fails, we can see what the result is. - File.Delete(sOutput); - } private void CheckOutputEquals(string sExpectedResultFile, string sActualResultFile) { string sExpected, sActual; - using (StreamReader expected = new StreamReader(sExpectedResultFile)) + using (var expected = new StreamReader(sExpectedResultFile)) sExpected = expected.ReadToEnd(); - using (StreamReader actual = new StreamReader(sActualResultFile)) + using (var actual = new StreamReader(sActualResultFile)) sActual = actual.ReadToEnd(); // A non-empty last line in a file from git always ends with '\n' character if (sActual.Substring(sActual.Length - 1) != "\n") sActual += Environment.NewLine; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.Append("Expected file was "); sb.AppendLine(sExpectedResultFile); sb.Append("Actual file was "); diff --git a/Src/LexText/ParserUI/ParserUITests/ParserUITests.csproj b/Src/LexText/ParserUI/ParserUITests/ParserUITests.csproj index 8394d5f6d1..bca2077f04 100644 --- a/Src/LexText/ParserUI/ParserUITests/ParserUITests.csproj +++ b/Src/LexText/ParserUI/ParserUITests/ParserUITests.csproj @@ -116,7 +116,7 @@ System.XML - + False ..\..\..\..\Output\Debug\TestUtils.dll diff --git a/Src/LexText/ParserUI/ParserUITests/TestUnificationViaXSLT-Linux.xsl b/Src/LexText/ParserUI/ParserUITests/TestUnificationViaXSLT-Linux.xsl deleted file mode 100644 index 28f50a5f37..0000000000 --- a/Src/LexText/ParserUI/ParserUITests/TestUnificationViaXSLT-Linux.xsl +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - -
- - <xsl:value-of select="title"/> - - - - - - - - - - - - - - - -
-
-
-
-
- diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/TLPSameSlotTwiceWordGrammarDebugger-Linux.xsl b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/TLPSameSlotTwiceWordGrammarDebugger-Linux.xsl deleted file mode 100644 index 831d88bd63..0000000000 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/TLPSameSlotTwiceWordGrammarDebugger-Linux.xsl +++ /dev/null @@ -1,5759 +0,0 @@ - - - - - -yes - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -A root can only be a "Partial" when its category is unknown, but the category here is ' - -'. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -A stem requires an overt category, but this root has an unmarked category. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -In attaching an unclassified circumfix: - - - - - - -category - - - -unclassified - - - - -category - - - -stem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -In attaching an unclassified -: - - - - - -category - - - -unclassified - - - - -category - - - -stem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Try to build a Word analysis node on a - - -Partial - - -Full - - - analysis node. - - - - - - - - - - - - - - -The category ' - -' requires inflection, but there was no inflection. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Only proclitics can be before a Word analysis node. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Only enclitics can be after a Word analysis node. - - - - - - - - - - - - - - - - - - - - - - - - - - - - -In attaching a - -: The category ( - -) of the word is incompatible with any of the categories that the proclitic " - -" must attach to ( - - - -, - - -). - - - - - - - - - - - - - - - - - - - - - - - - - - - - -suffix - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -, - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - -Attaching the derivational - - ( - -) - - - -derivational - - ( - -) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -In attaching a derivational -: - - - - - - -from category - - - -derivational - - - - -category - - - -stem - - - - - - - - - -from inflection class - - - -derivational - - - - -inflection class - - - -stem - - - - - - - - - -environment category - - - -derivational - - - - -category - - - -stem - - - - - - - - - - - -from exception feature - - - - -derivational - - - -exception features - - - stem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -circumfix - - - - - - - - - - - - - - - - - - - - - -prefix - - - - - - - - - - - - -x - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -The - - ( - -) of the - - " - -" is incompatible with the - - - ( - -) - - of the - -. - - - - - - - - - - - - - - - -The - - - ( - -) - - of the - - is incompatible with the - - ( - -) of the - -: - - - - - - - - - - - - - - - - -suffix - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -81 - - - - - - - -73 - - - - - - - - - - -7132 - - - - - -In applying the compound rule "noun-adverb -> intransitive verb, ic:2": - -category - - - -left-hand stem - - - -category - -N - -left-hand member of the compound rule - - - - - -In applying the compound rule "noun-adverb -> intransitive verb, ic:2": - -category - - - -right-hand stem - - - -category - -Adv - -right-hand member of the compound rule - - - - - - - - - - - - - - - - - - - - - - - - - - - -73 - - - - - - - -81 - - - - - - - - - - -7136 - - - - - -In applying the compound rule "adverb-noun --> intransitive verb, ic:2": - -category - - - -left-hand stem - - - -category - -Adv - -left-hand member of the compound rule - - - - - -In applying the compound rule "adverb-noun --> intransitive verb, ic:2": - -category - - - -right-hand stem - - - -category - -N - -right-hand member of the compound rule - - - - - - - - - - - - - - - - - - - - - - - - - - - -70 - - - - - - - -81 - - - - - - - - - - -7141 - - - - - -In applying the compound rule "adj-noun with linker ": - -category - - - -left-hand stem - - - -category - -adj - -left-hand member of the compound rule - - - - - -In applying the compound rule "adj-noun with linker ": - -category - - - -right-hand stem - - - -category - -N - -right-hand member of the compound rule - - - - - - - - - - - - - - - - - - - - - - - - - - - -146 - - - - - - - -73 - - - - - - - - - - -7146 - - - - - -In applying the compound rule "verb-adverb ": - -category - - - -left-hand stem - - - -category - -V - -left-hand member of the compound rule - - - - - -In applying the compound rule "verb-adverb ": - -category - - - -right-hand stem - - - -category - -Adv - -right-hand member of the compound rule - - - - - - - - - - - - - - - - - - - - - - - - - - - -81 - - - - - - - -168 - - - - - - - - - - -7150 - - - - - -In applying the compound rule "noun-transitive verb ": - -category - - - -left-hand stem - - - -category - -N - -left-hand member of the compound rule - - - - - -In applying the compound rule "noun-transitive verb ": - -category - - - -right-hand stem - - - -category - -trans - -right-hand member of the compound rule - - - - - - - - - - - - - - - - - - - - - - - - - - - -81 - - - - - - - -153 - - - - - - - - - - -7154 - - - - - -In applying the compound rule "noun-Intransitive verb ": - -category - - - -left-hand stem - - - -category - -N - -left-hand member of the compound rule - - - - - -In applying the compound rule "noun-Intransitive verb ": - -category - - - -right-hand stem - - - -category - -intrans - -right-hand member of the compound rule - - - - - - - - - - - - - - - - - - - - - -153 - -179 - -+ -- - - -153 - -179 - -+ -- - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - -Tried to make the stem be uninflected, but the stem has been inflected via a non-final template. Therefore, a derivatoinal affix or a compound rule must apply first. - - - - - - - - - - - - - - -0 - - - - - - - - - - -0 - - - - - - - - - - - - - - - -- - - -+ - - - - -81 - - - - - - - - - category - -N - -inflectional template - -Possessed noun - -category - - - -stem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Possessed noun' for category 'noun' - - - - - - - - -The inflectional template named 'Possessed noun' for category 'noun' - - -inflectional prefix ( - -) - - - - - - - - - - - - -The inflectional template named 'Possessed noun' for category 'noun' - - - - - - - - -The inflectional template named 'Possessed noun' for category 'noun' - - -inflectional suffix ( - -) - - - - - - - - - - - - -The inflectional template named 'Possessed noun' for category 'noun' - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Possessed noun' for category 'noun' - - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Possessed noun' for category 'noun' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. - - -Partial inflectional template has already been inflected. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0 - - - - - - - - - - -0 - - - - - - - - -81 - - -N - - -- - - -+ - - -The inflectional template named 'Possessed noun' for category 'noun' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. - - -Partial inflectional template has already been inflected. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0 - - - - - - - - - - -0 - - - - - - - - -82 - - -comm - - -- - - -+ - - -The inflectional template named 'Possessed noun' for category 'noun' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. - - -Partial inflectional template has already been inflected. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0 - - - - - - - - - - -0 - - - - - - - - -85 - - -conc - - -- - - -+ - - -The inflectional template named 'Possessed noun' for category 'noun' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. - - -Partial inflectional template has already been inflected. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0 - - - - - - - - - - -0 - - - - - - - - -88 - - -nom - - -- - - -+ - - -The inflectional template named 'Possessed noun' for category 'noun' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. - - -Partial inflectional template has already been inflected. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0 - - - - - - - - - - -0 - - - - - - - - -91 - - -poss - - -- - - -+ - - -The inflectional template named 'Possessed noun' for category 'noun' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. - - -Partial inflectional template has already been inflected. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0 - - - - - - - - - - -0 - - - - - - - - -94 - - -prop - - -- - - -+ - - -The inflectional template named 'Possessed noun' for category 'noun' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. - - -Partial inflectional template has already been inflected. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Possessed noun' for category 'noun' failed because in the optional suffix slot 'Possessor', the inflection class of the stem ( - -) does not match any of the inflection classes of the inflectional affix ( - -). The inflection class - - - of this affix is: - - -es of this affix are: - - - - - -, - - -. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0 - - - - - - - - - - - - -0 - - - - - - - - - - - - - - - -- - - -+ - - - - -153 - - - - - - - - - category - -intrans - -inflectional template - -Intransitive verb - -category - - - -stem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Intransitive verb' for category 'intransitive verb' - - - - - - - - -The inflectional template named 'Intransitive verb' for category 'intransitive verb' - - -inflectional prefix ( - -) - - - - - - - - - - - - -The inflectional template named 'Intransitive verb' for category 'intransitive verb' - - - - - - - - -The inflectional template named 'Intransitive verb' for category 'intransitive verb' - - -inflectional suffix ( - -) - - - - - - - - - - - - -The inflectional template named 'Intransitive verb' for category 'intransitive verb' - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Intransitive verb' for category 'intransitive verb' - - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Intransitive verb' for category 'intransitive verb' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. - - -Partial inflectional template has already been inflected. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0 - - - - - - - - - - - - -0 - - - - - - - - -153 - - -intrans - - -- - - -+ - - -The inflectional template named 'Intransitive verb' for category 'intransitive verb' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. - - -Partial inflectional template has already been inflected. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Intransitive verb' for category 'intransitive verb' failed because in the optional prefix slot 'Subject', the inflection class of the stem ( - -) does not match any of the inflection classes of the inflectional affix ( - -). The inflection class - - - of this affix is: - - -es of this affix are: - - - - - -, - - -. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Intransitive verb' for category 'intransitive verb' failed because in the required suffix slot 'Tense', the inflection class of the stem ( - -) does not match any of the inflection classes of the inflectional affix ( - -). The inflection class - - - of this affix is: - - -es of this affix are: - - - - - -, - - -. - - - - - - - - - - - - -The inflectional template named 'Intransitive verb' for category 'intransitive verb' failed because the required suffix slot 'Tense' was not found. - - - - - - - - - - - - - - - - -0 - - - - - - - - - - - - -0 - - - - - - - - - - - - - - - -- - - -+ - - - - -163 - - - - - - - - - category - -sta - -inflectional template - -Stative verb - -category - - - -stem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Stative verb' for category 'stative' - - - - - - - - -The inflectional template named 'Stative verb' for category 'stative' - - -inflectional prefix ( - -) - - - - - - - - - - - - -The inflectional template named 'Stative verb' for category 'stative' - - - - - - - - -The inflectional template named 'Stative verb' for category 'stative' - - -inflectional suffix ( - -) - - - - - - - - - - - - -The inflectional template named 'Stative verb' for category 'stative' - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Stative verb' for category 'stative' - - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Stative verb' for category 'stative' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. - - -Partial inflectional template has already been inflected. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0 - - - - - - - - - - - - -0 - - - - - - - - -163 - - -sta - - -- - - -+ - - -The inflectional template named 'Stative verb' for category 'stative' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. - - -Partial inflectional template has already been inflected. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Stative verb' for category 'stative' failed because in the optional prefix slot 'Subject', the inflection class of the stem ( - -) does not match any of the inflection classes of the inflectional affix ( - -). The inflection class - - - of this affix is: - - -es of this affix are: - - - - - -, - - -. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Stative verb' for category 'stative' failed because in the required suffix slot 'Tense', the inflection class of the stem ( - -) does not match any of the inflection classes of the inflectional affix ( - -). The inflection class - - - of this affix is: - - -es of this affix are: - - - - - -, - - -. - - - - - - - - - - - - -The inflectional template named 'Stative verb' for category 'stative' failed because the required suffix slot 'Tense' was not found. - - - - - - - - - - - - - - - - -0 - - - - - - - - - - - - -0 - - - - - - - - - - - - - - - -- - - -+ - - - - -168 - - - - - - - - - category - -trans - -inflectional template - -Transitive verb - -category - - - -stem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Transitive verb' for category 'transitive verb' - - - - - - - - -The inflectional template named 'Transitive verb' for category 'transitive verb' - - -inflectional prefix ( - -) - - - - - - - - - - - - -The inflectional template named 'Transitive verb' for category 'transitive verb' - - - - - - - - -The inflectional template named 'Transitive verb' for category 'transitive verb' - - -inflectional suffix ( - -) - - - - - - - - - - - - -The inflectional template named 'Transitive verb' for category 'transitive verb' - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Transitive verb' for category 'transitive verb' - - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Transitive verb' for category 'transitive verb' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. - - -Partial inflectional template has already been inflected. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0 - - - - - - - - - - - - -0 - - - - - - - - -168 - - -trans - - -- - - -+ - - -The inflectional template named 'Transitive verb' for category 'transitive verb' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. - - -Partial inflectional template has already been inflected. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Transitive verb' for category 'transitive verb' failed because in the required prefix slot 'Object', the inflection class of the stem ( - -) does not match any of the inflection classes of the inflectional affix ( - -). The inflection class - - - of this affix is: - - -es of this affix are: - - - - - -, - - -. - - - - - - - - - - - - - - - -The inflectional template named 'Transitive verb' for category 'transitive verb' failed because the required prefix slot 'Object' was not found. - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Transitive verb' for category 'transitive verb' failed because in the optional prefix slot 'Subject', the inflection class of the stem ( - -) does not match any of the inflection classes of the inflectional affix ( - -). The inflection class - - - of this affix is: - - -es of this affix are: - - - - - -, - - -. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Transitive verb' for category 'transitive verb' failed because in the required suffix slot 'Tense', the inflection class of the stem ( - -) does not match any of the inflection classes of the inflectional affix ( - -). The inflection class - - - of this affix is: - - -es of this affix are: - - - - - -, - - -. - - - - - - - - - - - - -The inflectional template named 'Transitive verb' for category 'transitive verb' failed because the required suffix slot 'Tense' was not found. - - - - - - - - - - - - - - - - -0 - - - - - - - - - - - - -0 - - - - - - - - - - - - - - - -- - - -+ - - - - -172 - - - - - - - - - category - -bitrans - -inflectional template - -Bitransitive verb - -category - - - -stem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Bitransitive verb' for category 'bitransitive verb' - - - - - - - - -The inflectional template named 'Bitransitive verb' for category 'bitransitive verb' - - -inflectional prefix ( - -) - - - - - - - - - - - - -The inflectional template named 'Bitransitive verb' for category 'bitransitive verb' - - - - - - - - -The inflectional template named 'Bitransitive verb' for category 'bitransitive verb' - - -inflectional suffix ( - -) - - - - - - - - - - - - -The inflectional template named 'Bitransitive verb' for category 'bitransitive verb' - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Bitransitive verb' for category 'bitransitive verb' - - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Bitransitive verb' for category 'bitransitive verb' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. - - -Partial inflectional template has already been inflected. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0 - - - - - - - - - - - - -0 - - - - - - - - -172 - - -bitrans - - -- - - -+ - - -The inflectional template named 'Bitransitive verb' for category 'bitransitive verb' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. - - -Partial inflectional template has already been inflected. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Bitransitive verb' for category 'bitransitive verb' failed because in the required prefix slot 'Object', the inflection class of the stem ( - -) does not match any of the inflection classes of the inflectional affix ( - -). The inflection class - - - of this affix is: - - -es of this affix are: - - - - - -, - - -. - - - - - - - - - - - - - - - -The inflectional template named 'Bitransitive verb' for category 'bitransitive verb' failed because the required prefix slot 'Object' was not found. - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Bitransitive verb' for category 'bitransitive verb' failed because in the optional prefix slot 'Subject', the inflection class of the stem ( - -) does not match any of the inflection classes of the inflectional affix ( - -). The inflection class - - - of this affix is: - - -es of this affix are: - - - - - -, - - -. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -The inflectional template named 'Bitransitive verb' for category 'bitransitive verb' failed because in the required suffix slot 'Tense', the inflection class of the stem ( - -) does not match any of the inflection classes of the inflectional affix ( - -). The inflection class - - - of this affix is: - - -es of this affix are: - - - - - -, - - -. - - - - - - - - - - - - -The inflectional template named 'Bitransitive verb' for category 'bitransitive verb' failed because the required suffix slot 'Tense' was not found. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -[ - - - - - -: - - - - - - - - - - - - - -] - - - - - - - - - - - - - - - - - - - - - - -from exception feature - - - - -inflectional - - - -exception features - - - stem - - - - - - - - - - - - - - - - - -inflectional prefix ( - -) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -inflectional suffix ( - -) - - - - - - - - - - - - - - - - - - - - - - - - -Y - - - - -N - - - - - -PriorityUnionOf( - - -UnificationOf( - - - - - - -Empty - -and - - - - -Empty - -) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -N - - - - - - - - - - - - - - - - - - - - - - - - - - - - failed because at least one inflection feature of the is incompatible with the inflection features of the . The incompatibility is for feature . This feature for the has a value of but the corresponding feature for the has a value of . - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Y - - -N - - - - - - - - - - - - - - - - - - - -Y - - -N - - - - -N - - - - - - - - diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingTests.cs b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingTests.cs index 2ff2489bc7..558a5becc9 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingTests.cs +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingTests.cs @@ -5,14 +5,11 @@ // File: WordGrammarDebuggingTests.cs // Responsibility: -using System; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Text; -#if __MonoCS__ using System.Xml.Linq; -#endif using System.Xml.XPath; using System.Xml.Xsl; @@ -35,15 +32,7 @@ namespace SIL.FieldWorks.LexText.Controls public class WordGrammarDebuggingTests : BaseTest { private XPathDocument m_doc; -#if __MonoCS__ - private IntPtr m_masterTransform; - private IntPtr m_resultTransform; - private IntPtr m_resultTransformNoCompoundRules; - private IntPtr m_resultTransformStemNames; - private IntPtr m_resultTransformAffixAlloFeats; - private IntPtr m_UnificationViaXsltTransform; - private IntPtr m_SameSlotTwiceTransform; -#else + private XslCompiledTransform m_masterTransform; private XslCompiledTransform m_resultTransform; private XslCompiledTransform m_resultTransformNoCompoundRules; @@ -51,7 +40,6 @@ public class WordGrammarDebuggingTests : BaseTest private XslCompiledTransform m_resultTransformAffixAlloFeats; private XslCompiledTransform m_UnificationViaXsltTransform; private XslCompiledTransform m_SameSlotTwiceTransform; -#endif ///
/// Location of test files @@ -138,43 +126,6 @@ public override void FixtureTeardown() File.Delete(Path.Combine(m_sTempPath, "UnifyTwoFeatureStructures.xsl")); if (File.Exists(Path.Combine(m_sTempPath, "TestUnificationViaXSLT-Linux.xsl"))) File.Delete(Path.Combine(m_sTempPath, "TestUnificationViaXSLT-Linux.xsl")); -#if __MonoCS__ - if (m_masterTransform != IntPtr.Zero) - { - SIL.Utils.LibXslt.FreeCompiledTransform(m_masterTransform); - m_masterTransform = IntPtr.Zero; - } - if (m_resultTransform != IntPtr.Zero) - { - SIL.Utils.LibXslt.FreeCompiledTransform(m_resultTransform); - m_resultTransform = IntPtr.Zero; - } - if (m_resultTransformNoCompoundRules != IntPtr.Zero) - { - SIL.Utils.LibXslt.FreeCompiledTransform(m_resultTransformNoCompoundRules); - m_resultTransformNoCompoundRules = IntPtr.Zero; - } - if (m_resultTransformStemNames != IntPtr.Zero) - { - SIL.Utils.LibXslt.FreeCompiledTransform(m_resultTransformStemNames); - m_resultTransformStemNames = IntPtr.Zero; - } - if (m_resultTransformAffixAlloFeats != IntPtr.Zero) - { - SIL.Utils.LibXslt.FreeCompiledTransform(m_resultTransformAffixAlloFeats); - m_resultTransformAffixAlloFeats = IntPtr.Zero; - } - if (m_UnificationViaXsltTransform != IntPtr.Zero) - { - SIL.Utils.LibXslt.FreeCompiledTransform(m_UnificationViaXsltTransform); - m_UnificationViaXsltTransform = IntPtr.Zero; - } - if (m_SameSlotTwiceTransform != IntPtr.Zero) - { - SIL.Utils.LibXslt.FreeCompiledTransform(m_SameSlotTwiceTransform); - m_SameSlotTwiceTransform = IntPtr.Zero; - } -#endif base.FixtureTeardown(); } @@ -189,10 +140,6 @@ private void SetUpResultTransform(string sResultTransform, out XslCompiledTransf resultTransform = new XslCompiledTransform(m_fDebug); resultTransform.Load(sResultTransform); } - private void SetUpResultTransform(string sResultTransform, out IntPtr resultTransform) - { - resultTransform = SIL.Utils.LibXslt.CompileTransform(sResultTransform); - } /// ------------------------------------------------------------------------------------ /// @@ -201,27 +148,10 @@ private void SetUpResultTransform(string sResultTransform, out IntPtr resultTran /// ------------------------------------------------------------------------------------ private void SetUpUnificationViaXsltTransform() { -#if __MonoCS__ - // TestUnificationViaXSLT.xsl contains an xsl:include href value that chokes libxslt. - // (libxslt apparently doesn't like .. leading off a file path.) - if (!File.Exists(Path.Combine(m_sTempPath, "UnifyTwoFeatureStructures.xsl"))) - { - File.Copy(Path.Combine(m_sTransformPath, "UnifyTwoFeatureStructures.xsl"), - Path.Combine(m_sTempPath, "UnifyTwoFeatureStructures.xsl")); - } - if (!File.Exists(Path.Combine(m_sTempPath, "TestUnificationViaXSLT-Linux.xsl"))) - { - File.Copy(Path.Combine(Path.GetDirectoryName(m_sTestPath), "TestUnificationViaXSLT-Linux.xsl"), - Path.Combine(m_sTempPath, "TestUnificationViaXSLT-Linux.xsl")); - } - string sUnificationViaXsltTransform = Path.Combine(m_sTempPath, "TestUnificationViaXSLT-Linux.xsl"); - SetUpResultTransform(sUnificationViaXsltTransform, out m_UnificationViaXsltTransform); -#else m_UnificationViaXsltTransform = new XslCompiledTransform(m_fDebug); string sUnificationViaXsltTransform = Path.Combine(m_sTestPath, "../TestUnificationViaXSLT.xsl"); m_UnificationViaXsltTransform.Load(sUnificationViaXsltTransform); -#endif } /// ------------------------------------------------------------------------------------ @@ -231,18 +161,10 @@ private void SetUpUnificationViaXsltTransform() /// ------------------------------------------------------------------------------------ private void SetUpSameSlotTwiceTransform() { -#if __MonoCS__ - // TLPSameSlotTwiceWordGrammarDebugger.xsl contains a namespace declaration for - // auto-ns1 that is Microsoft-specific. - string sSameSlotTwiceTransform = Path.Combine(m_sTestPath, - "TLPSameSlotTwiceWordGrammarDebugger-Linux.xsl"); - SetUpResultTransform(sSameSlotTwiceTransform, out m_SameSlotTwiceTransform); -#else - m_SameSlotTwiceTransform = new XslCompiledTransform(m_fDebug); string sSameSlotTwiceTransform = Path.Combine(m_sTestPath, @"TLPSameSlotTwiceWordGrammarDebugger.xsl"); + m_SameSlotTwiceTransform = new XslCompiledTransform(m_fDebug); m_SameSlotTwiceTransform.Load(sSameSlotTwiceTransform); -#endif } /// ------------------------------------------------------------------------------------ @@ -305,16 +227,6 @@ private void ApplyTransform(string sInputFile, string sExpectedOutput, XslCompil File.Delete(sOutput); } } - private void ApplyTransform(string sInputFile, string sExpectedOutput, IntPtr transform) - { - string sInput = Path.Combine(m_sTestPath, sInputFile); - string sOutput = FileUtils.GetTempFile("xml"); - SIL.Utils.LibXslt.TransformFileToFile(transform, sInput, sOutput); - string sExpectedResult = Path.Combine(m_sTestPath, sExpectedOutput); - CheckXmlEquals(sExpectedResult, sOutput); - // by deleting it here instead of a finally block, when it fails, we can see what the result is. - File.Delete(sOutput); - } /// ------------------------------------------------------------------------------------ /// @@ -335,15 +247,11 @@ private void CheckXmlEquals(string sExpectedResultFile, string sActualResultFile sb.AppendLine(sExpectedResultFile); sb.Append("Actual file was "); sb.AppendLine(sActualResultFile); -#if __MonoCS__ - // REVIEW: Perhaps we should always use the fancy compare method using XElement objects? + XElement xeActual = XElement.Parse(sActual, LoadOptions.None); XElement xeExpected = XElement.Parse(sExpected, LoadOptions.None); bool ok = XmlHelper.EqualXml(xeExpected, xeActual, sb); Assert.IsTrue(ok, sb.ToString()); -#else - Assert.AreEqual(sExpected, sActual, sb.ToString()); -#endif } #endregion @@ -611,21 +519,21 @@ public void RemoveFailuresWhenApplyAgain() public void AffixAllomorphConditionedByFeatures() { // an inflectional affix allomorph has features and parse succeeds - DoWordGrammarDebuggerSteps("msmsAffixAlloFeats", 3, m_resultTransformAffixAlloFeats); + DoWordGrammarDebuggerSteps("msmsAffixAlloFeats", 3); // an inflectional affix allomorph has features and parse fails - DoWordGrammarDebuggerSteps("mpmsAffixAlloFeats", 2, m_resultTransformAffixAlloFeats); + DoWordGrammarDebuggerSteps("mpmsAffixAlloFeats", 2); // an inflectional affix allomorph without features is in an entry that has features and parse succeeds - DoWordGrammarDebuggerSteps("fsinflAffixAlloFeats", 3, m_resultTransformAffixAlloFeats); + DoWordGrammarDebuggerSteps("fsinflAffixAlloFeats", 3); // an inflectional affix allomorph without features is in an entry that has features and parse fails - DoWordGrammarDebuggerSteps("msinflAffixAlloFeats", 2, m_resultTransformAffixAlloFeats); + DoWordGrammarDebuggerSteps("msinflAffixAlloFeats", 2); // a derivational affix allomorph has features and parse succeeds - DoWordGrammarDebuggerSteps("fsfstovAffixAlloFeats", 3, m_resultTransformAffixAlloFeats); + DoWordGrammarDebuggerSteps("fsfstovAffixAlloFeats", 3); // a derivational affix allomorph has features and parse fails - DoWordGrammarDebuggerSteps("fpfstovAffixAlloFeats", 2, m_resultTransformAffixAlloFeats); + DoWordGrammarDebuggerSteps("fpfstovAffixAlloFeats", 2); // a derivational affix allomorph without features is in an entry that has features and parse succeeds - DoWordGrammarDebuggerSteps("fpfptovAffixAlloFeats", 3, m_resultTransformAffixAlloFeats); + DoWordGrammarDebuggerSteps("fpfptovAffixAlloFeats", 3); // a derivational affix allomorph without features is in an entry that has features and parse fails - DoWordGrammarDebuggerSteps("fsfptovAffixAlloFeats", 2, m_resultTransformAffixAlloFeats); + DoWordGrammarDebuggerSteps("fsfptovAffixAlloFeats", 2); } /// ------------------------------------------------------------------------------------ /// @@ -636,45 +544,36 @@ public void AffixAllomorphConditionedByFeatures() public void StemNames() { // stem name is set and parse succeeds - DoWordGrammarDebuggerSteps("niyuyiywusaStemNameSet", 3, m_resultTransformStemNames); + DoWordGrammarDebuggerSteps("niyuyiywusaStemNameSet", 3); // stem name is set but no features in regions and parse succeeds - DoWordGrammarDebuggerSteps("niyumamwupeStemNameSetNoFs", 3, m_resultTransformStemNames); + DoWordGrammarDebuggerSteps("niyumamwupeStemNameSetNoFs", 3); // stem name is set and parse fails - DoWordGrammarDebuggerSteps("niyuyiywupeStemNameFail", 3, m_resultTransformStemNames); + DoWordGrammarDebuggerSteps("niyuyiywupeStemNameFail", 3); // stem name not set (but other allomorph in lex entry is) and it succeeds - DoWordGrammarDebuggerSteps("niyuwowwupeStemNameNotSet", 3, m_resultTransformStemNames); + DoWordGrammarDebuggerSteps("niyuwowwupeStemNameNotSet", 3); // stem name not set (but other allomorph in lex entry is) and it fails - DoWordGrammarDebuggerSteps("niyuhohwusaStemNameNotSetFail", 3, m_resultTransformStemNames); + DoWordGrammarDebuggerSteps("niyuhohwusaStemNameNotSetFail", 3); // stem name not set (but two other allomorps in lex entry are) and it fails - DoWordGrammarDebuggerSteps("niyuwowwukoStemNameNotSetMultiFail", 3, m_resultTransformStemNames); + DoWordGrammarDebuggerSteps("niyuwowwukoStemNameNotSetMultiFail", 3); // stem name set and has two FsFeatStrucs and it succeeds - DoWordGrammarDebuggerSteps("timikikwusaStemNameSetMultiFs", 3, m_resultTransformStemNames); + DoWordGrammarDebuggerSteps("timikikwusaStemNameSetMultiFs", 3); // stem name set and has two FsFeatStrucs and it fails - DoWordGrammarDebuggerSteps("timikikwupeStemNameSetMultiFsFail", 3, m_resultTransformStemNames); + DoWordGrammarDebuggerSteps("timikikwupeStemNameSetMultiFsFail", 3); // stem name is set, has compound and parse succeeds - DoWordGrammarDebuggerSteps("niyuyiyximuwusaStemNameSetCompound", 5, m_resultTransformStemNames); + DoWordGrammarDebuggerSteps("niyuyiyximuwusaStemNameSetCompound", 5); // stem name not set (but other allomorph in lex entry is), has compound and it fails - DoWordGrammarDebuggerSteps("niyuyiyximuwupeStemNameNotSetCompoundFail", 5, m_resultTransformStemNames); + DoWordGrammarDebuggerSteps("niyuyiyximuwupeStemNameNotSetCompoundFail", 5); } // These methods have a seeming bug in them: the transform argument is not used, // but rather a hard-coded transform. However, the test output obviously comes // from applying the hard-coded transform, so fixing this requires knowing what // the proper output is for the given data and the proper (other) transform. - private void DoWordGrammarDebuggerSteps(string sName, int count, XslCompiledTransform transform) + private void DoWordGrammarDebuggerSteps(string sName, int count) { for (int i = 0; i < count; i++) ApplyTransform(sName + "Step0" + i.ToString(CultureInfo.InvariantCulture) + ".xml", sName + "Step0" + i.ToString(CultureInfo.InvariantCulture) + "Result.xml", m_resultTransformStemNames); } - private void DoWordGrammarDebuggerSteps(string sName, int count, IntPtr transform) - { - for (int i = 0; i < count; i++) - { - var inputName = String.Format("{0}Step0{1}.xml", sName, i); - var outputName = String.Format("{0}Step0{1}Result.xml", sName, i); - ApplyTransform(inputName, outputName, m_resultTransformStemNames); - } - } /// ------------------------------------------------------------------------------------ /// diff --git a/Src/Utilities/XMLUtils/LibXslt.cs b/Src/Utilities/XMLUtils/LibXslt.cs deleted file mode 100644 index e0c21b60f5..0000000000 --- a/Src/Utilities/XMLUtils/LibXslt.cs +++ /dev/null @@ -1,337 +0,0 @@ -// Copyright (c) 2012-2013 SIL International -// This software is licensed under the LGPL, version 2.1 or later -// (http://www.gnu.org/licenses/lgpl-2.1.html) -// -// File: LibXslt.cs -// Responsibility: Steve McConnel -// Last reviewed: -// -// -// This makes available some functions from libxslt.so, which has some capabilities lacking in -// the Mono Xml/Xsl implementation. -// - -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Xml; - -namespace SIL.Utils -{ - /// - /// Wrap libxslt.so functions for use in C# code (should we try to wrap MSXSL2 functionality similarly?) - /// - public static class LibXslt - { -#if __MonoCS__ - [DllImport("libxml2.so.2")] - static extern void xmlInitParser(); - [DllImport("libxml2.so.2")] - static extern void xmlSubstituteEntitiesDefault( - int flag); - [DllImport("libxml2.so.2")] - static extern void xmlCleanupParser(); - [DllImport("libxml2.so.2")] - static extern IntPtr xmlParseFile( - [MarshalAs(UnmanagedType.LPStr)] string filename); - [DllImport("libxml2.so.2")] - static extern void xmlFreeDoc( - IntPtr doc); - - [DllImport("libxslt.so.1")] - static extern void xsltSetXIncludeDefault( - int flag); - [DllImport("libxslt.so.1")] - static extern void xsltCleanupGlobals(); - [DllImport("libxslt.so.1")] - static extern IntPtr xsltParseStylesheetFile( - [MarshalAs(UnmanagedType.LPStr)] string filename); - [DllImport("libxslt.so.1")] - static extern void xsltFreeStylesheet( - IntPtr xsl); - [DllImport("libxslt.so.1")] - static extern IntPtr xsltApplyStylesheet( - IntPtr xsl, - IntPtr doc, - [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1, ArraySubType=UnmanagedType.LPStr)] string[] parameters); - [DllImport("libxslt.so.1")] - static extern int xsltSaveResultToFilename( - string outfile, - IntPtr res, - IntPtr xsl, - int compress); - - [DllImport("libexslt.so.0")] - static extern void exsltRegisterAll(); - - /// - /// This needs to be called at least once, but I don't think it hurts to call it - /// more than once. It is called by TransformFileToFile (the most basic one that - /// all the others eventually call). - /// - public static void InitializeLibXslt() - { - xmlInitParser(); - xmlSubstituteEntitiesDefault(1); - //xmlLoadExtDtdDefaultValue = 1; // Can't handle in C# -- hope it's not important! - xsltSetXIncludeDefault(1); - exsltRegisterAll(); - } - /// - /// Call this once when the program is totally done using this wrapper. - /// (Not too serious if it doesn't get called -- minor memory leak.) - /// I don't think InitializeLibXslt() can overcome some of the effects of - /// CloseLibXslt(). - /// - public static void CloseLibXslt() - { - xsltCleanupGlobals(); - xmlCleanupParser(); - } - - /// - /// Compile an XSLT transform. - /// - /// full path of the XSLT transform - /// handle to the compiled transform - public static IntPtr CompileTransform(string sTransformFile) - { - IntPtr xsl = xsltParseStylesheetFile(sTransformFile); - //Console.WriteLine("CompileTransform('{0}') => {1}", sTransformFile, xsl.ToString()); - return xsl; - } - - /// - /// Free a compiled XSLT transform. - /// - /// handle to the compiled transform - public static void FreeCompiledTransform(IntPtr xsl) - { - xsltFreeStylesheet(xsl); - } -#else - // The following are defined to allow linking in Microsoft .Net. They obviously - // don't do anything useful! - - /// - /// This needs to be called at least once, but I don't think it hurts to call it - /// more than once. It is called by TransformFileToFile (the most basic one that - /// all the others eventually call). - /// - ///link placeholder-- should not be called! - public static void InitializeLibXslt() - { - } - - /// - /// Call this once when the program is totally done using this wrapper. - /// (Not too serious if it doesn't get called -- minor memory leak.) - /// I don't think InitializeLibXslt() can overcome some of the effects of - /// CloseLibXslt(). - /// - ///link placeholder-- should not be called! - public static void CloseLibXslt() - { - } - - /// - /// Compile an XSLT transform. - /// - /// full path of the XSLT transform - /// handle to the compiled transform - ///link placeholder-- should not be called! - public static IntPtr CompileTransform(string sTransformFile) - { - return IntPtr.Zero; - } - - /// - /// Free a compiled XSLT transform. - /// - /// handle to the compiled transform - ///link placeholder-- should not be called! - public static void FreeCompiledTransform(IntPtr xsl) - { - } -#endif - - /// - /// Apply an XSLT transform on a DOM to produce a resulting file - /// - /// full path name of the XSLT transform - /// XmlDocument DOM containing input to be transformed - /// full path of the resulting output file - public static void TransformDomToFile(string sTransformFile, XmlDocument inputDOM, string sOutputFile) - { - string sTempInput = FileUtils.GetTempFile("xml"); - try - { - inputDOM.Save(sTempInput); - TransformFileToFile(sTransformFile, sTempInput, sOutputFile); - } - finally - { - if (File.Exists(sTempInput)) - File.Delete(sTempInput); - } - } - - /// - /// Apply an XSLT transform on a DOM to produce a resulting file - /// - /// handle to a compiled XSLT transform - /// XmlDocument DOM containing input to be transformed - /// full path of the resulting output file - public static void TransformDomToFile(IntPtr xsl, XmlDocument inputDOM, string sOutputFile) - { - string sTempInput = FileUtils.GetTempFile("xml"); - try - { - inputDOM.Save(sTempInput); - TransformFileToFile(xsl, new string[1] { null }, sTempInput, sOutputFile); - } - finally - { - if (File.Exists(sTempInput)) - File.Delete(sTempInput); - } - } - - /// - /// Apply an XSLT transform on a file to produce a resulting file - /// - /// full path name of the XSLT transform - /// full path of the input file - /// full path of the resulting output file - public static void TransformFileToFile(string sTransformFile, string sInputFile, string sOutputFile) - { - TransformFileToFile(sTransformFile, new string[1] { null }, sInputFile, sOutputFile); - } - - /// - /// Apply an XSLT transform on a file to produce a resulting file - /// - /// handle to a compiled XSLT transform - /// full path of the input file - /// full path of the resulting output file - public static void TransformFileToFile(IntPtr xsl, string sInputFile, string sOutputFile) - { - TransformFileToFile(xsl, new string[1] { null }, sInputFile, sOutputFile); - } - - /// - /// Convert the parameter list from an array of XmlUtils.XSLParameter objects to - /// an array of strings suitable for feeding to libxslt functions. - /// - static string[] ConvertParameterList (XmlUtils.XSLParameter[] parameterList) - { - int paramCount = parameterList == null ? 0 : parameterList.Length; - string[] parameters = new string[2 * paramCount + 1]; - int j = 0; - for (int i = 0; i < paramCount; ++i) - { - parameters[j++] = parameterList[i].Name; - // libxml2 requires "string" parameters to be quoted -- what other kind of parameter is there, anyway? - parameters[j++] = String.Format("'{0}'", parameterList[i].Value.Replace("'", "'")); - } - parameters[j] = null; - return parameters; - } - - - /// - /// Apply an XSLT transform on a file to produce a resulting file - /// - /// full path name of the XSLT transform - /// list of parameters to pass to the transform - /// full path of the input file - /// full path of the resulting output file - public static void TransformFileToFile(string sTransformFile, XmlUtils.XSLParameter[] parameterList, string sInputFile, string sOutputFile) - { - string[] parameters = ConvertParameterList(parameterList); - TransformFileToFile(sTransformFile, parameters, sInputFile, sOutputFile); - } - -#if __MonoCS__ - /// - /// Apply an XSLT transform on a file to produce a resulting file - /// - /// full path name of the XSLT transform - /// list of parameters to pass to the transform - /// full path of the input file - /// full path of the resulting output file - public static void TransformFileToFile(string sTransformFile, string[] parameters, string sInputFile, string sOutputFile) - { - IntPtr xsl = xsltParseStylesheetFile(sTransformFile); - if (xsl == IntPtr.Zero) - { - throw new Exception(String.Format("Unable to parse XSLT file '{0}' with libxslt.so", sTransformFile)); - } - try - { - TransformFileToFile(xsl, parameters, sInputFile, sOutputFile); - } - finally - { - xsltFreeStylesheet(xsl); - } - } - - /// - /// Apply an XSLT transform on a file to produce a resulting file - /// - /// handle to a compiled XSLT transform - /// list of parameters to pass to the transform - /// full path of the input file - /// full path of the resulting output file - public static void TransformFileToFile(IntPtr xsl, string[] parameters, string sInputFile, string sOutputFile) - { - InitializeLibXslt(); - IntPtr doc = xmlParseFile(sInputFile); - if (doc == IntPtr.Zero) - { - throw new Exception(String.Format("LibXslt.TransformFileToFile: Cannot parse XML file \"{0}\"", sInputFile)); - } - IntPtr res = xsltApplyStylesheet(xsl, doc, parameters); - xmlFreeDoc(doc); - if (res == IntPtr.Zero) - { - throw new Exception(String.Format("LibXslt.TransformFileToFile: Applying stylesheet to \"{0}\" failed.", sInputFile)); - } - int ok = xsltSaveResultToFilename(sOutputFile, res, xsl, 0); - xmlFreeDoc(res); - if (ok < 0) - { - throw new Exception(String.Format("LibXslt.TransformFileToFile: Cannot save result file \"{0}\"", sOutputFile)); - } - } -#else - // The following are defined to allow linking in Microsoft .Net. They obviously - // don't do anything useful! - - /// - /// Apply an XSLT transform on a file to produce a resulting file - /// - /// full path name of the XSLT transform - /// list of parameters to pass to the transform - /// full path of the input file - /// full path of the resulting output file - ///link placeholder-- should not be called! - public static void TransformFileToFile(string sTransformFile, string[] parameters, string sInputFile, string sOutputFile) - { - } - - /// - /// Apply an XSLT transform on a file to produce a resulting file - /// - /// handle to a compiled XSLT transform - /// list of parameters to pass to the transform - /// full path of the input file - /// full path of the resulting output file - ///link placeholder-- should not be called! - public static void TransformFileToFile(IntPtr xsl, string[] parameters, string sInputFile, string sOutputFile) - { - } -#endif - } -} diff --git a/Src/Utilities/XMLUtils/XMLUtils.csproj b/Src/Utilities/XMLUtils/XMLUtils.csproj index 55090e5b31..a935c87116 100644 --- a/Src/Utilities/XMLUtils/XMLUtils.csproj +++ b/Src/Utilities/XMLUtils/XMLUtils.csproj @@ -133,9 +133,6 @@ Code - - Code - Code diff --git a/Src/Utilities/XMLUtils/XmlUtils.cs b/Src/Utilities/XMLUtils/XmlUtils.cs index 4a15edc42b..9a642d8556 100644 --- a/Src/Utilities/XMLUtils/XmlUtils.cs +++ b/Src/Utilities/XMLUtils/XmlUtils.cs @@ -10,10 +10,6 @@ // This makes available some utilities for handling XML Nodes // // -------------------------------------------------------------------------------------------- -//We're changing to using libxslt (wrapped in the LibXslt class) on Linux/Mono. -//#if __MonoCS__ -//#define UsingDotNetTransforms -//#endif using System; using System.Collections.Generic; @@ -841,55 +837,6 @@ private static void AddParameters(XSLParameter[] parameterList, MSXML2.IXSLProce } #endif #endif // UsingDotNetTransforms - /// - /// Are we using the .Net XSLT transforms? - /// - /// true if we're using .Net XSLT transforms - /// false if we're using MSXML2 or LibXslt - public static bool UsingDotNetTransforms() - { -#if UsingDotNetTransforms - return true; -#else - return false; -#endif - } - - /// - /// Are we using the Microsoft's MSXML2 XSLT transforms? - /// - /// true if we're using MSXML2 XSLT transforms - /// false if we're using .Net or LibXslt - public static bool UsingMSXML2Transforms() - { -#if UsingDotNetTransforms - return false; -#else -#if __MonoCS__ - return false; -#else - return true; -#endif -#endif - } - - /// - /// Are we using the libxslt.so XSLT transforms? - /// - /// true if we're using libxslt.so transforms - /// false if we're using MSXML2 or .Net - public static bool UsingLibXsltTransforms() - { -#if UsingDotNetTransforms - return false; -#else -#if __MonoCS__ - return true; -#else - return false; -#endif -#endif - } private static string GetCurrentDateTime() { From dcddadcbd94c9d638299a8b7138f50468cb3b7ac Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 21 Feb 2014 13:29:28 +0700 Subject: [PATCH 090/143] changed Linux to use XslCompiledTransform Change-Id: I56af533f48c91ed2502857843ab52f4fb03c9925 --- Build/Linux.targets | 12 +- Build/Windows.targets | 4 +- .../M3ToXAmpleTransformerTests.cs | 15 +-- .../TLPSameSlotTwiceWordGrammarDebugger.xsl | 108 +++++++++--------- Src/LexText/ParserUI/WordGrammarDebugger.cs | 7 -- ...ParserToXAmpleWordGrammarDebuggingXSLT.xsl | 76 ++++++------ Src/Utilities/XMLUtils/XmlUtils.cs | 40 ++++++- Src/xWorks/GeneratedHtmlViewer.cs | 29 +++-- 8 files changed, 167 insertions(+), 124 deletions(-) diff --git a/Build/Linux.targets b/Build/Linux.targets index 992e0b5a84..946d1ddf40 100644 --- a/Build/Linux.targets +++ b/Build/Linux.targets @@ -8,7 +8,7 @@ - + + + + + + + + + + diff --git a/Build/Windows.targets b/Build/Windows.targets index 44de165760..9bb3d4ae70 100644 --- a/Build/Windows.targets +++ b/Build/Windows.targets @@ -6,7 +6,7 @@ + DependsOnTargets="Initialize;EncConvertersDlls;CopyOtherDlls;BuildWindowsXslAssemblies"> @@ -109,7 +109,7 @@ ..\Src\Transforms\Application ..\Src\Transforms\Presentation - + diff --git a/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTests.cs b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTests.cs index d067ecb877..db49ef9f14 100644 --- a/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTests.cs +++ b/Src/LexText/ParserCore/ParserCoreTests/M3ToXAmpleTransformerTests.cs @@ -73,12 +73,6 @@ public override void FixtureSetup() SetUpM3FXTDump(); } - [TestFixtureTearDown] - public override void FixtureTeardown() - { - base.FixtureTeardown(); - } - private void SetUpM3FXTDump() { m_sM3FXTDump = Path.Combine(m_sTestPath, "M3FXTDump.xml"); @@ -120,11 +114,12 @@ private void SetupXmlDocument(string filepath) private void SetUpXAmpleTransforms() { - SetUpTransform(out m_adTransform, "FxtM3ParserToXAmpleADCtl"); - SetUpTransform(out m_lexTransform, "FxtM3ParserToXAmpleLex"); - SetUpTransform(out m_gramTransform, "FxtM3ParserToToXAmpleGrammar"); + SetUpTransform("FxtM3ParserToXAmpleADCtl", out m_adTransform); + SetUpTransform("FxtM3ParserToXAmpleLex", out m_lexTransform); + SetUpTransform("FxtM3ParserToToXAmpleGrammar", out m_gramTransform); } - private void SetUpTransform(out XslCompiledTransform transform, string name) + + private void SetUpTransform(string name, out XslCompiledTransform transform) { transform = XmlUtils.CreateTransform(name, "ApplicationTransforms"); } diff --git a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/TLPSameSlotTwiceWordGrammarDebugger.xsl b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/TLPSameSlotTwiceWordGrammarDebugger.xsl index 27c52d0500..e3cf1d89dc 100644 --- a/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/TLPSameSlotTwiceWordGrammarDebugger.xsl +++ b/Src/LexText/ParserUI/ParserUITests/WordGrammarDebuggingInputsAndResults/TLPSameSlotTwiceWordGrammarDebugger.xsl @@ -1,5 +1,5 @@ - + - + - + @@ -2103,9 +2103,9 @@ InflectionalTemplate102 - - - + + + The inflectional template named 'Possessed noun' for category 'noun' @@ -2125,7 +2125,7 @@ InflectionalTemplate102 - + The inflectional template named 'Possessed noun' for category 'noun' @@ -2136,17 +2136,17 @@ InflectionalTemplate102 - + - + - - + + The inflectional template named 'Possessed noun' for category 'noun' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. @@ -2890,9 +2890,9 @@ InflectionalTemplate156 - - - + + + The inflectional template named 'Intransitive verb' for category 'intransitive verb' @@ -2912,7 +2912,7 @@ InflectionalTemplate156 - + The inflectional template named 'Intransitive verb' for category 'intransitive verb' @@ -2923,17 +2923,17 @@ InflectionalTemplate156 - + - + - - + + The inflectional template named 'Intransitive verb' for category 'intransitive verb' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. @@ -3341,9 +3341,9 @@ InflectionalTemplate166 - - - + + + The inflectional template named 'Stative verb' for category 'stative' @@ -3363,7 +3363,7 @@ InflectionalTemplate166 - + The inflectional template named 'Stative verb' for category 'stative' @@ -3374,17 +3374,17 @@ InflectionalTemplate166 - + - + - - + + The inflectional template named 'Stative verb' for category 'stative' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. @@ -3792,9 +3792,9 @@ InflectionalTemplate171 - - - + + + The inflectional template named 'Transitive verb' for category 'transitive verb' @@ -3814,7 +3814,7 @@ InflectionalTemplate171 - + The inflectional template named 'Transitive verb' for category 'transitive verb' @@ -3825,17 +3825,17 @@ InflectionalTemplate171 - + - + - - + + The inflectional template named 'Transitive verb' for category 'transitive verb' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. @@ -4307,9 +4307,9 @@ InflectionalTemplate175 - - - + + + The inflectional template named 'Bitransitive verb' for category 'bitransitive verb' @@ -4329,7 +4329,7 @@ InflectionalTemplate175 - + The inflectional template named 'Bitransitive verb' for category 'bitransitive verb' @@ -4340,17 +4340,17 @@ InflectionalTemplate175 - + - + - - + + The inflectional template named 'Bitransitive verb' for category 'bitransitive verb' failed because the stem was built by a non-final template and there was no intervening derivation or compounding. @@ -5515,7 +5515,7 @@ UnifyPrefixSlots - + @@ -5561,7 +5561,7 @@ UnifySuffixSlots - + @@ -5608,14 +5608,14 @@ UnifyTwoFeatureStructures - + Empty and - + Empty @@ -5624,16 +5624,16 @@ UnifyTwoFeatureStructures - + - + - + @@ -5723,13 +5723,13 @@ XSubsumesY N - + - - + + diff --git a/Src/LexText/ParserUI/WordGrammarDebugger.cs b/Src/LexText/ParserUI/WordGrammarDebugger.cs index 798f1e0f44..cc4d766176 100644 --- a/Src/LexText/ParserUI/WordGrammarDebugger.cs +++ b/Src/LexText/ParserUI/WordGrammarDebugger.cs @@ -99,8 +99,6 @@ public string PopWordGrammarStack() private void CreateAnalysisXml(XmlWriter writer, string nodeId, string form) { - writer.WriteStartDocument(); - writer.WriteStartElement("word"); writer.WriteElementString("form", form); writer.WriteStartElement("seq"); @@ -109,16 +107,12 @@ private void CreateAnalysisXml(XmlWriter writer, string nodeId, string form) writer.WriteEndElement(); writer.WriteEndElement(); - - writer.WriteEndDocument(); } protected abstract void WriteMorphNodes(XmlWriter writer, string nodeId); private void CreateSelectedWordGrammarXml(XmlWriter writer, string nodeId, string form) { - writer.WriteStartDocument(); - writer.WriteStartElement("word"); writer.WriteElementString("form", form); @@ -132,7 +126,6 @@ private void CreateSelectedWordGrammarXml(XmlWriter writer, string nodeId, strin writer.WriteEndElement(); // create the seq node selectedSeqNode.WriteTo(writer); - writer.WriteStartElement("seq"); writer.WriteEndElement(); } diff --git a/Src/Transforms/Application/FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl b/Src/Transforms/Application/FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl index 18122f6147..54edda57a2 100644 --- a/Src/Transforms/Application/FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl +++ b/Src/Transforms/Application/FxtM3ParserToXAmpleWordGrammarDebuggingXSLT.xsl @@ -1,6 +1,6 @@ + xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"> 1.0 - - exsl + + msxsl xml 1.0 @@ -1334,16 +1334,16 @@ Ignore text template loop through the features of both feature structures at same time, sorted by name - + get name of this feature get this feature if it's in the first feature structure - + get this feature if it's in the second feature structure - + both feature1 and feature2 have this feature name @@ -1424,14 +1424,14 @@ Ignore text template - + Empty and - + Empty @@ -1440,16 +1440,16 @@ Ignore text template loop through the features of both feature structures at same time, sorted by name - + get name of this feature get this feature if it's in the first feature structure - + get this feature if it's in the second feature structure - + both feature1 and feature2 have this feature name @@ -1582,7 +1582,7 @@ Ignore text template - + @@ -1630,7 +1630,7 @@ Ignore text template - + @@ -1800,8 +1800,8 @@ Ignore text template - - + + @@ -1832,7 +1832,7 @@ Ignore text template . The inflected features for this word are: - + @@ -2750,15 +2750,15 @@ Ignore text template - - + + - - + + @@ -2789,7 +2789,7 @@ Ignore text template . The inflected features for this are: - + @@ -2820,7 +2820,7 @@ Ignore text template . The inflected features for this are: - + @@ -2856,18 +2856,18 @@ Ignore text template - + Override those unified features with deriv to features - + - + @@ -3830,7 +3830,7 @@ OutputElsewhereChecksForStemNamesUsedInLexicalEntries . The inflected features for this word are: - + @@ -4013,8 +4013,8 @@ OutputMultipleStemNameRegionsSubsumptionChecks - - + + @@ -4337,9 +4337,9 @@ ProcessInflectionalTemplatePercolationAndConstraints - - - + + + @@ -4363,7 +4363,7 @@ ProcessInflectionalTemplatePercolationAndConstraints - + @@ -4390,7 +4390,7 @@ ProcessInflectionalTemplatePercolationAndConstraints - + @@ -4405,11 +4405,11 @@ ProcessInflectionalTemplatePercolationAndConstraints - + - + diff --git a/Src/Utilities/XMLUtils/XmlUtils.cs b/Src/Utilities/XMLUtils/XmlUtils.cs index 9a642d8556..1037de7d88 100644 --- a/Src/Utilities/XMLUtils/XmlUtils.cs +++ b/Src/Utilities/XMLUtils/XmlUtils.cs @@ -21,6 +21,7 @@ using System.Globalization; using System.Xml.Serialization; using System.Xml.Xsl; +using System.Reflection; namespace SIL.Utils { @@ -915,10 +916,47 @@ public static XslCompiledTransform CreateTransform(string xslName, string assemb Debug.Assert(type != null); transform.Load(type); #else - //transform.Load(Path.Combine(TransformPath, xslName + ".xls"), new XsltSettings(true, false), new XmlUrlResolver()); + Assembly transformAssembly = Assembly.Load(assemblyName); + using (Stream stream = transformAssembly.GetManifestResourceStream(xslName + ".xsl")) + { + Debug.Assert(stream != null); + using (XmlReader reader = XmlReader.Create(stream)) + transform.Load(reader, new XsltSettings(true, false), new XmlResourceResolver(transformAssembly)); + } #endif return transform; } + + private class XmlResourceResolver : XmlUrlResolver + { + private readonly Assembly m_assembly; + + public XmlResourceResolver(Assembly assembly) + { + m_assembly = assembly; + } + + public override Uri ResolveUri(Uri baseUri, string relativeUri) + { + if (baseUri == null) + return new Uri(string.Format("res://{0}", relativeUri)); + return base.ResolveUri(baseUri, relativeUri); + } + + public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn) + { + switch (absoluteUri.Scheme) + { + case "res": + return m_assembly.GetManifestResourceStream(absoluteUri.OriginalString.Substring(6)); + + default: + // Handle file:// and http:// + // requests from the XmlUrlResolver base class + return base.GetEntity(absoluteUri, role, ofObjectToReturn); + } + } + } } /// diff --git a/Src/xWorks/GeneratedHtmlViewer.cs b/Src/xWorks/GeneratedHtmlViewer.cs index bd9939ed8c..41b3bddafd 100644 --- a/Src/xWorks/GeneratedHtmlViewer.cs +++ b/Src/xWorks/GeneratedHtmlViewer.cs @@ -382,9 +382,14 @@ public bool OnSaveAsWebpage(object parameterObj) for (int i = 0; i < cXslts; ++i) { outputFile = outputFile + (i + 1); - var transform = GetTransformFromFile(Path.Combine(ExportTemplatePath, rgsXslts[i])); + XslCompiledTransform transform = GetTransformFromFile(Path.Combine(ExportTemplatePath, rgsXslts[i])); + #if !__MonoCS__ + var xmlReaderSettings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Parse }; + #else + var xmlReaderSettings = new XmlReaderSettings { ProhibitDtd = false }; + #endif using (var writer = new StreamWriter(outputFile + ".xml")) - using (var reader = XmlReader.Create(new XmlTextReader(inputFile), new XmlReaderSettings { DtdProcessing = DtdProcessing.Parse })) + using (var reader = XmlReader.Create(inputFile, xmlReaderSettings)) transform.Transform(reader, null, writer); inputFile = outputFile + ".xml"; } @@ -630,25 +635,27 @@ private string ApplyTransform(string inputFile, XmlNode node, ProgressDialogWork argumentList.AddParam("prmGlossFontSize", "", GetNormalStyleFontSize(wsContainer.DefaultAnalysisWritingSystem.Handle)); } +#if !__MonoCS__ + var xmlReaderSettings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Parse }; +#else + var xmlReaderSettings = new XmlReaderSettings { ProhibitDtd = false }; +#endif using (var writer = new StreamWriter(outputFile)) - using (var reader = XmlReader.Create(new XmlTextReader(inputFile), new XmlReaderSettings { DtdProcessing = DtdProcessing.Parse })) + using (var reader = XmlReader.Create(inputFile, xmlReaderSettings)) GetTransform(stylesheetName, stylesheetAssembly).Transform(reader, argumentList, writer); return outputFile; } private XslCompiledTransform GetTransform(string xslName, string xslAssembly) { - lock (m_transforms) + XslCompiledTransform transform; + if (!m_transforms.TryGetValue(xslName, out transform)) { - XslCompiledTransform transform; - m_transforms.TryGetValue(xslName, out transform); - if (transform != null) - return transform; - transform = XmlUtils.CreateTransform(xslName, xslAssembly); - m_transforms.Add(xslName, transform); - return transform; + m_transforms[xslName] = transform; } + + return transform; } private XslCompiledTransform GetTransformFromFile(string xslPath) From f88588ea5bb7feb903d57408d871945b5ec90439 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 21 Feb 2014 13:55:18 +0700 Subject: [PATCH 091/143] fixed Gendarme error in XmlUtils Change-Id: I9062ffb02dde7e1ac076996f037aa3d7dde0339b --- Src/Utilities/XMLUtils/XmlUtils.cs | 166 +++++++---------------------- 1 file changed, 36 insertions(+), 130 deletions(-) diff --git a/Src/Utilities/XMLUtils/XmlUtils.cs b/Src/Utilities/XMLUtils/XmlUtils.cs index 1037de7d88..1eb7cd90b7 100644 --- a/Src/Utilities/XMLUtils/XmlUtils.cs +++ b/Src/Utilities/XMLUtils/XmlUtils.cs @@ -16,12 +16,12 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; +using System.Reflection; using System.Text; using System.Xml; using System.Globalization; using System.Xml.Serialization; using System.Xml.Xsl; -using System.Reflection; namespace SIL.Utils { @@ -30,13 +30,6 @@ namespace SIL.Utils /// public class XmlUtils { - /// - /// Constructor. - /// - public XmlUtils() - { - } - /// /// Returns true if value of attrName is 'true' or 'yes' (case ignored) /// @@ -94,7 +87,7 @@ public static int[] GetMandatoryIntegerListAttributeValue(XmlNode node, string a { string input = GetManditoryAttributeValue(node, attrName); string[] vals = input.Split(','); - int[] result = new int[vals.Length]; + var result = new int[vals.Length]; for (int i = 0; i < vals.Length; i++) result[i] = Int32.Parse(vals[i], CultureInfo.InvariantCulture); return result; @@ -110,7 +103,7 @@ public static uint[] GetMandatoryUIntegerListAttributeValue(XmlNode node, string { string input = GetManditoryAttributeValue(node, attrName); string[] vals = input.Split(','); - uint[] result = new uint[vals.Length]; + var result = new uint[vals.Length]; for (int i = 0; i < vals.Length; i++) result[i] = UInt32.Parse(vals[i]); return result; @@ -123,12 +116,12 @@ public static uint[] GetMandatoryUIntegerListAttributeValue(XmlNode node, string /// public static string MakeIntegerListValue(int[] vals) { - StringBuilder builder = new StringBuilder(vals.Length * 7); // enough unless VERY big numbers + var builder = new StringBuilder(vals.Length * 7); // enough unless VERY big numbers for (int i = 0; i < vals.Length; i++) { if (i != 0) builder.Append(","); - builder.Append(vals[i].ToString()); + builder.Append(vals[i].ToString(CultureInfo.InvariantCulture)); } return builder.ToString(); } @@ -140,12 +133,12 @@ public static string MakeIntegerListValue(int[] vals) /// public static string MakeListValue(List vals) { - StringBuilder builder = new StringBuilder(vals.Count * 7); // enough unless VERY big numbers + var builder = new StringBuilder(vals.Count * 7); // enough unless VERY big numbers for (int i = 0; i < vals.Count; i++) { if (i != 0) builder.Append(","); - builder.Append(vals[i].ToString()); + builder.Append(vals[i].ToString(CultureInfo.InvariantCulture)); } return builder.ToString(); } @@ -157,12 +150,12 @@ public static string MakeListValue(List vals) /// public static string MakeListValue(List vals) { - StringBuilder builder = new StringBuilder(vals.Count * 7); // enough unless VERY big numbers + var builder = new StringBuilder(vals.Count * 7); // enough unless VERY big numbers for (int i = 0; i < vals.Count; i++) { if (i != 0) builder.Append(","); - builder.Append(vals[i].ToString()); + builder.Append(vals[i].ToString(CultureInfo.InvariantCulture)); } return builder.ToString(); } @@ -199,7 +192,7 @@ public static string GetAttributeValue(XmlNode node, string attrName, string def /// The value of the attribute, or null, if not found. public static string GetAttributeValue(XmlNode node, string attrName) { - return XmlUtils.GetOptionalAttributeValue(node, attrName); + return GetOptionalAttributeValue(node, attrName); } /// @@ -218,6 +211,7 @@ public static string GetOptionalAttributeValue(XmlNode node, string attrName) /// /// The XmlNode to look in. /// The attribute to find. + /// /// The value of the attribute, or null, if not found. public static string GetOptionalAttributeValue(XmlNode node, string attrName, string defaultString) { @@ -245,8 +239,7 @@ public static string GetLocalizedAttributeValue(StringTable tbl, XmlNode node, string sValue = GetOptionalAttributeValue(node, attrName, defaultString); if (tbl == null) return sValue; - else - return tbl.LocalizeAttributeValue(sValue); + return tbl.LocalizeAttributeValue(sValue); } /// @@ -281,7 +274,7 @@ public static XmlNode FindNode(XmlNode node, string name) /// public static string GetManditoryAttributeValue(XmlNode node, string attrName) { - string retval = XmlUtils.GetOptionalAttributeValue(node, attrName, null); + string retval = GetOptionalAttributeValue(node, attrName, null); if (retval == null) { throw new ApplicationException("The attribute'" @@ -321,8 +314,7 @@ public static void SetAttribute(XmlNode parent, string attrName, string attrVal) /// Append an attribute with the specified name and value to parent. /// /// - /// - /// + /// public static XmlElement AppendElement(XmlNode parent, string elementName) { XmlElement xe = parent.OwnerDocument.CreateElement(elementName); @@ -404,11 +396,9 @@ static public bool NodesMatch(XmlNode node1, XmlNode node2) // If we finished both lists we got a match. return ichild1 == node1.ChildNodes.Count && ichild2 == node2.ChildNodes.Count; } - else - { - // both lists are null - return true; - } + + // both lists are null + return true; } /// @@ -513,7 +503,7 @@ public static string MakeSafeXmlAttribute(string sInput) { char c = sOutput[i]; string sReplace = String.Format("&#x{0:X};", (int)c); - sOutput = sOutput.Replace(c.ToString(), sReplace); + sOutput = sOutput.Replace(c.ToString(CultureInfo.InvariantCulture), sReplace); i += (sReplace.Length - 1); // skip over the replacement string. } } @@ -616,7 +606,7 @@ public static int FindIndexOfMatchingNode(IEnumerable nodes, XmlNode ta int index = 0; foreach (XmlNode node in nodes) { - if (XmlUtils.NodesMatch(node, target)) + if (NodesMatch(node, target)) return index; index++; } @@ -639,10 +629,8 @@ public static XmlNode CloneNodeWithDocument(XmlNode node) XmlNode clonedOwner = node.OwnerDocument.CloneNode(true); return clonedOwner.SelectSingleNode(xpath); } - else - { - return node.CloneNode(true); - } + + return node.CloneNode(true); } #region Serialize/Deserialize @@ -724,12 +712,12 @@ static public object DeserializeXmlString(string xml, Type targetType) /// /// /// - public static System.Reflection.MethodInfo GetStaticMethod(XmlNode node, string sAssemblyAttr, string sClassAttr, - string sMethodName, out System.Type typeFound) + public static MethodInfo GetStaticMethod(XmlNode node, string sAssemblyAttr, string sClassAttr, + string sMethodName, out Type typeFound) { - string sAssemblyName = XmlUtils.GetAttributeValue(node, sAssemblyAttr); - string sClassName = XmlUtils.GetAttributeValue(node, sClassAttr); - System.Reflection.MethodInfo mi = GetStaticMethod(sAssemblyName, sClassName, sMethodName, + string sAssemblyName = GetAttributeValue(node, sAssemblyAttr); + string sClassName = GetAttributeValue(node, sClassAttr); + MethodInfo mi = GetStaticMethod(sAssemblyName, sClassName, sMethodName, "node " + node.OuterXml, out typeFound); return mi; } @@ -741,18 +729,18 @@ public static System.Reflection.MethodInfo GetStaticMethod(XmlNode node, string /// [SuppressMessage("Gendarme.Rules.Portability", "MonoCompatibilityReviewRule", Justification="See TODO-Linux comment")] - public static System.Reflection.MethodInfo GetStaticMethod(string sAssemblyName, string sClassName, - string sMethodName, string sContext, out System.Type typeFound) + public static MethodInfo GetStaticMethod(string sAssemblyName, string sClassName, + string sMethodName, string sContext, out Type typeFound) { typeFound = null; - System.Reflection.Assembly assemblyFound = null; + Assembly assemblyFound; try { - string baseDir = System.IO.Path.GetDirectoryName( - System.Reflection.Assembly.GetExecutingAssembly().CodeBase). + string baseDir = Path.GetDirectoryName( + Assembly.GetExecutingAssembly().CodeBase). Substring(MiscUtils.IsUnix ? 5 : 6); - assemblyFound = System.Reflection.Assembly.LoadFrom( - System.IO.Path.Combine(baseDir, sAssemblyName)); + assemblyFound = Assembly.LoadFrom( + Path.Combine(baseDir, sAssemblyName)); } catch (Exception error) { @@ -774,7 +762,7 @@ public static System.Reflection.MethodInfo GetStaticMethod(string sAssemblyName, // TODO-Linux: System.Boolean System.Type::op_Inequality(System.Type,System.Type) // is marked with [MonoTODO] and might not work as expected in 4.0. Debug.Assert(typeFound != null); - System.Reflection.MethodInfo mi = null; + MethodInfo mi; try { mi = typeFound.GetMethod(sMethodName); @@ -795,90 +783,6 @@ static protected string MakeGetStaticMethodErrorMessage(string sMainMsg, string return sResult; } -#if UsingDotNetTransforms - static private void AddParameters(out XsltArgumentList args, XSLParameter[] parameterList) - { - args = new XsltArgumentList(); - if (parameterList != null) - { - foreach(XSLParameter rParam in parameterList) - { - // Following is a specially recognized parameter name - if (rParam.Name == "prmSDateTime") - { - args.AddParam(rParam.Name, "", GetCurrentDateTime()); - } - else - args.AddParam(rParam.Name, "", rParam.Value); - } - } - } -#else -#if !__MonoCS__ - /// - /// Add parameters to a transform - /// - /// - /// - private static void AddParameters(XSLParameter[] parameterList, MSXML2.IXSLProcessor xslProc) - { - if (parameterList != null) - { - foreach(XSLParameter rParam in parameterList) - { - // Following is a specially recognized parameter name - if (rParam.Name == "prmSDateTime") - { - xslProc.addParameter(rParam.Name, GetCurrentDateTime(), ""); - } - else - xslProc.addParameter(rParam.Name, rParam.Value, ""); - } - } - } -#endif -#endif // UsingDotNetTransforms - - private static string GetCurrentDateTime() - { - DateTime now; - now = DateTime.Now; - return (now.ToShortDateString() + " " + now.ToLongTimeString()); - } - /// - /// A class that represents a parameter of an XSL stylesheet. - /// - public class XSLParameter - { - /// - /// Parameter name. - /// - private string m_name; - - /// - /// Parameter value. - /// - private string m_value; - - public XSLParameter(string sName, string sValue) - { - m_name = sName; - m_value = sValue; - } - - public string Name - { - get { return m_name; } - set { m_name = value; } - } - - public string Value - { - get { return m_value; } - set { m_value = value; } - } - } - /// /// Allow the visitor to 'visit' each attribute in the input XmlNode. /// @@ -927,6 +831,7 @@ public static XslCompiledTransform CreateTransform(string xslName, string assemb return transform; } +#if __MonoCS__ private class XmlResourceResolver : XmlUrlResolver { private readonly Assembly m_assembly; @@ -957,6 +862,7 @@ public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToRe } } } +#endif } /// From 340b48f9adb5db8c8c3e1a06809f27d79f8e1ba2 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 21 Feb 2014 17:25:57 +0700 Subject: [PATCH 092/143] fixed failing Views unit tests Change-Id: I15ae05c04626cc00587a1c9c5707f25643e25e62 --- Src/AppCore/Makefile | 8 ++++++-- Src/Kernel/FwKernel.mak | 9 ++++++--- Src/Kernel/Main.h | 37 +++++++++++++++++++++++++++++++++++++ Src/Kernel/Makefile | 8 +++++++- 4 files changed, 56 insertions(+), 6 deletions(-) diff --git a/Src/AppCore/Makefile b/Src/AppCore/Makefile index 065ee818f0..21651c4d83 100644 --- a/Src/AppCore/Makefile +++ b/Src/AppCore/Makefile @@ -13,7 +13,11 @@ BUILD_PRODUCT = $(APPCORE_NAME) include $(BUILD_ROOT)/Bld/_init.mak.lnx AFLIB_SRC = $(APPCORE_SRC)/AfLib -CELLAR_SRC = $(SRC)/Cellar +GRAPHITE_SRC = $(SRC)/Graphite +GRFW_SRC = $(GRAPHITE_SRC)/FwOnly +GRUTIL_LIB = $(GRAPHITE_SRC)/lib +TTFUTIL_LIB = $(GRAPHITE_SRC)/TtfUtil +VIEWS_LIB = $(VIEWS_SRC)/lib PACKAGES = glib-2.0 gtk+-2.0 glibmm-2.4 gtkmm-2.4 cairomm-1.0 @@ -22,12 +26,12 @@ ifeq ($(BUILD_CONFIG),Debug) DEFINES := $(DEFINES) -D_DEBUG endif - # Make sure AfLib is first, as we want to get the Main.h from there, # not any of the others (e.g., in Views) INCLUDES := -I$(AFLIB_SRC) -I$(GENERIC_SRC) -I$(APPCORE_SRC) -I$(TEXT_SRC) -I$(DEBUGPROCS_SRC) INCLUDES := $(INCLUDES) -I$(KERNEL_SRC) +INCLUDES := $(INCLUDES) -I$(GRUTIL_LIB) -I$(TTFUTIL_LIB) -I$(VIEWS_SRC) -I$(VIEWS_LIB) -I$(GRFW_SRC) INCLUDES := $(INCLUDES) \ -I$(FWINCLUDE) \ diff --git a/Src/Kernel/FwKernel.mak b/Src/Kernel/FwKernel.mak index fff387ca69..88d8617d39 100644 --- a/Src/Kernel/FwKernel.mak +++ b/Src/Kernel/FwKernel.mak @@ -16,17 +16,20 @@ GENERIC_SRC=$(BUILD_ROOT)\src\Generic APPCORE_SRC=$(BUILD_ROOT)\src\AppCore DEBUGPROCS_SRC=$(BUILD_ROOT)\src\DebugProcs CELLAR_SRC=$(BUILD_ROOT)\Src\Cellar +GRUTIL_LIB=$(BUILD_ROOT)\Src\Graphite\lib +TTFUTIL_LIB=$(BUILD_ROOT)\Src\Graphite\TtfUtil +VIEWS_LIB=$(BUILD_ROOT)\Src\Views\lib +GRFW_SRC=$(BUILD_ROOT)\Src\Graphite\FwOnly # Set the USER_INCLUDE environment variable. UI=$(FWKERNEL_SRC);$(GENERIC_SRC);$(APPCORE_SRC);$(DEBUGPROCS_SRC);$(CELLAR_SRC) !IF "$(USER_INCLUDE)"!="" -USER_INCLUDE=$(UI);$(USER_INCLUDE) +USER_INCLUDE=$(UI);$(USER_INCLUDE);$(GRUTIL_LIB);$(TTFUTIL_LIB);$(VIEWS_LIB);$(GRFW_SRC) !ELSE -USER_INCLUDE=$(UI) +USER_INCLUDE=$(UI);$(GRUTIL_LIB);$(TTFUTIL_LIB);$(VIEWS_LIB);$(GRFW_SRC) !ENDIF - !INCLUDE "$(BUILD_ROOT)\bld\_init.mak" !INCLUDE "$(BUILD_ROOT)\bld\_rule.mak" diff --git a/Src/Kernel/Main.h b/Src/Kernel/Main.h index 656e4ee6bc..132f172e72 100644 --- a/Src/Kernel/Main.h +++ b/Src/Kernel/Main.h @@ -15,15 +15,29 @@ Last reviewed: #ifndef Main_H #define Main_H 1 +// If ICU_LINEBREAKING is defined, we use the ICU functions for linebreaking. +// If this is undefined, then we go to JohnT's previous version which doesn't +// use ICU functions. +#ifndef ICU_LINEBREAKING +#define ICU_LINEBREAKING +#endif /*ICU_LINEBREAKING*/ + #include "common.h" //#define kwsLim 0xfffffff9 #include "CellarConstants.h" +#define NO_EXCEPTIONS 1 #if WIN32 #include #endif +#if !WIN32 +#include +#include "BasicTypes.h" +#include +#endif + using std::min; using std::max; @@ -32,11 +46,34 @@ using std::max; ***********************************************************************************************/ #include "FwKernelTlb.h" +// Special interface mainly used for Graphite engine not defined in an IDH. +#include "../Graphite/GrEngine/ITraceControl.h" +#ifndef ITraceControlPtr // for portability I don't think this header defines this. + DEFINE_COM_PTR(ITraceControl); +#endif + /*********************************************************************************************** Implementations. ***********************************************************************************************/ #include "LangResource.h" + +// For interfacing with Graphite engines: +namespace gr { +typedef unsigned char utf8; +typedef wchar_t utf16; +typedef unsigned long int utf32; +#define UtfType LgUtfForm +} +// defined in TtSfnt_en.h - but this avoids including all of TtfUtil in the Language.dll +#define tag_Silf 0x666c6953 +#include "GrResult.h" +#include "GrUtil.h" +#include "ITextSource.h" +#include "IGrJustifier.h" +#include "FwGr.h" + using namespace fwutil; // Rect and Point classes + // these are a gray area, including aspects of both model and engine // Todo JohnT: These structs are part of an obsolete approach to overriding character properties. // Get rid of them and whatever uses them. (Taken from OldLgWritingSystem file.) diff --git a/Src/Kernel/Makefile b/Src/Kernel/Makefile index b1c9db8479..854fe1838c 100644 --- a/Src/Kernel/Makefile +++ b/Src/Kernel/Makefile @@ -23,9 +23,16 @@ else OPTIMIZATIONS = -O3 endif +GRAPHITE_SRC = $(SRC)/Graphite +GRFW_SRC = $(GRAPHITE_SRC)/FwOnly +GRUTIL_LIB = $(GRAPHITE_SRC)/lib +TTFUTIL_LIB = $(GRAPHITE_SRC)/TtfUtil +VIEWS_LIB = $(VIEWS_SRC)/lib + PACKAGES = glib-2.0 gtk+-2.0 glibmm-2.4 gtkmm-2.4 cairomm-1.0 pangomm-1.4 INCLUDES := -I$(KERNEL_SRC) -I$(CELLAR_SRC) -I$(GENERIC_SRC) -I$(APPCORE_SRC) $(DEBUG_INCLUDES) +INCLUDES := $(INCLUDES) -I$(GRUTIL_LIB) -I$(TTFUTIL_LIB) -I$(VIEWS_SRC) -I$(VIEWS_LIB) -I$(GRFW_SRC) INCLUDES := $(shell icu-config --cppflags) \ $(INCLUDES) \ @@ -36,7 +43,6 @@ INCLUDES := $(shell icu-config --cppflags) \ -I$(WIN32BASE_INC) \ $(shell pkg-config --cflags $(PACKAGES)) \ - LDLIBS := $(LDLIBS) \ -L$(WIN32MORE_LIB) -lWin32More \ -L$(COM_LIB) -lcom \ From 5a0ddbdf3fa73bf9472b17a8a2c1d32a9b7c13d8 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 21 Feb 2014 17:40:22 +0700 Subject: [PATCH 093/143] fixed Kernel Test makefile Change-Id: I23e915fe4824d913b93c2d6b5c8193e2a7e6afe1 --- Src/Kernel/Test/Makefile | 10 ++++++++-- Src/Kernel/Test/testFwKernel.mak | 10 +++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Src/Kernel/Test/Makefile b/Src/Kernel/Test/Makefile index 0678956dde..a336603968 100644 --- a/Src/Kernel/Test/Makefile +++ b/Src/Kernel/Test/Makefile @@ -24,10 +24,16 @@ else OPTIMIZATIONS = -O3 endif +GRAPHITE_SRC = $(SRC)/Graphite +GRFW_SRC = $(GRAPHITE_SRC)/FwOnly +GRUTIL_LIB = $(GRAPHITE_SRC)/lib +TTFUTIL_LIB = $(GRAPHITE_SRC)/TtfUtil +VIEWS_LIB = $(VIEWS_SRC)/lib + PACKAGES = gdk-2.0 gtkmm-2.4 gdkmm-2.4 cairomm-1.0 pangomm-1.4 -INCLUDES := -I$(KERNEL_SRC) -I$(KERNEL_SRC)/Test -I$(CELLAR_SRC) \ - -I$(GENERIC_SRC) -I$(APPCORE_SRC) -I$(DEBUGPROCS_SRC) \ +INCLUDES := -I$(KERNEL_SRC) -I$(KERNEL_SRC)/Test -I$(CELLAR_SRC) -I$(GENERIC_SRC) -I$(APPCORE_SRC) -I$(DEBUGPROCS_SRC) +INCLUDES := $(INCLUDES) -I$(GRUTIL_LIB) -I$(TTFUTIL_LIB) -I$(VIEWS_SRC) -I$(VIEWS_LIB) -I$(GRFW_SRC) INCLUDES := \ $(shell icu-config --cppflags) \ diff --git a/Src/Kernel/Test/testFwKernel.mak b/Src/Kernel/Test/testFwKernel.mak index 486f09b800..55c232e850 100644 --- a/Src/Kernel/Test/testFwKernel.mak +++ b/Src/Kernel/Test/testFwKernel.mak @@ -18,14 +18,18 @@ GENERIC_SRC=$(BUILD_ROOT)\Src\Generic APPCORE_SRC=$(BUILD_ROOT)\Src\AppCore DEBUGPROCS_SRC=$(BUILD_ROOT)\src\DebugProcs CELLAR_SRC=$(BUILD_ROOT)\Src\Cellar +GRUTIL_LIB=$(BUILD_ROOT)\Src\Graphite\lib +TTFUTIL_LIB=$(BUILD_ROOT)\Src\Graphite\TtfUtil +VIEWS_LIB=$(BUILD_ROOT)\Src\Views\lib +GRFW_SRC=$(BUILD_ROOT)\Src\Graphite\FwOnly # Set the USER_INCLUDE environment variable. UI=$(UNITPP_INC);$(FWKERNELTEST_SRC);$(FWKERNEL_SRC);$(GENERIC_SRC);$(APPCORE_SRC);$(DEBUGPROCS_SRC);$(CELLAR_SRC) !IF "$(USER_INCLUDE)"!="" -USER_INCLUDE=$(UI);$(USER_INCLUDE) +USER_INCLUDE=$(UI);$(USER_INCLUDE);$(GRUTIL_LIB);$(TTFUTIL_LIB);$(VIEWS_LIB);$(GRFW_SRC) !ELSE -USER_INCLUDE=$(UI) +USER_INCLUDE=$(UI);$(GRUTIL_LIB);$(TTFUTIL_LIB);$(VIEWS_LIB);$(GRFW_SRC) !ENDIF !INCLUDE "$(BUILD_ROOT)\bld\_init.mak" @@ -108,4 +112,4 @@ $(FWKERNELTEST_SRC)\Collection.cpp: $(FWKERNELTEST_SRC)\testFwKernel.h\ $(COLLECT) $** $(FWKERNELTEST_SRC)\Collection.cpp $(INT_DIR)\FwKernel.res: $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\FwKernel\FwKernel.res - copy $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\FwKernel\FwKernel.res $(INT_DIR)\FwKernel.res >nul \ No newline at end of file + copy $(BUILD_ROOT)\Obj\$(BUILD_CONFIG)\FwKernel\FwKernel.res $(INT_DIR)\FwKernel.res >nul From b52f98e425fd2a2a01a23265f64718ad5ad09497 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Mon, 24 Feb 2014 12:49:58 +0700 Subject: [PATCH 094/143] updated FwBuildTasks.dll Change-Id: I72ec4aae10d0b9708a23a5b075626f3e2c7c8ec1 --- Build/FwBuildTasks.dll | Bin 160768 -> 157696 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Build/FwBuildTasks.dll b/Build/FwBuildTasks.dll index 20a629169d4a24e8b79fb771a9ffc80c150c31a5..d2c1882c166fc0f6e7b0f3ff8087ca253743bf63 100755 GIT binary patch literal 157696 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 literal 160768 zcmce<37jNFng5-WRh?Cp)jc!S)l=0oJu^KVGbBA64JuSO$PA}~fPmKw0&>bBkeCgK zG~En%p#t95D2n5?Dz4|Q;)&M^UJD-UMZ4;%yB>J&F6%11-`^7%RoOkw@!#d${&ZzV zJn_U6PdxEN#1m&8ck;`FQV;}Xe)r!W1RvwAzs>f1@W(cSmyUjXY4DNS*LL~Xl4HNN z%ahMLe`?(&S$b}E#zpJSI^*Jt(@WQ#dCt1*vWwT9fAP8_p7^A77o}&Pv(Lalyn9ai zgd>CC*d?XlXFvPXNj|k71xt6SFNuQS!q73MfOYxrW? z|K2w=(Kz&soO;|uopJuf!9`PNrP(>>>~r>o7Y3e^%Xb*` z1Y<*{AE65QY*6<`RKyg$zND#UTA<=n-c(H_?9B3NQE8Vg3olVBgX*b`utACx;>IR%kn$=39+G0aZCRNbR`5V$AYEyAb7V7U3`|gfywX(w@6HqYG{P9pHLA2@eY?@0 zGxMk(GwZ_Ol9ffAI30n+j`hQNCa*_4=!Y`lxjc{Pb7$~qE_Eq2mRh8i(J`HL@HPRf ziI@jS$3$aJ%2=B~F@jpU24Kb9l@uYxRdZL(eRnk0s8b0KJ=--~ha(;eH#m{EvhDw* zH1FW|L4Iw*C`6vF%@h1~d{E(HrHa!%c+@)+ zU{uls_obBElKzn!r~_30h{6gfg6vB~*s*?PHQf`O9qU&mFcj}dHu8)s>0Z1hKPeqW zHG|4!D9)1g1G!vH5u(-&WNJyeH<*$mg`xbzd2l?xXY*53{cQ+K@P~nud4)+%P(5Ir0(KX!YP=D zQnWITT&BL`GZnc^_2)|AwA)f6JKg+1J&;bH%x_+P9t}wlo8wV{1nFtS>tg_B-&3v* z5Lc0FcvM=gj-F9+po_Lxyn7al*WM{!UqGoA)7z!AAibFIY;T|)6fua#n#dDT*+frjs4h4_F>sERX#GvGVw6R-A2udNPS?5)BTDG)@#ZXo1t;{CP9Cmu02>)!9bC;Dt!RV^?MoC#hG*PO zNF|5pVPMDCuKy)jMR3I&ui^{;FE%C`vcsnLs#!2W$o~Fo&jtX_ewD(jT?d zzGX4R85*mNb#(>>40NHg;1{JhPlnHFl)=Z&7VAXcL) z=@CThuTH#&fLYqA@+9>!SUGhh;DK89eu%Wvqwv(SPvCCn?mKV~JNGulvZ&R;a{4$> zCr*V#qkJTqD3uOqMXb7YAc|UvN9yox%Gu*V??@C~@LgRnt?y!BphUD{+h4^-D;DI{ zzS-xxwZ6Ptv!qZ6-;OD3-{n_BV2Y-{k@0oGn|Q-j!`hI9!$kGTDJ$g^V2)U8RdZ~A-D{ig(@fiPReXaFoTrM>*rBvdQhZ+4H(kQp z>!IKh^0WEfP=GhbakP2hQ))GXcj@a^r&vRTm&-sPVs1}NYCQYbGvv{ojjgEvwG|lkJgTO)Qo7B zhl@wm&EpAV@SWn(1^Re<`*@G*#uI2(kDcOSDSNq4gXxqAHQpO!~6I;-MGOELMe!cT6`ufegM=dQ^4Nvv{-sE*?qcauH}& zkDcPtLK2UxN3%4cF5a<)nli4Gy^^!wcN!!z8g=V zSv_`&N0Z~@(H*;ZPwd7MXjYG%;?ZRIcnA1+Cv@WpG^@u>@i4)CJS-oV-ih6K0?q2N zQ#{OdACIov#XG4RPoP;nc8W(w?c>p|x_D3O#uI2(kDcP7VLl#O zOD`UcoQwCAZajfz^_U-TWV}B>iGx`E@(GhN6){C%>-zG3 z?B~ACkIZh3^6u*d>Aml}R^X-u4#;V@-S=tMi)kX6m^8^~H%*v#X+9Ol|1wS4E>tCr ziMstIiWJ#MJWS+F59Sd^p|jA*#8`OQQp7QIUulf-(WP>ajfLqyfHr*Jk}<;5Z{Tjp zz1F$M4(Ns(xC_tYt;*wx#>#?wF?g4D9=H8q_(z557onNmg@t21IQ)Cqj~9Xcei7Jz zF9Pc;?@VvSBCy>GFxk-bEcTbPwVw~390Z&LkM=+r<$yiEXL)!b4^ssg<522WJhsXW zJA-&=EbwmsX1YjIM!g>?tg?ZKgRL^d6POuKdP@Nx$v0i?qVzock$OA6#~9ZRB{QhN z7~{F2;1kGmK=sQF_qU`Z7bcv^U`6)tZ^7k zeF|bTa9IwgwgR7_ZNNy^Gd&r9IQ4WvHyc#X?A;Iw(^G(M2&WD5SwW^n!-11i3CzA` zP$P7jkR9}o2354wpsG{T*hg-z(Hw!zQ(*fzm^pwkZtSL(J_CxE(z1kO!Tw=#EqSnE zmh?;WoyxM@BeVxs@}^QZhT?Eqa5qAZfli$cl@5Zyk~dko@H2o84^N%RD~_hl;>Flr z`6y*0eah)(+?Dif0ygYCE;ER4D$fDuZW!_QG367i<%eXu?PQ2szYF+XSb%E`tu~vM zxsmNb!lmSyVkw+f@uuhEj?(jZ)+_1xye34rl0qg8_2Q!C*A$A8dhl3sCVdelfGXBwEYhMu1)HRY+83~hD zlXW-UOAo{psr>bhN;j%cT>?&jn7jnfKrMMTzDeqCP;sC{YB%7f8i%v@k!?SJUUL)L z)moZ?GKUosG%+2@cv{)_K&)l8NW!vtOA}UMj?CM!h#psJY=rzngveo{)DF^6q+E#sk#7cun3RBcyF{-6UFb{v%f0 zjE$UT+tF+nMLz6B{wug^3_qaA@238nT3hvNuJj^5yxOZgVe)e7o2x-#ay{K@1k42Tg?c2}2@}{%7 zw$&W%kWA26+Zf&6T-R7<4Q+Fm#x8{^NgAo3bCQu!KCN;ar;S}4!@D+i^&Am1yA1gy zQgI8-Su+07T^yA*e~2P{Z>4_AC2f=Wbpz`|mmTh{^ z9B(m^OWXX+Q~wpV!s!=-n)T+e=|VM!T?p&VVO!Yz^@o>&o({vUUw;re*IF&I9^}>^ zD#04~MHI-jhhC}`n@g<(Ly0j5<#@e#(pcoEK4C3}Ij7O?vMoY5qR>-1&G8k%R`97jjZ9{Bf+ob5Zj@agnU(IW zWOOa8hlvSc0*wAjN{bOyQ<|K3VkHzj;1vK|M$%W}+_;2P#QU1yivL+U+bo?|DV;}K zIu7vaUOKN)7)1jQJB7WLFt^%h>ot3Uh0d|wUM!KiFOho12Kg1Y9&sRXDISec7mwF` zh^^v%7z!?y?%qbu!Z7^;uXWpA`}$zZ4AU6pG3u!)%MoDOl0-g8 z#~!utCTpsyudM}owV&t4xQ`<;a{*|xPlae<&7;4X9R#LZ^QdM=<92Hv)$ByvZq1{* zO|dL$Ww7MdJfzFD?vjUEpBg{Yso}9zV=KpUeWEzj#x`{#xz_)akTOvwJ_1DgRI>;0C&!6j5E6kQXPe4EJt6$x}4==LC_~$(3c^jdbO-q zSKTzw=6!oqQNh4!c=j`KsS0kBXAagE=P*)IH6CMaI<&f8vS&H@o}jPnw(pDtHB?s> zXQ;kKuchUgt-Of}FS`V{(Z8%Dzq1U)%ab3#H?`eL$7X@Djii`8ipSJL`*Ds>+F>Tx)aB97*w9L~`S zHvXm-;5=6$FVf>x3Moic1@7d1(}EBc`=TM+RA^Rm+E+o@*?9F76|d$g%t1NRKAh@d z=5VmnJj@&p_6!d*2e6Ux^Qa6#uu65pMs)4$9q{Lek70rV)wO`-PTnN_$-V>9=-|{% zc<3K~NWj#aaWh2y32y6_s@YHaQRue-u4X^S>4+uQ07!4<5hgzp?*8!MoCB?9xr4d} zwMKb+v#;9dOW!Kw9XuLkj763qYuJi&m=M+MsRKKctfp@Rw-TjqSG;%dXhxl1L9vlr zEt~1#nw4sHDUnC}Z4|b?g{A&ZP%|4tz6+PO2szkr`Zwku&iyNM|H|CID)+C-{Uf=5 zB=@h*{TdA@jWxM{P3~Wt``70F(OM1|t$9f7A+d+lJ*4g-{SK18nyE+v zB68J@m#X=AX#lzSO-3ky-z}BC2e+G=?#?}-$iWgc@O%7dN`4^>8ZmVHT(7g{ z5Ixo-prdu+Mz|Xe`TI8a>!3Q>@7TW})2~0oLirt}MJ20A+&K`hr^mljB*$z0dRJhe5ZjN?q7p>N) zS^sYHCtadjsB13$J3MBON~3RUqq4ObQy^y|!A9Sf8NKnIA#Y{NjNW)pmp9%rqc>ia zbfcWSAI`T}u{Zi!hbTMYv`W6x=$rZgVd)2XgxR-A*zfCW^tnx*s@}Pa-F?oL{EjjT zvwfHKTE9klNAi1vo(j~>*%(?i`z!#Pn`+jXWjbOKG$4#oK)CYR>2PNxv~uRfXuX8(!T4YOo8WlNT$D9bt(xf|y05}h|0)?D6L z-mPx?xay|rxUt!2ENc!n1}7RYK6@Urn>+zxBeq9|S)!&T;VecxyO4%68S(5_^eA;_ zKoW9j!Lv<7jdEjfaLCz{Z&wC~x(423@m|ZXbG_iXRJzr{No7Tt9Ve>3y>6(1Ua=$j z1BKI}FAKuPKsE!0+otquz|B^ey%C7-$r=q`mR~ADTMpWxx}lFhO!{Q22ruVuDJ zqnL?0kjKq~^oQ93T@14n3@;k(ZjE;2y1WpxQc&TrTJVe=U)-cwNLu*QW%@3`e$$cwBYlL#&s?b`Q>*?Q?R}c)dl{>ww*vIJ+jU;Z#|d%tt$ZNx2_Ta;SE?3vFu1Qp8!_U#=P+B4Q_05b*K2WO z_6PJYTA#ANL&9lwudPzq_OOplIzQeOBr_J|;lsUfvnj)N@>f*e*3!-=zS)-MfGYj( z1s-M&2YZ%>nZv;@^e}Tc*hL;@4hOr~!^{Cpz+9heU) z)$IdO%^8EA0%Jq9y`{fe!4&)nMvmh>^>ocaq>=HhtQQBtE~5Ks(Y2)o%+>!OzX=K?`#CSn%)LVcMW9=C0Da~Os8um(n`(N6{_iHL7n`v?5mcd=50aQnOEh!{F3|B z4E43JK(9ibwQYa9UpHxISCRnM+gqVz7IF4=09g5Ol^~ho3PG6MJC9+OP1IAn7>r94LjtkT9ZDxlwg{}>8X9hc6k6z$=E z1SWX@0{9wWoB5r}PbyRVTZWG6C&r+)Oz;u?FAyyv_ft?-*q6?97U~}31R!78)z!SnX91ZAklr%5?Gu1 zqS%h;wKuftofnbYa9T)}?UQ@Tll_5YT#U;0Y}XbUy_Oj13iyoLmPF^cLaga+L{7g1 zN`FVXJQyao;~5BR#VA1U06O_YH9P8}2E+SW>$|;MrM;zI@r-YJmRj*?WyVctXPe=| zQ8TEGMt$G+-w?wZ3-&<%BCNlY@^+zAXsw;TnjSKjThdy4K=;a=ta9JlJ{Y8rB8wZO z03+i^+xpP%D$g&&H>(w2;nhmN%G0~QhCBH>kCb{IuiD&!q6^DDB!=(o;)dm9CA7^d zVi+j56Y5={be`Xfcbku=xkYwkWd9`jpMkr-lKsWI2V5#^@>4N6bxb`=fb%hV8k~^H z_G#;+%&M?zsqR=ml0#O9H3zXnGpQJHRQu9zn)_QkH$>^T&GSz@Cw{A9NxviKxv(6r z&5f$8V`;QqSZ*>6XO|juWtr5oZRQ?vDWu6F`nzDZZzX9C(J1YAe36|_>g0?c<-|R?~u2FI;r$2z&h6gI&cDk^9 zsZYLq{{iw=zMbVg;8#7+Wr(?bj_57zTN))J6nHM;d15tLVx<*i`F)er1IQ9{{(mOR z`U8rR-7h^mQgz~&{OD-AvK$#74}OP#gX+TTkr;Er$uQY}gQOSbs^)x4qx5c|_0A*_ z2A3prc>1I4fF61^T_ahzxY^^20c*Pf#QY&KCqLe8ELhUS#>q|L{1oI6X++tvJrZS4 z_RJov&%?I$V9bh}>ieL#_kxyse78*Cbu1yN6Zp}0blVs^7xrV=M1b@oKaq>~zvw+O zK4RzY;JFc+nK`qKMkb%BFV9>pPdKets*W+)g$I({jaSL+Kep3Zr(kRTkv)6!RH1#w5%rOn!w}fUgp;e6L*1-0L?Bit9;Uqr?Cv3Su!UC@Ya-Yv{ zEx#A>Q^Y=O5c>HSz^nE1<`7Oe{X!2jhl3H#;hDq1uJbT+IM|Cl%p4B(5)U(ngT2(l z%mM6x(0ZJb+1@ZdGJZ~QEA|p))X-F-cD0#c%edX~-k!gm4X!Nq#FCib(6I^kWQ7!3 z^|=cm7$%r?Nc9js>A%!F`0!&C?#R{wC;vuTQ@`Lb(7|S4p6-{pH9tLx_=3*4JlKGC zC26O>5?f6GVaTi%hFp|vCR!E`goXeB(J%l(pt9~y11MYf> zp-m;)+IB61&Xu1SJQo_!&g(@fd(3J|{tM!x3h{bLqpet*B@cwSZI(n!5APzOGaFln zm?e3$z4Rx!S%uV6vN+et=P=dxrO-(2NNvvj+Jw<8UD>rk`jY{?@ z`Tq-l`ezyREAk8tHCDJb!Bu}((b>$F%#tRi@ac*N>*g6R!{Z>?OQk#@pNJcKw|8Z26umoiloTY_h`K^wG4Ivc(oflzh5HmV5XlG!sShEeH+J?1nf!yL(%E#`s$+k+=%XXm)ua^RLYJZ>3!`C1+g zDk|}}lpOX>*)e1NcmJF^+J&s7|dJBD>P1QpjJcIK19}zGcK~yS`8m|;h9`3 zoxY4mYb;0HtVCE*6tF#3MajLLNVx{;0A9h*k3}>uuC{yco*Y?UiE=B&m1(Mphk6)Q zk^^u^_A3J_oX$>TBa}$T&P$aODiLb1D@aTiKUR?{G9Y7G_m&#nxRbFi=SU?-_R!CkTi35$=J`282_V6SJMu)e138M$>>7aoC1Op^5iyyoE(Pb$KbgGpgxGoU;R+KOUXpmVKQ zCaUQt!LeKbQ8}>Wq&(60rcK@(IvP#&W=E|n-}H2ZOHMg}-}7s^RCj^uP2@2;E@rXnLLgDL0a!G!H31=jUV zRZs{O8oqgI!i^FSs3xy2NZ{~!63|}Nr;-|dStFb{Ug;J}=@9czDgS28My*3+@P_O; z6HHz57VGTmmC;=_{YO1(9fIW=u#14X+}I8wDUCyc(QB|iXm#fg#EhfXrlq20bg+## zs|VpqD4Z#G;l!hx56U49V|dGboB-2!a+#f-dX(t(26pij)}O5Gn*h^(4^ z0+2g^<7!$prFL+EictHjlR9M-*qLI1^6T{>%PfzWQh8sT z_Zt)nbIrxstmj*ju8&Axh^HE**Xc!1@lxI!Tpl;sp7zH;uN_Ze`NgcQnMvdgBS%3q zSFXEl_I2*1#xstgdSb%UbX|zUX;cGVInMJL6`L9^x9|IQ@I%0#2P{*WeGj;j&2V8B z0lRMr{kL^K^gdh*Lw~W$gN5GT4Sme6JI8(WZa(huxE4}=-0nVf8rQ_4#`bq%Dvdog0S=40ounXY1n@IZ%dR?P2G zM5P&UMOp{SQ`r2DcBkB9#q{i=J#jCkwjIb%k@eRcUml=; z+7s5mn0mX_Stl68gtwaO*jZ)r5#B!_yw@wQnORW+; zHsWR4Jx1-1OA+H_n>TZH;ZXs0tk#@;@2zT=U%RFz0?W0WGDGKfxQE$Ud-(D!3SUSV zX7PsXU4)yy$1CblxwrSQzoSygPq%Hxsu^GfS-EOkgQVHNSSEg4&rg-zMZ57JOUhAS zk2clwD2P)`W;}_y)zJmyD~GHDE6hIH%|c%}xgXKHIf-UvP9pJz{kKZLZGhamn!ja` ziTFzQzLrmdCmV}qQe!y#lk}d!Z-U?J`FXo*|9nKG1vw?iyy+-RU{?$V*k1M*PF+ms z%*!#gxkU`AWEUpX#52H~d4+(}7Bnq)iqXqBSxyar-EDc!-_|TA#(OoMUOW+g{)#$HCQxFgafNNgijd<`^7dE}IZ^oE|& zG{AID=ikdlQSzwRc_Nbs$jU4;@Z7!l1YA1%u_~Zsq{ofk+!cGFh@flfvXhkTf02aW zXq25P$QaVL_4KKYxTI6ty5Q}&a`14J?eGNrTxisr6U#nLVA&etslA{xwYMV{W!-tP zzCys%J{G((%5L{WqwH?)%ziDGG4>Z+#(@#csjiwAZJ&Mfd=;Xd0Bm72m*&*Iq+HL1 zoxM7K?491?pZz+ZttVb1NkaAvOcO^1TY_Pb#@>H8aZrL+oRy)>wA&p75 z0kJiiQen~Fsac^?YR}S%WUpe@QMtO^a&L9ClKl`4=+(Du@2ynkA-}PZ;hjTlM|*W8 z`<-BL(>rOQD^{sZr=_QwXT!p0kF{e{lMOSkq_T8{YjwngtHG{`(od(`5WoqS!Cg*2IdvO7Wvbc)gY_NOaU@ToysDW- z&(>{NmyrWCRLu55P}W%(&=s=dT7vpk&Ya5dYQLqWm(>U3MYe{vw4BhRCg(#7;bUOUlkG#WFUv$ikSQV|{HB+noP`AG zLv{@q#RSZ5G)#zje_={cN)JbH^-Al$vR3ESwm7j*--L=(Y&J0JDSsaJ=5APa`lDcc zK~FUOmR|Vfi-q6Z3xD}y;X8WaH!J)I*edjN({Hu#BZ1NcVvagB_Pft|?38ytu_YTe zZ#)*9*m8aU%HTt^(VM!mVzsAhj@rD8n*b{4rdtGaW7vMLFMZMyw-ht1rJ3BliVK5B z3M(=L)tVWCi?)(#@UpHIv2Y=hmTp1IZ8mu;_%i%&{=eeCmVH_UB%_7tfIKstjC1yF zlfF;Vn|>P)TIR0ob1-9U2J$_8%GEb{357yyRF0OtRHj~QpqlafqZbW zt>^qu*J-1OLdEH?K0H-wj<;=1?GfPX?k+PK(|VrU|2>Q7`beOaw?~%8ohuycmmc;(o{pfM%_z`NC^U2P4LNwFE<_`;v zs-Jb}+7N~Q*-fZ+ZEy9_eqMal6!VbrmD+>S{b|Cd`13f;@xI`t#MPg>E@Vc%f4&V_ zBhlQc5l8OS03&y5ERj2JHYc;I@r*_QIaGs%-1)YiQ>JAOl{v}z3ynah&gLm2#pawN z`xb!aSd%N+ffUU#>33vVDI)Ya{$x5o8&_G zEwDy?xtX>TYPe?K3+m)!ajmjb+ngZzBx>l+Y-0lqvH97)W>Cp)2ks7OSF-QoUg_Z5 zM8U{JgP}X2{V2#)k1X?~>;mSubPuPk@z{l@+0ThRmi^M6zp>}DnJyf2aOLwoo_})? zH!B{Si3IqA#run%c$?$v?JVn2B$X{ckb1;~hAzcq28XREU|3gW=dvBp7NZ$=)TBFW zL8yc&6EN<4mfJy91n}{UsTx_f3q%@wDT0Q{i;10G3fk0-xHz)> z0$x+664>9-M=Gjz-e92S_L%JoB)d}B+H_G%PUEQ=kMtQhCia21O8PPg=-`0eLesYE zV(iFEasvU$^*pSx?0gw5tEAiUXD^51=yJQ`XCckaqUmmGWfJ9K&}D`BmC&qI(pM;{ zmy7-_k1YLHJNmEc(*N=UNn|&Z$ZJ4cOdwrZWIuXv0Rf!94Gfu$1!hxxHQe-MSt!a&*}fSj{M-Wi2yH>`{JWm>?|aUV%IQC=_I`QF zGat~aZ{~v*^ae`O+NrX&Qxq?AS|1~5{iOEKY;e@q$1{ROb}maUl^5+3Q>v~lGKYhG z*u%`>VB%A4oS4*G9O^Ch=wrg*81VF$XGY|5r>Nx4hnL$SV-*HxT}HxbkzlTmZZ%Ba zD9ueQ*CXS{^3AzGX_IFOr`IYvf2M^hYZ`YBmlP+YMNSHK^dq+GT-Y#uJH^HY9a_WU z?i0GSCCQsen2X@Sl>Nv=s3+!IImK$KjEBdO{-RSk0~|}{}s>}=l5BDMLKFv1%FNfu6+H&kC;0fZ*+O5)r_zz1rp090M@ysXS6vhSxoR+5)Z8rEz0bqaP;Nrt2%tU`bGIM{PxUkgmKr6 zYg}`0-j-e-{F=f&R(WuTBvsUWU(bxEc=lFea(S>`kzIx2cDTl!y_Ko|ml*kN+qaYB zsW;QWum_~2L4w;M>rPE9hiJtrdHPmRI`^PDQFbpy=yuSqQFt_L%U}7&DpLgQkZ&{O z`yLV*J&ih8Ku|7EJ{0A*3z=>hK&*h`4+Qr?^%)r3!_=KZn7$;ouyW^tEy zv!F^*a2fKZiNvm1W*4!!_DEH_NJ9R+qB{~N6Qxwx+}{wNt|f3I ziHRAM$=^sdt=OB~we}a%WImJq z)Th{)i@5VM@!sB2GPCz!?970(#%3iiUs8%}?=mMea#Q^bg7qg8oMRgYsT-|~o^sH> z_RdXrAr)!#Z1?3$I!`0eJ~3d|%*;dU8tb5`|CtxqHS!5;T445Ta&E>wARx+xZsWWf zz1w89Nm@!qBQx-&g+sL2CE38LBYH~-^_CLpEv3*~1+KS*Y4*1{AlDq^*zd+B@#@;|54xy-ZQ^^8}0>ZD!gXU3nN%{LlkRQJ-bgIPJ4ucg#WJ z&GFrX=c79(82?f^GqYfA*jN+975C_5DfuWmU>fbT)0LgR5bd}mmrTFjWL<-}uPTz5l{SOx@QB5M$yN7uQ?eu~vqV;BFM z5{%g?u82#?-y^>;lQrV1v4gnF)on2syLWBC&`{^G*c-GznR2&*rA(T}uJ*JKqC?1Q zk~;`gZW}LdDq6jo)!kNK@-fn*C{sWbn~Q$m67J_;BMPou-9)Qm<>WUXjJsr9I>S+! z_Q)t{-I#9H!4DH)G!@P3%IDtCDtH za?soMY2MoXlS(`7q+(*&OrAueE?MYJq+m1W06t5AtT`)b(R(*S=A3`1zms*Gcto5Ea z3;<&dSz8NZ7=qh&m&#bS(ML|r!kq4WQMwbQ)0R}8=6X|au8qD;LT_(%BdaiFf<4}J zrW3Sm2Boe)r(^D09M)?XX={AcD5?7}NZXoG^$`NOrqi?nA?)u|H~BQIN+$S))b%&V zlb}xf@g$XnHF2R!MYG?ghKzPDrzG2(Wu}J(>UO}~p}1R~kk|)>#N9=a-{k=4#hold{`so3? z)WTK|YpsKyji@=a{swZj!4;q7aFb4=`UL{nQU^jrfBAKats4%}{Lhz=WSG0ZQgDB* z;J(A8O?&-$WNm%DIiLmX3m#?;2m7LjnZv>U!NbhqU|;eub2u1tR4xs3I2cWkgP8-E z?nvFl`^hTjt3F4t7Cqw0-GC*txcJ!M)x5YDVcj}<<&;}_O8T4tH3UAv-~fRNA$t#T>}*56)FPxfzkQ&c zK997j^=OLT4ND|_0WZ7JoD*;_#O*$QIPWvzj+dz)Lq<(Nn0y@5 z-fpG$!`y~Bweeg@V{uy9@8-qvLKnRjH&3tD+YTP33@YL|qAJ?c+u-t zS(~xKO1~+&EuD(kw%J_fv#`8FHyv=h&2r1c44do``|Y4MmfaUsw8itK2qamC@Z1UC z1Hkt=-RIz*&NP-yD{?WreT}6#H2sz+E_WQ?*yVV6&T+$CL)&oI&~k=-Y5Gr!Ajfxb zgb8a>h5LG&gB{red^7GgM9^${eoia$(_F|(Gre0x2OSrm>2ficb1~$&81k3leszAD zD_oi@T$(MP=5@t1TMN@{rE^Mi#lkdK;cFL3~-<@;0(nU~C14r^)t#OI2afv!c=3k9GH%g*S_DV>_8*AI` zp_IiqzJxeB@50?t?tJWDV)L_0z&wUXPv9+e*B{MXa2IncGWdVU8!fdz!N>4Ff%j#+ zi}-&}py1q#IuA~*46XvsMLAtK-r!ll)fv&p>x`Ac?7MLXW z`u2;vtEQyIDb~+x_QgB~8gIgD{LRU#+F%WEE&DOwm&~3FnVfY|^!%ylqnc-}YCgvm zR-En*(%-N7sch@WScDlLFBus>Giaocs}_=y9i|K44)q$0?I}@xrkN^^ zuYWPjz!(!>&h4%hkdA_VJcuR+D@g#S0kF@ocz`WFxeIg{7G7$E7bI=pSGMwx-S_u& z8B3HaXG|9Dau()^Fj_S!txxFY1^H&^`GWM{C9$r)#ZB+)h+1h>2Wy(M=0t5SUM}_e zAqCT5WX_d&)kejJ1sA`)=I8Qx+dkgtAQNn5ZUKpmbHh|{~AGZLxl*E_Bb|Ff|#vm2fQP}uK zbpx{2cH*>qN`1RH!XB}wQCGGqjrTz*`2`Zll0$Pd)Y6NiNjFKL+++t3mYYu0uy}5S z=v*L1+)233wYQyJ+(VOv6{YVN=gfytn*x1%Ae>f{TC+Nset+Va;h}v);a$FdL3lg*65Mv>{8giMNtB$p>QL9nveM3XZ zKO+R!$+|@>x_0Jy;=32?cx@g>pH0|9y|x59?~XLe_*f_ZTM2qPzaa!x?5|!0>^1z7 z1#rzQ?F;N^e!cSAFSr~3$@9u9FQu&iuv{kfij&AkK&_bMbw4FD6#jlnlX|m{%P6}t zTvXDM+d8Nw-&TvoJ(Af0-sebg&z>8^tb^OU<=O&Dx9;`rNKH-dwQv)?#X7({TDy`m8>dpt77-OBYcZuQSJi zdpyNP?>SFrRFCOtf=}}Ex}iG0oFDTV0mHm5T;p8XBIsUYs+yle+id61_D9YMaW-=L ztfrv}3KJ(ZF8Uaa;&q63isHq2yhDi>m1hpqt8eD;ov763QxT25pm8cRXuXagJ??|} z9%7?KmuOi+$=h@F=%83@j-9k?@GAhP5zpP-S5%iHDGaY*w5QURF&iY;S)$Y+xe}Lc zklbHwr%X_?6YHZqH!#D&^dW6gjc2~mZ|+4TQ|n!y$BgJfK&TklocRTMeSH&yg7sMj z`rH)a3LvGD-FMgMYp1tD(lJj|vK&v|+O^`#xfQ>lF;T(I`&Jxn#iLzYaS1^u^7|}5 zwW|74`5w>^Cw|_;R1rl@OO9lH>=-b&Q=rrSeej9^r1jDiNO{?zvC!FQd08 zm@e|x>Bl}n;NX&JbSfU%{BksCaLHAl!qc+_`m?J^r)u5cz$}Uu_gZS#;$RRVyX;k< zxt7IW+Bc^u`E~ch_ta;IhrQ7^ly>{BMr1+BAIQN5T3f6s-D+D&u91VT*v#}vOgI{u ze^k3rP0k?5fj1lYI|gx!Gg9ls@|x}u`h$j+%JS(f~47HHP{a>gCsoY4MqOrH zZse_O^zYC#!@OyV%`nrX=Tyd8**_4!TMb+^GjZ~8zWYTpF)u#R1G^(l4*fB6XTQz3 z(KGHyUS;})ZlT7PkoB~Vs7H?DL6&MAR@ z2rYG&K~1VAIa8Ap14_Y#=G#4_)KPYUqPeRUU12aG|5;E=d8*d%s!h|mu3LDYE`Ci} z=r=TKi(I!Mavs23T0B;s`aCbLabwsX8!t|u+<|Bpm}gj3s@IP&=uz+Bm~zo4_JDdR zztpdqT>;ZJE~}(pgt)G?WJWFa11{sLYJEhtySJt^^Ie!73qHOMQro5|j(FSmfUKij za_{%$r3&ZX9~eG!rgzJsZ^oE|=)h}Kk|NaT##K$ zPBdi|r+4t^Ek5Zx=G4H7}6twO3$2TYmnLGwhnEVXq#3pn8i=eb?K>t%w zr^2hd+MC=%fUB9#3Y9v-0C$ z`UfDT0jpaQGjP@HRxTIenCLal8V3#V>UVd3Gjwll~I)Z5jV#8 zsPbmH%8o5i$iIeY=1-LTyTx0~#QrMT+)$c0ze{B}yRkqf`PBkO zOJuWOBd;d54YT6B;2#T~8J6zcMOs215|`Z&Be{>bW{bqS+sOVv+ts6G8HxFeaLRVp zmWH&?#y~^1!jWAE#tu(sgzr_q4=QJ(LnYUFkQ=79G%+5t6C=5o1mkG-AI0dMJSNnY zXbwl4USA0 zMAaGzS6w<%j$E~V@Bnx+*@}4Q9n+J6=y{0jBDYeigvqN$rw44ysCZh{#aR!)+wQu+R7?Re;nuB<>u|M%Ja{wC| zZw0c~&Q`mWul>}Y&|{OYQ$f!`IiRD{iBct0;&*?6$e&iJwY zq2i6-Gx({`(;sue%8&Nf{EO$=92PeHQx7wTgZ<3I%mHj<{Cb-+J%_waT?sW#b`2^w z*2k}fe(qOhoQCAQ*ZZozC>!3`~=R#Iy^Poqhsr% zw%%LIo(`SD&8QkP*Zf(s(Z{-jWSTR$@%-Vj%W!2gNk?cz(VW*6AYdu!zzbZ6lpEgT2tb+0711e^$bsHjO-=2@1{S3cFx&CP= zwVR>JQUACA_5KG&9XNIo9{LCSlkbwM25hlxuDCfcI53Z!jq~HB3_;w5<;qF6l~7LX zT?6|?#@c+m;?@NbPZRZ}o#(3DmS!WzQPfOy@C6Bcdv<-xSw$OcXbC9Z&}d9-6ti_B1C zXzDCERy0yLjZiY^`dhJ3TtXn8U%Bje^N=C9Dr9YXp|YJ+%g zWltdm-`f>TO!QO zB|g4~tFBLNgJIi_=P((8^gzdEAs0t1~HP+9k-uh`&6QJ+W^U6j)&@z=5gZsoY>hQ>(vZn%ntlPWpY2B z9%a2yT&ZUtrqF!{i~VbJcc&0;(fYo11LT(Um#QtMvr>A}_=4r7zSaeYsBkOQR^Rz4 zEpP1hmh=JZ==$ACO5ZepdK#sO?~WJ~V$Cv+(0rHv&g9q6?_z%9N_xS|Y)rwQz)u+x z9Q85yYk7a0U!mW-lLAw}_X{sybASWvmmX#g2Senp9L(WhwBZhB4hOr(!_47ezwt10 zIM{DJ%p49z)8Xiu16UJVbYI^33zNO2=cdZ4OU_RpISQCw?5&8)UC$^x)ohdBdwS*| z4te{7hnWM|Yl%Vq{ez&u#7t?@poKS*s)&%b&zt!FU0ce9W0)WAlg&o&6Azabea z83zI*TWgK7ckL8fD6HKeQYfrR88lJ$*`1;!`$N!)4yyu`AM{W{3)FyJDX(9E_+Ldt z1$x9?79g%Xp__{^QJ_cMZ2{s$5mA92agPOvTZ@Pa^oV;dK)j}is6danaRK5@MMMR9 z#Lfc5TZ@Pabcn2P_5xg4`F(FAX1s`{gKtRjHfU%T>sk=^J%Itcue|2ICP43& z{gF&K6M1il0639LBntFZ109cQE%og@r7}lV$KKwHz{&Uf?rq*aGMkmj?icm zt~GRl-9G!}M0q+t^}Uje{*KD_riO&cp(=5V5t=UAF83{t3rN?sL#|2D!lukU`>6T@ zwJ0^$jQ<^^T&vPuI@H!!uWr}?X9n+}t$UWzz}(Td7}vAVVms{W9f^e92)7f!MUoft zVyDI9Bp{e~m$tKhdKqpzz~Q>}cC|2iA@&^vPyW4%da02sp7JbBjFEbnSY0%M9tDo` z+XSiXD4XJ>-(S}aatPT|;KWVCF>Mg%mx~ywKKwbAH8(_ut_j zt>^RNPW-Z!*@EpR8P*TGyQI0HvYkU#dB{j3%0a6=XpMKQ^^Vb+8)8)kD_U@1^TcTE zAl1QYcHc>4fSEnE7{1#vwERh44VLj~bwZl8K{m1g)vR7@JHO%kUjX<#++T1X{^TC~ zT-;&u4K(UPHSj^O`DL4*uCZQ$+|4f4@F~4$Nx^+W!F_STeWQ0rZYyTpP6c#7)yGze z{?#egRBSx@&*|OW)q#1R(<3|I_w;c8#Jk<7Vg6Sus21HdZn|2#pXdVK(k%VqH0zP2 zx8OB+mKoH+u^?^Uit5$H*IxL;@uS+bw=#fkJm2;itI@=ew2i9*bJ+E*$SP5VnqtN{ z-r=?`=W#ZDOSQ`G40#zDn43${Sq8OU z7r|Sv?OU~37V?9C1KEAfI18Ujson_#QTi>O8`u#4A1V|2ZdPh&&z7XL+;MUo?78no zyDDU>^9HqfEqJ`w^JtC&kIy8ZClEbMPEu~I$!Bi~xwX9gmyc%-i#Ppe4>N~@{kMmi zqd;Hxz9jhdXH)udvelB?qU6*ryG`@1omG&@`7fTHIf(1Wd*tP>KFk~zHhrImnFE;C zrqBud3zMf?lBX(3rfg|gIcYc5w#!5ID9u=?d(}V+5%E-!IhAeatlr_Cu16Gt+2U>XCs4>Rm+lF z`CNiv#!4x(|FN3YM@#CmMbrC$WS2nJee8{aHWwp(L50wdGpuS#I!>Mq^{#2E(kW>J zb8MG*4T0w_@$z}`C&_A&(BU>lb0xmA&5)2&bjEQTiH4+BvOoTI$PHN=n1o z_ok%Vi07LU+66Q}9?K(_(rJ8Vr`1dDHYtXed%>W_jP6b;v(jWWWj}(D<=d!)j@|V+ji|-!u?uF8mNWORA&;a{eY#KM5(Dg% z274Qs44jt+6VKi2h)%g_eS37@o6?X1(eA0%Ce?hVNn_6>*rp6Wk&2GBi}GwOXz0Ox$@*FG0FdpL#A@bmbiQsMxP1@;lfc2oA~;`sHjU*P^FKNi(&UF?(j+|XUXjs~_0JyQ%Ip-XBy9e58W_G9WBg1#!6O#;1%c*~#z&ugb_w)^@m9`FO zZM125DP^84|Ke}n;@R4YsU3C8&K%l@|IQKDQTBDIkqs#%ylBKBb`Fpy`+hf2R$eq( z%R_BSvT%WchO!)Umukne6+||=uN~%(M)x&u%H|{zW53ryOI{4}r6xyftA9fh*4oSa$AHIv%bDno<7g{^bJMB|1uCAsv5=&zq_0By=hH+3GPd_EDcA)Ac zl%bT>-e-3w*N}y3_DKl35|T8k*|)r(S+s#D`;$-428GRXtJ!BgBMo+PDFo9!V76K5 zu>KuTaWS9rt!323bXR;?^%-!?m>{+iwh?PBTP@)40S>$7!5R`joiMt`O(~0nu8y)N zaaWJ*+J!oYuj*c(dP zsMKaBm37#dj7I$7(Y4kx$~KoY!e+L)>t~Y z++9(6yx3oUWQiBGLv!qAe_EA?ohK39v11lAkh6La%lbg}njSSJE@wkCN`Q*Z#7aRnfF2zkWHY1c?a<(b?2v>yBI9aT}0X6 z33r`KLg^dhC1}3Y{^;VLknuv>~V6cjWffenw{$XZaF2J@u+;pSWegEd;({& z$;j=;-wH#GXRg-w_hLNuY_^`O`Ln5DjK|B=$fV1GMA<3lbSYooa~}9i5=o}OtGT)K zw*qi;>7T)sSB-Dt>=CZ!&@JaaID<9<_Q-z&a-OjR&&!>)i4T~lUIU<-XXoF2V3a-X z{2us?xbx`$(sMrQf*!{EapxGn?KzKpRu}pzoXF%k&ccYj%h6^30iDS6eV=f|&;hn@W+!aULiDR-Wj`o9!gE8F|C{mOi z0Y|x*23618s<+uPW>DovInyya=U!WIA6#&sTyS4oaDSlSz8m+d{66h_3+~pld+>t`?#m1An+xvm7u^-idEblisUGM&#$jmJ_C27`T2Y>Cl^zdZ2zP=2m@C4Fmo8p%~ulE@59VN*a+X) z#S#y$FumgxZ=~6(?*MVLRd1zm-FoK1z^b+$ux=Yp+XUnM3FGhBZ1Vv(HJon}y#X|v zeCRx{8`pjKn9+PrEBgX-j_qU}dDi@mZRE4Mu9K(RH6PPUt#FcAi&dJpY3NQ(?SOHd zxX&ohX@aa-b-XbA>+V?XPN=OTMtjWfiFq~X(!Y1`%iAEd!tIfH2Jf%&6G_@5gR3mo z@jJ}H3|^Rf9`G_Y2RO)msfU@v!IpWLIe<0C4+>5vh38sXyo$1Lll?0Q3z1N;?fQ4a zf|=gQs|gMhA^G8|8(Xq{Aa1?N?bVD~*l8c6DFY{q?AS}YGel&R?{wTLf;R2VCYW}z zE0NzJ5YtPqf%NFU+^16o$T_e4n*uhE!A)oEKIo=1P-Eh;y>&YuduzE1chKLfNx*%- zTyt(NCk0lvFJy(e%u2GIL{+Yn8+uIt6wL0xSo^mtCI&Y;);3p605$-geOUpGuj{eP z?sZUeiwtNAljicLyTf?f?uu1?(x0dBk^+TtPt=ggH$ro`{f&?)rC+tWskQ1eh<_#J zg`Kbt=e8~O1qw99G^&rcdNW%ooLx`KW3wCV`94vw173LsviFd>p8_ovQn$&_A@vaj z9b4{o#~c8L!CD?>4qzkW8-u^)%|MiX z>s?4EOy13NY7erh&DJ+b<~t~%FnJ43x2-@k-Gm8{hrM-Sm;ia$+ZKiikcYivVVD3G z#!Y3g@IY3n*6RFzLM_v%t$GVT83Fn$$hz(GYz_;X9`-PEIM_-LGY7Dd@zLN*ys=-A z&HG`@&9sHd`*3SV!%GO&js~}J!EIkIcMb=}_f=#$TY5SCCsLd+`8#r*{D@l8&p3WhVD+76tZgR8 zmPFP;qL#IYPY?Qv>uJrGm~G&uQ~dIX4w3&8`E%5>-Id%GCS~@HzgZ5No?34j$%$+J zq0)Aqw#LKE;b3b$%pAZ*#*Yf_qTiV@J$0?=KFG#5x?yrF zg<&n~C*(*mm?$9u%`}+Y2O_Q!ZD*$t(KlmxM2Fu>ZX-e~o;#1E!bFrFDs~~YZtO9O zt+cJWP<2+qjZ=kVC&z`$D-HV621;QeSiLeT*yLUUH z>3fLBEo5Uhwm9@`r-R>tj&$v({EBt4vpDVVe8jDvw|}I|`kMi!pV-zP zx_Kw8Xq|XhuV3bHVV_sns%*n^^yQ?Z!bEV1on8$=49* z!fa_y+ugV@U?0#icls_;NMXCU8^%Ob<8;QNx#A$rQp{)z>wFyzfUSGGZ0!YGF8xNl z%ErabWsVaz94>1oMBv1^eO9^i3KyBtMxN6>yOG;G zaYZ+PP);WFzbdKB^W#@AOG))I|369^8W3iclt&Gew6w5tn=Y%`GI<}vX>Asq7p=@J z9u{ZibjZEc>$lN^Xqfm7r~^m+O`yFpFzasu9oYL?BSjc4sk0~O5)>Iw1JA6h-YbhaE{}0RH3K38YU+e){wbk=nt2!f zaJlh`%9P>Y5$&&2BWnfL`qSWssOzwp`&m+`SgU(D@(v;mJQLDBJiswL=&r!KtXtJ& zNX#ol7|sc;;_=1uJi;DFbb2NPUmlU0t$K67yD&1&HL6k$fCqoX42_+E}Wn0cRP+Adb}q;*+XH%0i^7qj@V5pC92At4)*k3RHP7Bc@Ec zwo(c94)(D+q0Pws9MQ3l{N3?2jQlukp!^nqH$3O=@c7_dj?B89hqLpTk7v(qiFots zLO63e|5s4e1EJ0U2U#Kgbv zvGuC<19`9iUAghJx)Jy_rAG>!8S=>e61k|B7}kWd z^AyZRe*pR+#^Kd(+R*dG9X?<1LFpIufFN7mH|{h!AvviKV9O6e`qsocmvxRFvH5-y ze!jf?j^f3+j`$gaLtsB3V>EXMWabJ|(oc|+ACUL)aDxjlPFy+Yh?K3L3Le&UKTj;} zYUXe@!V}j$&&0ojQL9>0j%Lf-qwH37x&En9r@z-`L)s+ z*F$zwWKNsS+-7qzYoSi&#j=UPn0L$=pW`59%oYP_!PlbFCx+!~S?LqQ^0lh;iDCI# zSNg=Td~GUyVpzVml|C`xi^Tb1KHoE6#`_y+sd8};eHX0(Bf`yUp6TNG86M2|2g5wS z7!B7Kynok^>GqHl1z5Tp2Xy8I=5XD}JRfhl&ARfPe=fNs10@Hk7r4pr!A{^E@A>25 zpz8co27f}r7ZevohwzR56A+3W)@78#I)h<@ zm*4PUG`b3(4B?jfSaxWq%0R~*mntIXRsGmUo5iJyP*lSYccjRdbBspUIYmyxlHXOA z9(N>p=+8+SjU;wB7Pb!Z^S0mjr?v8V;>fs8v<%H_fow;2srXoiZ->R{2044^h2I|> zDraBuLIQ+%xF<#2@kByv%URQkjXB(`^%Uclk{7NezKJ#xN^YXH;@~XSI@E=X3spDF z@(o6K92AzYE}r4|1$!R3cxKGuUV{Bw)lzp{H?vNKy6Y5sMXNmc!SA%rhhieKRqNIn zWxV_Zg~CK+9Omeg$u4Uap39o$W0eah3uYpp_)$791{shye&C)N-cphk@miU)-t*9j zyL>f=Ra^qjkb>Cu#3o* zb#)4h;;z#3Sc&#dKp}A3bRx=(Q$)T+I5cX4g6IB+H$oD;-g1=X%W(kDj*W&nhc|@7x{O_|qQep=BQeWiy=FtUJGVVPGR1P-Hm!HwSmkrd z^=Z6m2Z>7?thTK>A4Umqww@cuU&;|b0}1l`aE4W_5$ze*r97>sX4fmzPHSyAG^&ji z;Y%8xy;{S&^B%d%Q~cF)vkJLE_pRDL?tvYH&v*D#KmXYqx(7bX@u{rWYUkS9p$24s zA_n4Me-dBm69c{=JO`>TzR_dRrhY-2s=Q!YyMw+MYc%>5?!0(30_)a~K*TpN-m|;W z?|}6@@Ji1goCxPX67NgFFHD}BpwESdRX)`)uM1M+3zWGy0J9z>#}C;VEZzv)U!JRD zlV?_7yy}VQUS{sgXvyC4P6(&m>p9*{`w>8J-ZO6y5fBebM?E;69 zglno*@gw7!Q!4bL|9X4O{pan0LqE)!#2RdkK1ZP%Slh%i{sdfj>N8wkHV?T!M_P{i zBm^GJ5`a)2muyR(JfSz8hqdW&(OvE}vNj#I1hjk8d0=B=dd;7=ol~CGjJr*6Hwr%j z)V=ZU9OuzVdF!Fq$rggd4QzjVc~Lgf9T#RC)@WC|a+CjQ3!=YfTH6W--15BLOZcwd zUmu1>-OK!)>V7_|+JFzLv}#-Nw&i1}tN3)S=12d=j*{nYdGK>^Xfd{Bz9G-xHRg5X zvC^D}k=y2&!!+h#D7WRK6JlajE{1vQNX`hGhx?omigO}1JmJ^mXY+oAWE)|FHuZK| z?^U!Go--Gl*y&M*4qdtKwx%Je%jKtPem>_CjXd$6nfInqx!bAQofvcQGtE}HSXFwx zOxe2{)>}=m$CKk>tDFey28S^x(Y<74K6oAjw{!lhjFwaxtv!#JW^NrU+@5y{mTAnv zWHp<0J4HQ77nN(}sHu_{vLkAjLA?+Qm5x9DO*yM|Ok7N>xK=INv&SyabQ^vT=J(+u z&jEa&nGAbSL0iTNC3!`FEJauIw(22uKWMaOUeTDMD1?l^?C#*a~qI8?XikQ5ZG z>JQsn4ck*z%f-jLZ($OK!}?*1-;Xk1huZ)ip-eyG+XmklEWmB(7ijK;ODX0M)0dW-9RE$>KH)j@8vIc<_V>4qw)xU*8+%?A z`+)e5z^*};Z8vP8Xsh&%^Jixr3UNidJgKegXQwYsbaBk-uK8#-Yd}wW$@Mz8 zAM~YQPY!J<%<`P==}S&8E=vP1@eBKS4fpb;sbbF*F7#S~JnV+ufEs&8csHO{!d}7w z!V%yq$(1jC?#;F8;WOIiNs&IB|GGZBY`hOI+ZAj=BYd)bn$Uwji@;K`Ul;oWu>*WL zG)CA%I7PU~m*bbgMt*#`1s?Ogik5lZw?5dzuRdyinIE@`U;JGD*zW#Zt{45e&i9FZ z#{XOR0|JvoC%!a!>IN<8>u~t7r~>;67wF!Erz~};QX|x z(XmDhO|Ef&jZiuj%khtQ8G=WGj_rCC+hu`pqwr(UmzoUXGL9Bb7H&vm4~=Dx$=-~d z%oIK@+$uaIJSY5J7%{osWM3Kv22$Q+PITNg|IlB zm9W%DvfMB_DPbq13~BVasIMdUqD1K!lXTjP0LWvQt+ zW+YSyRBdG-`)seEIc#c5j3 zCr?*mWk;3y(=|!uEV)FfT3i$7$WN5Fs0$P(DiG=tUBWR2FBdLhKT|hRjYQp|UZUbf z{X+djbrW@)hKfoR^&5>8HA>VUlrAb)6sb&63q%=evZyDaLa>!{3) zij_aTDPf-KUc(dWU4-3)^{^~=SW@v;kBK@d%11pe>VhbLwN}&(QDJJcDB~`!i5hB~ zC|^;LYKN%0P?xaP-!+PnmnITcSA8O3twc3d=S6iF)lS_)&HGadj*LSH$B8DZ3{eT# zD69%aby7A_Pl)QQa2$!SmqjHir>H}sl9VSl=Eb{~p_Ni?W^G}6&_)N0=fNY!R`@4I z#d!@aS`{@Glfc(UjRUttO$Of+o)CU3G@{ubB5Wk=BpfcBE__&6Cfq6fIGWR}5Z(|v z>#!$67$fW=93q@7oGV-g2GC1&^1$77=75LmJP4ktvkd%Jcw6XQmpwIw&4dZUKEgC% zj&N>WPG^bOYlWM|vs-vrct-fG@V3yq9xqi>*i4uJhLWTC9PeoIZ_YJb6O5+j&F_b& zZSw`VB$?QJG1$NPDtNM+KM&4m{vtf{VmSVj!mYxOgjaLH+AI7(__6RaFq*zboB;Z}zAU08v!SpB7(ks{ zw)IuC6t<%0h3~Y?hUe>+d>#1pR@@%m6@DW8s?|F9e-_)b^#<5ATfYX@X)UR>&O`kB z+Hh(mZ8)8`gvW$8+Hjg-ZQ0N3YDL4_F((QOgbReLh0hD$6dn+s5S|y_6q@n8u8{bN ze#nE^Ny5u_f9mI;8+U&O|F3s{1v)w~1BJDPR{TaCIEC)Q(H%I4MPio--vBFXyWDeX zz|f+Q&df*@OT6oFTklxJtN9co=lhfNsn&-9AHZvxWBv7Ym;e zZtm78&_TP!J}CTLcooDb+nv|mM3^GX6mt6spt;?7i#*hWOy*Ycelo}ZOn6y%OK7IB-&a^8g=0piaIFsM zogbuVY;Rtd)zaqlX8)?*+#X&Q9uS@b1L&9DbAnQf{^+xeQj1)DnSsJcP*GiBOE8)e z`o8GxprpR9p)5W6eial=eTBn?llxwVr=TzA>W_Y}`L-Z?|8G26P?)eWs3@U7=Ok13 z02n~e^yk`p7et*5V(u8kaoP-KyT8yX#Y16J4`3?3 zD~(5_8fiQVHB5U1p0;VPq13(8c#KU0ah7SUJGI7RxkMwyGrgMsh}c(zj&zP6E$k>9 zE-XmroGi`Y6fBQ5ww%o1__f9{Q@65UIgk^F|ixc+E%wJFvfIb`Ct>C$jxaYo>QU zH$%ma0>6#oBjttRospuV8jaKs!W>8J7oo_4y1b2C=X&f!;?v%agByuURoszIgn`y{(s<5w*+kr>F*2nscKP zz5J=%Qi!<*>aeH_u0Hin;kS*gA;-MnN)wf!RbjmngiY6q(+s37S}m5CH?&$UG5s5H zD#gxCqWXxs;Cip#OJ0F=L#v}!Ok9TK^?f0#nN}C;@fs#+b-msmEVl#a-Z&=JPlQ_8 z)KY%+Z$jPDs-CF0W>#2xQIoVv6;-NLwy2X@-6zVwxwYI1QOR1pDym4UgQ9k5^^K@& zTKyra5ub`fKEoPtuG6(@+JN)9TB~lNKGABF#B|15%gqp#sMSNFW^1)Z)E2F_in^rL z2cn|ltW?g38m`rKQOmTlH{_fh&?-`toJzyBmH39gBdnkWr?Q-;G>rBRrc0t0Iv;45 zh@-BWeDM=uD;oCo4y8s~z1eV(cNoQK^{<8_y~8O%tM8y9C|N77MkBpz&;YF(Lq$@$ zR^6a#(j=|MLe-)It%{-Uq9U!0Ot0 zYjrnNJvyM(FvP4+XSB+PYCzYtS_ajSY%=L#IlTzgh{Clx0M(e9Y4r_M6H3%dHRf{S}qEbY^Z`%x?%(2Dy}EPbLC_oG-k zsTKF5SURH>_taRb5Vg?xbu(7ybr|>lSh}PY_x@P=Rx9rPv2;T#?)|ZJODpc1Xn?J` zO;~+1mYiB~-;5=Ht++SFQn*&!8)GR-EAEZ4)JQAtjjP_z!w6+b`{6gmw&ENNKO&hdY-~1TV7Ol26Kkwa!c4&2|`3c=$kX-@@O#m9uJyXlyv zWPjU%&RELXDz=0=(0Q#o$Ceo#=$cl&5tcx=v>Ji11WZe?$~O^V9m!j(SqSS$;aWY2 zuuc@E)sqP8M9s8%0b!k~wN~W_>r9DS&50R@~#L|dxD&iQnqa!WY} z#qBb>(n+njA9bZ=ohwth47Ej6K={141YG6VVTC!l^>n9WT5;>?PS-^3cky=bPH~Bx z%6`{^I1WqG>hZYixbBdyRhfiM(rO3t(w%Zd?Q^z0mr$?_fHw)n~0;enaV&RzJ25SHmd0zZKKbrpy>l z)3u7iMbiwt%?zrLG`qH3}NG_nO5r%Hjd)8+Sc|I-r$y~ z)uFam%<Gh*hEy@g;aWO|Vu|;>(PQ6s6TXgiRtmtX#^z2w{_`wW#^d6$s0w zWUXEhm8R8hQOmSCCTfFL--z0w)lZ@hYh`cGX&%$6hN$zFqGs*GRW{w$steR)3LeTi zvr0RKHVk9+o;pKi#uVCZDc5kMl0*AM&8La&@Ab=}^Ezf>`z25tcp@TNc&ZS^WIX}I-1ow^B)QW%K-beMSVxITAk8bEN zuInPYtrgdG5jjUon$8OyN{|PCt$yxMhV%Y4MHM?82_=}(T~Dikgfim+iqooQ!YSlW z-nf9@sVx((nDeQd4ok*z3#gA)gR$HK8m`swz!JkSt`wD6`HJf6o|8zWVtf6IEg>;IZ_tY@?_gOUd}T zhYCbpQ2V-s1n!}^mU7kXy32TvinKZuehTlUT%c7u30tI>8_=~*;Cr-0t65ze2kxU~ zTCMIH7x+G{)asqC?E?4HYD>A!cP+tlJxWDcZRrDwU(ES@&&i|P2UK7w;*swITBa3` zUprGtqO4SoQfo^&AMIX3M=3$8HQmdMqm-=G3kdrc4bW;Q!u~~RT78JH zPbpKYQwaN%rfYQ(VaI5;RzD)_7%dQ0?EDR3$0_a+scR?ydO1$dkJaTK(5B}u;}l(6#;Taw_Y7C3 zsM~T&B}1Ji3|si)yeta*oN_GXoMqnY_a&{=>UPiNfnQRoR?g&m{l21&S_LLA5B!R@ zX;l+p6|`Hch6t;m16s92*jf5St0Yk;wHhF*LaQ;NE{Q6pNy&=NQsN59Cq0eF&zz-n zQN?&2E34s8S|ys6d?4^F-4MkkIu&@HHms^FAFdeFHc{5G#zop8>PhOJayjrKZCS%H z=hLv1G6UE8wVDKVnPxx5Vaw^Blt{Wli$u+*2N8Ca%C&kN>RY;{)l*R4(WJFjnj4|M zr!%68>5Y_d^#h%MTEd*~r`+pzjlR|Dgs2-@alKrl+gfqGTqD~v)^ZmmrngqtMFneh zJ7sy`HHs4TBzg4uJ@7guKFiB3r-)w1jh|?(sD;$5mru|QN-pKFh0adBPSH&opjF>q zSInD~CTc$FIwI(2`gR@1ET(b28U_8E_LZ@ElIHa45cD59snyb6-GY82|MeWUoL%DM2KrPYg4^eAHEhpdJ=|P6t_M9vyBcG{m zS<30`gKGu2{AQ&Y)(6)Lly{}V(Wp%YYsE*SHWj5+gFd)cpc-k_rq31Au3Br=txuk> zLnUa{w@)EdvQ|S8=Ai~?m5DG9m8Ml5!kj8ot0IIs)pV^MLzqj=)@l{PTxx-+VrMDx z;;B9nWgR(sszsZ*M9XPQpGbtQ6vgfOMv#}fRHc3m@>aJjMN9ey+I>~dD^e4*zHdOV zpQ^XjO685dF~I?9k*J0AW#4l?K`Q=rE9Q4l!769F74wh2lY&FkhAK5HI80sAs!6|v z!I3KJ4USn%z56{8TwC>d(@JGZzkuL6Dov|wMXgkt zRxJ?LN=?$L3&L8f=~|^CthJge>Pct%fFsmKEfBTbdC!2;MjN$6hdqX{wrZsgdk$f3 z)mp7~Bdnd;A?kvw%de!_|UvOC9Rd)ip}eG-dm(QKPlmuX+vIWsI#-se|T(q*tlpK@WzE zyJNZWRbjmbEeXl0QmKPhhD@qbyj+f2X{}wxf~jhQrJP?3Dxs-rvsT{>Dl?|49a?=i z=oIFim1|`me8rrm4vVsST&~L8OZc<)%(*JZQqD<(ODIIbYLPuV_@ z<(z*YEMIwR>rd1|*-^AR>r9nh)- zVfU#|w0a3)_o*{ly^XN@)p@OsBJ6&3O)EY=D^j;Am&5T{k+L1+((WTZ&MH=kq82*8 z8FmUPS*u@%T``N*V66g%<2S5I)2hjE{DxJNwCXw>zhTuPt%eQ9Z&FUj?_!lB%4+3{ zRe>n0)h$+wtT5-~ktMWPEz|1$k@(H5)@pSZ&LupoHfXgHVGpYwdIy7+c7DFEVoQ~TgurT zYhR{$&?kE`8UJvi!$`M5ez zZMhZdMz!TusM|W`d&tWQWjk)w^~cD|3gxfWDTJ+5;aYu-u$8KwC@U{ds5C1~^74er zyd!LPRoKnoC)5D^EI}J|zKc7YpH#!OnwoYq_(_#1Y9Y-`!we`j=`)E*_oclQx=P_k z3NJ^Gr4UCdJ| z;TucU9=*nViVyJdS4=HNM+B`^Hc{Nl?arr_zo;i^`sgF{jLOmKfze&Vo>9CM?;FcT zCpgQh)Z3#6hPl;O2wPtjc5QS_h+F+OdPLZUsxar6fnm>8sb*smoX=OO&SPRi+-lgE z5n(S>g-shXCTwGsdSFaW*h^Jv3sQMiZIN6rrz2y!hP|p!-r)yBJtMj53I{7@` zo9bJwqQ;gPZ>n2baf{rc@B;>a3!U5|cPMX5$#&nVf^}Hp*gW5zs-{-G#uh>~5@ofQ zx775jl8P+%mYQuT=YwNQ=q**G)ni!uTWX0`s}QzJt<>sSgzZwLT5-;HtBqQ5&UUM9 zqOA43t)jl;^(~+m#=al+w#w9M*VrRrd(<&e)_7K~&REL1B)x>n)p@Pfq?Z}x>Y7#? z5w=&|(&|lw?Nzq#r9{sC2zys~Yjq4^@2YUEzDC%4DoU&C2zyU8(~2@mXrF4Wm2XCw zu}>vxRTE+Ft7NU3BJ6!NSgX4;PSJjqrd9WhE9QPRNt9Lg4^-k0?z;X!C0ok5IU~>a z12sUa-5G^YX zA+=U3b6lBmNNp5lE%%{1cHO<)hw6-_oDYvHp%2x0tyW{X57jlTo=4bWbxW)52s^B7 zKU&*iAHqIT-dY_;*heZ{s|({!(Z?!EtLx*gm>;WVqO80eQPXd@^KwMZwv_A}kEkN8 zhKw&Wj;JM~to`jLYNb}Zzx_n5)ryZNK2cjNCHvb?RJji0J?tl{*{{65VrSNPoR?DR zmZI6?)58Cy&TCaN{#@`em3&)b(i=F~J)u^LT2Ake&j~-FZiw3FgT0Mub&sDls+Y$D;%F*im%sk&SszB5N=ZVZh zs3IM95n*4bMLO&@!oE-|MOn4`rQ$nRaGa$AvYrh8Qbs8#J0G#Q71y9!aV@zO*JnlL zaz1?g;#OSt3bjaa@B+FEKLRRLlwqlOQG6#tU zW4F{&Q8hhS;hM%o?C#VhQ48n+>GryM`Si|h0w(r%pYGFU9-8!so_Kb)h)VI~buBjV3tW);vh-=D;IjoiCyRQ62&8Ot- z`y;Nadey>yRLykQP=x)6g)ncn_TTd){03bFO}YtU{%w?j8Kizu9KSPYP&cuAi#^~k z{_1fCHsttOprY#bE8_Xz#<|Tow>7=x*z-Yyo&-(WD4xB-Q{ulU{vSXa{R-OgJOsXzIuOKM z?*Agr`-o}K#}fZ^2ez$t``5hvlgG;E&IDfLN5V^>LDxYO9-PLdKg8d-Bl}}OMLA;6 z6nmA}Pl>(fzp%YKaS9e&;mKYGC5Yz%(4a>^ld9+HP4Vv*|GS`)GFFzF%llW`q}qub zvlnPkDtM>IYAw8_44Nr1mr2a0#I}|ym!-HKD$}X%vHH&U66Y3ZBQuF(p6$YEUI$J3 z4YZMOSN0eD1Fe$&H{053OT2YV!maa2^PjfqKlyv~4mem;L`zS618L?OQoQF6ztn8llzRtT>0^G3Z2ie?iT|M>L{Kb;<-mWbF10Uq#B6- zLX}6+$6{M$2^+}iFfqc2ZPhmC(2%j+q(S1Z?#YA4Msxq-pD%unZ>JIo<+T{}0&J7s zsOGVjO&G+XT?Y}i8~-VqEgtqOdPMlwIFBQ~K~G7j+csrc8&zMndVT)ScKspl@-~HS zlQ~Xy>I(b+ZA<;nDgRSw*a%)@H28lm{p#)N;WSQ}M@~hbh@C37#q%=qWQ^v}C7?mp z_{Muo8?6%m>CqHbnS#|Tt9vGo;boZyAJ0UYda0+xvmP`h)J88zOlvJ)il2{gY;@^= z^#4=6RrkL(me>9Us5GmG{@<{xZ?(nadF@LOSnLOrWA0+kwO*@{y=)fl&=P06R1i3J~T;ZO@Ie1n> z1Z~2T#ay`WzcEE)W=ITpMi{0#Q4+jyifarnvOK%)l4cRyqEy=G3HYVwK5(-%3&%7sdX}z!P5;h_tqiJ705xhQ9@gZ zulMbw<*@Ng0&oWLz4L{_#*$}mxxd+4?nFOI|2DSMK?*Y8LcaNImpAd5x}((5ET^+H z$=pwuX_kp+7|;XoU#F+cBUt+j=BMz#VxEG%+x!Agljuz6K)%Oasl(=vcqd)HVAkqfkPNmBW#46eHycIM2*mFjaMR%rFXN3#L%2W1ex8W;^B^ zTb0AU*x0GKws)#oCVSR6K15x;>fjptz_HBWEwaWqs6KOG>*(~aIwE1;a+Dd{B>%fL zd0Xtp!^3yM&$YzMrW^Yt^spxT4@;bV5~o=CdK|}EYGbK`s)@&GJmaC0cwR8S!b~MD zdt@Nk*isL-Q} z+9v+pvc>m_XPXA{$9Y*%r@b|%Nc|Q#=R#zM{Ft9Sgf9Q9ygNIPWW%5McrrClx2g} zQD-d`tUh->0S|BM_E<`RezrAclC~$A&zdR5Ebb`=$4N4Jx}L*T!+x%GY?m>vx6FE2 z`x=#DtalwScT4)sB>iTRX11i0ZG7fBZ_Y5jaa{p_0k2a%&mYV}qoe0dczWTQv8Vb*5uTvQJczoMwyze#2cF;KHHPOa>Cm*cvT4ScrB``_d@VeJ_Q2pw) z#D-^dct392P5$1`*p3>v9Ix3<8J)a$g2%kdZP$%V??Z^gTj#RD<6&#$Q-R!TIOQ*q zau=@)w!z{bto_ryha&w#?;ExVdd&N@k*2tRaVbt4JCXA;BSk&o?O{(*o4m^q%Hz^r zdd0ghM#x>>-td3q9cWKOjfLAYQDgP&IqEL+32edbs*C+7UGYwa-x_Z#y!zWy=x6T> z$jNWsgRvCnFbz2=R0U#3;H}{|Y~1q8j9(-tzo_jh-5y|aiMUSs+Y1zrr3F~33)<~r zbD}-MY~+(;FILTbj$j|hd$fb4{qOOYV(I#f)*&BnHgNE(3$j)45 zKMIzBT*mh1YM+hv6!R^gSM4sj`?03hW%?7@g?IX;NzCR$J4#ygdLJr5Lv>V&{roFv6()U;U z0!g8@l)BJd;_K&Fg8cJnzrr`l(cXN`w~b>la;|Wdoav&oz8xG3WIL9K|2qB0_qb7F z@)hwClV?&y{;eQBMU3xA2pXN@t^>OTUk@EQyL?A;by zxs`tw?7RJ^ApOpGgziqM`AueqKd)t$Kdwq)EjehP_xpc=?Yr0?SFLC{Vsd|+<=Blo z!{>sn{1+jeRsL(tUud2GQh46*U+LJSd<<(0T<2IRwYO63^2agKIRPI!lGL(*PaPX{{qx?o zz40^J#%AsD^!~}AY`hhe?FFQuZ0`t91mJFb+eNW|gw1v9<8hRXz%Y+!3JAQ*W1DQd z-9qj=cYAPeNH&W zq}l?5hl34+b3F=eiNWuKoWl%TO7Lbcz8+kL-0lm0*khgTXz({4#p*=xabqj& zOCDQo?QK_4SC@mYgSL>H9y@JyLjFL_$A#FPhjFA@sCF93A-mA3xvlOrQbW9)5$4Dc zKPQhQ!OqKSe8^CnGNy!t<0yj1x&Sjz$B%GE(AK?iMo%y!WBS;$e3gSLv0 zXy;zrcOea(2i1Q<6von^(B_CA9opKt$rc-$0QLz@glAl659cYxMx+GTW>^>WxTgNwQE!XGb~z7Yg#W;KO!kR<{PqQ%QjdrE;^@N1sD;t~ z4fI()(m01WJlbzkJg=DdAXl9c_IJX51V2R{220-@EPL29lG+)GA8qH})R^gtw%>Ai zxY~=Sy*(y85T1775iUMXsOL(dQQ%~6T@qn8Mf)+%hBHEfjsheb*0+l zRSNh@_y8C8KD=_8-U=V)T5j^}ea`=ASBm;Re7q|_ajVO~8rP_7aI!1gs2`Ez%(j=y zF~fe(8Ln*m-Tt7_E<)jGDj;wcJP8pvuCOP=GsEZ?!N(+%ggldKhJAI!Jl72SGZ7VN zrRyV(&`~@L{x#cql)aJqR?05rMX6uMQjP5&gEyppijjvERBZn(B1avRcCy^&s1fZv zXbY?Hw5!-&uf_(~V*AJ%FToy*XM`@dzgh#wLRbp>O`&qI?GgqEBZSey#-O4W!uG-> zVTv$SI6{~qbmHXAc9)Y9)mvaUwFgXA`@lZxAUHsM47N5nG~VFQ1Y;kb)Y!~C4aS+x z@m$8%<}@(geAUyS8Rn<(&oqx?ySx{;$JLlV1Y>A^;DZq{^hn?;aE0)xz^7ra7yBi# zUl)5<;I@cFSvE?9j|GK9s#b;7;EvqEL( zIMKo+VTQ0+xK6lNcvh$!5?`1k%n%j}*9rFu&kB`?#1|$BGlZqW^}=#th47q^oV=7N zj1txrCJMU>(}hLCQsFvbxp1$rLU>k4E>2SkqlD4IL}8LJU05V66_yJtgyhL7LB1smsc^5*<;7dSv9O!hr?6AR&K4GXaXJgczfSDE!hPa7EB0A$$*m7FT9_ov5Ecv9 z3HJ)mS{^@+zgM`Mkj- zFiDspED{zAONHx%<-)zf3gKBH)t2%KqlD4IL}8LJU6>&(5*7|)_!@vIYjukfr;)#Y@eg^lY< z9>mTNW{am-?8RcQ6ML`lpm;6|sh;Gg9;Xl`cA_vzm{O0+n=W>?#3>THR9G&o5S|rM zeW@#9lrUP@xIU+oD0Y%CMLg+Z7YR#+o9c5;R0AoUFiDspEEX2@{3s!Xja*uv}Onq-GLdm?%sa7RAVV zh2_EuA;q#kN|-227nTakEjy0mlnX0_)IydLCJHHDJiGY!(i50P!ct+mutG>3B^_a+FkM(=d6FarVUe&@NL^$pVWKcySR^bJMs?*l ziNbVYk+4EY-6REJqA*=pBrFw{3oC@wUE&K9h3Uc~VX3fONIfK`Fj1H;EEiS?si(vd zCJNJq<;m=?5K@Z75f%wch15&@!bD-Zut-=cq}~!om@X_5mI}*-QGGa0qOeq0F02qz zUk)u5mJ1V8*^@3T5|#=pgfvh>g+;36rY|ZepTW##GDYuSEz_u(hX13E7~i?tIX?puPt5&yiR+Cc*lEp^Dg%e@`?6| z^XcG|=ku$N&DYbnrf*~47QTagi+$hlec$(puj%LK7wgy2FUN1b-wMB%{r34?_50D! z=I`?F>_5Z*KL7dt>-=BwKjMGg-w{wNpngF2fMEeM10D!i60jzqEMQ~6{(zGK=L2p9 z*aBUF0fBu2hX;-i%nqCv_*CGzz-xiO1UiC(f}(=j2K5b^9JC4l51Y9(FS9%dj89Y~dl{S>gAGuMK}G{80F3;Xj7kA{s<=i5MTjvw=)p zRkz`p=XRXmbKn_f9=I;##G6K3G={wJYzS}6V)UiQ@otILcv^G`uH!w8=NvvmL3q+Y zFy09fg160t;{_EF^bXaaJvbM-A6K*v;$2mr;GGC3@jI@9>e2;V*}6pa@#caCcxzEZ z`hyygQjKx1XcOGO*_0f(KIK%+$)#e+OSL3l)e3LGYK^zmw4q?tmLgR0_)HUC z)(U-5Jln?^`+O*oyOn`FbUnsRF1P4i&a62=I-2!{$M3TF$K37;3f zBRnR&)Ra@ZCALp9PA#e#ds+&+2?q%$2xkiy3)cu=6z&!tZ^pT@O7Tzmw@UhRGp>h! zs*S&v@qa_X#4;@?h`VysxJ*oxA|0ohKeZVugIkcb!w+E|LED_Hd@stYv zTXLwiRP}VMWvz4`Y&iz0&2Po2Efy|owFaK`t$5kIHthFq#|&-9{szKWVW)N+XMot& zvd!-1n0E`4gsH-D!db%k!bgQq2{#Mh5>^PU5x`3AU?)!VxbRFTUgP&-|12~*bEviK z?_IfmLb`FB`rX*RyPG?-PYGDWhu)lK58<9Zye_Nu4)tOG@jhJ7r-kQ*-wS_|(ES5B z&KJTf!kYtUhTye*gP4)RT7x;w=)oLwjo9mj)>;M(;m|Z;!U$eh&k^hyCY&hD6&4GZ z3a$Eib_A!nRXqE}J|R3So~yzeLfc4AGgufklGpN#*soS&jZqw@uCTg)Y&DNn>Z{^W z4vxR5ZwnkBB#&l$$mq7Pt=3|tFnBDlYyVgd{ZMH62V}5kq%cdEE4){@K=`Z&m+o)| zr(k)kUJy8rm%S}?jAuJQI3hfiNH*rN$mHT#P&I{uYkP&#}lLRk6EZV2C&1jfeOa~9!F45ZZ?Y>Bx={C?j4U~9}ZGLY^duq_P%+tDyE9&?ur ztYZ|IfG4~e@QwwCV-Avmu<_tX$^u8>IcEl?Q8qXlZ%;OG>@*b|OSxb=W)>M(CLbI} zGr{q6515I$M!3@e^P&tqZEYSnk?sd4;qD9rY0U>G<4IZuQhW%^p~c`-dIX$CkAk_h z6r4`W!5KJzZ%`iIscB$MtH1&rtzo_|o=0WSEF85NSnIRkY|Mi)udDe1KktJs;0~!t6=Rn=p7pd_cj=kZn?%nhY4z>V}3xC!%)Fpmv0YYdd< z8*npjGc{1E%it?GCN)sD@4zke1Gp8}xeOfD{sg{`XQ>#pjs6X8r(eJ~=vVMf`VHKH z<5+{srVJbbo8UV*nl(@=5AafJL10@Us58$1r2Fe)*9-;{F zLmcZGbeL*^AK`cxv*9TkJc8q11J6sU4}OZ{UjxrTY78Eyrr-%24I8M1SnxEpPzvR5 z1^W!BPz!Bfe+gn<0-kYU;F!D}>~qu}_Sc}o(Rl~h7eR$GcZ7WdR4938*gu1Kx;-Vq zz6Ijl71R~>e?W!0=nnffs8Az4VgC*)9NnkDRv^X`)f=`0#CW3m!gdNhRe#uCxSotT z)@l&wqlSRKY8dFJMu7fm6d0gJgQ03HSW9Jqcd7A6Em~#4jso%a1vL?N9Z;dBvSHT) z@h$;11$F}v*ZkB}*o{Diy32*#1jKB3%&NlZA?&L1VNXyq!HMb~a1yTNqW7seV6K{n z_%qf0unR!UN>|0OXMvbOsOH0-4Jtfo;X&B<3g@ba;JHsNhG(Aee)R}E3)Q3WJP0bh z&3-BDhd_n<^OwV34C1MEY6a}2pu(NyPrzOdD%=si3ib-&6RHIEljLu8(fOz+SdKvcX!d>cBc=oET@RWlJcg?;I`&|(4 z*ud3vv}#b%2kK4O`$2_yFgsx%02S^S-39v)hDDb@xtAtcy%YJFzfROY;O=VO^u_l{XvEI z3w{ba5X4+n<2dYK5O+WspTUj*@tzpt6zoV)Q55dB#Qq3WRLA%Nb~K3hJs4lXt_v!> zt?(@D`XJu0Vw{8B5X75KaEBoFMET!-Bj|A4~UtUh8^|*5O41=JYWw5@g5Yz1$!`vd6|Y6?BO8hOBp_} zM}Z1&XY_+T8dNmS2!Ndd;(iY!2zC~zXp#{Edm^Z4nh^$jsxaS(fL&lj!vBa-3--ex z_9I4Z*h@gPb0Zq|QV?z1s0(`qh<6bg^>`7OT(H!F~Z$^rF!Q_9hUsu8nrEUk34(6r(-tS3yOu z869A61u-w&=m>i|h&Krtonh|;@!k$22{xWZ4f`FVE9|#H%y&1s!`=fb+Gq5H{hsiE zkplaW(HlHs^hM~WMt|7<0u>!MQehth@je@45bP5m?jVnkYQ@4z+J!bEi7qJihH%9dU)l%K9k}(p`P!FreRjE3vep6m( z6_G|AqlwYdc){3a>@hwvE*L);KN@(uwAtMpXpS(m%thv2^9$2y^S6cDVr*A!zuV&M z?d>D%N9~3q)UnaA#c|eg+0oD=&ZE@hQ|IT-Th0ZpM_o_4Z0f9edH_xXsdFZ#7UTOH zvo7vVA$8FlmulksvbkKoubNx&-A!FLe@wMuX2DOU*FgThY1YPfH}!9`J-$i(Vk;YM z$M>(cx8?gc+gI}ahwYktEBkNqZQ7k<9EfMPHX+S~XJF0|YsF8;2bmrb?^{8Hh215kQOi)H&+dkW6K@ZV5;9I`%~ zW5cgVe#5M{{4S`8S9TS3@VTGk!57;@3bDehYNLhyNUOdNO|p zVm@YH3b24Lw6lCXQ7i4GU$M7qCX>dmVlz)yxG2;tz^Jq|EenHk$ z>X%h;Pj23nlxYQ7c@r|mXK8;7{QR-PCgkQ#%_zvuokl&g3R3d5KWSD*c235)oGhA} zKR!1vCwm8A z;p!SINY2X0%*yMUo0EegaNTgBEN4C?7Zgm_Ij~$3n!+{CNr@qu%%7e+EkBFvbzqjZ zk-w~rsnuQD!?ml;E`=z_K;(diS}THR-l&zjB|8B~x_Ff;!Sm#kg;t@3ha|FlL< z4%=pM)@!3ji96gY@Bg33$m)!E8P7!9;aLto_|N|s@m;8 zLCm2UIWw&V`k}pWR8FA}S|bh0;_byUpHjL{n>jTrFT>p*V%+P^=Pghz0o0hN9(4_Avo;S8F}ekz zVrS5>Nm&TAHY9J`Zn@*J8PR}{vTj@XT?z+hOq7k^Z)jFd?szV8rO|yFhN3L03W!OX zJ{{vtc0pAPE*EdIq;dHLXvPJV+Pz4nXTZz?JdtoFhK#9MgR=5wWsgU@a!1o4R2f4m zs6Y=EmCnk=24N#kpPrMAR)cQr-kvBHhP$b`d4;<756CE(gu0(Pj*G#g0yhLPlE!2G z*c>v1$k2e1v@);Uv$d~pR^G&{!C6zM=kSQwL&kR+&gu5cn3X-TdXGQ_$4H1CKiv_m z_*gZDGpiGETN^SBqexC6N~%Y9Zt{B29fZ;q^p{ZznPfrTvh&a%Q8wOsx_`NSDfyhI zfw{Q_S(zB%G2U?}Ml<0xbloN z0W)(l^19ESo`>y*t)7qN5LfmRl>>=vGZ|7+c-JmF4=yAdgQjPVr~jwDcZ;q2%J2Oa zNlBZOOiJ9c#!@VeDPLl1#=3emBYUWED3X#HOQtMRzQlF}irkcT#GCgfEoqWzNCtU0 z2nIzS=Actx&=Z`_!=M=S1VwOgiss=w9JE0Z;N)Q*4tfGK4@EH#Mv)?ecF^Xa-_P&2 z*8jFQB{@!-7OgIO|JVJue)siTYyJ1Nx%K(GxnO!)d}#UMN^5mvtx!r+%aewq$Z+}A zTwC_@PGiBWuWa_ln#57^x;nACfdF2elkzNJrL6s@R-__qss;4E-(0`Dy0Jd_V7;-z z+{B?RbrL(Qs8%N9Waa5x#BTxYh~hk_eTvD;R5!mX=9rqe>b?Nfn7VrEaicV}g_z22NxT`!WYY^_hNEUp?E@)T~u&30qvZewX_ z@*2b9PMq|MwMm1L!=2{CfLu=AO({ih%HdgL9nyj{(h)wN9P330I~lSdl>A_%ZN(YMyp{x#Q9xWTD=WZxyLJ+Z_Av93H3B9C2s(|vwB~~X?_*bTgJ`V%NI=IO-yZq zZP?%Eva&F}7*#i2%&f^cOXCO%vo45+lCtA+;`MAW%9BCl((~-9c`sLTWhZxEHUJH% zhBx5hq=nGfW+*?%EaL~LyY?C$8LCctzbTU#EIWLV9I_9hf|CeMG}`mhVsk6<-{r6P zWRmbS5|)8sLJpO96VjyNQhzgZpJAs9t_iiK?@L#ts?n&V7SgQd8(g1jwxoSrm5$>V z3A@Xy>W&`pq~v4IwePBPkr!19;)Rg8HOPtPyQ_}}SO?6USFw?XIJG9G{iEW$%jqV!&tj*-rij~gh`rb zTN}kHOpGj>Ar>zrq{MG&q~sl2ovW+!b4zB%@_}+gVpZNzFRXI%3ZAX3Tm}k-ZVi=z znKSXomNzl8U8pSr;FsJMyO?I5ZcQ{6=TMKA=a$;lxmjKiL~x%i0Ay^kCB&3j(&(9? ziHd0yxGic$&4NODZ?4s}6^Wrvb&Sd>VVI#OT3ZPpGmSNAa~yv8Ps>uF@J+Jf&TcdJ zn=+?UivktgMJDuI_^CsmN#3GcWnb^#l@@bZvvgGSLgy6xu;HskD>6lq$PC~!8}7he zZ#3@t(oVvc$;yn(fR=j?Q;VpuQg)bZ&(EzjlKvQ5c__({hbN)e$nf8SfKS>ua9pyIY3rN9qD4waUQNaXQc2ihj~Pra zH`i4%(U_N)=LUuGqh~jrJNaHc=DU8QBI;j?D1Y=KBM=g)Lg70FO)j@qmvbs!*=V9Q zjR9PRVn?G(Ue!W;pmp}` z%S&^@^&RGV|JvMdt+q6ycQ%&A@#|;5sjTKomK6tN>TWn~f(aAAV$X8GwZ>>Y#LLg) zPhu&>qvU3-$ZS&t@+{1d>dTj~=zzR7k8pX#Y?b0kGsIfLCLLi@N7X{(F4^K97|w9$ zycp>o+*_Jh1(8%L5_dGfYj)B=$L&1?2vABrJ-)OW}>F=`C zt!e6f2z($zy+;LcHnci5=1I?TB8ep6I$f83L+?yHT$x*L&QGm;wtCM3gE72V77*b5 z5Y08aIz5JeC)K8oc$jMY+9|sGHZ$`aVE~kXRNIWa5Ur~g8mH{(H=1i=$5Wr3Id$Qi zL5Zmq`Q_4`#PW8ktZG!9ToJpO9-Pry#vU?vQ)nT2nJo+MGFcV2CHSXijgo?sO9=lrPJZiR-V+t4rui z0q0LfLU>h(ow+Nu&t#$%0h6<<>vKyoTC4Iaeb(i*40Wz)^(4z|MqJQzv-)_W7TQa$ z?X|g;xjRwzn2N}W%}WR@Uw|6y%8_GcOMdhH zFE4Gh@0!22e0wRgUpE?yDNHOhxd$kr$1SvKOc_?XBs~{CXv<++UK52E6hvKVvvNy1 zSn!`xId#^B7q>LZj4r1vmkN?aw~l-^iaQK-elluu~6$6jvZcvQGJ^?$}JVJ!NaZaQVJ5fyYcn6};S7YJ8`Z zduo9dN;!;UZDOFMQgnG@`qbrxRSQ(3zKa8t3MN+XuPiBy2w?)kCJc`&!ZO!#DBL85 ziH+suhh`l^p<5O%#k6pV0ga)ml4?-59-NnLRAfeu?6_hzcrr$>xuq;Wb2}7)BGf!J zHGw+U5?K?m6{cJ`@u?`cup|iN>}lC2Gm!_l!lc$tp_?($k_czKnFrWvqPsHX)LL zC>b{ZCzhnK&^wLR432na!GlTwMFF==LQ+jx9fw_RgJNjwgv4&Hd{;Kq@I>@Y;AfgU zjIV8sNzciKxgUvL5`$XQJZhzuNvC8=21d(C1p^!N_r?~Mn=4vOd?qGQR7J8}GIVC% z5``|`pPf@ET?ma*o02o@t7|ZL?vER`T?kRqu9P*W`9=((7#4l9atAEMlEip*T(n%# ze-a|z!g+(VEej}rx4HPx@_p4LdJ8Shb!}>ZE?YQjz)b!7GDOlEMq?=AJM*`0jjgbA zC?)Xl%ntcy!>EsCQR8x(b33$oEsP3%w)((PEjRkcqYBUK=cyMKv`%Y(=iaSbm$acM z#xkA{qsE`ict!TQvltWAz2v&Y_5NyWp`#7TG!AD9IX!=tZ6ub)v^wP+dPoCXah9MY z4QwS@VnV_7f<9_#aqJWZ`mluLrdfu&+ELEBB$4&fjxmD-a~ZCzO;&$Jga~UUD`9=^ zb~`@XLc&ETm{cs^(xR31ftebusR;BinYe6FWXZBp^4@G?<(h0PAP_v{^u(5f2}hA*DCW@Km&P}b0)HD;U~c*o!K_6 zq1^wy*3eF#Z_G$EWV3zo=#A4RxwRd;eY@58tm!t!%5jPn1;E)dO<}r)k}SuSio&t7 z-uA3@YScOtI@03Hh5`@LSS~=)J0yLpxl(7Ws$!_=nPqX!^UH!y{(DtLW5ZQd4Vlpa zkoxQFWu~iQDYxo`DYfb>QBH?qqc`ESq)N&oRPd9!uVgFuQc*tEbBFpNml$KEd0K*0 zvc*&tC1kx;6$Y6dYKY8h6-7jzyqtD!8?@E75RS(4vIcibF>z{^qho2hJZ5( z)}*7pLAfEvem+{rQF5x)zO#Jm)|rs{4m;M7RMNc4t~8f|%8N>DK&jMKURq*0N~OFg ztuio0(qj~ERUS?AjQ(2#bL{ZQl%7jFh32YR&B(p2vBxbI+nt+Bv?tLYo|b1X(VljTv%bG zY?XzrEYh_qB~}&*TM-s3iiGWu87qu5-AQz;&ILt9b3?JCkq|#*211dRc!Em7mV#jb z%bi9cHwaptnK5uf;6@-P7h9J}`B!C5d!!Y=vYW#9yb|YX9mO%E!YC>(Nk>}Ybtw3* zl2E8!;_r}Zmvg)DI`N5;GS6kQ0A=c~kk!G%=|o_mPMKY^(+$NM9SXb3jWO_1Xj9=k zmZ22|y%UGAWss{=lf*V#BZU>zuM)N1eGQTA?j(dM`5MMua86$?qItTX_ zJ~pWE*i>7rv+gquIwGZgJq3tZC|+r-dyTMcp|q4~G7`*0S(a-IPG%XYw<+ ztt3z7Wkz7at6peHN{dig<5C7Sx`A&syA}wlJY1AO%mFHlUK*%tUsaUAB??h0-ZZtY zQ|JncElUubVVvI-+~KfTT-BFT?OWPkUFPG|yj>q)ax=|43Q4g;ONs!eZTBhIN&21U zhK|`beZ^}0M=r2R*A=1(Spd{Jv8^<+tdFU7tY30=z5m3oE5+JPKaM3sWd{(@gxHyo zgIWZ$6T~uj9xAu~cY>r0g=z_cj?pcObnBMX;k}jB`zx;4qovC1LBU`M)3-}_vQ=lk zjE?6d+isyWUVO;m9n&G4w>DPpa6)E9aaS$u8-l{7(!RwP;o^3f&+&a%)pZ@eSTirB zKj@RU%%4VWr?W%kqCV)%x070&dsmoFN5f`U*E;JcY9-t8K<6QrIM>xt0a$EU6DEHm z&qbsl$Od)ih*qOZHhomawyM=UA2E*BrJrj3(Qj|vei$QD^BQaiC+@UiDB z3c<6H94BttM2B8tGTyKO718wh?#YaHaTMf=1N(6a9cYYu7P_@`hyNCb*I_=kw3kwu zwBK#*f~91f9q0_BjA5I^9b7qjvn`J?EAN8(sfD{c5G8W}cPRHjjEq9G-Ca7LS>4cP zLT3R?odIRk%~Q_sC8#6Am-DEXfVT=+f|4@uk%3}_!uf<+9aFH1ow?MFbFmuf`HG+1 zZ*z(xv~98$srDWF3huRC=BSqTD?!pZUh4n)DzN$R!8ED zrpX4meBVw)UD08is9lX_ZO*XioQ3pSTmo?D0+F*`Y`cc52+Dn6IXWF74``0F8Idu< zyBi8^h9*aY=q;f~7UZ5bS5|#t5f4Gl`_Xh$s9H+cL4N7D1)YkE&RIy=tq4dv*e0WQ zr&AyTxkNmtdt~OEQV9&0%^>%BWeSz3lT)Tll^orXB4uh&Ibt_~999q=*g|M>na&=h zniUeZ4NNQd%|ZH-GYzTZCHZpc-b)lM!lU>ykzEW(36WUfft=AO zNG&ljO3)R3sYSN$Zmzz33lG`2dqlhP05OCjH^t3B&aYCb^2O5l3$Y-yrFU&Ay7heD z9&8_-1#4n$KN{Q)4|FI;H%`{Af_InIT_~K+Q$5o!Heg=ks+MHBXQWj=faLj-MWPlQ zoUj`#g|rS^>O8)O%BIXL${=JT>FCGY!u4r~{#x6op-a5cUCQj>wYjx5VGXN#ebrAu zXq6cCV{27smX?KO4n`>3Pe#rA(POrb-TFjAYZN~+X4REyE{v@#=)0{0qxU!|w@eW{Nn1^|!=PqogL4*!{iY!tSZ7JC0TQGnrG-bH0h-P8=md^D=p3^?J zaJagXCG(RtS=IxNN0n2?aEm%zA6)Z3-C3i&5EnkrZz~RUX|5IPY2B(D zc}|<6T8>#!YD5oCekF)J5zE3{JXC0IL#b$L#ZK}2X%!JiiDmL6Gj8PbOQIaBks}luyI2BDe>yrPsBlAMI`E3>e#zROwR4 zbzogB>?p>;=L~SUz}R1mr$WI$wc>2pvUQS=Njqav8k-kT9F$Tue?%6S$&%-PN$+K7 z$O+L@XsD=8)^I}CHto_|F*DY);q7o=*YO?Z9l`VBott;VCR=toP(0p-HId(T2B`Td zkz-9m=?w#R-ct*P5F5xFXl}ZmbN`9>we`MOlmn{Sj}x#Ye7)JL(jDEMUr)5$2`DVGS%Bk}gduNAo3A zCz@jP8me{{-dNpOS&+8u4E!;>yjz=hAxUYWV=FGEDbM=0(mbWrR=gi4FGh{@zR8=4 zEOKFvpl@3n`FEvW3ZoT!&ih%ub)Q=i_!zA;4L$2R4Z1@Sb$4+1mdl}xjdlzF!b=xc z*YiXx1twHW=d86_lPeP6FcJsJhlm5<>PNT9Sy?MgUp{Dz9a`zNoNC5bdakxVNg}(ECz0dZod8q&)TIjpe zR+uya6?4Wm)^$0{;EFkU57xxHu}2LoS0Fvgeu6()Kz%Jv-{#h~*4i2+%~Ox6uTS}? z(lj~+E|=GgPrIcMkIqjP;L+Phl~DjkVRpDVb*91`G9?@?Js4EXk@iXmE=x@`eDNPI zIyy-T(&JAa9fO1)xTKi8FLmrRSDQsgS zaN7=kr<2TF*637SH&2nlUWI`K(y;5DVgek4lLb<6!=vq~U zK|&O;v^$7@>+Q)8Z;f9ao0*xMxpiZDdN$_Vym4dlo!MJAXC`lW&eiGhv8%VPjg7xG z^^OjCrK?`)o&~#8-C}%GTB|JBn^wA)#n$zv9>38k`PDjCuXWT} z(j<|j1V-x90XAvdp@>#R@U3ns!)v4|#PTdjX%)cn8&<1JcDLGBuXU}h?9SR@(Fc|# zu!vQZnb7{OndWs@o`J*f8+s+6-3)VFG+L?dV!Al2x8}wq^BS4PA_98XK4j7O9$WZqZmpSDcV?wzX)WGrUc0N44)(Sn zfoltAimNnJl+)SF0$}NurQZ6GDk2<2@?=3wkGx$3lv`G*;I1FhVeW{iq_8CwBzQ=f zG|xx{EiDz|{%g&6MS9r|c)Q4_OjV6HvBF|PxVA3dy0^3}$@P2K*|`cR5$13avZ}3U zD5tzhN+z16`FZ`;!^qbqKAmc3OxcC=s##*Ma#pbOX!CPzY2J8meAVAL>GRb~0_=kL zB|*9ppQpy!4_D?R;p}-_chNYG5wyML528-2EetEj5f&4o=9k?E8Wr+7BwD)1ue?PR zK+cXz2#6Y+{P0b>OFJv?mQR~*`J?H`P{)X)GY^+<>kU~Q1q_{9xje_CS_V{XWd-Ru ztDQ1Nbmv(b{1Q3$Ln-&FA2jJ(?KA;c!dkVoqb4w zu%S{45p>p)M>F4e?cAkimuQNd41aHHXR{Q&=qQ2CIogfbg(RgF#9NhW9`!2tw|dn) z>P0eGd3q+lg9=uoGncw0a#+1`j=@9RFsF&bQ^})V2WhNkXD)TS(a5TIEuaO#{UVRE zeyHYAFQ=>ZS4diEqO2EYDazRH)$n=|z_OW^F3*Ys#uv^_uCyfri5uKe5QN1xHlB-$ zd4ej#%XUnLMK*nTA0F08n-x~uyt|nVMQngTt3lr!!MU$;N|hrL2XxZ8Owo#j>5Y~Z zfx=_%ke^URbpfxLv`8JT`WsQIsHAlfH4#`ti(Asdq|-)tX8Aj0ZPeBa9oe8T279u$ zM(3`XzUJsC^6XJg_XA$XAfxh^x)v~cYGtEl2})usD@e~-g_NOr`8&coMx~2XXnkaf z>_Nx5vQ=kCd!(gM9!5PF-BE9J$En5WH66uAU@{7lXAiMJ0j>M&WoqrCTa>U9x;#(m zhJ+4DTl}!SmX~66ZO{DLoffyI?{q>}4rj;vj(L3hyrG8mR*EgBW2&~&TWBh9rgg6% zLJ;$f9=&nVpdiYqFNeu+!^0}j-gFb&ipH37 zzb7x(GoB6$sDafD-Ypp`Ch#0fy5IZo3a=(fy1>UNj?v_8ra8P<^g5lmryA*@b@kFi z^g?K_Kh(C?-G&0C3dRZFiXbQ$w=CDW$rXQbP*`f-R>rwg?bTD~C=%fD^#zmKvtg4s z1_r_+@if)og=#Asy5eo^m0?eYEG2OI^%{}zKmg1%)<1}fEOo+gDq*;@Rwwr6@3j4o|Yt?h|Nyp@$ z3PQ^R#549%S+Ma?A>O|RvVqoE^G6B{ciVWmz#?_75QEdsOap{LrER^j>`yt z#AixTmQTP63rR||DOh2ivR<<}c(-}d$BeUxW2Th#nkfVCHcwLO6S0!`nBiYX3Fh@u zD)1I^U~**Y{7o7sM^zY|v7-*gL0$1vD7RsY>Ed&tqsR19=|=BX{y`G5|wp*Jfn4r%434BGp!Ru&)g{tJDV+Sz3- znZ~%G&674VmKJ0I3rK<_})JDwYO?iQl-(+%!^ z;h=HO9aSjQwK=<`^SfEL2aHnEnoG5#)_tbgsLQ$!?QiAQRP-o|ss|ckmK8O+=XW5( zXf%8sQyaa!v2dqxSqJe}J6GGI1#huaRgR9`){e1cqOoB9WM>WV6bCjsrDyUB<62oU zZRNRl?%M}NSj>N~4sYFbWQrtqHvk_*$LDl3YMJf5M$1?4=~hUW662iYF@z#~B~Us> z)MX6CLZA^&m!0QL37J5h?oBC~J|0!+fz*&rW{Z3(hQ&H@DPJ+U5S>K)z}~#X8$Y|2 z*^QJPx|P*rvrup>C_F@^E?rPZ`yXAqZ_AyDP{pifE;kUVdg-Ch5}+?S&O`jB)Kfk@@i0 zq-bLE%$dge&9yv9ojm2Dkf&!u*!h<*^Zq3@P{PPU;R zfo&*fNk2uquBWz@|F(XL>wEf{+>!8(TF{RA_w}rE$4cwcw(`iGSANq{)P7qzdKs2- z^y(X>8#+hPv_4bLqSD$ERo~&>|9y~!7kow|`l;QAah@ZZ4;Wat^hyZtc7ta@bGxtE zEa`jBaF}}9(7e*DD4kdNlIC2P;mI%3V;F`yC#|1({oHROgt;eczo>bv>L-9l^pm}b zZZm4%GTOG3550A|T(wp-hql!`D+-6rAN<{i0NfFEw$nhAz!Z~Wf_Xi!Wvl|A3{UBd za$!BtN&Y#&+T9eGVPH)qE&UGzr}fKlr&S(mE2_C1!oh@mm}%W67GArfXPA;UF!LpS zQ*U0s`V0y@_nMy8h2T}j*yrS>O&F%mr|Q3HwN*MiuCb=YG{2=1SUn8SDTR4Ig*)yr#A~>tOlb0}zKnhs;?l z)PQYCy-rzgy3eAt#@v5NZC6dC=2Q{}t{D7aZ&veQ^sxVmK3Bp-oPQX+q>>e-S`vmZ z2n7%XL^eEgP3@PI(=^It`A72no2m(f;E&!b>0`6XeV`t$$9a`TduCFt>7Dspi+yNb z&n&7p{b-9pno}_BTh8meblK|oZ1Ot%nm4dB1Htq1PPO24#&+n!zMEk-T$aFH2;nuj zYg{D?rWjrvGBDB5?|A>3`d-lQ5xyJ+>}CC)cX;#BZRV{fd06VXYx{iz#?!{ty9dMG z5Wap@5Taz979;vi@oV9#xIU?rT)@NWNnsGaLA;Z4+PPimlk9w2?f$fDL*M?>`C; zPug!M)x%kz0~#D|PCSMjEoIO*j#l((q= zXuuVf>OIlcH@YTwr^1PyY6CA;Dzy&J-4!lZ^((14yhRwoOP%GNFoc@pCG<5zI5H*O z*w+8DCKpZ(i_kAQQXioUW%=9+g}&QL-AOj+IK33@%a~@EC~G*WDdrEY2HmDQ)Sa= z?4ss%2QO?5{AT!AMPCcA$V5=>YPhBEcSN$ua6@KoOiVQyen%i6prCj}wI-E&RYdxVq5bq*@=pwd=_mY%BcLSFjwB*yn)b6n6vaRChl(PvQOM zsn<%WZ zxh$b1g|bA^-|W**SPw4>SuFK7V(T!7#&eHFee4I3P1z4@m*jcBd&i8mA=HNb=xp-P zlE^!Rg#gmQA6~BX{f4laNI0TrWT)8L%UN-F>4*ftg@V4l)Ycs*Q#nk4;NX>0XGCNB z?DDa~{MW>?|FD0g}H?m&isI=|Xv#4rR=R zeUs|RsTNKr9J4M%r8s5~1@Q0qB^O(NN@4!8+0-w8IjxW+C*EMk(R%xiYtQ!1{8v9JyfqcTduhRE4me zVF(30B~^>{8PUi)VCd^b$bg6?Ivy@MpQnU_H$rIt!*W`;-a`pKIEnSFuNyt6kl+=3 zn?FkIkx)FM>A*T^@%)Nd;e@8d-%bHc;#p>kTsUb}X5MxbUDRZbWYnaGC2-k1-XRux z#@*NiOG0copID2f0?g7mi!$+zwU6J_T#}(qOA#V0Fa`D?oapX0yRBv>9tTs+BQPbQ z6vx(r39R)YCuc%SEpQNyz#e6{(dQqoq&{(p5dwzfQ~`9|Az8#V(DGN@GOfdx53TuUFD)ep@`J~!Ll+ioYqbm z^x@!y>LFkWN2>qART~?}($$AsX_g;uBII5_>kE7q%hdBAP+S@ePAf-eO6)V#W>hK% zY~LlNp@R&}*J%xV1L2s)XAa8>?BG94DGz~+%b49Lm+%}grT|G>ioiK1Er7#7_H^;O z+NRksJMfvDLp%=V>pbf!3T{Zfg}$$en-W(#j-amd5AA>qqscOhz`zatoz{P-0)D#D zU_|+gDi6nqgE~LB2_8{D;GhwXD`YSuk8)bldfnWaD{67ce8#J$*iI@9T^Yye&a=0E z)Y!K(yqEb@@JGXjV=o*Z0#mxgW~o#9e4zi~C12p7XIMf`7_ILMBZPrY34Xl3aJF3Q zeJl5PF8p>`aO#Sqde2%6jL1y2gtzeR-0XqHA`~fl4u^pybVe>o!stGy2+BK*ol;=O zH5cyFlAh5@u1294SORY3J<-8ixLyi<@+fzk+oJ{Pl34A z>#o0dmZ!484i`T%sVdThUaOiVX$1lWg;2)aleJEI2|mvCD|}M!Z%p%dU4`U7Avsv#NL7$hop30@jyl84V?e^O zZn>G_|M1J)H+r+6!0a=4&2K?y`H;+#I1bi2e%4? zRHi$#OiqVpHU5rzf)8=DaO!|Nckvu2?v^Cy{JLC;yqDv0YTr{1ZYS!NGNLA|nu6kj z#Kgk>Ny7z3vMtUI`}9&>jf)})FIRE7AoW^RbfSIVX^TfV?9Q{wkxN;0jWBdz5aq~> zbY)DmIIVB;!imn>?ru^aNZ-;oZ@~y}vy+4iR4qyF;2S14W#{p99C^90+a$x^_kzsh zZ!2$A*jY08rW9|LirgAZ9wDN|U>;bJU_93!F!SI27d$l;|hy|lySJq^B`H(N! zP#1O>%RON47174iO`8t*FXcWN*EdK(8@9$h@DT|xjG6oq;7RHlcwx8{giq|^n+phV z@>UT7Hu`|`jOD__XN9DXq`bZ-)O@7;li_te{kH7L&;Q?zBwShu!?6Y5Z$_7aO1?3v z5Wr;N(Dw>cPsj-8e^W$8zk;*{g-rd~Np?alep6`rL@}%!ZJ6J`{qksow*R;smLm`T za?Z_p&dpEqE{g~bM-aHgMW6`2`dWBVi22{XJYt9d|6>W=qftUQ8=IZPGUvJQ+T-|W zL;?DBq3P?!Q_t%uZ2r%G7i6JseKiD=qA}1Qm_yb_NgTd7645)Xv{?&`XbpmbCqP>4 zwaO#7K*i%Aw8m+Hv&qLbkthB7lOyN(3_Z?IfAQr|^pAyxDyI~Xq4OF^+k|_Mo?RkI zPF5CfzCb20g^pwK#xgmvKu$P(tbG1qu&CJ{H*(%fk^GMz-65`wJpSle63)Yr`F0cx zGh#;YVe}Gh!Lz@pa?rs4)uTIgKu(wV7}ppVktuO{36v<7ldr+)Qj+EjHIFGDw@Bz~K<%5)Fe4cQm>kfOwf z8}f7)^mp2NOL@5$$(bYk@!P7cHH9XAOW){s0-P;zq@*!DzaLDVS-2GHuo@mOS(!_`f;n_N!PHQsIns}18%@1ZhZ)1$bDS{e~_sz!` z&Rw;;EwAv`)z?XJs2`ZYNM-K57G2mDd6EbHX;u*XvPOBEKmPkc%HP+zU`)aU&pgP2 zm}YU$j|n{paFx=@eNMtVm$lbA?j-E*t%{sL7#QB6gt2~02vzNmo-Ay1SuJqs%i$xA z7+g><-_ZYa`hQlRuPODs)CV5J?>$-P@P>z1zG&2|3;;TaRR@~oTms_Slfm%liG3~g zR`UaJVGz=%-Gy)n^i*Sx;gClhJuHIPW13TkiaP5iEi28s?|~^1ba!|ze+EZrIlY@h z^NT@{Bh~UOXmZ5W0-6~8n(u0`wOmd+lqov(}5f)IKio2WBiBAhy%N9A>jzEZy%oWsM7~`O(nl`_X$mSlVBJuh0lghDz}8wfu!EU zK-#4XgT$c|ox{G|eh1Z#{qE15El!|>;i3~{IXZBM#nfJxj%Uz{kP2hFFU|rOSvvxRL<_nhw zf{R##E_@n~ns$t$0}g2vj-rMaTq09QE~jl_A84%H1_)_e?VG(AS~)$6J%zK~=G3ib z7J~dFAF~r1-Es5<;JNbX-pl;>h{7#zckvPt&76fJd2ZRpg#CHRDa91Rv7$jN*OfdU?7~?({wQ5HoTNGV%jKL^dF17s zGxCp%Ip34vRUPR9*9yebl+F%)rGB$bf#Z2izod~$Qq6Gi1zC@I;T1dQo?AG(ED7=8 z6Hz_(*nAC7@OWCflzQ(TwXbk@Pr zheMtD%DwnxW2Z%98jX3W_50PA)!t74 zEo!{y)gPMEJ@1n$(e-)NLZ^D|u$z+$;ZQoE?5B#qCKq3v^z3h{cCHahWyexkF8iDv zjxE*S3+gwW4)*-;47nexRwdtRLrp&;9cx?etJU1WUsWFuM5!^3z4i^tUrRX?ApL`p!G?6vttH!H2Z~-mPm*Veief z4^xdvCjT(+qjLnc-wm$#l<%xhowCrU&T#1SKeCfv?}#JE&uYZ@bHwVt zqkQ!%9v$npX?GE8>Yge(k*Ir4Yu42(njyWrUMxmYCBZs>)~$8ohR3$=`&iWbRn3u8 z|@8)rw5|;tHQX$XeS252dtG6RGg?sE^XG3@9CZ8>SINmS3at6QZ=gjocp(UFmGrcdKZOw;xnQ` z&sAwtUjK*MS=E#!d&c!F+u^APYu`2hoX&@RImpz*q2h>GL&A??vV272z9Osl1>t>p zeWy%+-;v$(gBEA>bVfU-=zBDI>O))42aA29-*q);=E-|Lt3Le-Gz9sCe? zSy8?$^|2ydt_nVn#QJ(YEPpv1os}F^IpUOZ(4>BXl{ll@FKMCU)w)xv>3SK@RaX!9 zv0GN%UUQ_xCM<1HA8U@d|vn?azPmZXj-`q*w zcd{42ikF0@MFa4Z^cQ%*VyRV6wr`E4oJK- zTs)nbuYA$^;Y7LDj|6e*wQ_}4`es00Oc92BMo_n{m?_XAJ5Bal!CKqRJ<%=X+&y#G>vdVQ0Zd;x{`5ms_;Xdhh}A z;rlPpB6&PO<(4ePCDUpOu5RkD^QWywH~+-9YZ5`7v8jNP&e6;;2n8 z-GKPE`lu>@KTeQN+JOqDm|l;e*PdyTKnP>_WOHGB(#d-;z|kfZ`E55#og|!;+V(yX ziKWOKMUrr{(**PQ~NZ+x4BrsT+m=gV?U6@G#t!@>f`84ISV@^U0C>G z5_@+I5S#L)hfaZ+mEc|yJnmp8MVP1p!@(~Y5qg6n>}{aHiihySpfkOGZypt}`3K`A z7Q<_W;jn?c3Ly9VUR4RQLwDWe&g-H-pSP=hMQungXkssMq9mc6R)cVzJ(2N8LE)&=FUnp~5Q5Fs6(Pz%;Z`6-Z`K_Ki6mFd?j ztd{Sba328X;phNfVA%Ju%HI|X-^iY?O5=sov@J3M_`h`{tkM)dlR8S!;6o_v3|CFGQ6&6YGglEW@b^Q}qcQqOVnr2T|L6Qb9WgeduV zq{4u&yW}%0cjM*UQg`?1iyVw36>SFAkBAH>AK+{FGxKmZw;)=TLDLNN#?>hwf63%VG<6M&B6hS^ACQj#O{ciq2 zwc`Zr`f&qs#-lpYZ1ktD3I(@WHE;f2waPynFf0&Iv>iYktHR)zj>7j`wKPE( z%a3qfh$SQ2mC(}#S>cXDdB6g7>h50H&Dr;$Tdd`v1zU@qy}%C~f`Pqp&6WB(UJEW4 zbj7N%@krn_IkxZV$q%Uoxu-8G6gVk`DJ8a_)HMssSSZtu0>7c0YvMfA-HTFzW2zrw z3HDkg$0*^(={2cb0zBME_nI>bS5V3VgdooiwdYj=6RP1SvI$c%0_C$I+?o~aY5ATo zn&V=|FOIO>sZJi=BA0 zjLVek91D-4_#CUQ7U3Zl&#rFqh0qv&;WK&BEXDEW=-aOhUNJl*iall8O2{-m2g0_OJ~m2kC9dfq0;kCg0SuJ_i0@ z*tu?2=b7SdY!1nx$;BzJyR1#?4Al)u5B$$^op(D-D!{=@HF%fQn52rk3%BHhr%i^F zf&{MeZ4B2X-Y@Kmk)|F9Z zc?`Jv@(oN;G7yOXbd0A;L~Y3ibl1ZNOv2QTCBELs9Uf#sC<9z+hmC13sxF%R)vR!L#=zh`r*h+h0Ev?R7SIZkvmW)1QnG6Qu-y=xd&nDpX{ z!&z|v$IEGj+$Hago@X^4{EX#aw;Gh@Z||TEPBM#4@1Z)u@2Q5SxBIe!EJ&FD9W9O2 zrp9dZt60R2Q)eLX zjQ*bn1us=08&!UhB!(!dv-~eLa{0>{M7>Gr`rod-JV)6hTE9Iimj;sntGRsp%AK{e zJF6J*6!ghC8zyqY=}e>jyc+!oqUXxvb#r9vU&uPs(y^$g< zWq4;qe0#wlXEXF0+cGPPVbtQc%3a-rkNz$re`FY#P#?GjEJTQMC4)ySrp-az_ss6`uB&nI|f84dc_M5f*92X{W z7&&1NHgPvk74m*VeF1-X={-pmoXx%$i#H&>q1t}W@}ZtI1HD@V8uLj{oX3YxfCRUQ z(1}jj$gx_K5o33NMV_#H$SLX053gXnEEhT4x*jp%q1Li)@ns3xdr7rCddhAGIuOiw zPzBeFB_we`D3;%DIj$?fqc($bh?v)ZCEtWOT-4hRMk{j9ydT@@h4Mm&cSYP6Ccrg| zC!6=3qBcvjNLnlLL7F|~8vL)0PKUH0x;$%ZHNUTU=Y{}hW1DXB}p~A zsqj}n6o+TxL;vm5ItsAOZQGjb2t) zRZOO!el^O1K!Rmfi1d}5bwt{OwMkTp0RC}R0!HG31r3D9RNmJw?#RQVohK#Gbg;x1 zd#MB7+N|2SwtvrXpEMv)_^kkQZ=Xpz=bGpYtwE49)N^H>0#C3UL)%;V!2$VTK|ZQ?ywY0Kl@<(D6@GVs z5<8-p=m#c)ngHs`6WPjLKj=&J04EHDW26bxLpI;X;?O=5Ptxs|++md1?@H6NwD|{pCON_%v zPR4Fdmk9QW*P@=U@r&@|vL|d3m*jn$w`7{wP`awPC)@ZlYI%Bxw&CRj!|6vuAyxu{ z(-~F-*|VNEt+|4!mP`T?YHW5a)$dw*$os0WreGN@X@g=6IA7v>WWw1O9LMc7z4VN@ z?3D2Z&=B#A*L?;b2yS8=<_5itI2B(JhfA4Wj+8`AhFlkp?i=mVRBYyO%&}0u|JxG! zdzw9mI#mDcw-p0}SExTGUdFvx*KdSU~nGyY3>Me`(y)2#&hcLA) zejcbkk!n;;c&@0J7PNr6U+RH(t8|y4Zeydyh}7A5ed4p%oR_X?#N4c>*HWdWMgG9fBULu>b zB>@k#uUqWm+6NC4QMzbAQKu!V$|U>+HYXxmxWKzI`1WJenfK)Z<+9=cD&Y3r=(Jwc zk0J`94c~x$HKK~}Q=(E4yQ$11KU&{MX|KoG zf7hr8AKuFy(`$Ib(rmYw>!>&sDyOT3xP`tr20A#89~eqL4Jm9Nev$J=(YJAQ!;jYg zyWW4k50E4b@+bF?QCtsWFH>%A3(`2Ik7p8fiU*6!ity2_l{}GCqADvVk^GAHnbb$F z23)$8lBl1^ipkPD#wIjVm@p69;*J}wX_Q+U-AS(&8sW&(%kLq96{5tDeZ!dUnv!(j< zlDJqBviW;nX;iLHjwnO~6?)I2GAy_mkg2syq>~7HbS-UbwAD2c2I?(~h4S5_o$H$z z$z64aHAgm}{lK#yCB1M8^2$0lMFi3juO!hv+fxSIqx4KwI*)6r9Pf24fONWX{a1gV zVEHyR%d%=*ISq`t1g~ENbXSR~hYWOM+DEIyFNV-WJr*uS*H6^@@X?D659^E@;c!pZ zY>p`L$2sHSP#%TkMjR0sEe-}ROUT$^uqgJiZf^8!BxR^YQfeXks0C3cjPFQYq+Xoc zp9tcEV3k*B+?O|r=+DXFNd4SY8dFJR6Fin<4#MO!5-nb0l*eN3bs+Cviy1I?!ZA4BM1l*m z(90shI5}|tBj)@1&X7E2jBJ_C=xO()0K>C>^Codo2|m4Z1L=m|Ex8oVAvoOP%GbZx z?nrS&AjawNAj47-BQGP7NEkBp2z=;1=V`qoZA^=R-%#z7I{fpAVsqg`-*+I=o9mDd z1TRM-*|WrW<1oU7gx=Ep$}a=<#Z-PIMefe~U#92k&$H!5JnYMVEG{%3H%4Bb%p=sO z-qXeTWfwLdh45bK)b2-lPfvm;oNpEZe0OsZ^qe9_<*m9BNpz&{O+TB>TC&j5OGL>a}Sc@oTA6s zo%j1T#k)mZ14(o8eBaGhR9HJ^@OILX$r2=L`HC+*m+sc58M(c9Lw19n!u%JVMdEb= zyb1Oc>@7n|nCxY6Ub`lHb3Qv3`oQiUu;(1}?e|L2Ye-KS&f+QI2=VE(AjoH&wj|O~ zL-ZeX%X6d3n@!jbA(sMa6RKO=R7z4Z!2S{gZm(V!@?C%^4%Z#rYHy66M+Ckjrm@NB zHAlt#FqmIX*F^TeA@?%>$&0Z0U;M*QtT^D8n%c?SevSxz)6zUAvoOucLPXN6;O6fa ztAG5+1|OT@%WH=H zv*HNo<&J1Lm;}f7h;TVzO3Z;h?`J{lj)=J*@da3_^?Fi>PbN^9pyYxhsH__+zs?k| zvt}w+zfo4^{V-VM=deG`(2q!lXR1-DINp`+`7j3RE5`?&3lq)CzHJ#&GWb$2;d1{M>BeBTgbmm3kvQPqA8)9X5%m|{Po zRfZUqo<>KR`5EK1pP65NawCxTFH!3W2Vru?W?Fp7@0#&kdi{!1)#2bow!dl=^N`Ob zoWEii>wc=-d7(H$q}t|B-G9ta0J-%{ha4ab!#6Zo+UmobB*L6LShp;k6@WBeHl=nR z*uu-EC02r$>%0Bn90A+Ctf-3@Ryo0tHhL3TxQs#%LiOg)pA1}IlBCy3r+QVPd3vhgU{X1gwR*yRKuxnO5Xgi zDaV;0A9~6h)6M_#$%da5;82pVCZ`Nhf(h-e{G1DNn-3o(4=EQtf5&tZ_nrHMFpUhb~LNsKhoDTd`vmJLr?wq&~A$L+0#=$xl8rW>TziJ zJgtV$50Uda9~Y@THdGtw>p!-;zhB=ye5+`9s&|jKzbLr!!Ta{q=k^?`Kh<+E^zAtq z=%k^(>&sNGe`;NCsKrrDU`V|W9UD@rm*J1~)iiv4?qIME>aXt7e24V>N>BZ1I{H+# z)Nk!jee?H~<+Tp%Qd7D;7bI1~GQ8e|?lOus+ut)J;V za-gSI&p+zBt8iB%|GG!=uu7gsE8p9 z4DA((hlV%*&G6=*?HkzzPB#CdzWFmNJi1#%*!*|GTYd8{h38)JQ{V9BU)91cwS)*g zJws0kHepSlKktEfe2K#SgIT^xhk%^#UE%;fR5kR`N2JcdAXNLb4(RJCk(&}VsgJ7q z(W3^$=i*H9@$lwf8$WyI--^>heQP&0wg!g$t6yJ03v@phlD7s$SfKln1Nr?Ppcn)$ zD|+fcPfotRy*l9=O2ciP z=oxxi>@mD`(#D2El=oFll}^1ANnTG+FZ9{EsHqHZjqOHGj_wJX(3GL>=RNi7HEUA8 zPPf-Ip1SQnW*uHrhjAk6Q4{SK`Ff1x!&{$N$8(0b`qrGr>K)n_1W`j}`j?)SY#2?B z9vv1kY*HCR3n0yCpYov!EWTGT+oJ?5sU-s#(GuLtLj$3=zV#_jgCkzGzO|v8-Qwu2 z4dWqaMZs&M4R8K;1Ho%LUqJnJVZ1(PjQHc-qVU|%KFRy=*7w9O2YdW^%bxo!S1owh zqN(Z&IvAo^Z))QGefsEw4Yqz?Y@qzDo_?`Gf1mKxAF`zPvEB!w?G`Wc6b`z%w=AA$-h zd}=LzYR`YHzWXHzK~4U|L<{B>dx`Ai{i~xSuATVve5vV|}m)wxGAauiw~ZXfLY3sA*c^=+S*D6u9Cu0i$^fCe5g~?|uAKA|D&+b4&1?a`;$ z@z@YbxyiuN|IJM7@^fe}ZFeG`FR@}=d14g9tLTJy?-aSWp z_Z$}c^&UPf3)#;+w?6?MfqB$Z(Vh3~w)c&ekUYwE6jvxVX>0(JrdFVVVMST7MTzXy75uTL!Ye{XHH&gi9|(zcJ=Vl%ZI2Dc9GeGe>4(ql+PMJ>g{At z`VO&QV~zf0Uh(!NJ2)36o_ta}zjAF?t+%&-U}Sec{B@xBNNs;Vc&)!K7gi#)yT5*| zf2jVhB;u7YG*H_$RNs)8eYootd4n~P2G3EPE;CVowI3!VqrcXtYIF4u)u_M!m6+SR zr$4qh6TdH*gCJefKcKGMx7(YZ>K9Vxh2A*Afxeo&h?;y|#OLWDf#Y0qpngE3#^KKl z*Y+?xW%S)&|L|98yB)Hux<5Rfx4Q6^AiqM;pE=-Ps(}Z%uZFuJPCQdTld4?sDi^%U zg{;a2xsf%Q4{)$s+Pi)RNw`oyV~GpGMz0X3F(XROq=yS~>W@m>ZT^IhpALcpfv!*d zoIItxAys{qT0b_VZ2nl~mD3+4}W;042sMUJK44Z#0 z-B>>$N4-zp>R;j=^weJ*+6z07tREPt?Uq_NHY7G;ZiVp+N$Xzoe>F|}!0p-vk2)-R%L-AR*me$l4tlE zOn4NI-TbMV?Up>$m&IrOqLc~+?r7hh;cq;pxn>LnRyIFZX{~4Y8^)!Ap+0KLRZ_Dz zL=@CV_reZfLy!Gg?(RLuWMO;vNNY;XZ_0MbztQ*M+JLa}3*nnozy52ATRrs;_q<~D zdiM+(Yh?blcwtyT9Fy}LokPi}^Xt&itF^<1+NPF<{q<%2euBQECzmtGE|JZ|6{tnG?VKzgD!T;DpbE+N>~OX@P4gQYxA$o*uO zWs#mb(7S(R4;covd1s=*)_Jlm*JY)CeF#E+ zZgAJH*RKmfS5Y=}DbGL-x6SkFo|;IqbyJ!`HU)$M^}Avh>BIj1^R;J`?YYL&^({G5 z!kJ~&uUq#TR+a2O5Y#_;w)T{RVg*)JHr4;hdGD3dV3@sHAO&K{bHDrIOzVwyafU4up4}V|?0emPZdWm->KvG73yH824r8Y-!x>!PW-s4$6={q^hnYBeJaO$Oq#SW6CrbuzRMp7}q$BdE|DhwGIZ=zWSc z`Y|b}ztBJTK7Qt3|IWYu(!c&HlS~nrG5er|$kyM#R}iTSILRjP7Y9Yht)JD`;J7Um zgxCVf({hOdQ|Mbi>rGOv(pPJ~C>Azt8T-gDf=H%}P4}wxfHD~W7^7&}g;iRwzuRBi zE!OGn?S<+4YFd%ONPB9#q!HxF$$qUHhq$}8`RBEoB2)S^NdFGCR27YT7-|6IH$*|ar`IRY$A`l0*J>sz0{TN}YL@Nesv_07%t??~DB zpb-V8Q9hB*pQ~@l!+c3k1x=%c3;%>>&-|n}Q`B?jW2BXf48rD*S$Qzj@KaJab2#I3 z_3Z(3P31?__R8nk9y~m}JxsxzT#D@z!k4(>B%I3k)2g(65*m}qe^otH+oz|P@0rR~ zOO`6m47MnFw}EWp|1M&&+FTt6JZhnKi5K{zjvtTkV0fifngP4b~k&^)egI4 zNn>j{B;|=5ZT>>qxS#(LDdwuWe=0uY-zWP-)ooFQA4#%y^H*3!s* zUY}YN+SL9VEr#OEqzAUY_bbxyTT@;Cna)vJO}2DSp0GL@L{Q-uRYxpdK8W7A3A)v|LIyknb{IljSlyJ1#g30i~ymGlTMOD7-;*X9t_1lJ^+bx$Lif7bywg1 ziB_m%u(_a@3o1^*&Cr5JOCG%J&o9@GBl3etz4#T2t1u#%`-K<{vC5v(L-tL(NPSZ< zs^5gt%HJocpF^OVL%lMC@AmFFie(+FZ~uw@iCu7R#8Wu1Qf}vm%n{;2|Lfvg8R?;; zigpM~!1+sCU;onhV)K`BEHsx0>aW!HGP#7h^iAF{9=r@HZ0`0CENyG)|A#8obmjSr zyqmw2(;_>?I(+C^p>3?b{jaSND4&#E=^uzZTH715hpbMiuy2p(jH&(K>$Cm9{5OJD z+J3{nn1NEw;hyl+<@=X5noA3_bM1RNsIr@NefUa`-T^Rmb!2K~z0q2kTW_we%<1&Z zSH(+Vw)ZRVx8~N~SzVcYFyC0CZ1!$z^?ti2{K@H}v#gn9+UG_v~B=cS-qy zj$8WXXF8^>=AZ8RU;YE(4F3PuXP$dHHrKwQ|JkK4LLbFH6H4@`SGMHRQ7Cp`+4$nm zixxM@x1)Kh73T-o(dEzYhJUf^t~%`zbR79)+bqB0l=n1YbvZq--HF zm(H<@eK5{jHV#K+@7Ts8Bd%#IX6El!ezLJf!=T_TL$g$Xm}9*84a!-K#T5#1vi?k1 z+e8fxsd5||2nw&ZRlP^`an$DO_~NXG9|sP?Pzb*k_6xSue-+!hJgcpJej?_)p7`&- ziTDjs4n7RR^RU`aN1Q-$@SFN0#fUq@m+l+U*Q*9+j&J8Q&SP-oA>I;Jy%8$^KmE^0 S2u}&dUKsoT|MUMj4E$eptLa4m From 7311e465a600817e26f72c43c081ed6519cd4219 Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Tue, 4 Mar 2014 15:35:48 +0700 Subject: [PATCH 095/143] Update ParatextShared.dll Change-Id: Ic32efe79ee8cbf48bebd80e67b3c97e5d073be2e --- DistFiles/ParatextShared.dll | Bin 1903104 -> 2060288 bytes Src/FDO/FDOTests/ParatextHelperTests.cs | 3 +-- Src/TeDll/DockableUsfmBrowser.cs | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/DistFiles/ParatextShared.dll b/DistFiles/ParatextShared.dll index f02882beaf839a9e9723252459ffa22c21505eda..898cfa89a005393ebc948abf1291263e6c7ab3f1 100644 GIT binary patch literal 2060288 zcmb@v2YejG*+0J8yW4A$?9<72C&~7m4VITHE)vBy&8Cm_Py{^bk@ZkU|Q1A(bQ`N;;`;dKLfg_nFzfJxP%K-p~I&((cSN&ph+YGtWHJ zXAd~){Z_=XtSJ89ddsq&#GAk6@_gsVD1y6-pYFCEPd-2A$&US>pL5vS)9a;kJ$0IQ z!r7&hPB`ZrwXSsHDJ5_HIi=IjDeZC4p{29c$)_yn>Pl^GNUz${vi9$YSUyWm+;TG^%}wf=PzO{zudB>%U|nlyc)&& z*X2d)Ai6-n$rtl# z`1a8d<@g0&-8%^Y;f;A`L7jnj=(ijKS>T;=mI5MqwZOB`I%g8zZlP%6TtvCzN8W5J zW|a=eS*w;Ltqy@&*57^}x7<^@jqg9d`rS&_a>@%_5O7=w)G1rpMKNn3q5_n$i(AdS zc1DNQk#cfHcaxJZZnMcL6p!BI^c9cYweBf~p~;vobrO7QnF%cqmJS@=ZnDMR-=DPI_!sLM?{7_QSDEVtooIUCFAGl#+V6 zw;V599jKNzw6(mwl>vF{qDXF`-CNd4*ur!~4S|HPQ@&n<)G#1BN{0)#RPip=i_& z|A%z`VDh*Gag9jq29-0fmXhYO01iEz0SVN1BzPx02FZ68@_=&Dgre-IIT5up0&@$q z9(X@D;_d=p%Bk;)*G2jAqqe&oE}In&T7l|@Cn^`7C?lshU9FJd-S8xR$^rB&)QGTd zq$}BYST}NNcSMM5h4|@MCN2umnW#Dmtq?64cUr}Y)(7&A0-_DgZB$ zQ%ngn@a{q4`PJ!oNF#<`@bizVVkOC+u1&?>6sTow8Vh6#rousWkm%0PFA*t=x(Y3} zQcO2hnWZ(zQF{VpHz2jBbAwt5kCR`W0tL~pz2G1EZkch(vxz$=99Oi>C$PZIl_$l2 zF|T=!S_gtgT4c&HgOv#-LnGug$p`W=%XW08b(HI9b=oRVHd-lWqAle~qu60d9Vkm2+JefRLa?=#Cszz&JVVm(%!MC-nv>xTqLc{Gi0g zcRU{T6YzjQPNe%JJkn8hGG0zpor0G-6%P%GYe;90?Vct;hIjQu+_iY;*XYn}v?uDG z9t3A&Juwrm&JZYR8%kL!0&#=L@t(MQW-D@{C($0B>`4kWp*5C@SJ8~1Hl$u2OF31? z(QcUMvj9UIC%Uw&b^k9}<)}-;)-!+B?t9yX6j5g*N<^K5rxsEiZL}hp``a<2>Rdph z>bw9G;>;_Ls7L5N5^7x%1z<;;NH$tN%5MBKVMRyQGY0xXDQTwP4vZcJvArKbgES(_ z*0J&^TQmZ&^X~=)+lAsl|1O|A(uA>s&RhsjddYW@(VheL$u86`;I>SB1Sd)f_Dj_5qqgwMo+?bESP-JSXfV-YmM2YZ*5#=k(^9YuiJfJbHb zDTtt#qlpX!Lv#l&qG*Um3X)9VswQzBjtUV+D0WN^$9`XFa5Uv5RfPY3N9+eru| zQ@;Wc(3UnyI6m&Y*NV+$M+5sa%5QLDNkbb4n( zZ3LowEgneIN|tqfdzY15tL4T#o`1eIop~g`KZPG%UDziotmtdkl1~B%8)EeJ@5q9> z4ivM|B^wwLb>9bH+B+1y#@+YBJveq|r+0RXb+kUY_?Aq}{Qv^Jn_B@+#>pkr^?+_< zJGmv}Xq2ab;(icd*qSbw!+!5~gou>JY~ylokfg}Kjc_fiYpsip=avRq2ew5cch+H% zc8z3{fE>W)bg!_^90CV6O8JIQ>$Z%2@2`DNyY-N&6EfkDif=JwFhDmUX^!9G*7H%z zLbovULJWGY8@QVhn6m4);MMFxB)fhqolt)`Z=;iS+ODJ7Pc>mX;QSDss3}pq!5C^e z{HD_>fZ{Z@i6HS5)E$9a-3e!5u4O&9TYWQ}>MlG64Hbsfw@ifI4S?MsH~BvGVev?s z8cx=7g~@R8nafRvlj&SO1TS_LJL~r_(R%~h-tSR->LY=_Uwt%itNY-r-;am-7#=?F zZx1!Oec->3k%xRXuc%LqQMwdWtn@Neq5g3adk_yTxtw}P+!RtlJsh}8gN*SEV}x=@ zEUz~b0IP!`igvCuKpO{ z>hU13uQ)5r8p-9=CxT#arxu$!?1><(pit$(4&f!v6O^DoZKBaJ9uh3-L%=9KdG(|O zP?zimAwJV|d;4mpqbqXlOfwLWkT?Z>U5iipg`Z+qSfUcql#@icgi*9asg&*f5aRPg zcOQs_(j>^sMuQ@xzqqzNK}|yEp6Ys(*{TzXL_w#(|+UPz-cjH;*!ObQ_m5s>3&s5B?PkyGN*(d44N_am(V&y?N}3r zE^2p2n+3e3t&3S-1iSENM!trKsb1JgMp0jfFPm7xMhtz$Z@|~t+ZC@B6Ly2NqUwtg z%jrtix+C7rV5-M*y$sve>NFq2QO^pBdY+_`OV}&PB-JbG#`hX;K6vwSqK z0+)~UYamr;`8Z2`9ORoJf`#0``(32iE=I^{F@VdyF^(=-XC{eJpqXPrVSJAvr!l0v zCo!JeF=#f+E4F1{4U?<*-x1=bDt5xnAK@rjYcpVY74WnRl@s1fSa3)yOy}>N<4EzvmJG{IA%mwCDe~WDz?f| zBLJzNz++14SawxXt+_zc*L|;b|Kg4m1Idpa-z z+zz4$*TGn221a_UfL%#l_Y&$ER0ja52(>q$1+lOeE>R zXnr-jq;d62gbn=wvw*r!UbE&Nq*Y>IQKz*TML7UIBkD~if$2+8|5SeUwfk{mBti{N zWiyopJsI~maH1>Q?7?gX=1UUu@~b=ZA4+IQTr~h^-AS!p{9|CF=A>$01<#rB+@68v zI=TFZY$oQ+tHlRxF$`TvwH&4)8%?U6_>LvjZhT|5l_nz_k7_)@GEO2ICvlCF=uWIB z+7s(>dg7=-zXKB(#V6GggrEvSSQ)3jJv@|)lZi9Sz1d_gn-Z&#O`9C|R8HyXksN0` z5vx;jJ#=v31f-SUMN2cC*<=v5CYwSfW^g8zNo3+{j8BA;}kV;w$Uj30or)gW6?a791<@8Kfrd$09 z2$`;su|(8A3rzh5uR%YoWhbX=D`(;acG7N{Nn6ZZb*3LTFn~Hh;@g2GHH4T2-s^a|e+574Z{%&d85fnT9go(!Yh!@!U8cvWL$=yKjaCEZQO|W-&|K8NEXMr5 zg<~f4yRZIt5K1|H*B*$#c`u|m=KKc}_$MB=+6wh7o$s{0Un1qiMk2|~vdZh0jcUF0 zNf6CLOY^e&g91SKnQ8e<6wgA&!BhPk>0~gk`65Vnqkea1paPiO ze4MrYMO61Rfay#+le+HoUDv}-B>?VRG66(eP|m4L0humj3YokJa_B`)-s*+6 zp%K_N7>^F1m0_1{YkQQ>EEJIhC>!u}Wg4bMB5+|!f@=#7yis^-zd)756v8;5~R%{~DUne8|g`go#d_9vZpP_SCHMz7$x+sHgJj&m)rDxGZd0Gy2p_K2u#vB1k>(itgS=5-)QEYBS zkjT%mZh=iGLhkh}NTecmgM`%;Xy)w(@!XwYchg~bJ{M8*VPd3TR6h*CojGmBve8^N zwuC*f1gGzhKoH-(pxk&UiP?zRUIp6S2J;pIBGxS%Z4Ve`z#<5un$)ckW}=eI&}p+0 z>JyOvQgjZiAj-p_zx2}+Aqp$gx-D~aa4o$R2>C8_1bns_%^hWJa=aaw;8k?T>#ty5 zn>H=uG`GPNQYJZ57M0PKrE=Z}fVd@-%16{&Da(PY;N7l4eHqLgrTQgPa13M^>SC@n z)vO4aMB~>sx|FLS-)31LS*g2Nu};B2u4YFcQ_%43`Xsu#ti4iZSPP9>p9A+LlvPB! zX!+sch;-3v6%1UdEUF*za*Mij$%z4|bn2j-8bH`#xw73rX-8|A>pcXz5>bzUlaZ|n z;)L#Dte7)_IZBYg-59Ezngv)_#Z9W&aG(oEBCrjr2yYegY|IDXuy_O0j?vDsKHWR4 zy%6piMrRy0qnx1LX}fWOwe16XUN4--*AYI4cA#DY=_b?3rIs+~c7t`pVJ9i2*`5c# zuzh&IHbEnNwAjwZDyO2j$v8%Nl#?UE=tSEQlG{+5*t!j7ezo8tjGV;lM<6BkBoj^M zG!soWnQ?SBF&&Bm)Js_(z}O|cf+Z`9!o8Xcv|WeL1hwR_zg2%q4_7!Z{B`6MRWRe- z1&yj>o)MN9TMF=2^YG|evJnVLy`pv>M2RjaCU;UfX@#Xl?M&ou^PZ(HOXZoVt8^lN zn+yfCPmdfb$R(>g!`SuLdA7xT#MOL|T^&~#zou5pvbrt+V<9FE1WxBbpf{-(@E{Nj z-Sn*E%YI+GVBPTqr=(%$O^d{N>ZfeWf}P1ka#6JnlCm4a;AkWJ+o}w|5ASwV1zxcP zK*BIF+PEzRS$pSSCAti3d;tHwzTdsdUBWQ!U#scfclEVJFkkSXS}&`pb$Be4JH zqn!9dLyzfytTQ)vAbzZgJ`!jS1J=Zp0$Kw;^J-fni5q>c6KNy214L~f2A@pu4g@bD z*j+&P6=lV0ZTz{9RD#??%#JpfUddQ7c*7c32o=t{Ud z6OP&o??hhh&6oEZu$fo;z&)5)cRUcgdN3^C7yhJzg-WeXs{O@t06i`&N~#Cr^+^a4 zV%rW^$(`m-!Umsu`<9(A+wMsS!TNO^>q8iCrHZN5a2*8KfTnBsUIhpSNeAPV<>ECl zu;_gVUTDl%9*QU~mbX&sFg!R(C`;Unw+8W8Ks*+Xx@KUFuvj@5Vgz5+eXwr+Hl)?z zpt{(7M`Ahm2r@x=gqZUAPWPmR4e)&=(B6jc&Yn(Lt6w}PNXkS2w}w5<^nr%ym4H%q zQ_xkb$@IJ_C}~#1^bEBV>;^Tsin_qJ-7EccJCmq&L$^-#b&I1gQFX0=8d{e)dssiymg+ruuhj;Iqr1Dz-C zL52O~I(Mcx9g`LmZ8hPPYz#?{hwxisFQE@$6;GB$7{@))kMCH!oA^<65`fs0g69;p zun`3TVTw_8Dj@D@csTA_Jj?&k#jj3>r&@?iHbG|)%P$rh%W#R5F$)@vxkn=l<Tf39p_Zj3a(&%^H*|~Gs){P03}p+ zX**yq-wUE>8#U_XOhL~FVAaJ!2MnD;Mie`bjcFm@Iuu=p_f@29NREPE;@^y z7z=$}r+xtfMhOzQ>tJY@j{EWA!rUyGcJ(EG5hADt9-WDrBWrEtgrSVurzt~W3}u2w z_z=oiW-}Zm!<2QNI8H*5BTrNTVLVWd|5MQqV&y|B7mHTtiQ=1q)y2%me_hmA4;+lg zH8~dLJCKtgQDgR%^nS#OCXmpRY$9Uw$d+?8o$hL^bT(mUfG|P?Slp<6F}gI-@fnAJJAW(L*H|@WD_Qvx zTkV9YqQ=iKE*e?Dxt8}JW;JfRCp)OJIT)3^`&rgr&TqUKv8*ccj#X0I-AF18bWhQd z9YrKN#yvI;mvJ%N2Rj=GbT8qvP`?zfCfZo^@A&j;kh5eq_VKULiqj5yN3ZVRWM{||Hl!yI4&AsT3s706? zYVNJ!BZMDJw~K{%2Yu1~#PdaZa!nY1Fn&6o>S{@k(bOVHPF(~4pxcf4Uzvm9KG=-o z&%y*T3?4$HIei5a5DrG*W&@+$5PDOT1Qc~$F7Iv&_D0@=G^M7aYB}|dNOzPVfx8Ll zo4O9LY#a>4)%)PY)Y5vN<%DJwAprw%Fkp65YDB}v`w`VRIeq57hP>s~kM+{RTX<>f zJ0~pR;cQf03?|Y0CPuFsMr)=^E8qNp5Ms!tb(mC$j&&=Eax4JP1^A3e})H6xQ z^rira1$K7qzCnBr8aNZDZVrMGbgv(zZVA9Sbt~QOqX@Gb)B^U+r0Qs)GmAY@bsMm% zbFmlBg>Kcbla?g{@4=`B)f6X?HY0nLttJ+gI~SF%)(P!k#Zz|x3EPVwV`@=%gAJ|P z7jUDuCd>Dc&)bop`Ve`mZ^Cm>qqq-YPIgdBHmB}DK;t=9&2Mww;!b$0C{)&ooK|+J zOlmX9j61iI?p<)JEqJ)caL4kv^B|#j6Z&DINeqBLN-*W9?g@iG5`gao7zSML@tf5# ze~*q%8Y0`eqhtP;w7Y+#30Ba}7?t-*lg*DHrh5-0!7Z;BQ7j*2Ixj%7?naswbf!lb zk=xb90lGYY0M)c=urI>8Itl#Gt2u-9pMxjvzd;xWvj(>|!>cxcte_QxS8 zb+=PJ7-j|ZyAocLR%}~96RL)1Z3oTy>EN!mbyU35@m|QbFXG-0v77p|%5EIMl98IT`@{+oYE|YN#2VN@ zua_+hj+Qy@(?~*FAV<;o;M`QH3x|q^F|<30>hm!GF$Ryg4>0s15ptVmf1KPz+y@zq z$;;=+^N`WThYav5IwKsHEQX#eqMkG!Mj-asK7v>MQ9L+x>|M)JeGEP*(&Kmyw))Mz zNESU-f6ykHFsU!@Q*TYn>3$MiOyo)vNopcV?>FtlwH#nvy=h5b z4l#`z3@GMKv)m^^8Hz!9eg^VH-OXSTtB*_7sHjde50~BGQ(A^pWGR|)Ob`j=UZ_As z{h5tP5-ryk(9KxBx&Yh%61cF@{gm4(6DrHHOj!)M++RJdYI6c2jH**=E6B zk|%FRWJV;OP=95zm@`Ou!S3Jw;vyHhNX=Yu3`TYT1VZ)D|H#5(L;B^EAsu;V(jDbc zhIG$lc$Uc|ma32_HZ)OQbV>_q0u{wI(vKi%|2M)+)ISSuM+p+Rn?`Nb0dwFo(KF5>Nm#hnflehfeJQ>1x*afGcl<^CbUi+ zWsRcV4~}JA$97a(5*AVl8*xIV)a92_llh+5=?G)8JnPS5RWTh;j62s*0#6}7>S=&b z@TVXZyKy1YdKzFJQaMdJi2+DNuof`AJrhj@x|DeMwrv^mj+G6JSEQrDrdmCN$6y%n zEC4WjARXmghWaA>tm|LGTk3*sO-1L+Z$k&{XgXgB(}4k_g=A%uPB?n*sAJP?%fdu7 z_WrXpLY>>iCGW3kqk!J~JB^D9eKm4Bb3sR0H%ce4QJN<1`g2H6od`hvt8gJl99Edt za1peF-jPu}MBiSZW%(KqM+p+R+s%^uI@!K(5=V%r~bm#>lb^1QW^gG5Id`4d+qtY=ZXoL^x7(4YC z&PZe9)}@e0et0c*Sfv1HGMgb*Uj$7fitB)gp7a3b9p6W12n~(Gw}3c^pc@fXdl?%q z;^9*QLQ(o9;nmfUjPt|WXkSiF5r)-%5h(IZfRx7)c46H??p*fC zp0EaA_Rr6q)#2Wt_Zr#QZCQU%@AKoC0%$hROBx+QySIUM-^H`+jC>EV)g_38hWs&vm%nBrYqijv+l_rC7a=n4 zBP6D&oT0;+aV9IBH4}unW2ukdW140t>chStg2|ch{gFTZbQjqS9$x|$_VJqjvL}4V zsL~H$Wl`29V_X~KW9T#I@)*`GB zGrsyEF!Kv{#y;n`_XPOJsUHC{Sm{qx^9g|%HRGT)r(Q;2IOQdu7O@GbR}dzh^)Bye zP)f?B0`90(gM=DGD2HCyKV6U#uXH=!m%$r$l8N8Q?8iVE97|xpP6@wU zUNMt(L(U^xCqj7aWhCI|?+Lqc4vRsn*G~{r`dW5FwV*%sq2*mb6H_R-nn2HnU|K}{ zY&WCUWuS}7ivHx!7-LsFyw|{Z0yEkv%?!aj+bg@8yigBhAX zLIXlX(6M5O)?6cUjIde~z|mu~#Q`Ov#TE|k34-^t8*k#O%g#Ko@Tf8-?5(5NKy&O+qnG6|>Glp)X~5s9z$A99Y976{$#H$;A}0#3MBSdvC`)^O~V0npSY4d*2}wG?WD3u|Pkp4K32kp%fc zZOh`VL7g#f9Lj~_=7-bT)V=a4Xpu3ZOE5ct9JYAH+=}7#c50LK0Wcud!%*p8hsUCv ziID+mHkxP!Ce?Q6Hf5ret8;3Yi9c5=lEDmVe35 zz*?B;Kln^nAq>uoYQ7aG+d_?=`VD9=xo<+`Xt$qZG{A=JfaqX&L+i!ChE`|_w$)5W zEWN?vJTk1!j%dcMbhvxK1m`^Z z;9e;0!+K_u#&=y5$I`J3=RS>u(XEuRH`{LXEzw@A0Up~CQ3B-g0>=A2;-%wUf)|T7 z4R07ft1{1NHA|I(;}s}Ywo#R|-Idb87_Jy2h|08+F>LBI) z26*48#rqVAPU1)A9n&&3hJl(ivdwFdHr$kOb0ghO4PMU8RM4{u#L`5C!V(2$1sVsM zFqp=u`V%;6UK@lRWWv@l?9U8?h)I7xykss8ZuGdKO=tq)(og#f5n)ethdD8MqK^6H zIJ1WQ>b^JU`BI`&PJ>yHIX_w9kgkK%U|w24Q6Q&5Mw{f{b{b@iJt<-JaBxsKs_*Cu ztSkeX%!tW;AXzrq7mD5r@~vR4`8|k$A67#c6&OgNFLQkt8}V<4oCo3r}y1{KI~wTpXQF zDH{*L>P&>OdZtariU5`8kf?*Ytm~IzCS64VH{g1VG(!N5J??OVuiKPl#E+1~xxTs{SBm`UMcGXEG}lk-3}JbW}E~1u^C1el3YE%il3gg2BW}+GXP^eM0&PxL19DhYW0S~e(b-!PJ+8Q6j?E}d9i z(Geys(1gl2zj(1J^=&jX6lQuo4VjZex51I_E~Z1WzSgFYxOY^L5t)$JJ4e$2yGoGG z2U5nFI&2HVWG+rkjP>b&v|fvw82&?qN8C}Aja&#YDgIw1KKnEiQ;w*+DcVk9^Nc|E z%@9GfY~1-a6$D!wQmTu1x`{$3iFKv?O}lXnNB76k?aTdH+V zdzc*Bo|M&(l3OnJ2sRCNSm9~`wChq^r&Ll-kynS>5Wa!xoU6Zv_??sBd4YFT4%egQ z>U6IPhNS77myM+>3yhK7FCy`LUR{FO898`s#@1LVZS0RkvaxvmWhRq}$-Aqr zI@xp64H36A!-`V_agGfe!Q$SzNDGx|6ffOysq+{CCZW#4k=l?*_UeRlnM4lfqfX-q zJqcF|P8e?P`$iLKt)QGJW0i&ccs17E5c+_eJiv|}?|LM&C6SMANff*X#N8L!lIZsy z6}KESzy(XH7m?*+5DcOX4Si8ut;-2-X>`OYBYp12XDKE3u_7og^c$nrtAOkVej@HF ztfQdZ4#W#>z%xio9RfE7gxQ2z16M!h022ju6r7cl;((`qa&} zd5!_Ru@(MI>Q28j$})7_1u3 z=8vL0bmJ8@mXtH;zI$!R%`uISe^JOyQ;bVf0`mSsTVzB!)$c(9)#;`ri9hCfiF;rKR7``KUc9M>DRH`B-$-*&WyE*JiaD)YfXt9Hbc#73SluiCm0Ne$OH| z;}fUXxMfVDvud#Cf=mqy8CWLp70Im{cuwuVcLZN7Ra zc8mr~%YfDAA*@LXc7syUdyw2griCkbuwkMSa}{2u*D?V|I^CM$ylk|(CoBwSR;71Q zn++ewu-exL9|y78*IVhsMAPSB$tu&)8jB-t7sP=P=I0Th^>;DkkNF7buhgPoQ~*68 zK!$AT2nI-);>E-$rnckmXBhh&^n^M5)`M;wvqP59;1lGRDMktU{>R3}fR=8-m|fut z0+6O(Z6nU3;H)JgvK^p;g;37p0E3#YpN@MCv__SIEs1EpzZK9Xf$9!XZUW}OyjG3X zw($ynIctLYvPqq;u9Y~V1A^sf6$2lMw!r(;45J%H7Ba3zpPwUOGTatX$Et4Q?VUHV zbQaz=CGYIQe}|~&IMANy^$974$bu!s7 zhvqd$s>t;M48dy@r_BA`)(5_1`XGmsoz;bQcuVCalqgTzeFsIUw^R}|!iQ{p#4UqI zO`^7lMJ6K&H>cWFo8cn4|`CI_%jhE1~c3wMHS&@5!!#mvMI z9ysoWMbqIKIJ1g(aU2tgxh9=0*wk{3!JDMeUadeeHc0iUsgjiSr3INi{ z7`e=s!uKeJVK6^Rkigv@3<*cjjn*>%J~6f>20;RMv%pZ>1J<0&2}T_%=^0t=9;J!QK$LLBzUo=8dK_xbn>{Tz>=p)-N~eqfIY z%%#S#@#A{Xcv}dmp zSn^*cb#jO!dge@K!Ls``NuST2HA4?EA^^4 z?rThw8YB7P8T5m}%s#>+t&>^`<`w2Pp?zX1pG9%W#>aG}FYa%93^2{MN3-eh)$j$5 zw3qDH+SVLv-b#u=+W^A%mGoNUm|(2~Lzroybs=3#bX$t{*}}{e^m)p7Qoqw!`S2b_ z)z^z7=poNe7~_zTa4d2S9{G?;U6MEZ}i8Jpt$Ve$L{I}a^*wxY97Ta zsqY8@O#<#jpuYO;c!-k7e79fyhBAp;kDy9mLJ4PV2T)E;V!e=usM@Z9yOlvFA;??< zcd|HlMk37<#CZ!5PHZ8tS7XC_arBTud4S_Bv z!YSfhLFa|yyfNs|)B!&8xQp+JIyCMFS6Z|@eLNr*EoZ1UmX0~zfRs;#s z5hxuU!PNkkQ?b+BwMUPCimxL@!aA- z_#!jn^qGCtg75SLe}mwQOk{JN*G(w<1$whx-dq^R7?`}cljc|^FZK}>YFUsGdi;#g z?O$m}cj-`=vPl^ctZ+sM@D3vjIwSN?%m`uqCL@A>YAYl3`z+H9mN!peSqfGP`U{eG zDa~iZ83eTnH-MJD#5^3?(SBPUgZ+Kybm!V`nImKpHE&%jheXhX&+V8@IB)VvEFEh@ zi&N3gFNj|>OlN}mnPskSq+70TtZxCDx(km%J;M2ahE8$$v)Tn0NQU6FW|&I)up}0O)3g<)fYZ+PPXVXV>kGsEvM0^;+SoeaX-?yn?tYL(P<(f2|nrksKrN{?Sd>2|yiQ4_xi%yqk= z0ap7;t(G{`)qa7eP};Gh-2@S(EpG&PPqg$}Xq;H=3!5Oq28>1vK8K>AQE0!~KS5Dw-WOZ^iJqtfBt5#7m~LI0*a(_aB@8O@ z(u2|vCGc@b%3R-R*ioNSo{k@ZMdDFLUKR!k^Hg1y8*U~dJ@ZNHFGU`dmxM3~748$`WW zeS!p~E~x`WrgZ1kL4jMkihb82eH`D;c~y|u63=_P$-CekCU3PWz%Sj5e3f>dz%QwK zr!slnK1lKx7H5PDMqnw!FFjD72LkmuSW;l^4%nurVA!VHXPfTQ3E*H78w~MoX|X|n zaRM6xOB*(H11r%UXEfcw(hugKRHjkY%+bWmHk|{y{TfSmX)gJhSd0wu-fZzhe{pGh zF$%2H@FNjYGlODe`;jw;r=%@;1pT*S_qDJg9hl12vviotwj1ozVM1GPm)erR(HQpU zFs*Gj*qhsu7|2|z_i9ay|3<_s}e(!57%JdiW?HLf9mx!Y?(DG}h=?BwyO<@Gu++vshiR=o_Gc9(-|K%3D^n=|G zO<o-ibHPms*9LYhXz zOU(|-nf?joOzYwcj&8>rBL2jpWKdW(^m_-kDAQk@-(Fn==Q!f%q7?rb^y{LeA53ow znAUZiR?hoqi!}WcnC1x9uTgZn=e1_V#UHXv^m{L~$k9Ks6b0wkEl$PXT?{y-ADp72 zZQ38rDM!zKDbnp7&nUV|(Lb@21ZQK5Ed3z+v4E^DH5zh1cXT`6-xz0NkuWG+B=mbT zO92P;Pt2&`Y)c$n1oVT04+k7b#`K8RJ&rmw_Z{!aKAAi`#SYGdp_%(Mf!tvW6LA8t zbT@J4JKd9A>@D_6Pt<)EQ`S8{_jtO^71}xX1o}$Hv2A}9{T|)CoJgSeFtVku*Y>`{ z9Byc(%~7m>xwbIF5#c0&`f3oPElh(?L?(PN-3B}868m8SIEfrdPuBf= z$1``S@`yJ^=C6W#bPoi2e+#^O!du3jNd?A?G_Rl+-2-_$xQC+kDU~Y`gsYQ4BwEHo z1-%htQ?+L z|4)JsNT@Ri<>CUmFyy`3mGqoBW+t(Q{u6;U0H^!FN;HSdn`A#lR~uO*ych{DYw*st zsZYhk)eFEVBkk#&Lp|KOYD}O1pe(t^4x9sSW%^}z0#i`W$eOB)_kl7GOja9rV3V#+L0yDZBJ52&6XjIHPTxO5DN;`P ze7i9fVnksRd8&MlcNwH(2=KJb#$%v*vU30lQqDIay@Mn@%0dOl5xMjt5T4y@?f*ib zm(Y-WCLHjt;fCtAEnq_Ad=P0J)^)iL41Hz^;vTTBWMLRrLnm;LGj}4KO;r^Az#&*c zx)ew}5i6b>={Yr8#hzv^`YGKaZT7`T`&43MH%(v&dnsdCHAStQ( zx^9>|At%P;UZJI1AhgLO8Klku@9B{nk($2ZMkxV6%m8%Hg+0^&j1~dlZTJRo3jz8* zQSL0!(71apqw8CXORNwJxjjW!-l7xF2}~~8(Ll%RVH$!E;!tmcU%U`|Nj)lYF1_PherD1;zvX8hz1UU(KC@WvANdGh zI2|}0+iS|Rd-eN3*hVJ>NPQhhtMz!uT~8Pfa}5W349*9LU!JU}3*bsuc8aSD;lN4k zEDlgq`$y1vVqe5XfJqY70mtnE!3ws`_YxyLa!-I^mUKQFUeXZ)s=@d~6qmVgK4a~@ z#$V%!%9_$444$3lrb3uLiYJT4+>|tIJGP-;XLYQOik$h`=8?`nf z=Ha4W-BK72fxGIEy^e2W=KY9OJx9OQ2jE#h2UWjzjE2;4Jjqel16;P(Ghfx+?e#31 z>ejl9^6G;K)Nbf^8tC;K08uweoOO%?cqidE5q>k_yo+&v@Wo#{z1-W;yG7_}9`g2N zy0m#;APeXR9N!Y1P@K*+OZN#NQQX8=sg_4eo@*~b-C{68ITqqN|(pA?#AsoX8 z9%DinyQmG}geL4HG!1hr?n@JH#Z`BZF`Tu-eSLSriCuzB7{1N$)qaU{ulSZDrfXZ@ zazx|HFQBeCMIU{!t)^AI&v$>$8hFX-W|<5u>abqK`$)=0%iI^=T_6ozpqQ6F0+c|J zwjf~ruc#V(JBprl^r*YxQXj^ntI}g`-DO-@{Cfa2*Bt+BtbeMDZymw0*Z-PS_p;aV z-6Dt{VAk&ek|e}Ob7T5uxDjvajv4EPzB6SXYxZgSK3yAM;w*he_s^)Cw8{Lr_kzdz z2`IqP%}|QcHvlUhQar@{NC2k|D%}crEAXR1AS<;Fgepxq#X`w2wi!K^s|;cBLZ*l_bvz`YFGXww@IJZ_+B9V5({v-pG5jWq1S z*32J%c7w62m_X&*#m*aNP&Nk38CJqxmTyV$)M|H5e>>2IJ3D{}ezY<3@J@lxh<&jT z=>w6}Snr_w1bCf2Y>)TPNR7n?@sO;EZZht)Y1Xt`a5z-lvn_1PMXf=-#Bf4>w#$5T z2g)Zw2z(&GMo1!|_n$zAn)iW2+-`e6UU}w?{LI1|118=PGf!B_;3Ny>8UPF*CZSZy z$}nx-BSHl}nsG%QH9Jz)E)4Cq0)_f~Jlt7$3}VmilVA%McjwZ*o%ycH@hA#mCnxMA z^Q)bsa7Swz-^ji8R%8>sWf2dyyW@DfxFb#inlV!Y7`KYe^?Vl(U4Sth(R+1jpw^Wf zSp1=QY5IIwN#)i~^(_1&WXxRz8cRXQ@@@w+1G3hGk!A=F<4xoH zB4Taagp%0e6b$G~05!f$_?-gp3&X$Cg7-%n&%w6^n<9~5h~CWMo)PdFt)=s$e7iLf zrPQ&0u*IJXopuVtog} zXFDtVcyqQk!0=Z+^#vb;mGV1&^b?=HVwN%2kRI#Jr^lxIWq&PX37BQR4bM~Zx7?+_ z-MPiP*H7>rIV<0rAEj7Fp73S0OCT$P1TNn}%QeBTxFomXp{EBu0?H z`K9y9D9H#d`R0Xp_PpTBtNgl-gs4`P$aIQoYw(L8#}B1fMn2^ygXKS`{w*d$kigxU zz>ph%I^!ds_7Qg@;}Mn z(HR|~HN#a2|E9{%CMed*H{etPbh2JX$e{N}uvieg!p{fgGO;cAl#oG!Q=|sUuK>BW z2_4d|@!WdokNz%nZj`E#6VuQtP@UKq$!q7UaB3F|WajeC%p9|%UL(@jGMem`z0^Uk zGZL%1XoZHo0a&jHgSz=Skg31SQ|CB%SN}1>nr|{|@djV`NE<1L>HaBPI8XjdhT`Co z`WgJ_i{lgQI9?8YOTCD2}U?c&Fnbl}fHrSS_qwq&NscW~d4 z-LXs_boD3w((W%2?d1%Ip4N(!wdukgM%HQY*I>t_6Aw3km{q_<50-`AmfU^B_JgJl zB&09#cf31^h#%pojMkZWoP&QK&iejAz)yhv%%yd8??l_&s_pjJg}fHmk*wiM%V+95 zz6n07rtsdbL|WOFs;q@LHaq2=5J(M6Rl0z;Bt=qVmP~6Tv>b594(b|nvwE#HTj$TV zuDDXqXRyz65kgNS?mOL%XwT+M2RrO9K{mOEp(b1PEiUXJwG&Y@toi07Xb0ucZF zvyM)Wh)`mlv@PNmIPq4at9?v>Q^SD6t%>5PUl=pRqAx8*}s^|WiAhEZX zfs>QiehHkYJm}_b59G0I%Ei49j@)?Q$b|=Emirr^sNdpI{~aFg@9{``HwQAsCW82u zgj7)Xe~ExSjgI#U!rec>tNw_G%#_8o#d$yUd@$$!31IWR>@F)Y!^$!*=p?b5&dyTX zdwbjlFb|uR-Iq|!IFmacp2k*q*bUr>hUYd6U4oQl&-;bYIjD1{eiNpo`EfD3N#x9Q zi6io<<-Hx}<1DHHu_IsqGkCg4AE){YoVDYo%6rOtH{zMEYvY4tIeb|tGco)30cAq= zok`i(M&YkWsZ(r1Lj4Wy^{|3AO1*Urd#eOTehky0P}5S`p5APC{bptlmLM~|xi#{) zWGyOQW*R=;_Ya^nDKTw?GTk*`jXSq+hW?+74kPOp(L{75mkuLRQW|Y-!?R0bfb?XI z8Sl+@)^BAx_|RWwT62(c>_UPpf=t&WBj03sWV)nSV86$~u)71wr8eaKkwUo&g3iXg ztZUr3&BGrxnOLH$OE$m^;mdtDZG$q>)TG zuRswjG3M6;T!I0%mfs4s&t>BwCKBEoAR`RnJgEC`L>#OrqY!=$y0m8DAe@uW#>ZCi zQ&jTh@zPhKxJPclySyCG7!Vr#GF4%C-dN2b4h-kLlPdvIt~lMj8e9#Ib&mIsS-5}X z+6u;QuOI^!KawZyk5{Z>Zu%@V(AA0oNf+Kb1#sawJm~ZZ9_+_{sfO6=8GDiUC%E4( zhWC{PkZxM0Bi(W2f2@1F-z_NU1-@`4BM!~@Ri7S2Mw~c zCs+`G;4KWaa0pX>=O%@>|D)PL1Fb{wUWNCN8KZt5Wj7CgTvTA8ah?RnOn^mUq2na& z4-A)80PH~2dB44a*LoTMm<6@Y2*G*27dfy_fo|!OxK(WM_r4D?xM;92seN6zTd9ItRDb=D(%(&n3l$ZlESs(juUZXh|_!$Cxe{QYac{c`BQYd4wKrG7`f&% zgyfpf^5wmb0Y~#GI3v=p!+o|(iKTYLQ$y5FaO#_Cc_^xil~6)Nxg51KoYlR&pCUin zzF|L~hKd2-5|>8Pi!8*cR!vpbt^qk+fUp-s@Jr9qYMo>U{G|%1+2P z`Wl&f99hD6C4m>N_f$!|F#u-vRf_JsO7j&}op?D4U!%d=jKXEyoS%xyaBD5-xYGdf z7K1-`I$UBgr0ba~@w|>q5TxaBv3DepR0c?$PNCj|cUK~wi(hxT%EHa1+T7yKWITuA zdoKW$H*hiD6e3gQQ|V9(GKZ9a=v6bnM} z4tVE{#}6VSchJ^h=fFLT?YG4H;?uv#KW-AmQx))FnNs#k@WyaAQ||*1h1cxIJ058c z;3X`@8-(a$aN^_6O!(@v2r8ig3Q|~!BWD1rA|4yxgZhmGI9J4U&LI5~0`Lj8<{Z37 zzQhbTRaKVw#MV0OBoM5A4=ZghK`|Sx6VX-9uB4q=B4qiaCSKD#uwq`-3om3 z;#&vbWuaSCH?BK{w!2Ex()HHHs7mWEhOrc%^f!37!dXbe)?JG<=F4Z0l?=YB?9M?h zv$0oDJ&>k%6_s<8RfSzIoM8?@Xmaf^U=Vq-r9G6H40{BhA5BSYEFO?H zCtWtKx`W$B1{eFK+->l{%>EaUMskYQBaw}b9Vw}Jix&MCq*z6S7*6J5jHS~K8aG^& zsRaOYiAFAlvgmLj0Ber5<1u=ElcjRxGrl`(b(O5YK7=;l4D|I_2n&*Md>M}64hT^f z!aJ9zI)Fv^UzIBPna=hJcaab4@;uJg)j&#B-3?Nr3n<^HbtO1I8|B-Z4z#E<&?0I< z^>~vm<`YGmo<#iGesRoqk2|=iNOw?BXjf1P1f`bqz6wFx4c0{|(|Q?2bde54w8I#! z0+9LyT;XAWnWK$b7dAETLsB0istRnb{!?t~QN)ru5V7t7|8G+VgnR7%CD;7KQj2?g zY@K0_c396!V#Ze370BnHN`tmK5b5C96(cs8u%Y#z>Xk5w52=hhM=+yk(o=c{3B3Ac z^PUZUUDGvsC|9q6mr>S!3-Y$SZ-NdZj81c zmFXCATfYUVHNPgz^6BsBr#o*>*l0K=hf!V{{$$|Jsl_BFaJ3xZ9A?;ZofS;*6ID)o zQVB7h z%h3lwh@2$gg`CR}81Gv+3!fv`U)MU8MZ;5J{JNIf2ZSm!h`6IrQ9I$4Q#<2nGIuvP z$V9QA`C&LPC7*VdJ&N*-_brDUtk}lCqm**;lv^E_-3TbYC=M>YKhx?gLbMvz_XLt& zY#`P1@HyMcX*z$HqbW`=POtBRRCU&zaMpZ}WDS?Du+VUAsbr1sQDi2}tP^6^|L$vH z=mwOSx`Be@uH@ z%i-ySn?JN2RMqmESS#5T`EZxx!F2#pk?LIi#kq;_X!Da`{BqMbfP%ij^L+I-zsXmu`2t_~!pr~Q zU4CW)u6(v$M~F@tfoEH1A>BD8dpC@evO`w zw-3muG(Hlo&miu#V1{YU1-M76&|f4mNQrO1&~Jhec+NX+eLae~ zamf7zw72aCiN)xB8pc{6hkd2Si=0ilo$jLBtZ)EUZFU zHX_$Tu1z*V_VSi&=+CMB11iO%i-qtREQS|nn!`pC`Bp~W5U`Om=ZdAU%o#Ph!}%0{ zD4+DdZQcYqlsEcIuR{oJc_VaUxeM9*T6v@2&l}wn^CmF=7^6fEout;0vCx2Wq8lBT z6aCgvT1H(_gQJVAM;Jt*N|}IEF&QolhI^lAF-L#tHWZmYOZ{;qWX>aMN?Lp9&Z{qz zD)iv#<#?=GQU5HEdHW6Tru#f!MwOnTyM$h~Rf6f)o6p^+33R`}r`F|XLIBcN0&u*& zxaShxy41Qo(J$v`O0dV>uUdMWyZ2pWK<{DCxd%{b`dtjNFwXgNpcN3*3BI6Q%+i3n zapxpL4uZ#BC91|6;_p0{3WoNPyXe`<(ym13GzG}g~p%lu4PcP`8|jUm*imX)oH#&cfP(eZdGl5pYFyR@}#@I6j1d+ zX$}QC?yRH44~DSSwF3TefUFLcrjLM_lFx}B7y#@BlTil?;3pHK5YQGyV}zo-3XG`2 zuHP>)wXRRBKJ~;H%?+JD{FcB7QgJKjx5(cIoCF|W$UX_o*dauh& zVK2LTCf@j%U4!wY&D2q?;C;xgnM!FZ8Iuxwe3OOy@#`n0(+{MH!zThl$>;}cA4uE{r+0u=n2tt01yoAU>c}FDMcB6*5 z>;V_o??J^y$2TGE^PuDPJ29t?xfF@qB%0k|(TgB4g|eAb-ng$X z9M@sg%RRm5$dFr;TCYw>N4^)PsU2U3Y7TU{YRo@`L~Az!sk-+-%2kwyR<)M&MQ0;X ztrCbF#0b%GKWrj1S_nn8MIOXAU^N-;=RV!n2Vu)-#cGk%E1)ury+p4GHP$mx5VaR7 zA3xv0jxHpxgIkUU#;BeJpKX+=#B6jXca>WtZNWP z@giEP^vF-3sWP0x$rBVR;^Nd)=0ivb|$ipNR7L2(Y08ca%BBy09bk*i1-o5{D_ft3+ge*n<5AeWiCy$pNsQ$lu`4i;@lI~p(*-W z7pG{SzG>%Yf^aKwUu!vE7w1Dvf+cEeT$Z8TAXB<$t_{?3#5JX(og#1TBqwdXct-X+ z?n3BJ#BS@H2hb_H^Fi3;7kW2=&E^lb#XA2%R7Tg1k#x9MIn;0s^KM0Ymae1VZMO{2Qm3`QYXddi+s3-2?4|HvxsOw<5s1 ztEB<-7w5F!(?OX3{bRv@q*c_EFls{3&CaQ#19x8S7ji!-N~rNqklI0acyulP1+2+y zf_NSV(40Alwq_2F3<8Ub+HDF641{w>fcLpp?&!~}V*>)Er%<{4v-A%J4ElFm5gpab zWA%~+jT41$YLB01?bdk~tulGmZk=b1qw`F6IM3n_<(dAs%`*dwiw44Gl%TdO3xVfb zS*G95GTl>TnPA`O(~T^jHzCWc7=ez_R~A>x=UAfz)0?hN0P=r2x4kuX1#f*-mkj($Hyb|ZWNOP4}v<)ORX3K8NB zv{I$N1Xiu$%y3o-_LZ7$l(1q6OS5^OG&lx)ZUFvR7<^6u{7qz5SOahL-64|7VCt+_m* zz1Pz=rzCwPX)62NXUSvxT?pQdNO{UBqt65^NhjBz4ib7Y9V8uIAFTTh&xsJ&Q2KD1 z^su|_-U59q=P!Z6K>*+WAmAjJBsoubF=WS|T|XJ1=9|Fr=fLS!rvU1niibK454#Zn z{Rzy{iuzgxpWYsvQ)jdT+|y{H&kTThbync^+e;GfS7!(C_C78{y&tv8p8lLVC%_(2 zaH?|ye@>kjxO^|M=UnfNS-$|U>o{hPG=GIO z^^tb>-3YJtx)<=(g;Tt|`QN<|J{<3!u^lYUMdH>05yfu+)EfXrR0ht7!X3wsdogh$ z3fB(v>l)s?Ry=Rdkb9rN9f_(pQO6@{C8Bg=x%X?ESqJ)UiE+y6_M>adipeVoh~@ zPt3iPPHxmsVXtPb7e|{KNp3UU2Xj{HG6Yr*GJ*NwC_Z4`ZG45{9pD>IdU=x7nUG}W z_{mHrrI|*emxFHY5^Us;jpwe$4i>3~FPl8+oV7i#0KP8zgciYj0WkX@+>T4`*WW?C zAD2HvRe5vt@AM13{?@LiU(*w9{su2h#x;m3pQaZF0E{C5aR9*B0uToP|LX(9F@mXB zoKQs>-zCq@^1K^Q_q|YDtlgZLD%x?TOiu#&H;p&g1ZDk(}_y9SBWuSTk)1PR>T8f>}qI8&)* zT-(MO`J*2JJ0G0-HH<)z!1;ML6G89i#(b`IevtndzX{H=R0^MuQ5z8#pYW|<<^5VX z@x7A{%zfpD`{QaD(vOKq)pZD}#xarfJ~)877!6158?Rgnk%hkj7^&IVvo(==qOupZ zKae`6HmNPuo`j@Q7*1lVC`nf4X-Ix}WqP?!&3SkA?Go5Yk## zJu~XghZL$O$*M#}P9atf%tWs{9UBv|`4o=)nsI*gBJ1F+a)w_JF^e6CqFk_pBX(Qk zcThNYRGLW2%k9IwvAUiDh~a=DzNAPpL-%XFhFQzi@pTQ2A@jT)GpS$$){aN$tqV48 ze>v=V?WVmw0MdJRs9Y#Jt$bHAJ1m*bO1G9AKOsm#83DW*-r*j~zD{>K)17JcZ?E_N zphQ@vxG!Jt>-iGWy#VQUN9!L1$&@pK8lv?NyXSFp0Dz+e30&PMIO-<6qy}Nv>&4C2rbRYPp3usMvAK=>XA z=~WZ_)R*X-qf7oplzix`*U2*SqUF5Ynthzr4KMP3nKk@LEoaWPZwJ^O$ZtgKNmQQ0 zJzBq_TFY(&2W1_S>ajGUdpm*tvIA&vUU?h5F9a>S@lOaSg=L0_n?z3pHy2w2o%Y3q z;tB$wVPPRY{3`i-yLjn$inj|kw_sCu3KsVtph-H^nITxLi;#X)e?Ip}HWtf)w)7{c zcZN9ht4kj9*yMTOnqoX;L zDbf2DB$?9kuON%{gE2MTl}zx1Gt9P1qdAZTy9z7?7w*&rz|h~4;)#V^9C7>B+_ojt znU^n`!cicsAh15~D6j!oKVf-+$?_rgoRxyN`v_jOAH(28$8$FzNOy+fU1QzhP4vCxkgXWB=IrI$ zij;Nm(b`T%AdkZ-BK-V4Uz@;y?m|P%8^D&`h+)$cR#ZQVWMg{i2;VTW0F0^o0IQ&p zqfc*f!Y*9mtNRhs+DX=;s_V7Qb^y14(5?vj$AGRLz=NmD>K})rNx_9f9|SO6nHATU zuRV?G4Bm+3G#+B?hw(5C^^e9f@%1T`FFxgfYSf2pyli$znJr;v&*(yHo7M8E3)q=P zgnWMtg=iLk-U4lo`}p?9eK&y=`dD#mzGL=Hp?z-OH}wdar$Eg5PKP*U&BksynV4OF zl(_f`Bb<-XNm-!r!c(uqG#I9x?s6#%63(l~fvoYg?ETdNhWdj+y7l@WOG)DuO4#Ao zHf2MsV3&s307Y1@`a}@Rdw{yGCs-I(IvJL=xH>$-Be>|#b&!95*+}woCs?0inmGt- zTOj)X*n9Ihxr(a)zjJT*?Vg?`>6uCQ%w(Bi$#9wO9+C`564tO2lwC+r5%3WKl`GxA zgET!3D()Z(Dn>;`MZtaF+1wZ0^-&)P?hB6#;;tBf@6V}wyYEaA(AW2Q{`<|m`c~Dc zs#B+`PHm@7RXq&!O;!Xd#m+X6g?4b!&=Di2;413Qc2Wwivh9ek1y4#&_W4U^LFV1m zEkJs|NbY36NcLUb;NJ0@w==YB=)`#xwY%o|on$^%@lp6hbg0ruq*k)0#hm6&DNb3* z#Zo-k6B)z~3St%!8E~Q?CieuxcV=QQK53Dkp-hV%4R1>Erx16yBi%i)BsL@~qf)p}=OW9c!;W zKpy6aBCV%Rq=$y;3sxB_v>2S$NjrzKon_49R0t{~Zzg9i)2IdY;6>v9iBS3$=kSV%@Qa#b_0Ec?leVsxX><#ab3$apkCzeb0 zXHa#MuRAHF`dSqFy_Q4W$C9gynh19hVe;M=fu@w>YJ@(A-_J*P5H&i0lWp|@=kU!{ zJ11y-2+AES{1nldH{7mtc58eMkNB`Q2bgtOyWdKgBO!L?wh^rF1klYB1aP-aSaE~r z6X2=zk)cn6cf%gKsdZqmcYB$MLp)I{Z1_5-1U$d_QG)hz$T-Q_;=z0>XZhx5zz}_w z4<(l;XNz6V@>8V(cMt4K5pg5U$}8Nu&&zx?v&TJ&{o2e=E_O05FLT|ZJwCLkkK)O| z6%zH7!<$KYisx$IgUQvoZcdih{WhI*KUUb?vu`Zj}^r zoybR!w+KQLDn?%f!b9?kQ7N0oX>$XtT@K%(Bsl^y1mRD1@{XG*r)QH+oYlT0tM61+ zzXYN=foAmysg7z`wbgs{WxV>UCvmCc-Pn+fv1ZQJhw`mqOy9Mq1J$0EJFm*jDhG8T zT}?!yCx8RYuv`8bA8F$mwnD zOJjB-Nkp@PS(|H@6x@%#p;QL3Bc*Di5@VOEj?lrYy{JBq#(aX6^BStfU0BFEUXJdi zkM+I0)>FkN?sbPMh2^E zk!W3ITd4(>W^LS=j*wyJ=n_)X3U_<(R0?M_in@(9lFwy zcb8sm$`w*7_3&FzUK?~}~ZVwR+R1cQZP%b*+(#u?ora&B}E z*GW@3mvt-01@>JysL&YUCH+=b_c|j1OU_#gvFi^yhc3&Os!Ova7IG&o?;_dex4}i< z@Eujbyi=1&Kb6fKa=2^riCpU{tMgItq~u`;sklw<3PF*F)pjNiTNsbNrg-rq#9Kw) zo+p0zF9F zuO+i_D>Y&}H?dnAPg&a`%GG#o)WWO)*7$$|Y6nU@=Iag|`-_8odI6fR;Lcg_9qO*mg=PbZ^DQ?G* zEMxG_+y!yFIgSHdLx41oG;RbC^LrY-^7G&pN5cKFg}6Vx5O?D% zg3L?*yMhGiX88j_@@dHZf^htnHtA?&^F~|1X@a3uG@me^<_C$ntFDB3OQ*#&%hZ*zr{HIP04>j_PmM*(i}KKND1C8#=|W-i`VSM- ziJNPCIx~7IA#0VCqfr-vrwIXLF-#@det=2dZQoks_=~{DPLPU9H|naixXpYK z8wk4-fvuHgwx45LA6fg_X{_*vq#Mpj9YCM)YbSGTc^`Z+ zRyza1yCer{>2 zo}nTkU$1+TTRU# zm;`Bdun1)Ew$)7cyN=1D>5c$H+9g44_HJ?qRAvbXxE{T^Hn0Fc{UUCcGUsi zjWSKUhTZNfdL{Mu619t#_^-z7&iHV9u%D9o9Y~|MvU%L$PtE~m{TYIfW69bqp4p*0 z*|Qs z{)rGGdX=cHv?pb>&=QN4Z#jP2K<`490U=cL6X=|`_cq!bg|a(BU>fna zsrSWJsq#J5v@v6V)c2ad5)SMCU2a;kCpelHsHKLf6l9OHx@-IlP(}|cc?)C-J)Uts zT}bmhpF($$_Vk)(EeKAA<`+QPJw}0~-Fq!?s|cG9cI%``gVDrfd$6zi7Of{b)jlg-8exwwz=0W}d&iRnbbrji!>1JmYBh6Ru&a0st_sP_Oj-?7*KnOE&TMoW^tA7`qljXT7;vRWb74uO zF4K?RL>P$%&2S*P0Vh{L}KyV_Yca{zf`tGT4{<`Pu}LWE-2Pg7zv zw{DU1vu0YS2xEz%Xh!PR!x~+rD1x8fiYolJ$b z9I6Mm*eBs@W9(kweYx`VHp{c$7Di;V3Zvn zq$!2Zgc?ot%Ts=MA>~SY3c`a)F&mzSb2u!4v@ak2os9PvYCS!<4(K63D1(JErL>pL z_k{nz&KRioTyoJvAV^gi(|;=oH1(qGic`QAj)R}Q0?GN#f>!9{z`e|4_iQXT1n9hvq9 zU2|V<2$~w6a-bl*lB%0J(>12JcAuv_OGn%Ig@HWbLrcN$av$~0*=euCe8^SvD0GVv zyZx2Rr`8%fmXDwhUq0P<>GFBFcqj^yUrm)$=`C~pqoAb6a&Si-zJ>8Dy?-H|%b(`m zsr2G{6!hWq*NvCX-wyHUAk^Ebqfkw1Zlbjo^Beoiwthy9JH^2t^d$^m@j|tFIsl@0 zv;7J(z{izN?eui4!TvZ_eL4;1X7l*+u}T{Ji%t__GGeQea`Oz0+uSC~4clHz8AzqL zGmzTPTcQ3HUEaN16fOdV-MoDrF4s%%y^y!9=gWs4L0y4_bLxSr%j1BC$nW|-%lap+ zC)CZ>m{VyYTwhGt2;jv3i>AE5&6CUVJXy^*oeLYMSYPVRLwHOzvardx9qSz@Af3ri zxRJpHs&^JSYooyMi!?t=*c{N~Rz7Ul5O7!x?N zrS-~G(VO~)7v=%k#z?mp;aMK%u+l6Lpz#OQdzpG++vC<$r947VWKoMUOf}+r8L=Kgs{yvHJkIZJa!fyy!2{hh&|@ zWa=`>Y+4K=+>uPs#&*>>qOW4~VlY5^$7?u5jXj8;widJ;arlj)`tmsQM*_1$B4#-% zj`}vx=s{V})fe~1LId(O+LNJv0RPJNEK7FiI2;toy?7ftcD_oE6gk+D4TFlG|bv)?xR_-E(m;alEFfIU+U1YPyYw znDr3y+7`tzRHVlDQ5@EVifFGTJkg;l+0ecQNL1P6ncSNxd!kQhk)%&JPiOEEpgYk$ zv>0zv;w@#OoLnoBf-6TOqwzHqDY&xNImVuXE3ch<=u&WHyrXBBf~yopDk=PlYL&vQ zT$xtj5+to|DEC-=?AltUI~0qiLhM3}j31cJvjWajS`#2qOO?HGypS+h#)(e+ z6AInu4s7;XUewp2$?3xOcia=`&t%4rOlL`06D3yFe&_hJu|ljkDf`6x5y?%^InL9C zluzTrE>VW!`0=IbBm_%J&BE`=N&DzZ%Y^fLui3?9ouj^Tj6{ee$*FN)gfKF;kDoV| zE;V^K=DIYbOpib=cJ5FhN76K9pLi+-Fq%$S(8epf z30o+-l+66&-vTG=4!J5akpi)s{L$$&nBx`{=wjBS_%J3C3-1uSg?Ad$Sr>4ZtUEu8 zeGH_!{fU)MFLFJrFZLl8E0F~^`aQRsE!R`Hv)7iy7nFq4jPyb|+`33}p(5i>comtR z-J}9YUgusy3X_^|=uFU)2*;RH@}gIBhdtCkhwwGMt+pUy5S56h$7_);4q{~mZWwLj zh!xvM7%%Nn0^3B2h6s{=xww+(ea&R{Jl*Y~U0|2gH$I?}pb4;^hi1F2UU~2`Y|h!Z zZKQbN97#Je-QdjxW_V6HGk?oZHuE;(Y$ZRIW$yKD4nv0vCDPq3@r$O)E+cLvBvUm-r_gq&QvZjur}Tz?OTgJzcXRJL+C}NHoG{O)h*M^u*_AYnjc@b!DPDxr98tMs+8O%U0OMRP<4z_f^*n zdf^y0=IT}h79bxj1JsX_*iLGL2+Q%Ue-_m-Z+rO-Fo4_tOdoZj7~?Z>%QFX`kr}{A z-`h}dMWUWg`>?ky?Hm-!k_C%-YZEd^{eR)EN4 zI;OH^u!n@)!A7PW=0@g_4s0}mWxKGk1Xk$6mQ5|CkVVH~B7#4^G7}gTQ~n4xr9I`3 zVpED!{unl;GvzPCChSxGa%{pmWrd@Rs(d&(<-3An{V72BD)E@^?hi@lweXZ3lH=6o zD-fvKaX1#J3TemLf?ifi!}egI_PYt5S+ZLu_d@QD)7s=bAg=@HN0Q%E)}pKS0<-k^ zc2!(?pG8QxgJVjD}PHZt)~ zCOuwDoZ~xe;fp~zX)-F!hnOmt;n1=54G5N-8MUM0u zY6s+F*PetJ+iY9#;VSHXo>vI31#!sZIRQ_ixJU{X{f^G3m;1R5xA{BT^R=g;@nBW0 zMRV;;FYgM{U~wPDZl3jF*-jr;S+l&SOs5r1g8U}WIuQ3ZVH{h{P(nSK3*-}?9d>_% z$|Bs0=oh#myKrV0T>}J>MGnD+dt-(-kd5-xbn_*cb7!a~H+Un{1#kKGMbfY<>!9BV z8KZiiqI9zD^Aw0SqqDpt1i9G@Zz1yR`M{l8G%j~!T_A&pYmv1jkt(T37bKD1(TOC` ztUh+mJ&B~l%}Gkk#av47>_if1Rv(v=c+km2-zXkrPqi3vvKBU4&-#A`g{XCyco+3(O|TY5D2!(YdM&&B430Utn)->3QA%5UB6e7vO& zqeIhDsddG%?E{opOW*Z~-!n{AWRLz6#%LcXKd&XD5>8P&(GvweMBs`ctsbwrjUt>S zpMzWkQOeR*;9Dt?_QB@X7g-nUPAu*H1sgFWmEyKlF}@fXlF(xPEnfHma*7a!Et2_M{f$3Iv|;!c7Z! z;V>|Z7dB$XydbONg-<{*Z%wrh2h!HZc;SOUjTe}JWLQqa3yQ+~wh1r%mIS}eZ{7WT zpxQ7R7Gnh`%B1-SRm$kIMkun|MTqq$-mmmfoxu+1ka6rRwf zmOrLi)-#NmjqK-(Z}itkS?QN|PQC9SygTsFn>*#nd(}JPA*Hhm9x{Ag9x@_RJfxa7 z9_msr94z04(M}f{=3Yx3qTL;#LD0_hPu=RS(^(!X zx=Du3+U9-gt_rH4DvjFeI1h@!2X=K6G!KyT!DR0rB@`pN!FHjUcPz^*w@Q>JDIW|4m4$0!DjPhcp(#Yq6O z0JtOpm<7P43BW7>=q(*ivzU(Kapd_esvEUg(PWni*wwkcOnn!^`nHYq+fo0(-fpv1 zO;2+zS-afJ7s5M4TP%lWUN)5(ap&oCcHrn{@u|=LYgyA3cLxg>ZD=2Zd6#Z0u9q4g zqpWrPx`6OTXO;jR{N9vqE(3sJaoed8R$AG&O(8L?)B{= zavppy*rcwG9;%zt={qx!JF#E^%F({WEbuUDb3e8gy*bf!U zoO)XVzEZK&!%Y;Y0W`}nY^5t6TJJ)WfXkE0{nbkB8k_0&u)Z6Qw$d-<>&KLeEnWc2 z+CAdFeb?@rz#0(Zj_UXOQO8ls@hD|=aU94GZx*?{LR>$p#PRtYC9+3sY2`GTnHlEF zmp*s1(;&o6t~-TZD<)~=(4*wYm81PA({=0Ra1^=v+khrPrl&rfb@T0+-mF#4`aM%9 zX3kFtelMg%j{?!qKy|1z5bZB(f9}LmeLFVxf%tgRylrtLuala@NfXX^GD3i2V8W-MyCj^!k|BQWxu1trDHoc?~Y%i5Q6pj)RG;@XsBpnR^He zl0(<7g#T9R+jHeH>9^hkanfZIHO`d~Dza;Ykg50KmgWmvS)wUm+{W!?I4<^C`_rkr zk{L(y{giY2nFM00v6nO!i!f@NSuud-EG*Q%0y_jr4uP&|=Ix@#jd+(?sPL_V^n z_A*nbSm2nx1MQG2IMiNKz&2HB3&S1JzoR-fRtRIx$y z3hI~}i6p{tb+RE}-@DmE%KbfosW-J1F|i}s$oBMR^U+2!T3wQlg9u#phPjRC1_q4D zz;6j+Z(!74VRs0e2_5ft_45^q$_lZ!y5Ha;D?>QdxTz&p42;ykP(+$NF60IxSvlW@ zV0TfvoM8r)frpOGVJ9Tzs@vT%nfL5auD#oOCavUB@;@uP9+lln&pp+0u-EuZG8jpS zqki~F;A8ND*BqB~8h5<-y1=AOvu$! zWbkk?AwovhYFjKD-zM}dtXgBqOm^H42QwNCP4uaXZF!(`Vocwj!+|O^{$BV^lJLBU z+Ta~$AiHNWhic|t7@-%L*x6ce4j&6rS=)v ze9&0{LD^^67Y^Cs&b)>3Y@gv_;^}N%GKP89$lA{aecZiYWmcYJDz=|z){|v@ky&}h zsn~w8tcgJL`EvMfJb3|j7|SW%qI7c%5`*SF2@mBm`;bSNuhhKFmi}H_0cKx9tiZzB z!3p$=ZpXWMDoI6;<-_AkEu|7=8K)X|s}EdhRcmtx^_>WO=sPV8VmyTMWo_}f#f(m{ zdo7V1pj&hr_$Kp`IiO+mdr>CYo2I27dKet_{mZ?%dT*r{-ufYtmLN9Yh8Y+keXIyi z2QQvK0%+S|xk#@^cI7NnnH5L7eI@lHr;*-=A1=KO@jJnmC7mX*Y`f&bBhbLJ$AfhS zuoJ=`ZcaIM)T9Cu^H#5Q9Oc|PRv(3r-J5U^Gw?oIX0(NZ)0iq=d=%zKR8M!s^`!WW z^}^t_6fgWSIc+N@)%7V=*Htif^0=<%4CjL5qr!0qzFYv=Ry3aOb~rk9l{a**!W#Fg zZeIu@w?oP+RCjhzZ&nGn)Cwf7ml;Rp0Ro!2%~MVw&A`f4JnWVterP%sm}3<=xi6o3P?owpNBMyi!Tw2mAFVeX#C(@`*{mDjg}e?lyVl zYQwtc$wgAb3D(`5ilW2jF1JGoma98h`eRVf4(d~J=ZC?|~R$u~M7hX#jxm4xM_ zG#LI`$sCeO=G7gX`;>Z?&Mfmvy^S{trp~M(-xAMjhsYzj=ZX7Ro%l-{RtZ&|YT58} zpoQ8nWmif|(Y~g@yh;~GFhO0dKnq&O$kjpf`wk)bO8+|c!81LzrDX(1g}8)%E7G6q zVmOiEZZtPayp$|}&!st#*})~;9d$pUt6S1Z*2B_3>^4b*yEK`D=f>k+OY;b~G>su~ zE)q6)0F2Hb(&r%_E!30DIVLsk^XU(eqQym_{%K=|FM0}G zIO&?hd068brSRMs5oCO-?GqGOvfyVASNbiJ^amOz*7TscE=zU5TV;^S=6C>6BOb#` zH-sX=RZe-h(^d&Q-sz&7ApEAnsLA}fiA}ehx$I^)<&4;oEo*pyx|qvuqFJjIvu%Dv z-nGrYcWRHxlah0(G!`AkJrCJUBQAmo15(n1>?(XtopJ;O)8P(L6P+cKI@t12{m(q zK0fxnEbZIv^<&?2)4tttAogvheKj)J`mRFde$seD`LKK*nNVrN)4Y7zpd8&#Q5J($ zz3V?i0c{_e?PZ!%f9&$+Q_1$K#zjOghfg#6mDnq>{W|O;vHce8qp|&N>|?S0_t=-2 zef!Xy(8k#F=r=6^W9_uUk<4~j^=2}?{D%1<{4lKr&9tkJ8pzt%c+wP>m$NQ6%XNtb zl^F+lWn#JBEYyvEcwD=#xZ-SI$dkW%wZR^jWTp7c#DSQy>}ioay*Lv-9nxgq9s7mY zr;cjum7sGI4$3;npre?%ty|WkUas-PB$$;ol5X{vF;gYeH4XpaQFKu>ZSey4k9>qs z!TRr0cfssS6W05)ST7>^Ie`owGOewye;?t>%t6+@UJ(jg<9S1m<)+6nIG8QyX-#cQ z*{#=Z)^%3CUgi>^o%D393#_%4a-&Z8rArXU`(MWmh=>Qc0#SN(JrQ!3xGyLKx@LQy z0T(Tq2&hBMMi)Wz?6pZY{-SI&lnsFl9wPgxu4jSCh&lVRB;a2au&ICo89ZcZRGoc! z65?+Paj`-OWblxsX|;I?Fzx6>yF(x}cJ z>gx{#i04X&y17!^EB_}5qsx>IbEj3&pO`$Ag3ZyNW#ayWO!$fbrC`hE=#RKfYDqaA zvYCqyr-J$v4DzgmL0pQ~0Bs7}p};tXkhlM9At}V6)rCwRRzT~dG{DkPGn*|-uxQMf zeJ&X-M-&rnT-UuX;{t$2{fMM>SfBwe49a5b*R-FOWjyX?S3rG@Ycd^qmO zZR?uZ)%FmTw-ClHrsAvRU6vM5Ycr9UedB>!x*)mCF_g(2;xX&f>uR4rO)$=DpDuva z1#ME(Ul!i!IepZIIuy37TpE8B={EkvfZUNuX$H|OA(=y~02|K&o&+?BgB##Gth6e6 z5H?{D{XK@1>wZBQ){b-Yai6vRvp`nojup+%eUp%_>W$_A<^y}Gqn^hiL2Ash`*?2d zoU>KmWObY@U!4%=R-`VkanI!FbYH9PcoH05se~6a?y1?h^SqoUH8Q<8?mf*#XIVk9 zV%MFk?oRkT^>L^A%f=_6X)Jm+i4@sE^!zEm9N5-R^Etp+C5nYvWBKEI^SBOn?dX;F zSD2kvbmHEwv5CZOIm|=`osF3LihI$I?V!v zZX}-N_OH{Vp_CgxAVic{t?j1ZtB#7Rx|EwA_B|Gs>soCo)am2tjDp&+rC|1Ys?cT> z4^hXiTNlXS;Q_)A%V)c-zLc|WVO}!4Y!cMgfb10svVU}t31n~^BWk^+AfFA7rlzW+ zJzgo7&lc2rEqA{o62seB+;yVO2`e^TkUGF2>&?vZ)slzu`JOua?bUu(bT%YJS5Xi1 zN_Wf~-$2D%TO;|*U8>vJS0=P=7i~6m63F1;fn>DkGhDFkr*|mw<+Z(jId65}SB7x3gH;X8^sCr73v+jU8(Cp<8FcN)m-aL_VMYCN6Eh<*)Le1 zWqD2Ir@to_Nc3crF)V=`(^HQANz)3SPrhqQdmNkwV!#&&xJvH>XgMizK9q2V)AsN? zV7X1`;R4z7O2+_TMm`itZ{dvCJE%Bol6PCprVzUhQ9=}8`3f-*(x~sTsrC5D(P&+5?hHIyL zdhklKQ#bgnL?#nH2(Ls}3q!uTg1x9~WX?Pa9Ov9FZT-1{*%W~M%$iFM_V&)o1cXP3&B2~)|8^a75-{4{0N zRUY$NCoqB4hAuiziJqXWPEYVlPR`gm5lCAfrV%I0ev<4GDSw&}$j)+^A=(P~5q&6n z{6bZZ1drqQOMYMFx9%r=&>OTA468|iy_WEKSDeDviGsbB?DS5~(teEmD;BR(y!VzJ zu$UA)#&W8#XpmvVlD*adi!7d{xIOr%+VCp~pe9z0uEW+oP5vX6Ky@F&%N<=WpU29_ zYsqkAjK*Z3G3X-1q1Vt7>Yw()FH^CT0zgpk&r^P5=%UA*LL@Faj&E)HaAG^hajAkBpYLhe!U4MQM!>fC8>9_+n!#2-B*Z0ulG`X zcoGr$U~xSXX>u&m3eoFGzu!roX|_r!vWSK1frAB$r5VrcjRYItCwe``P|y>-0h0ma z61WXPoueM+)H-nuBgs&fxV8iMar)UpdIyk!&?39QZqD^au%Yhv8YO-cb{)?0TFRJi z2$UI&|Hm2m$BjHLTFJOYZiIWor0b~Z##x>u8;mX*ZC%+zTeb+lG~Wc$=*@iC3wfR3 z&bK92iQb|VJN^6PGRM9->ECzH{Lpvz!E68HXi80g+303sj2CqhWmQY)5Rf^nMluRE zGRKi%2@2(@${`P%Efd;)R)$Tf)hyiGjqsw_RvpAjlY+-kRjC&)A~)gzjWH~AGM|G7 zx*ZOOIOs7n#%#unbC3uGRM? zh(OH}`D;I3K{)Dy5seCPx&R}VIHwNQ(-@5$PV?YF;mdFimpE(YOW+L-_LEOHKzu`; zxI2TFB}ez&=lTmOLC8B}g35Iq|DxKKmEw-)5FA?7pGEC<|3*}|HrlETs@D~s>+8X5 zbw*zw*T%Wz=1o?&j04;iaEl7*jR3d`e4bCX{RRc|o#*}YJlR7ca;>+~*o~{%Zw1BW z1hnv7g!F}jVjqnshtYq0Ui}Xnjc+G7B3Sl)?x#67{-%00$ulponqv;!gwt%VTW7UC zV*|G%i?2Es^p&$m&(~M>TFOfhy@Nyo;{cb+@q}|r^*pSj0!aCKp{m^iI!ZP+&QW;V z7dU#T8mtX#%4Xw0To38; z{ntxBDdcyO=cx;=UR+Au`f~~c+q`h8a;C~+CgL2A(VdM}O%4zV4TImC#cttR6bZz; zS)0>-K|JGBe|S-aHvxN0^{2eG7(;EPt+xW*3AD;qMkC{ZeDp5RcD6ZDUy}@!X<_Dz z*47j#rBpN>D;1Tu#z0+(I~`w%i%MGb?k4&xd~(6|sdb0u2=ic*Dx()UmV9ZDNXTq{@gVKi}Y3Z5$03Ci_8 z__`DChF!!H{Ndt#wiAz>$&t<(CG%j~UycR-Q=3vHBS+f*46ku!;@`MIHg!l$r48&O z8x#=P;EnRL${@HCvw4%yU&rd#BNLZX9+@v-?ik#=t5E>Tw5+&w$O z{V>!iOslr>Drlm|EBPZPKv4rIzAj%utj?>-zMTq!`lPi=n9(e z$A3;BgNKJ``Sn3yv}+@;@hc*E;S6D;2O-)D(QB+ct^@sD7kXkB`alA8eL@u)jd#QS z!Ne(B%>e5`;|gL-HJ)qns3dSxjq6D%2)|7aXXTi+yP~WugmtiX^%iLgt{g3#XOq67 z$~*2E>fTbGfq<275bf5t9Oa$@3J(NPxDk4YYW>U8Fuz3H?&$Be&Sv=6TrXMmx3|3oMqpE4I(CUEBP=VF)~`hXjQR3FR+mk8S6VG=cnTDwUk!t-Bd#Di7tq1 z78ctvy`KCH>Knb5A~ZgvI(N8^1|GeSPul(d1#aF;45E)yr^pZt!B0Togi`S8)4DXg zOEhp4P6RoGUQ2})9R!B9d_5zo@e3iamC4>TV&!tVEi+irOqyI? zG39})n6y7F$eZ#KHQ+R8w{lW^^xiE|J@Bc-N1{)VyCNdd@=#&jUtp9{9`zVW^B5aD z(Q0g{iw`1|T0Y`Q)nJ1*RO2A;RPKlJFImbBsNp9;7~aOGugU}?6^q9{1Ge*05Z(l3 zHHOG+db*K)bmkd73ow+j3jj9j>8lRz;6Zj&bcMKXQj|Y(@s!xh(#97%Yw92l`J0~d za@AdisCg*gqntj~Wg^9Et}rcnEJU5pcVpm5<^12_J4Z?MH7J`{LT}V;Ql;&uli6*{ zsadhgs(N3{pBAinGR1m1{COdM=}J5rj#H~GuZ9c6oeUCYI8Ip&5!uU5-LIZ4<4Tg&BAZffJcbV2;>i`JbqD^9{(jyVYz zX&tSyJha)smwV$2v7ZHhEZ)L`t=&aKX zXLqq}V_0{%ZELihdS5cQxy;#P#_eZXdFU(Qt4upcz&zQ@Op~<6ZPw%Qi0lSqzpcTT zx8^hs2f4O};D9I5H2ms5>QKG3@7UB%;OzvYH52l<3<5ajaBdXvkw`t7sLi`*Z{cCg zAbJBpkC_MJ(duMh>>I>?CGiJx@D`g!|=!|^S#yedCqB+i`8|!ZfT`5F%#tV;OFuLP@L{fto^Z{?hfFz&z6Dgnme+& z&3%Rb0tY1aWy>?c!FFeVbwvlzKi$`{7iY|KBssiQ0L^MU32Pbom>;mKY;`e|BOlHd z_=TQA49&CWS_(p%h)zbAP)Tw2p79=&oTCAVa%}D{~SzTG`NSEX_qaH~DMK@PZhJzj`G(?>JFj*&O?vibg=O z`k7d+;Ag7frHz&vr;LA*sw7U zOt8g4XVDm*kFCK=?ay#)wDFi$5*VfhUca`;x3c;A)pUF+4nXyvm#65OZSfG#*(B0y ze~FJq=a9pq0EGHY+U!>C)2D(lC5^cL!soR56Sdle7(ul!r#E=aoiEqg!?M-O?YO zIf=9IMszT9l$6hVUFXZa2)!dNGySMj_fPlo(C=qS5G!Z*OMPzguRLjy(BF0Tmqwvx zv@}{8ftqXAy;d`J6DGL=ohoN5;sF-PiM(fM@lJ&|Lrc5@iqnf(ickzonlFb@ zoruv`AsD}6CeNyMI}h%ZqwDds@fn2=9iN}KuD*gXSnKK*X1uPJ)vc?4#`Hl){@Xy> z`q(=8KA_;s>I}KHI~SYt`tYNj*MA}AI-T-m24UFB?O7r9S~8dYnmv68wi6aN_Z3Y2zQ*tC{A&EB`CZBH`TTB=e>0f-^4rSqwfz1T|MtUt6u;N;+s5zj z@o#_3b^Kl*|JGybw;}$$0aL$+;@?J0{ocs$W`2jozqew(ji1zp^*cKL-G-^(o$>E* zO#R-$?_Ki72e_ioG&@H-;@eGu~_{F1-_zkFR8|8JM??v(K!{8q(3Myrf| z7x8QIyCnYYiK*W)@$XX1|K#^+eqZAE)%eH3fQ){KUG4V*%xn3r;kTCG%lN&T-`?@> z4ov;-;`b?jcgMePV1ARI{=PGQ`qhjqi&lNDj}{sJjh<&tqxSf-VsL*4tl@XqrbMZW z@^01OnQgxvgR^OuoI>AJ+snULX3PBSJ2M=E6wYhu%i^KTDd0GeAe(W9pQqnvSMVLe z_wvr^RSA|z#pGwXwgi3X5w<0SnJQKYH~W69CRctEy;$=LAej@$;Ncc^)JJ*IfheW7 zepV!#yCEP}v=1cF{-YC3AcMPT*DQ=yTkJ&z5Jg9$sE7VJxd71z6GTt$AQH&n4$*~P zG)}ZSv(^Q47=jNa2+r*w5NKAP4uU;Ez_H4mB0z-UO5iCS1Om|S1RGYY`R6)VDGJN%tz?& zqasr4Ve0oqioZ7Pa4^f$x!5l-Q46Bw(C<#fyqM6)s)R2ve0g^V(1+8v)M|Wi_XRvA z^O&s~5;K`gz32hrqBE)U!bYQ(WgVghr3A_p37B z5j}1Le3wM|v3k@)kk7V>s=}0VD!tXcTw3`qvC=e;Da|`dHM``fv1oFXeknz%keL>T zS#D;V{Y+?13X?gxvBL|W?uzx@#*MT119%PI*FDvGb!IyJOU+?<(q1^P?WMW7KEt zD(YeLqaGGVJtrpW2=lhxIk(GqY2vY9)6V5HiFWv|q8%pnLtXgsh$H&A2 z+68kt=8Cv}oQu=JTM7b%`Ur6ue+2rTD zS*6Vg>t*$LTTpp z*_&%l*m@6_s1YNW{Y1ijSBv|;4s1>!gNH{_a^X>`FQ;pLT;`~kWd_I{d&I+;SHCkU zr=*kor1&Me)3tuK zYyF(8UDenjM)sS6Hd6>K4ZkQOxmcvTX(t&?E;B$zzE58M*V32LXSrb%lyW(PB^G0vhu7Ru`Bmt(0Ay9L=Qk;X1qzWdmqcQagTRZ0L${*Tt zml$_-E-zLvU8~I*!DpE!xnAyeanU!$MFJT-JX&1T$H$S~tr35S)8ai`YKSn$sOgPG z&6D}?Tj1y`jIGWVMrTBhYB1hym2|{vl+%oxB@|-!)}%fkj!WC>wWac~TPmyE3yEMx zA~<>j%kFfKC7|wR`Sfn3?6T?QrR?am5>n)pXsIoC=VHU6OX%G(K@)uwJZWrOz#XCz zul^mqBrCWZbT&CLi;W>nZEOz5L~YQU{W1ZVh+UUR^J2(#YX_Xyb#_v^Z_TBdB_1r%ba+8E|WRnK(lf(D09FXv%XN)Nwbc#US>VTYC7s<*B5M-XLzcuTB^kDsoS)VK`Jv;$6F=8FSrV-ZTWc`#`&l$q{5wku; zRxWQMzBdwUa$;PmO;yomvsqu#{0 z%#t^8w#*)H;;k9VTL=7Z^<8UN>QD48#*brKv(p6}B*Yc!eyB>-!D+6GU%Y61BK$Uu zvL^2F!`G|6ovuw4d}-brA6z>aj4xj;Wq)DNC6pHD)#lLsm}tX>Z^Wg;kSRvAWA%h} zcn25YT@E`hGs0;{>V4Io)Vs-4uP0Nzo=kPpF`mP~1FJDd<2GNT#s#-K0xQTrT~Fu- zGucYtw$WsdC_Zm>pC5jQZ1?85z2kC8$pTdVuA}{iAAVnCTHmxwd|eE}*TtUTlYa-Fr0v3& z&AbEp?wePR?qcS0@49E>#o>DHvv$K|sLV!Z6LqrsWS^Z#V;R?asvY-uIK8s#sL$+0 z^dzWwe-{XcyUD1YTr#%8b)E1b4Q6lgrMIH{xR~yQ+UlBJk@`rO*M2reOM}sHIdw*( zbiCAdG}@X%Q#eN*0zSdOYN{zP%VBl*2AO)1?Wwtj$8ty7P${jzNuhym=}}%ZkN%)> z3Amlc5!dq_95kMZ+s3;5b=_%|9W{4Q2FC?(cS<`yf>6MMutV~Zpm8UA>JD$5OH1FK zr(#f`Kll*EUG!RCA`^9#>rZ(U(^6#^nEDTt7zZ0Kgc@|#KSI#(LFVC8jn}9w4B&;* zmJ3Yleai0S+DIDu3+Zr*wH1wTTUgV%3r*9`(sU6Te|;EFaHy`Y!TbTVy1Mq=y`dLs z%f?NZbblWt@Jz3@@%}>3v>vKqr?ar2jM9o`QrWc3xZ)vPnA@p{)KfKm+SbM_a?{sL!zvFtCBogO~?rQ1WwWj@4QyQuoK6jFOg&&FfjRzB?CSc>KLONqVi zB7s)5WM?BuhG!1$3czkz-G{Y?9L^)v+CS%AaZLx_*6M?$z_mcutWlk^G3d8!pQrTcg(Y5Yp0<{!-9_AY;@cQGqNB|Em;cf|+9c->2%_Stl zWz&&3qNSt`XuVBGEU^tX9oYdh$HzZOz}iKRR6ZzWTB2JO8u8}B!g`J1QW#6+230fV zbBDq{uRP8a0(f1tqkL`YF`b~DjDB-F`)=+#k7+e)lqPiN#_%} zkQLV6Jdd=NQcJQRdrXj4rVu3NXg^y)D#mk61Y+h}i1(1^qvT~9iVEJ{P^4EC;3bcv z=Cz5>gi+fB#=zZX)mE!=ZH~S*qc+E$V%(ZsL-N~dNa#$d4WToo<`YbPvAT*j>p0rY z&NMfR0X9P$pj9mK;uXN!Z*o-OgT zhdY%mc5Q#eJMOkBTg;ZSH_^YiYpF`P5x2Ml6yH?Eg$ZyXcMbLjsdZm5J$Je>;A+Bn z|6Ur_y40qtLJpPeolbvkpX};j_2BBE)f21tS-ocU!K*WCA9#J{uMhlf_4Y&IyMO-k zobf@^0a*350ZPd23uzUmPDX|A#;vTav3{(4O9dya+l8Lp{fXIWj=+b%m!t+Qiq6A2n_d4+>*ON6T;?*;`ziTv{?7V-zbzE7 zsenhro zzM%NMQ2dOb(a)73y4!E!VXJVnFq~z>Z-{ty&K^WHKf0O94H;89=LvKsg}!*+xb{j2 z)wuQw%y?Xr)s1U^x4dz#6-Zkj#UQA5Z<(*t7MF=CVBzS;}_ zLE**O{S9et$k3*}@FAe?sOev^Exe0h6NRZCYk&KLCzMvw3nSz8?0g+kfVeK~+^J7s zVs(BrbXQODJq1iGbbKaL?UB;12)joX(Si=`a(V8T@%DGg>NfB_4|Vn={ceA6^_=SO z#cfmPCJbP;yS@D7MAFN4ldFAKHd3s$!l!M={g*pOD;{Q?h`G}-rr#E0(g4Mi!PHn| z=mb>FiW1RV|FAda&#fHPsip3L9w&9~ffkf|ppPfpJKO`kFkUYW`Qly0JFWR!ahAHp z<`>|BIdyfsN#r_PyKFgY=O$^cx^g%?Y7sT>x4)xcG~!_cbh@ieUh4tyd9B~^jYb$u zT>pD0`S}I;X+8+Nui&?Tk6FmJ|DeE0zn*1(qtKF%rPzxKaPUW5%@yDYC&;V%5li`t ze#Fi*eEccSqR*)F7dYHNA5!m!>F)xp`?%TugK#8S5|sIku@hNse4lK3;faDJy)5JZ zO;kklKD?0a<#eP~*NBvwnWd&n)s}Z)feZ;f+#-CMe-g1Lh%!*z3klJ$g(7kMN)GNr zkdGfdDA(~`c#=`>V87o9><@xz&jYywoPWRQC{c;%R&F2zZk^!SEg0M#b2X$Q99~HP zWVsq5`|{xrKoR{&pFcw(H^Q8P@cA!T+35Hy;6iFtxsX;rlnoHdl=I;)6=x7!lLAy0 z0!GpRP+EWRX0|yHZ{QT`-vcqW0rC|31bhN~0_W4rW=RUE`uLNgKamj1tc{}@kkgiob?8`kK%DM?hPMvc3s?J zd~+i8xvHL@tTg`zBHOAc)ZMKT;}9pQ#rB}?93Be8Wfh{9ZKZwkSskp;e<}iBlqjX zbot$#my(r*sSkP0he)KojjYgVariafM)7rxwxE@85p@&&gHYmLfuikc$3NwGcI+dE zU7y|!7@q9P#Lt{Tnf!_}Nrf%1>20il;N}$hy4;t{Y|On-qJ#n~2A6o}nUWuPl~4@^ zjg}nR_jHGEeJA>Gm?e?$E-i#t2PEr(S1`B19}#WiY3bVSMZ2Isp6CDj5fIQ6mqW_1?x;MH80-7B5fx`jM|BFXb8B z-p2l?EDVyxb5i}>kCa0+8f0>-!9@yb#YYCsk1#(`7`+H*763m@0A>O3vjkw4+q~9~ z0l2D@tue4W7YTk4+;)**tNOFiyw8LlqzEl8M$HuGpJu81^K1eir*muK&o zsLZXkGlaXQ-nbLgwgDOag=*z4dnNieSi4p}?QbuCFPZe*`lMIh^cavcNbh=rCncZf(_^$&0@06#O>dD>GldF#Ck~1q< zuJ<5C7J<3^PwRHZI{K>Q%S8^{lbh~M8+%k>a{8SqYg?n3Lv zAD$|iez6-*`ZKH6IvTyqV=}Aa_dHYwn#VEWRvq+%IDY7|IYOs^Ld7TsS8(KO6v?QD zPD+(AYKi8o!{8vD)}o@aRH>@JMfGNT{UFboljbRk z&!Fx#&&Spt!V5=x*i14c-3_K`nLmgxjQ_*!OfVt>qH(XQ{Z5x~RkvhxD>bO@kyJ{) z5M4s}+91i9pwJHASkp}E=Ude8y!z=%QISi((X-m7S#dvf(bRoR$;Zv0^3`ExE-Oi) zKj;aeIzEXIPi}rZe{v(fv^B+4W_9Pi`0F#febCJzROiniuYc_1)iWmRuO3B<5|8%g z8^=)>_BeKZP2TQk;i(y?VX|A^s?NRb)}OapGY6YT1(#zsputjquWOfGj&%3>=ujV5>D;5u zK_WW&#lD1Be`fcrIK9I~Q*r0!u10!-7*1%6?4VhOZRUPOqnkR}t5`_%5$}W3T?ahY zm|MaMNaOG|B8ES&^&5iMkMKP6a~-Te0L~Y7>v4bW0PPOow+`@%4&VU*esnO43-k_K z@}A1p#<-pgNH#i0_gm_v7C@@E4@(|HK{q1?l=fa|eGxy8f@~_%BzExi>`+|0T!4 zc&-qh&3cgHtX0D07|{xXF^!$Z?nNsV=Uguw7m(3!AC>zAj&L{m%r@z2f^c{27e5&W znp3GaB~P3~NQk7tPae-mLQA9FyLxNOq1JmSm8_w=*>3oLQ zdJ}776KypP7wPM$1C3)^NAH9AXZ3|%ypC4bU_lHP)4mqddy~U(i&_lIq5mXpmOl5R z2MAs9x{IX+E3;s-`9FZ$3ZjLX%s2o7{8)bI-qQLDX?v}HZnRIyP*^c9LWUwJGL**? zWd|9`!gwY_`IqCNiMEsU1bz7Qy7AKKJ#xIoJ55i}hfl8?FP+}Q#an6RxnzEN>s)yX zN_rfL-?2Ow#)CKntOET0u`-gn;!sQt@nd1Ds6XWC?6kjYeDl}h9!o2L*o&YnqO)CFE zxCgo0937zo*-h|Ddv_(=QeJ}|bU`-^PP=LbP+1@5q}G?)}1nGaerqe&Le;W1!nkK^pD{=dk`XxeWmA4wbP8}a1< zv&#u(LoT3aOJ3+3*GOYlH5~mXbv^qs zY$5feLoi)%#E76R7P~8TPvb-wA>4Bt>%7OgWJw0WLuQfs zYSwV}=i7Tzm9>Mud*ga-k8f{Wm-i_(o=hj|o1`a%`_UJQiFp=CT@Dxq9DPkdlU{h1 za%u98&0zN^|CBzjST1VArBdqUd>87pY|Dz{V(4h&jQs^2^IBrK7;2imsbXlJp*$fP zvhvcbY3j2nZ$E^~-MhRB;76B<+QvsUAgm!5(Np7^5X()y$gy5r6V?hF-|hsxKtV}K z@aSMz24?V^8?c0@#8}j-r|zO;WO4Or4c**zZuRT7{cevSMo=FxbtVyI3D>F;jT;P( zzb}6nMP^K%f$&oQf^@;m*vq;cJzi-{)~5gxhM0wQkDr;PK3K$+=%q^d#vMSn45KU6 zeOPV8h52O4Erwe2Hpx|C0U}~dz(2E zcu9sWy-emz$24B!x1CZyU%4QA#xIC-bb!k2Gh#yGNVbDuH*zEl(jY9Xj_#r?x0#D7UT{?-3}{Oi;4U-9q9zcwBJ<^O*Ct?Br$`S;_$ zG96zp>88q$X_n?IQaq8#d(Hc*S{hzxV^K?!1bNC#Jc*;RTws|A_yVt`p<11sOs}~{ z1JM8<&5SR!+LFv+BX#|E>&qP@+91_hswk~t`x<*ZmWXVgbJvI-Kr%DGs?W@VeLGm! zrbcJ9EF5?3M>f)&7Wdhty^Oa5KZf}bG-RXavy?3FLtAyxbe_xsqZebnM1wQZl|@s5 zZgb`hVy~syL3ASyUS0{Cn0-M@n4ad@w8)_>VKh%@ zJ__=j;Ii*m{g^+j~}~dTVAe*~y&Y zJ2F^cS~uoinRWd)0+`G{tjslqQP*|I{%Afl7M+g%n|sHX!Lrzg+>Bm_6Oqox5JmDy z9@8by`EUai?0)x``wl(BW<)e%&B>ob8vi7Xft=pvy~NLN?aPnM^e?7URHESl#ENf* zC{wq!!?T6J;l?t+O)XcGWuzG*016L1bjwh7vA-%jP}$CIw)k>C$4X{Pco6VlAUDn9 z7*%f|aL@Jn%pKN@7t4~$MA$S);-h&B>Svthy zA?p0-P=IoY#Pg$#xEei_VDk{__Hy;h&s376NuE1wGRZ^hVgVi?=~R6mC#W<}$yovL z{-wDJ=IR~H#0m2DuhO;h4i6)>!OSX4+m-0%@Ni)1t9GqFbaKAkGLL?GBIon_=fwwFh_H)@EL&XT6afysdq3va;yLEnQw7)Rq;JDW0KG zTPj2^rmiQe`9j%de;ti%>ggkK8b^1NJEmhrba|{CZmdbhiT%ij%>&)Z6GuQYB^Tyr__Mj zb&FQ{0Gs zeDU@jKr|oo{*NYPZhhiL+!run#Dnh>u&&`UMH`%*uRzfYyFoOAh(n*bV`zb*7b}RH zTx#rZk{4fXCVI3hryd?Vc?{O-nK5YDOx!)kMQ7E*Ry&m%*MQZNCKT1F#`|cIE}~{K z@1X&iP_(urMw^Xn7NWBYCPRKL>7$jyu+`xQL-#fqx1PIq4sT7wTefs`nM4rksnIPYx)WG;&~ z#VIPw@yK?KCmr^nHs;YLHKt0?b^T4^OA#QA+r5FboMXtW|}El%8MDx2R*hT0kt1y*aI z^*-9=zmk(w&dO_cbFLIDIZbmiB~de+X0sxgS6%b+e7Ub@ONPjqdN!H1!^u_>SEwM< zU~Yd~tO)2e*`+GB6~=4cAS>IWScexQ6|#j!^Ayr zqyE2wzR40+0gRQSH=Dz<;@~Qc%1+=an$exWRZb&2fveEUX?VHZe2cPpb0@`e^SK&G zuHxge+<1Up&giY30F~%%9eZ>O*5<8zqPO#j3u)qZn0UP0e5c^=;^PpF7o&HZ!*UtX zd*LB_xJlJ81_z|w%RBCJw6bHLfYQu7qJ?1|(E>ESNZ%I|Z2_W*4vO*7`LxM@yeCCl zIeIJ{=4fgBLWr*H(26|wT3W4>=T~*;t%Q*&F2Y87!feY%GtKo9_o> z^Z`RF&+&uiBGWh#gJFq67490Qv>*|KPRjxS9YvtY~PoX8GYFBVy+k)P;v%Tx@0 zg}@&c_RVSVO9bAc&}XE4<%1=$m9 zMVvj^$==HsWG@E4azXZD@O2Ba7lU86AbV;)N%mwE1l z3byS3WA4r4-pQwbtP zHI4HCh>8;mVw_PC0cTV|1;Gi&i(ZIcoItN$<$9goHNNj#YwvS*Rd-O|@BZ;RztmZK z?O_djp4PUS(8ivau8=Ci^p@=`v)}k7JK|b1} zRpPVQd3pU%*yCb~;y0aj{7;L`S9T_NAWSwApv1-4g_B+phag0zC+#X>V z$Q7CGdQlf9it%Fan0n^)pinKs)R$aXOT5_lPg5erhzR18#o&K zYkmUa%gP~#gu;=Yl;gF0A!O4Mx0g2DG(zXDlf4jG$dMtx<~%x%QAf_457)I@sO6=hgD2)#(Fu|un!%B&RU54Kc;R`Zn*6{S6 zqe1%%b64l*md10nod}NM>nQU!z6~V~#OJojMOfR}W<*$T$|)l6+%~{mbw8nLV*H5J zGsaj2Doi1_sxOS+k2LcuF;ZsY>R;Qb8+(^qy0yMst@Ql(6pS&N7eET3Jl$A0(a_l;@h&x-<5KavU&)~pkEq5Uj;sVzp9y(|G_9)d%7 zL7(IUaoklnki)_P7H%d`(ywAZ5616;?Lhv6r_ z96wmpl>~5{2kUR^f678@hS5;-!Kb4TAWD9NiR@ehP4cAte*iTwQ;4d$1k&3O&Omap zF<6w1PhpF;s>CHLKD0(7XP~XCuQAxS>#%rQ-K+!)HU&MIHy=jc$z#Ftcr@T;1%q=n zTyGLRx2SwGhY$3=5_do1FQF*mjpZ(dHPG-d8ycV@nmBDW?lIlVVkhqpbM87H+AB#O zFeJ6stxFy;#S~U_v<@vatRqr)wVhUZ;_A>-<2Vg1bKC054eF{&TPaUB>B`bxHZR|f zG@nVZ@zw}td@N@TG`mvXy5z_4++x98ikzCLX`&1{lco@I0*n3B*Z3Yb(S;yBQ>s?0 zJku4)Ju>i#k|wGzLG>2I2AKmMaZaF~e4tLM<# z6j6eY&)|uNGx37~$9?qQ0)N2w6UM@4i55?zF`bPc$UH&b@Y^vPXB$-rKAFdRuq<26 z#VBO$gAgigUWWAA2WQ}V0cDoHLBMw~>>&hOjA4$H@fH0#=G^qFn1tL(xQc0d@YWQr z&9d_&Mp$IFr5-UXmzK=ssk>@koWi5#iWIJxm!z=S3(SpPH;%BQo3`qdv`{vO_yzx1ivNeg+b4cH=2hg+8-tVLeeqUatqFt-Iw6LvGM z^&6_4O9v9LW4@`F(T8{_!xih3->pgPnpfcg;CzqvB>GlA1Rg;k`;d$M*oru%6>X6RXAqFy?+Q z&YhaqLVX-Z7lO;t*bbnrYvytA6kDWi`WH3S>kz8>AW|veHY)LWon$C)9s)+)@z()v zI}_VGu=S*I-h@`$9FHGZ`;_13$nUZE-Gp1Ly*%EEF>EP5ooC2(9s1?q;TZNOx%QzD z5@R$hTFT(;82R?LpUtn#H`+%7%n9Kc21d3!4`t+HJM;CR);@v>Xteg>gnQdZ@zcB( zGPcoFax#GOG3=FsrML-&{0U^e<_kVLy=0)eh1aVh2bu^{DkA(r)$O{z!HC97~CI zg47>-FXS&WH-HiF^9Fp@oy)tXLvwm|R(^&_lwPLMj>by!MuakN!jJ8yxPgs)&^`ES z@Se{GLl7@`BQk>$*hXx7|FGH=Guw&SGJ0SScd z4JJ{lb?Gimxb1@sCCEGF{X>U)<#`vBb>Qv zPYYeRVo`Tgea_HE#rd9ZfngZ+QAI`9&PCsDyBndn=zTsb>e zTS;i`$|zSG7jt`e=FKI@xXP*}HsjPib4ICL=c`yKCpRMpDyxPS@G8Kn9u%}&m^}+o z!dVn(s9)(8FmL5NuWDrei6^PS%8nCl2C(C^U)Kg<>RpcNv;`me!c_7i^qLk#mic-YC(u}};rOZ>XY(pyjfIev(O6G}laOXf&BS#~ zjfhCz&w+prB_-0T+K4}nlt^~SOL)G#{sB`vqqh{AAA&gMHvA~JD2XtWX}8lpENF6G z+tx99C#r)DB9i+vHY84?lMUkLSvCkO8yKgI-ct10pn9sNj*JRhgx$ndVV$@ttP@wl zi|im?@ipX&#&vU3;!#dOXdh)cF&@6u*D-L=iNK|jlho9|Ib{ykJcu9aRpWB z6qmSUV@96t+IgMg66dyACH!d_c~)RYlJIElaG#{0x=0e2yfh<8ckP@`lEk^KPYHiR zMv|p#)J~(NhI1O-+>ReNfljeAOs>UGC)aEfstfJp+QUl$nm-*+MsOhQy`pO`JgZxJ zT*1RrSC!G};n_-5XTY;qrIUIu9cDQmlAA`Ctzcz=hp+Y3O1}1)Mn|ZTF8c;uFk3~IQKBc2- z?&el-i+LZmh;dyF;p9=~0Srtdg!t7Mx-jAB8&x z7not(C#sTqB*l1MjKW$9qvS|DjbXkFcq`WEdg8ATtEDGClVp8+RHQI*X4qo)VD1Ky#!1RS(R>0f^Y73b zOoS&lA{Oo;=-zUI+*>x@nijCS`ur$)@AQx-Obf{*KRG>MJS|{#^+=RFFfF89iLitB zR7nS~!XlTI)9OmfT^8U^u&o*;k0LqM03I281ZAczd5XL}gL%sfiUPRRQQaIuftUFX zzuohlLU8U#K)a^pN3Q6eRi=~7Xq=XivgbK#%S<_q8YVs52 z=BJ@f>ptQ%xIZIq(s3ORVb^ynUeB!xFX&xo+CvdP9p;hGbok`qnQ!Uv%)?WdbeQMi zDOox^BYuH-l}yD6cOL!{jNiKukz7RabRtRjd^_+WEc-8`=nAkEj~GEo6n_=in&K%W>}ThX;5Ai)-izcM~vf-u*)67$w$b9jtA%- zt)EF{c%wPN`n(fS?+MX~uTw@r#nN@d1WDN&CPH;l`wqAc#{Z!bW3*~ z=ktQvB0n#QuDS6z={u$gduR7r;>MfeC3Cb4yXa1^h`j~%Am~0eEP>_Z^t02zo#SJM z=-^k<`_Rg?($QTp&q<@#o?n~iGp_!+IW2L$v9kKQWlg(Jn6(a_4o5SiZmq<_b7)g_ zYcU?4lifr{{=g9l_7U-Fv2pJ9vl(JarKw6 zih2FDlvBTU5|LbyDU0sn2>k8#!CYG^s;T^y#QUL?qwL6h(LKz|JKo;@ncRgnzP=AGbnAKWOcj zsn(8`UY`w@)0#A5R%?W71GS}oMiSSpGUEINc!_s#r^*DkyDdQy;eRt8*+Ql|V>Jp} z(rDVDx_BQ~TjKK}{(gZXBB`97_P2D`w@<4)M7x0k8(=55G{#nL!jStQpB{1Dauet8 z0!X}NopK9qsg+wItRjzEbJ)^522^Zm`>ogtZAki@!uskUB3YlQ zgYNpPP}n-JpGiE+9s3u@jr28E9fYBdQ+#^Fb*qE8WMf8B;;rsfhv4?~2qvdx>R?Ca z7?4iQGC&v%T&nn*kAk(^+ws1Ve?)Tw00ZbZqfV4=ux^3b>fiQ`*^5RUL}|N{r^`OG-5pO zk5hdCmYB;UrIG%TfssL+XKF?`$jLK9xi)Es@lS-WYq-Q!?iGI8SCVb(koQxP!=Pm` zh1_mU^E(-SSpW@n6+^WcHogZLM{9rL_&glT!WO+#4{=xz);LG_k7TUHQW@dKOYhF8 z;Etf;rTXPkkJ(cd)U)V3abik6S&fS7+2=fAbVNNlK;)zENVeoW@vw+`a^!>)MYHJJ z?|gZr$oex|lQXH3*Pw7FSFs4*Ck%axCHd8*pMo|Ek%l7#*oL;G2bu%vdAT7-4sm-WzlQ(3Is?J5m!xqJhMsG4- zf&^wy>1nCuXr2ouxi#Opn48f8=c3A^h0Z0K_#H~!+|?)?bX9DMvhLDi8C28Oc~L}s zdW0R4DHhWh4~*$~-x|vIF!d+PmLulNk_pVd%+v*qZAsw^Td9W>QW%-|HOuDe>E0hi zbC%q}Y@C8>Izsn8{!u7#$63pg&$?{(6K42i2W$&S(Wul`#IFSgMP5eZ83#BIn{o3M zs`CN<{2qZt|2vL}=2e>y0@q(?eia`mi49p%WZY3-mK4u)hRpBgF4|5@ctt`I1Q$42JO{_C?mB&IbJBYPFOOmQO&A6*eV7%Qvq%VrzXCT|@C?X>#~} zhlg5Nt}I@TGmib$)2*D9oLHRPHIuexYvzpM{xM#IL&5q!e#hpAwX1iAvQM`Nni`Sv z#f=Q}Fhr>?XL%Cm*Wd(SY`>y7hJ;d3@R;l*Fmm7N*C?p+&fyeMf|uu?8}pK{bud(^ zrMyU4jp7-K;6M~Vi3A7xP^8h47o_;&9$Nf$Fv8}k0n>evxZ<;M_Hn!iFB1T}N4a;R zo~%4;T6wA3;yDWQqfz_~q*9PyHA+^D3f1_VK;l(}Z{ed_Er_JrMrcJudEuGaYw*R< zSlHEk1c6JDT)3AXS$vIu1=jnU--aKKm&V`0*L)X0Me{xU;-!kivo|DQbJISzG?-is zw)+e=a!Xnl(Q1~|omI2=M%FQ?WCu**jDZi9_YkMs7p~Q|FT`_c2OO#}yn|zp4OY%U zFzg>nTf*~@uLd5*0?`(KA0%Mv>IeArbJ-;rkl#W1g`vQn_<1NN7e^OAe-QAAgbNox zpBd1%5A;1S9`+4H7Z*>xaJaW1A3PFOj+zIdgbd?}srcV0aIsumWF7@nhLO_>1DGF* z%lwF+0_>RL(nkDzo~7$;Uyb5}+Z9vzP(I$Hyb9kc_^p(3W&-V4@-b%c3TUFSHfJsY zS9s>K(XgJMNGO$7>t9hdDO!;mH!1IRe3O_#Zhj)zlAg*XgPejB4OnfDX2BTj4h4QKH2I!yc@ zObw4JtViMIn+bSP&)!9Pf-x#$%)!-*On@({xi|6Zarg*gRh--xMhZ`EN zMAG)M)2j%^+-DEt9+;I5lW()WalF_TziRu{41#B?@zLhAqNw<%5Xx}-iv@$;uH~O3hs99Z3FWsdd@eVRQFqFezE6&G2r8r6 zxq1az!NbY;G=BzW+b<_Vv!_M4{$viuRc6TmQT%pB5tN|YXhTFJ7Yhy(OD+P_n_`}p zBDpilrPC=}2BE z&6W&{@nW8~VKO|JD9G7?@!t3skWOonmY zLp|d!vAo+jG#O~)5Y#x^YJJ&&G)=n0BD`Q3g9FmkBD`QZf8yAa6t_nhdkRMyc99K> z+9p^Ht7A#a5mBD6a&-D4VFG}dN{Pr#__t~Hn!Q#12KbXUk{JuXV1p;{6_r90}Ju@k(o*5 zIcNg@goI1EDE=k#4>H_jc(F+fEXF}4Jj3pg@oZGO>Hy5H!0c@SC%bNn2Y@M#ZW<^S zU|sh~JYa5lP+KPpnE#Sgo1Es8AG7fzp;E+0zGoNv@K#o?5Dy|5eVZG}{0ifVLV)L6 zf`y2mPd4#kKWVLCq_Bjy#l6~uYhcM!O!P@f)I5bx<6QJWFg8(|XYRwV^sz!e%qhN_ z;T193jqqY>i1}HFJl}qcKzHA>yXbDTbiMQ~-LOUZrxEkf9?6t~`9G!LNtsf3Yd3}c zL)ekXnDs>Q(K99W#s6TjS|4^p8aJapAa2-VHEEuNij1+@OYnga^&zDgjh&i&A5!Q&S?Q$p z(MwnDUhC?b4kFPW5YAtYKxJf`7C%q2$@Zm#!O#MopIsEjOUeI$#+R^T z$y3N4=4lv=f)>_&FfOHDU@Hbj=p_dt^C@yfJ5Qq9kxt!yhMrE*pY zd#ov=cm-Qt7vuAOj4%3*dws_}bVxtg$*1`=JlxxfbHVu7Z^IVzo^Q5E8BqF@Hvkv^ znyne1ty5(DI3kNQHY~@TxTYt6$W9FoLpl?coS{~OXq}M=1 zK3Vh1+_p(fvl`XhR(>S~RlA0*jGd}ZS`(%a@=Php5Bd8@sQh^vouY6eVUty3>J4yK zGleVijX;ieBi{t%yl&);K+f+*z8S~`-N?59xv(4gRv;I3Bi{z(;%?;Ifvoj)V{an1 z)Qx=yvHjiHcM?0$jlG%J!EWp=#13_1-$m@KZtShZ&hEy(o7i$Ub~~|iy0PyecDNh+ zUSdbOvF{^xZa4P*#Co}`+4uosr)BO3iJg|aA0l>I_TEP9wEX=rvC}dbg)Lv3mct(< zc3KwSPVBTi{ur>ZA(0P0fnr-n`;uGx20&r_Y?Rcnbq~DF*U%vJfML!Sd=Ry5^ zRX-2mBNLrF0dS(juRG~3Mv1|(&P_&xJr7oU5WLU)H?4|+wNuP!VKan5*Y;fmH6fkK z-A#m@%F)vuWFp*okcpV&Z)lh8VQ0GQu)Y!0F>UTRC?|34b}rMe-#ROu9typk5sVD^ z(?cw^?b0-hy$r)d&Hd1JnCyNI24r&Lx{JOVV6p215#BiH{0CbKd9iCj^@Pp;LhiIb zg=E9#?+AWQz~2*O?qRm}1^s+cKlk!8`7nNEu@?rCq9!K3r75BWuQ@&WH5X)xLEeqQ z^%PNp*HSR~br<9sr-&({1mBhtGWiV`ep=A16tFBpno2)D2kZIG*TL9Y z`?K)FFi^%ATc16mP9-AzB`+6%vcJuDua?+WU~*@no&*pNMz8&|}->(Zgyi z=@AQh7&uL**Bwvj{S)zYEtFNjqi5GNiGAj^yeyv3`={fvxJ{==>@(BL;`#LcaXgmi z>GX(wW_npXpWZXYdx_*9Yr02ozUCjXpod~LJ^#An3B6s#!)RJsPpKv5rzq6s4=BxJ zliHK!%>TfZ>*zlpME{9JUg>GEX8gxz43IN_g8#D46xajnd$LENUhpq$u|{LNEZ=$- zYyS%UDq4?SaF9QNr5Xklj0TCnfyDTB$}y;#7#H*e=*)v9Y+ppO_+047{25I2kHctF z{1-r&S3Vc^4&nMMToX^JHK(W2L4aE~EC&l3!4Uc5c;km@x~%mTt@SO|ay*A1U-Np@ zdyE%|(*}kNf*0Jaa-%(GQ9}d%PNd4_ zoh=8PzqC#^TyXa46jAi_4Gb!FhyI&;fd@WA!p_*74M*4_vB(UHg?g5|$m|p*q%&`^ zIX8b71i`g^NGTMobP#L*0uDX5bQEiUHUn}vstgy#&n`#h0-t(kVyzLBt3nG?t-R^S z0_lLTHwdG~UF`K0S}_7)T4iRXeD-;K7KOz!=IY!eETf-V^_I$Te*CChV}3c0$Hw-? zYZMd|j&lA6(}z^Xu~Da}ZvOFXR%?t*F_?P^t2+=#Z1>8_aB=*(bBa=wc|fS6xQs*3 zg38LvghOQoCWx?g$%t8rS%pwYRBFU_l$heqieDpK**LA|>@W04op5U|7lo}4;DD0I z7q;FHu)4V_;&6VQ58jCk+5_cbq|_Y18J+$@*k*W4r&$7W+twpfO%E7qGj2grsH{9* z6{b#X5Eh}H#2F1aUtgg3tOKDeG`Imx@_xY zIw;Hxt#J?a>9F-d%1DkUZv!L)$=M{4L;NYC1RuW;&5gVt_9385o{1k5wmt$!*!n0@ zVwGCyq~F&vZr-^d2ryxTIWyICToJr8rpdM9E}$@3E7h6%rEFd zo_6kmaun$GQ?~ym_L=*|ES}#lPK$?4Nohx)>R{zpbWP{?*F+y=`NeyB|4DbEYP9L3 zJ)P-e)3sRp6@EVrmRTMSM_WpvS#5Jt{KmFp|A0=DLt%`2k+-Np*Rsux0LSMc>*MqB zlNKi_|1W^9O6bdRg?>@kx*gdgiJ&$77~n`72)Rq|`3i|uk0>TS5i}YLthbD3B^|+g z`H>F}2d!l+Q^UyqQj}{8iLgzokt{XLWl4rh&!|J*HQQa zg};EpUr6Cu=eZ|MnR9qyt(y|`U>nFN7u{(3k+_vU)$OVuv(iZOAT`?jk&}ztU^I<5 zQv|{4W|slilZQU?a1nX9*zvHTi-$BSq=jkv`I?xHcXCm6^V`jzLB+C?243|jRu(na z^Hf7xB6{g^UQvfvfv%@D{RS#gnpkB;X?Jjizuz5f@fA!$Y1=a#EZke$9#G+&9qnTW4VlO9ipBuM{}*X+ zL7d5Pb9D$#9D=KX1!UEQ8?Blsk zZ@cZ2>Wwr|_w-x}&RJpn%Za+zCNI#r1F>k6SE8Own`?H*lQ#Jo;}rrP^Vt(^4wm!T zcH)%BHk2CFa=eC5q}!=lE+WLae=ECMBMruiyK?14Uq4{lUm@{t&BRGhlSt@tUFdwh97wuc#E-v zk{UXE8{qa25GibmwU2)ja5ja1RKUA1Gim=Y!~RG>vG(!r0=}IoJeGlvXW)(u{BZ{U zM8FSXUef-L4Exgze1c$$OsP$c7CEsX$y<=*Ey#2fjMsx5jqEPhF(GGAO%ml*&+zb(31!@bF|WHIU}v$!ls+!^4x?)G`P0ZmpSc=UOu{zC|;- z=h-{5gm-0FBlYXJBfD#C{lpOK*Wc_~zh?NFyOBfbop}m{)jS0Qg)L&7i7LWQB*Joh z!J4O#aCO=q^{?&-*1x(#gtJ2-N!*MoY}ecAeg<<@5}cY1KfI^Q;=sU3+ndRRf|r?s7_kpUb550<1+945bn{ zGY9mn{}4*7Z|=%6`qYN)o&y~fQ$}Uh=*hR3{xzvwskH+N8P7pD`+OqZb(}p840iPq zS^SRz8`hKs-Mf@t0*^2;p5@cXwIMS%O=$t{8NLrp*mnvUzC#s6R81ufpZq#g3;moH z2%|EjMC#w7M#j1{qA@;}3XM6&yE(*_Me3>$VMTSV1!2D^NP}~q#Fhp}ivqE`RDdMm zWk21Wwmbymmv>3;Z<&~00L^_OoZN(KmxnVp5m#{Cc z$f)A7O}8cA!?Jmwj%7oE4pj5asS;bOT=}QB}sAC zxoP7;x6`8}@B*>2>g!R^LspMeLTYn^4qsW~_SmO;m+VVmuT;?8+1L})!MvomG-F<( zSPL(NVd1628X|GdaI3^!&A8V{;nlcm>4Y$F{M0w)AqK`tFSDwsjzhT z!iw7ymhN2&D}g;>>8^BM!6vFhSV{1OnXnSa3QM?KSmKNlmN;j!K;phW6ISD@ zu!JG(EnUL0eR0hjVP95pd$Q8KOIanbCoA2R`peNR`r;DXA+DtP?o3>XX2m58aXVgW zANE&Tw7XAE%6L2YW@(h@@UutUUiQ%K>_`#bWmZW< zFRSS8vLhvF`F*Y==-H8?+jR{R|J2UbRdB90$dsQgJuhh2ld}Ds|ZWRe^OJmBIEdybdE2P1vHfpbJ_L-(>gV*J5R&{WAo0 z_u}6SMcRAuSOd)QzGbi%*M0b`27GukJuhd|(-YuwJiUhN!M_G?_Hp;x^5uhhSs{>n zf($FKQcNKT9lxO-UIT~q4s%v`PJl3fgla0KUUL%IGxJd0vGaBjE_}}i*k6d31C29| z97CH0Ko!kG{4N{9owLK>g=bsD&kJD|Apm!*7Bjf@xE5Iw*MJ!Aozp9~2nYM3m0=&A zV>Bzl+r)J{25@1Mk2KDM^D&JU)%rKd1jOD2xh8n=pMwFkF2R*yi>fq7f`@L}Sfc`0 zKZm#2OBKMaA?fy$rULE zyfE*M!58z6a=e0SOm#UhzI#zLiB~WsmHF^qIV+0y#J4{z6eL-^IYJeDe@Cg7jVzvD#c*2m9g3NX$tY#Fq8LGx2SJ-&{y?@1Ohv(p&JC8Te!dK1EQj(v-1FdIw@wO65M) zK+FPpTD&Kuz#ZyYW$d3;xS16L!7cLmMOf{|9Zy`95yiDhZG1coD>embgC-wFGUhU5 zw7fGlFTM?mm7rBp62)3ddy!J4l&YjOMoLjRiZ1~r6uY6YD9UeB7*dLC3SE?9y!%y} zuap>6C`r~>N)1vfD5X(Snjj@!PrekC2Kzv%&oKMi)Rm*e6uKyxW!UK)RZ0vhlq4rD zrRAhlR7&$m3GK4ne~t|($-VWV5G|e%V{YKsJEdY8-L!rMB`#K45>o0(Uf#k(+wSfh z{R?@X!{H#$8pb+j4Fkt7=F9eFLey2VV;+ap!IBO)H5;9VH1Z>BKByD+3UQyAhkj9#z6o=q>`YZiMSp~l!4 z>a%vV`!R8Ip=$0#)|DV?b=7V#{E>WgJz98nt`iZFs|SD_85wE5mkj|hqpJp>h7^Mp z2d}L<2DDIJ%X%qJ%tlatUeMF4csOK5C3M`)qh!36ry+0)j$&+&^a9+nFt;E+8EvNQ z{VqlN5z^0BwBPTIf5&R|d;FAg69dV;1HqO^I(KCi>Bv@(x2A{DzcNrFs({u+u5!Y^H_sRSUCS3BgTOV;x^?#8P-u_dd zfhLuR`RJ6cz6V_(uBYLY+kWr(jARHjp5`91*r!ft&z zUWq}B!Lc65^eI%))pK#I2;bVy)&0;Q!4O;VmF8}!>#PNz2Bys)?)Jv>ffe5FLV6|E zS&3bW4oBe$dhs7uO@cLV#SdO^m((>FfdADe}EiBAL6c(Nlybf`21QEKDvhsVEkDp7+3Q?2% zF>9fMMpzjO`D6kzK;F`B_2Mkp{N;EyjevTy)R=2gy#~h@_L=KA3@X@g0}3?qm4O`< zSVTZhO+2=v)YpK)1R0lAX<^8X&7K#;SL@geyQH|Wov*Xtol$`i6@=j#`_u8|U)cIB zSj@O%uPP+O111XkS5!V+&1)fA)e~SOQRAp6dosBh$ee-P|U*+wJ@1;U~w|-^Lff4qu`SK_RH^p{0_?RFz(Bsks0pQPo$rMus0`& z9|D8IAI`D}Oa|v*QGs}JI47qtImE$4!TT_|#f)3<#~(t0!TCYlB*aboo}8LIcsOh<56x-_Us<^{ z7fud$^D;t8NA- z=1_?^H{Tom>%Pc`<|3f_<#(X@J=6k}8dM{e@-Ug=jD89M#FUjxanMwi*8Uol`cSwZ zMfg5733x4oE{3N}Psqc%GGQkidF zN<5}?a}W9pq$(FNeNt0sG)XXw*+aQ+-X`%aOv<+V@r7``7G5fmlYat-QVGQ zxWo0G%r(AWVQMZ)PjPA#zvFRXsv@p=bj|N@4HTxT;x`|^)zXgMWtGwnw%L3u)&0dN zL;TNS8trGX9CDd^KUc0wTDm67NMx|Dy7}-Nd=Vj-jsLjGgM*ZlWT-SrhH#g1k_?q5 z$x#3Jz$95HO_Bwehsd5To*iJ#16CG_1~<)1T3+TZU+WO^BrQ%v;*v901Z^;Z^{HvR zXUm9^(X)f`S@JkhB(<)(dF2Pfu|EpmqAP{SmO^AnA+oFx*;R! z?}Kpn&YR#y?B0h&_I7kM^2b@CTFfzDHgS8h(Y;G~B(NtB-F1u%I^`j@BL^i-ZzG3p zCk)|kVFWkV3L}xdjU0`f34@Ism>=xeBWCIIWfZq3Bi*}{Q3881(%rTHMpTD@lAyOw zO1BeG;&<(n3eKHIlgM{vTR9q81tbgszuzSwtC26DxIF>s-lc#N*b|WM&Yd{H_&ae# zWV>y$E7c+{`4KuQdzOuEC$kOTu{SI@cceoiKgr0~NU7AwDl=io{DUr;*-W}adxX;l zQ9bkoAK_#t)8%eZ*rI!JokJJDi6OQl|A=sB^dt%Itth&m;f$UH_s-}^@ZW$S4C{ZC zP3-L=AknowY>{R&pB`AFqiT-iK%qsrj@<%xSdH!kS+!-!>eahSla%+lAk96x>twsm5vk8PeQNee1KWI@PMT<1cX_`*Y_Z9)d!sv<>Xb{h zV{cR%>iel6yID##86QFFiulL7r=5nz>+c}l|G3jr*((ZJgH!FybLayO+G(Ok94D;OPF@V%A^!q?~e~hU{`iJrpuyWKG9?CcH zo#;436xK@O1ll^VvuNyOo!7ob_V-eU>CLaF_L+{b$SW?)7xp5`aY2jzQXJlXpRvw&%R&O0>_u%rk z>pGA-lRb$GtXTLm&!MP2@v;1b@-Z7JEa&!*Le@2q73chS2c`T(q4`l%zu6(oo-PFf zjIL@fk+sB02w5_auGBmZ(c4TrY%vyY8ST!kh2w!XC*UVa5*SoTi?xcn&G zepsmiBJ%=Z8hDIUBa0FYY-E@EF-I1*??BRaKQxt9H~j8#o0e`ZsDw!u(#HBCLq-)t zk!Fqy>xbDIQdhj{GsY`b$4<}T4hL>O4~Ds|1k4$rgH!&?lj?;i)@QZ#U8Hn(E?Pv&7#ZPltz)4Nr=7Uc{$K301 zEVWl5CC_qaqmcXsX~Dp6c-7wUiYu5vH=c(TZ*iRsO~vQ%=Un`>VbGQ~Uc~E##GaRW zVO;^K!Kl)_0oP~R%MpGoc@~04F|KZv zv|XZZ$giwZpXvg*9qfA*pX)v&?@uZbWxxh^Sb)>?o|19^8;Wm>f1Z_9J=3P|BA<6HZY*WlFY_h3^ z$$j9k6(z=+U#Yz>eb>>RA)y#!mWby0blK|e7ePT&;5HxQ(7Roe=ITU<`UZ1)7mKo^ z7)SnS_aPq`6oP{wbMr;?$qkn(!~JVc0J2;v_uqtNX0A~U6f@hD>##x}6q6@F$ZUh( zI#|XFnm9uc4HlDMIBa8Gab8i>Hc!_m2EyVTu2JIfQG_+h`um#I_EN1d>MRL6hkQ%$k`cj{{1Zpk!Bm1#DRxVwC;lc0a z6VR?69v1v?QO_DJe^Ia=nmm~0FZm=A6YZ{j1@bOe)e?xaV61twdy>z>Ul_#z$$S|~ z!|wG98Vi!IJ0>KBoLnK(W-H2#noGe;e;#H}PsrzwPnKT_jR+y0-4N71Kw)};BVbX} zAaJ||KPU7SsyCf5mP-zU?=vxV6#Rv$0oX?Om^u}Bt+Y(RXR2tK8qD`urtU!qCG?M& z>LXLh{Vr`aZmF`e-={qj_AyefO1Wf-LBgx>6SIurq}BmM{AMXcA|)V>AYv1KEJD|n zk3l-f7nhDwvjXLf14@pW z$ldr#nz#>o_*M$f8*gCVny2XPip^UG{Q zjM*WKWol>~ZHin>9AAoz0Uxu&9l2#YVAnjp9HA%Ps`qC9&M}B=e!?cRtci{W8_x@J zNaN{fpi$d32Qi}g&jN3LE9=gwdS!VcljkSIm5o7z$s@q*&yRb z?x9Uje^*f;>>8*>Mn?hwvA;tI0K{5{5CDjE4k5rXwy~u{8{4s4+`I;R^03C*d@+>O zeir@n?F0DfZ6C-qz$@F)OYl7e`8RnGkc~n4m@5#6TNe$S^~m#BRkU=9{w4LsxS+Ib z$J%VR;X+9u4f7Ht5q}2lz9u~2CHy35>-c+FFt}RhCJS&n2ltT!Y*3WrD-n4K<{ukI zn@6x*vX^ZESDRaZ3}IrNU4re>jJ}Idw-Ne7*j$we<@(cEgzPB`7vaneRiQ8t_7>x- zNa5LajsRkC0}9!B!ZCfjq8wEARDOAzwzA2=&7krcCr5#{ZG*!gNBt)NvY+?^tW9UJ z=n4JaiGm0@-iyztQ`U2ZsD@*0`PzQtVeQCxLOAJSU8B}FNYqYf(5n& zWTHvk4>2xUbCTo#ieT<_3cFGKs$70EZlGg&dhzBlY|ORpQE+%gF<1lnj(~j4J!DRc z(~1li4fVDe2nDv}Tl%cjq_Z%RkK6*qF*QH1Q!Q}Cla4c zxVMe%);x@wx3QX!Z*Ti(`9^K50>fQsLj(90+lR`xuZ>~_cd30CzMQr*KEDu0hYJD# z@f?Q`00l?6+ zbUzxaTodb%TnpeHI_v(k*{p%%D*$TE~FGmrIufi%U>=>!}!sC%h zj%%G_!JLHDz!sq#S1zT)ARjc0o{xWolTKlLJl)5jLAgIblhHpi=S$#S51&D{e6SRn5HUrtwCdQCqum{pQ7HK_#fsgK?hpm$kCVmYZ z7jzDRHv|?1y%;a|9D@S|3?W1EHe;cCsl-?-i^gulxM3e0f|-0C(9&~Z86aw2i*|B~ zD8X~pAhW^sqg?Au_`oo&6SuKju5}hra;%^+M;&47EAThhqo(69XJzb-)1%GuqH$@l z!ZCh6xCpXtq~2Cry^&CqZ!^7+OL!>#IOW-TE=aN-M8e4gaFNh#;Jo!I@Pm@~p^{(A zvV&HMS!wb6cH*y}DOn9{UWeFvpp$dQjo=N3eaayZmxg8zj@Xf~EtBh@N%fG2O<6=? z8WRitdKMMNXfV-Yk;To4z5@DREN=7F0artAaXNY+Rjt*go|DoQSg1+#^jh$O@?382 z2Wc>|ZZp;{cp{4jfmvxcvI>-P2i^JHQKmw%#RNx$Nou@cobC&vM;OK1zf+G+j*S@j zJxFF+U&XIViROp3#PW^3=iGHQr-+qj*O`?r3%3!;aXCc zDuiW{@ySg{UWzc*tD@#Us9IA*2|j))Lc{|s1kjzH={^zkvxCZE>uaFRGu;p4YtM8O z#F_3wrMUsLcz*R8z_h=PA8B6J0V{T|9)&zdVcx5;`wQq#^svyK_`VJQ*I-wZ=ei}u z786+e4q`%qGhy4`B*_+krQkHKK#uo>6a8*ffd_x#sMR)v7`g}`L;4imI zqQ>q>fiBU1`yu*{N<18PT56N9@xO)m6L*I3A&?8FpbBApFrddGxqp`jzu)>6Cj9tA zZZaWv5M0`*CBT5 z6mfS}&=~8|1d^0|E#u34#Tj#(V{PUbyBn!9C*UjfH`91p2hfuEb)bPK|29K^tkAi} zqU1DmN4i$EBeYQZ$|^2@aQuD}c;a8EYFnPuFE%7_l_lRO z<>V{vqe2$b5PMe|OFAlzC}4aon%@_u4dm&rf&4ZyRW4C#e~aSCK8bZZ3Z4QFC!q|C z3^or%apU>UT$>SQXj6JR^Bi}ga0RuMrml_Ox|@)qwt0LxIlnVH4Cywn18dlTxE`Nn z>f77`B@Gn)6x!sgXkL#%8phlJFnJNwEmyo0Ik_33r0v3@aMXMQf=m%5_!x^p<1u=2 zJ;oQm5x%%%ihz;9oKVI;Y+92`kLJ)!h6UX182hYUx{}e!ysj}o*nAVxX|qGL0}bXO z+A#T3eX6$g%`f(HUN1lB_1&7K904dY#){>5jOA(Ct_<<|u4@;l3%$@eC$MSrdT0D1 zOk^-BlY@nArsIY_G7fg-D%aQ$V{NKLAU`Wl! zCkW#+$xklE8Wc9FINlh+g5t?2FZLWd6L{p^D8}(|2-18je(*l^dUPl4a~ZX{f#Agg z-idKi`_c^iq6~YXfN!RbFA(r81TV<~yimYHnb>&(9zxIvcp$;^394}VLd8Wyw8(^> zb8In$IRasQ_j)kwCZ-HqF|PubHr~ep;yF29K#5PyS@luc2@)a$PZRlW>HSPop}SyF^U7>&Udg*=~SkazvqgNojE! zjP8Ywx(1=-E>*(GH?vgfuDzr)Nh&BAS(GM8cUO{B-KaTLI3OG)e_)zlh7?;5K^~Z5 z>Qyms7kL;=Ut>Hu^-JnWN`?L~dSuQ1DCfj!m{TMUGpcHClJp2C>$CWD*Us&foH)$J z-^;eA2rZg-NK|HX@@nRqs+R690a*Z?&Ipg1(}V-UvXE@vDM`_toR)DR{-|VKxkNM= zc~8p73nVp`E~iGq@kM0}q*Zs~J_*5$>Wl8=MHwZ!Yt>GDNthcLM)gHE$bKXx%S$hz zRxgZUN*(9Hq|y;91-L#BV;jE=)7z~D5$>!A#7s*qc|Tc^brqqh39p_ZVR!hE$!ILC z5OixpaGz8VRv2B#X|d6$--D`VUnP}BWM}lDRMsKNx+K{3v9vCBbm7RJJQKqAljc7@ zXqJ2vV(Riy@>@zQyhHErA}=?ioW!@VumFQ^*Gkd*9l!BLyLR-x6odG-!Em-bME-|F z6{%{RUy86MJLvB4lX!OhiF3X^QB21%uARIJA$esijQdbYwqiAE!NAo-;>H+8#bW*S zC+t&ZjMM)NaTbT>a}bAbIP?ZQ`NzL7*>O;?rTsDx2%EP;#`Y@-$`iA4)4KgC@p?DC zUMJvBIR3vj1Fs{<199jPu+WE&^9sV%_B9gbUi7=|R}gIRH~A|wh})9MeZ9yZ{6Meb zQ)xP%6@Yx7b*ayZoj%$-nC+4|tk@OvL$=TrB_5hrf+6jcrMq7H70N6iN&tk4nrH_~ z=F^x|r|8>>Mmtq9pY+ktj%~T_Ows0h1b0Rspx=#b)!t04a>eA|P+ zo5Hol=0R~t;bG-BTG3>DA?07v)rvn^=z&T>8f7|a-hv^T`5=De5MMa?dZA ziS;%a+q7PTA&O%Wyd_?0Na@vHEo9jp!ony?%j zwV9H`N~*V!&rNJOWWZo)eK^BTAqJo4)tGb{G_MFQh@H_#$v{L!0J(A0DbBlbZ4;VQuqFXD2W!y$z;x;uYzUiyZ=eWeoO=BRg}wtJr-+*5PyA|T;4iSw$pt%{JiyxCY0#y0jcpH; z1BSrC3V1f6$-}V%I;JxOK~03=*yLeEZV$!N29!u+p?IYMhPch7bW^p5wEh<#@J&sjWaICm8fV^0=+QIxjbVTm0E3^k1tcvQcypx#UaM*49iPJlp(xuYSsYYlq|yHM6Ug6CLFf-F%KXM z)dx(n73a|`ZO&t9?W3{l5mtzOUs@Ldf50sJG!hKs2bip!A$S7vJr8BB(mas%aL^!% zSbSsJ9L*_|R~9GP4zn!6-VQ5NAuEwm6b9t6Qfv>fJ27`cDx650hl`E8*G}$+huD*<2 zLYDcW`IH3Llh(_o-yg;q6Yd5sn+%2^HsCh}hkRe}67xL8pMit1uX6J@I2{L7m@>Z5 z2vyuZqkvJiYNvgs!mlO%e8M`xJRP8xT4_xN#uwwfGh37Xs71d*R^jDxB7CJq`5_b# z?yUGN3fqas2GAp5UV^4_qA-c8rTOvR$?xLRK1*2;Z{%sI{X!4%86wV8g!aPhCe4q~ zpj2YCFeQU)yQS90FyIlzwa;N#YYXcroO)ONa1Q$(=wvhdg{?SQ8RC?tnGL15jy`Hp zEn4)V7S+<08ldvVF$!wbBCGMMSnfocs6|%IXThUGkX4RTfFPqfG>BT{s$%W|zN3SW zTGV;`d8Q~$ZWwO)k@ad?*L{&%%%Nf4#wPA?K;g`@^vU zGf>R889_4>)w?M1&A|xYI1*J$`n)%SRcSK63F=L-Q<@@bl0Pi0v0bP1G19eS zl*g`hOjE&H_Yqw4Vf6U52;aEK*4%#s=THc%uHS#PI3P1$pi;hwpTY52I01Gqp#H*0 z`)2sTc^{k;eEk6D=7-X1rD;XxQ8o#kebvWj_tFO0WyzqSJ%VT!#a?J9jr6KFK75EYoS%vno^>VO=A-J>+UND1Zuw<@8gf>GU z8b7i!v~~bAA~_ekt_NVqE*MN9d(2xAp}HPNWP@US4IUg=W^2k-s3{nsh;(cC?x-cj zHrMBrtIPO-DpNiYnXA(q< zl=SQuY^j)E(uu>hjf2Y3Hki}vnb@}+iM=qf_k^=KrHS2bXzP*SK`T9RDjjddJccxo z@=Aui8EsV&whpX~HdL>dLJI}6A1cs}B1X1!KISV2XB1}EWsJ&?Le2AZVemw7{?R=H z5EAfdJ;if-iiEKTvJwe%t@ct|S5lJ>lgs;{{;RzWzDCLuLw_&$8c_)6Q$7uf;jR#(@+ksDa8Kqe2BgGOUT~2ul zT4a94!QZnA=5iLLOkaCbU;hn#HEIQO4g4l?qdy;iml&*zGqfy*kM~qyYz(J1H?ifp z1?YToH<$_wMd=fhFLZMFMA%}c^M$Gyr#DKCdTtxe!^zXp{C12_mmxb5PR5@Hb&W?S zt-BJ+l--okfm?7kKsK8XvB1j$iq)-Bgbl6Ph$TzfQgOD!MjX0?XbpONm+r$*ou)e+F2)ghM%O?e&I0|w z3$&mk5auT?rC+3hW``9&(D=DlhCh2DsvRK?u_0hP&2lq49PJ2Ew;`S$bRmYqMSh4K zLxYnafw`YPvk5u6bADzkU>H0iKLRLQ8tOS1?s7bQHt?rQo#d1}XIM&cx^h<7Quj~c zUN(*~nL3}K6L&>iL&~A6b}>3=W1Ti%LE*$gHsFYF!56hjd2L7e;lM)|ZVd*LCDY;e$hn1 zYGMaOVBb=an2*`>!u4SBLBSAp5eD^O`Nm)nq=W0@7h`187>TdoXAq}|P{1*vdYHet z7}I0ghYVXBzo8M7kpy|?nV?gc0RFVnu=d#=Wafc1Yn&Sl$uhR>hpvP=bPdq1O6U+} zW0-F}hK48KdYnTT4#uTz&GQUKfKCSUZ?+iNhUscy*djNI$!wIZ{_(o!9WUXaq?r8A z3i?FJJ`54IxPntL`y#s)P7Y(KoP$(y+ME$gPIJhDcqLn$8~LOKhCQ@*!*}Y-1Bn#cErvDm)m20uJrAJxDd-6k3j9HnT zsD!mM%vr2BIrB28Lk8gSyO<#(nE9q@O`_E0OXK_J%oPX~{{-{p{=!hN`6++_Oz4Oe zHQVIi^;f1^6#Gdy<#w`5N`oaAI5(`~$}ni+*rEK=VVqAa=aW%4sZ6I|<2aYQ-xaCalEYGX>cMlS{5h z1H_o=c9)W}?}MYKZS=3*@Kn2;u8Vp%SE*!kwotEf#JNwSG%%;%E7W}&1t zkd`CW(BxKDH^KP|V(VcwDg&p&%|N~;}T?P&$D%~483OO$yH^frK5 z^QZCcCW-uaNkXz49NcSg*|1wv%W$5HgESeZBmX|=LMvXAzH_$Azo_*kKlBq>XyT`b z#`;W__WYJjCTbDi9U9fc1pwQA5k4)&!#Z^95yVZn5H2faGhn2xD+GTHgWw$2!FUSO zB3#MCJUfDY<288m3nz70F^f_$2aBFktDATB4C6X%R#l79s;*jkLCQ~`Sw3Rx9tUYK zEj@8qVPZpH>p?J?wHyYKC=SR8!wPEG0FW|cwyjgI9CS-AK;K(4nWW0u zdO(A%ID42?$i9D6A(dZk@@A@=eKXX}td32qn=kHbeT}+&3o46DroMw*Y+`A)G)0u) zrt3R#e8p`!-p`+AEUn_-18%E{cwTbcq$6c zKyg18^`KJ9x4sT>ContdSI}U+2CF4&(Mks0J^I?mfDDtLr3{A2oU3ek@dr+6%QT5G zrmfWbxq!>UWW9q62B#5hW0ggENg63@WkRnshRJCzfypb=u$iiS|JIEDSz{P_J$n_} zc!-(LmakFN#&JASB*p{hIjTj?sFdSns=CG=o(daP>!5_m4Tvgj69(MLjV_&KW0gTX zxxMDyP^%4nK0;$^faL+KsK68j&P5@kF+CoRqDB>KD#NgfcM+4kgGsV3PMpy<(U^v9 z%q#b98^_ws#Ox|)e&QrougCZ3YwXq$Ty`dgDhPFV${EgXqq*pdvBaD{=k2j*uqshH z_^7}C{qKD+py|i+rNewD7d#u|9;}UEG|U0Ami#$^!TJP-jL8>Lin-)>9z474__eJL zMyZi%5Utl}>f1R!I?Uny3U;1DhB^S@Oeb18Q9!4k^?q{gmep@r)R-5w-U(K<0|d3( zT>{`Y8@or1!JGzkbuY`;T=Iw)=V=el+SI(c0i%k>k<*&DeRD~1(n{~kkrubfW?HDT zK}B~m>sCNxxvZvu_kCQdlUtC0+%%A#2`$ZsIbVc4#laF%{kt^8#ngYSp{SLHYYgVi zYuq?$94p`S>Fsefl9`?SN)toh4k(0nc#x%wHiE15A;)&}L0gIogCy$5sE%ayLIWp{5s zED6tiX;?zr5nxeY+Jy5ESBF5lZ+&HN5S)j)r!4{I>weooHLiue1FTEUFrQw_(_FpM zKqp(s(>As>dsxh?Q_LKTxyfM~XNAd~bVzmTHEhz%1^5{r7@t=j(04CzVi)gT?^@-=JQC_8aOk%vI6qWNn&HWC%otG9s|+m@lM6hB6{U zN@P}f7KqGJB166Fj=_0rzd>^tB0WxdZJTFWh_7uP#)ziXk zFgQD75R>10F=cRe#^7vauv{*K!LrlB57LCEaYn`eEcNzvG6y8*WF%n@Cy!?@k`h3KT3WVUMe>#vuF;IQQRQu3c^-J1 z=XhJ6COy`>4GnWo<6x_wK7TB@8!B^Sfv(x)WvM_%f91Y-7H-K6V=uc;YyVhSJ3!VC zwBd100<*4>Xug^6Q~&eF4=vAE&KnrC441-MT_VC{Et@vYk&TW&V3}=-%{m7pAv;EQ zqgc&X2^W+XKtj8B9@Y-hwJJYD7eZ+ZJ*Bb5D8mq%EvXALr7hGX7nK(w$wf|SCp)G* z866#rw|lmrLBVSs%WeZD5OmJxn9D51WU?eD5Bdvpg5*^28vnp)&Z-!8g8mJt z$w%=M{}4a8qK^kyY7?R>>x-3z-pi0ug2Z>!tW!0Ghed_{F+)6xn^E z0__#W*p!WmI<#KUrz3|6+`&kP1Uk*d!DkK=byum_*L)1I%)f)=I1Zd=J_dLU)vB9H zQGUe`7CzHGw^c7ox4LzG^Z%voP2l7zsy@)0+cUS9S(467x@RUK(*zQ3dPzuzB?%A` zmdLI_mIM@$eJ{A3fY9_95D?i#T-YHf`;PlcKoL-J-(gfhaTgTz^Hbyd|Iewrbk9uG z_ue=8rEk@#s#B+`PF0<%I(6z1&~>uNpWl{4>+j%KHnV)35PNdGne&!nxrkkD#%R0~ z`BJm#`A_f{pLY+lL=7#Hs2=(r6UdCYqyy5=TOZq2J+T#TgXUx8>%W|mBQ4S=3` z0j1M=O*y!M;G6>b>uZ?t|NOZBVVIJ-74J_JQeF-%ri4?2@ zqi9efI*jE&y~XNS$xS`%Dd%z(i$qlG21e}p=QxzBu!pP2pq@Sf8a-OT@+wve;h|!J zGm0a#GI+P;J0&nNwJj^T;36_K-Oz1g81-Yrun$CGZg4N$NhZ4jCW)q`{rOZ8xd6%W zb{zS11|%dkn&@c^Hly|D`nzUyr~FZz8&%ijdo`^rW_$9maYo$% ziRjued(Z{@W-y83zmv&e$%b7i--Gv)dN+Ifk-L71GEf*ZKZBz?)d!JjZyqIqQJgOP z=dg1>Jm18B>_~BkjW=+ecj12)I}Nxi=$wWBSPA2F-7BW4k%1FguMoN74vCkby0TJ< z=0#*@&zB+%1xvZ8C`jMs8R=4J_hC~ncnZxVS_-0};9qN}`=y*#y?CU-?pUX)HGC&b zU|wPwr&U&jlG&~(9<>$B7}^vz=C?=VRQvPk;6)@6@>EBm(raM_^JB!Ehx9T7eF8Jk zL;@VBd_Bz6hk`}Lhi#Y&P19pa$(Wa=$Q`oem*N#yjMpfq0O+g%RHL#BcHs#newmVXH~r}<** zQHFD!+{v4A1X_j}zi8|&uHBWEZZd`4aqUOcVNTe$0$tBJ=sS6dZnGTt9;O#o!Lc@1AmKk5BDpLpiD?j%}s0rOXXr2WU~<#D1lM z%C;GEK7A1GF@dVbo>|InQj^<;nhor@*1EAtaRq2Fw;~a)U}E^c5iY3((Z`bObJU)( z3RkLl(3ufU$sz_w4%*}>@GWh~9EQoy%WtJi-SR~!ytxk83%|=M14Gt~4uSVM7Fh1Fjr<_y=yxZAs#OVcU+-nviBjsq; z`(8ZjQMU@CuX7giukUYVAciMLMF>I%gj1DFQ=-RLJ_d@%sQ837a$z&~Q&qO=koW2+ zC#g=Qy*lwD)L*Ous&_Je2^gAB5s5=aq0JryXPqD=S36x%-KS8Q0>KrTM^k!urQkAc zhm`p>Iz-KiwYKk3aR7E3KsU!GXfZ+B_UgX@)W>!V%y4KtxAFa`f_R1xjbA4~{q$pC z`4K~?=!|zarIrYY$LJAANIw9?{1!+#5J`NhTPsp3phYQQ>KQb=F|1h_pQH!?b*9Cr zGKs~`sY;Vtr_dF}tY2qa9Vl((HW^PD2Nj20q(4&$a&nbOj4-(Pr~`czT_y(^k(w-h zh>4;>{dXX%$zoaYuL%tkJ80hs3T4p7^2T1iAZV07zFfZO#+nteqiL+E^(Ow`193=h+6emktvju z2xI;TT>hS%^{~9ch|$EjfFm|s>{a0*%s6Ud$W&;}pv)1TVtEkV`5zqKo(jM?nWDfq zOKluL>f^I8PNn1)y~Lni>30WO{CroAgAzv6+_H0UYN6V{OQUhA<$bw=bLAa6E`|D9 zhf0~){?hlOL2%M5F;qFkL=+8zQ<8%qmIaXgJ<%EWKg4dWl!O(R&$oEg+l0^U0sPK;x8`v;sZVesGF>~|vvzpzwKj+sJG~=@k2`XW`76?)??{4&v5FZk zu4SxKfdH}QBi4a&EJ95p7KlMCPqEmm($65b=q}4Spv`{^E?Ssl@dM4hjMumvXJs^1 zqAn=wnHxapyfnw36b?PegZvAIFSJ~=L5@47>=1gni65LW6neQmAB;qidAJhn8F{I| z5gZtKsh|;@9C@j>5w9XQP{%2_APVK_XK-`m<+*0C?YqK!d2|_^9eH_DnRttjCr~hK zc{8C$VMnU7Uqm2o;uxd|UuaCOkDzSd`&|1CY3Jq5w9* z1}~;pta~tb!hGJ`nm13XPM+Ebp(18M95BP+TnqH%J%ZkhAk0ug$J}5r4S2k6w(_HKNi`c1B&0DldZ{?@6c^f}ix!=wfM!6~HY`_;b zqcFKjqz2;zFYoG{Ir@G)(^r2pR&u#ib%7@jz^3GPAuL2B{Ug&nb1CAblxVFGmML}`t-aJfhmQ4P(ew=r-~J|$JVqmPde34fXY0dt zUUOhkZO;=`C;6!HMg1R6REymP>&g6$p4o2WUU=9)I6j<(?|CRss+x8E4CrO`rJ9VQ z5v#lU|BH0y@A&De^rv-OA3J6^Z1jr$Ad;kYgXZP2d|I~iaqj>tIx)2DHpnhB?cej9(kds7~W8!{kz6@Kp@#CXd-Qk8+?9odx0({(KT(nXO~kw^xD@f+VC5m0 zz_@c;hN^r)s#N+iw!L@{6t?<{B)l@<4KFmC*$(L$BOG&J5a~4}vqe(9>FSS)xXYUI zry>dMH%em{F#e<*n1PW$xA7!r{I1|$WM40%Mqw6dHThrbUH4F=8Wq4D7PrAJ$(H1| zr6t3A0iKMr<8Y_^KF~tGl1yxAXiZYEd)f(jXMkB^LZFiJ46MW%9ya922DHmc7?4-O- zX;F^x%UX`=4z4_-i`jA`IytpyJaY|PDM6b;ldCScXa0p|h|;3ROj-I7l)zm_Cl-=K zjmL4poVoRHW~QgBXB|EA;;s2G@b-07c7Q$<3ZIjVd$Q{fW9;GVI)2R*q)(6FxRKcf zrHjFv8xXe}X~2-V+LPFa?a*U8Dq}_u=4xi`RIBpHJS&f1=dAp$ia(!DttZ)Ff|Sr- z=MRfq!U~xJ*zq!V*Y*v36>7KLN$ z0xE_384BlV;cy^;!lkuvDdAf#N2~jQ-5vp6#h5{bWfB#}r!B$?vsW5fVHw4VXJ~=b zzH^QW(>e2EXPdjVzFg<~&fI^f`%cS;-IfhSaJ5Vb7)P3dG;DcXOewaqYZQ}hULNge zG||@D^YgfZL!Weizn9F+_Iet;3%J zK8?3Z@N!7>EJOuxA=`A(e`%yJw1WBhKD>!(m8axO6k>@E>TUo-Cfy zSUd~wQ4BA<0w-)!@XmxhW!%>R%|!c-EuQm0yX5ga&f<&4hVht4;~ua%Zsio4bjW2X zFe~qk@sU~1<=9+xZokVJ#`*{EJ-7~7-@#>7tcB5MF!2_Aa98Uj^8_X$DK+-#IXiQY zL|~BFD|pPF^K1ee3o_|{gks6>x6GieDenmW-H2GonlV&Le@_>AMc97*!fs%p_5Din@71C zB1ydn~c+3CaPcX+=6&xTcNhc z7f`RjLE6+d?Q>2%Pw5ZWU*UH_Y!U?1tG^xS@JSymGdCVVUV2CX3g;t4LFJEQ+>kJ7 zGs>F&*Kk>{Nf@qPX)@qwJ_-Q(F8c}^(Ak&sG`4x>3MvNrRX8=BB&)h(r@4L^K+%2d z!duCr`v@@=$MQ@-izS*sX%$Pz?$}ONe*MN+E`B;e-VcG1JrWc=h<33!Hh`J*rK<4G z^8#mwV|0DWc0J<^eNQB`&59G-7Tc_25D#ga^#y#bZB{yAo3*b{U#l`?<0pVL`6FB1 z2Lp;RBjt=>jK{eFSb<4ko3#@e%6|mZ>Bbjg3j|&`U}01+3%15bSpne9T+N`GiCcdq zz*NFoYre>kqNJ?gw7o&URAcj}3~?L$G@qw?Kw=ehFQBhFHjPanqx>e#V< z)l+TW!OQHn={U z=aH>Z`ia=QLX`5obJ;|mB8fvT_w77RX3A9i}MI*@=q$PWpq!Rj9C z&SjEP;zGd7)o`339<0H0!S6YF$b{43{}FYS3wF2!y92VQQWLm3pSb=GLdH(`tsWK} zfJig11jSRp@vgrspc^wqMYJ(9;QG4(B3e@$GlLx)Gef~sNU<^FpNi?UD|iu}beu<8 z^BCLKQYK_#q=?AW`Oe=FNNLtuWM;?thci@|k|Gft^#1V=G2f5M0ejG&f)D%t{bn&rj|a9I z*L(2&yUh0tDr}!F;hgQA6)-9Nxk8uhH+C0g%c8yjDd%a6W(;;ha`XISz^&#u{8YXA z3_#9Hv_8b8H;&cj1>U>Ko@6iOEgK~R8O&g>Bqu6)%021Kny$3B=tg&QU*j{N09!hR zF1N6`uSs9!T~e2_4%pAhAL-O)fp1p1jn5%aHbz97k5@@Q+X}({r0^kjxpLh6i#ihb za>79Dv2fFnwgbO_dcoCP*f~y9Qe^Zb)!356t63bDs$E`iCdy~9hk)1bD0H~~JQP)C z5Lx;t)L?a*lO>SBHbJhVdT58i?m*69(-^0$3$Q~w3>O|2G$nko2)hJmb={H0{wMKQ zGG00($q{>N0BXvj;2MV4;Rq*8R_uoL%hMDE2O;=shUaJd~B={c$Mk zWim!e5SxWEKV@x`g$K+)4l_BrQ>L4rqM3v26RcP3Zi$AMrkDil2PPNyws2$aaGl*J z$j=pR=O$atI@zR9-RaWYAd@pwR4hLrO?H`y7n4`2DGu(HE(31v5mvTQrhq~o5X^In zmV>vsKp7|5WY)fL=^ zX0_t|QEr115ce&`0qrC#E@U@dnu3EnEq&1=kp#LIN`z$t-Pneep4sHg;rcacbJlS` z>fs9J>qG8Fa}IBQ8_(}C=MuXBi*FV#TVl*<}Lp&)CA`9HxbuCF7zG_hAXjI zE%CA6=V0c5t~&C}br)cqA(OoU$yOtBwz#Gzi)URI|JF4aGO!(3=;(q7H{1_ugt z%+lEZHZxGqNR(sB&UwIr(Vj`%j`dx`Tzr0hx;CD0Yj zkYzS|CryH|noc(a546WQ2iyfb*Rt#eQ*$o3k-2YRQlzK*f3F}&M{Nh|k!v7ATgwG9f+VW&AY-Sa3o7vHF|GRyNel;?dc zkF5$Vz!0_zf#a%^YdC8q)53+5W-`^-_FY0w@QJYE-LyVQJ0VHkW6;IN1Ek7FX=mGt zv%T&|rR4k-_H)65vZaCroNT0w?U)OG6Cw|0zQ@)ulzOjVMN?)QSMn}q!$azjU-Nlq z$8g_k8IiwU{qvVIJ@P{_?Uvp`cW2>X zPs_3EM{rX-?~O230p3N#)k8R*!pM7z+#-%PPoAiPQ$?-Y&f>vi`}CzJFGiw% zvFj}iHX$GPWmv;`a7f5wUvRemsk2YW%TED*J?b(z@L1=}V!h6FUJ(-JE~o;I_$PW8 z@=Xu-kFj)uk+3;ot;_6{apX67>rW#>mP$9 zAbH4jIK(IC9%c4!j9r|xMAWzYmQ$VVfXeXPJLCNwXf;LSPS_{A#|GvN$TF)ZTW~jK zi>ZxSF0FE#hZ1#lYCgUy+ODU1L4-U?WvLS0uqPy|~A7TN2-1g2$UzI7JeL zX{JF*Nb61KjFx_}H`2(Q;X0g;ZWnxi#V~;hf;PRoGrmC`K!l1ny`wcr+L=~V{^5QL z<)e*AAN&rjY{wcbVmP<}*{{$|tJBjm#3Y7}vL2+f@6AK{JCMFZRCMY&D12ezVWv{? zE0y-YPN73sTc_@5PUX9QS|=%4-xG(*k5rXPV$;E*D}{-!8(3GjptJaL&TL=tkrpYNAM9)7{O_Qf)rK;@oX3f$M?GmD8yq?2IX%U?@K)P9n3-&U{Zd>L zI*%KnXvRRlbt!3HAhY&>2rSk1ZesQXzK6lte*_|kT!=>O{R&Y zCCWxn*v%CBvXwXFGx_Wd-FZ*YX1KIev^`n>NZ_sEyOv)}b?LFAGAhpb^$4_o9wT@k zPD}G#4?Hpk21CRhRTks4fqUIk^N@Z|p|H9S&~riH--f}sDmZgC31=#demV}7oVDjF zU*bgCsok$`>YuDa`S_Rek3`?bYHQ>&thW9PX2cdKPl2W(NWN2G_nGIIh;w`t2Qcbn zSX-aM+bQQk;JcG`hNq1{DL0_|E?UCw*1b5dNNxR9Ezx?cNS$Ts?}?~4%DWy2p| zIVOi}^8s>|tTQ+O6fs_Y<6#K0>sjD1)}3r0Pf))gZ*~v@v(T!nf<}w zHgMi>cO3&&&Y3al=Y%u_-k_VSTa13VeTnfGrI5dt2w*M`3wuW9(a#~k62JfFI79aRznyU2 zKnncxiSUnFu_<#XqO02+7CW&(4xww{T#UQ5tc8L>x0UwgsSyf-_ATTp(_Fs+q%g6D z7L)77sl~r7pAG#2Zm~;-Hj91GmwfCI0td%mG^ul!jGY{fQs`7&m!sp|i%xhR)xe68 zFJ;cboYEn`eytM%bXTwqL#31QHY@~Pm|O6$fab@)9b9Ij*&%A z7iUhPa|D*a1x`I(3#W4d6yOLi+hD5ITIcbx^D;PdSgFv=-*8Q~1uYJSaGlH$*&eis zSxcfj%o7dC0AC@04sJ(Y%%$u|M}&<*YH&D_pv@jnOqT1~;M>5irydZ;J&5B8Iuv`h1$#Ec9+hxo76uQ5 zF(mt}oQIU9+65X`yLedbUBSPQ=`1M{Cp~0~p?qAv`Hq&1^Bsd}#0&F^v(IiPb zgdQHql%LW|7sun$g*^?ZLp?CJ;Wy;YMA$}jCs)&1*S1+;mN{v{2GWGxhQ(xM&~zGzn#&8l^_$ZRdq zIsdKrG1w)@ZTPhmlnZi-u9)9a@)oCu@ec;|T=bT>2pGqDM_GHG!Ac)Cr}OGdnYR<) zPni|(xd_z1gX7c*tbD@!dl1SOUs#0&|5}jfUq?E%uVU}QK@7Z&?2QUZf+N*V0ZgvR zJsBwg?$aRKuJq_}%$=9RYHk`2q;o%qd!P3bpJs(~)x6-X=H#PU@8QDioBtkA;Tmkq z<;u^wc*TO=RP%QrlgfA>fLB!*Pe2SpJ{UoslX#|eb zW6_o?|02%w_mU@ec5h@Bn7eZZYucQu$pPUF?Kx|X=XErG!MMBQCzuYq<5oG#681f} zLBwtg-jjtQ!bKId1-X#*EcV{9X$b40j0{K1?ObA&NnMMCj;#&1C*Vm z$EqIPg5Y!Gs*Uyq*jM?78Wj2(q^4lLf(#{ZGc(HCoiHp>+tgRV1rS=^z*&pIDo}4I z6Qz`|&s$PNIQ9&sj42UAO8%;;&Ji$qi#NTo>Pr<0=9)go>%o>3XI1lS)Ic`XU%wp# z5A-fh#4g*1;WQ6Zyjq*|H9BF6e_&*93v1wnq$B0u2_)6wB+SZQQG0j8+>#=dB+}Ad zfZT;_YS(0Hd!&<;F8VjP`cvjKPK){}K@4!#plobNYJswr^PTBLlR_0&e5e*S=du?z z%WY6Rv6N`hmDrh-dVI-%3L80)#tv6+^_+GoLVE#wu-`A$7E;OX2xZwYzs zg>gK`J7o(%AN!QsI2&1)R_uZHcN^!>jfvkmVok2-d0KG^?)rfCWy=;#CXFBzADTo^ zzD%1+QIDWhDuFRfU%Qs>3geC~-E~3m&vBHVjV^)p5BeQ{>v%CuH__@ir{LkC3?3mh zjKZt%DhJZ1xuI!hx8?OCw|*|do9E%j-l4*>By?ig6ORl{dio8PUAgjtpm=5bxHrd@ z$~zMMo%Pzc4;qyN8dYwAdjmR8M6-paJqj9yy1ICP%5&g z`^B`jw$!hVUspP_tR67OQ!aoXlJc>_tf>-Kn02z$22(zojKnF&XO`^GAt$3lj`l;m z>hdORIN@^GLHN+%0TJ5UWJ}POocg5zV5LEn>8ycRk<0jid*)!IpqRV#b<{QniM8+# zF6g%|yoYXGLnA;-;zG1+9hllblyhiXj#N}Z&|wIoWv?7Ir<&8V{^fLH$4H(um*=u+ zCn$b$}n}04pW(yVai!~fR0nt7303{A^3*l6vwZZ@Smo5&TNBo zOgIWKoa;yN@v0#DPs#Ql%9eTu^kLxv)~#MstIEYsHeu*5mbK|phFlGcY&w-(1y8L9 zJ`T`^KFr>y*onBKc{KoTs=f=DvnFe~FlVL(qPP2Gc!;V~`C(Vk^{CX*T&<(+$JY_wCntfP z{Epz-97*!zS1!BdisgffMR`zB6KhK^2u6-;A9083koa@jj^NFCmN!GO4>i}>AwqMi zDGr&Be*_vI6Q1orVC?|6{vjY~(&IK#_%#sAF;dce%?)s&(irA7JpP&+0Yb=4_{d|X zFkdqt`RbJ)+E-y@S{=9XE$p5)U z7NH&HHaNq$8c-I~?TOTjpH@#n(na#-u(RDN?Y`k2>=D5mFm1U~l%Q|`>hrG{anOjm zvkwXW8}vUX4@S9-37H>9VsOux-*C_PSlJIuL4WSk z9LShoeL2?R&0a)u>sY4bnp4#Y>n%-4Q)pd=nM;s?Spkx*e;=eu`X$JZBNWYtflMRM zG#`oFtuKfZ^#K0rdxJ1@G4jw9!P`-AyW<>Zze%zueY!`ilnEsoM0yiJrIS%zr6chp z8_wpzi2M>H0LT0_%5Tuz8BsV(x3L?{r)Y4#4w~pzBOh-7q3RFcMb~&ZaypY_mCnUH%#!r9g^Aq7` z2&_IzrKtO<2tSsxCA zg>RP&DzQK@hA4eZo##nu2YY*D~np-iNu)l1+fGq~d7SN#57s%`X zgbP}QoAI%)NB@DmhjA?D<3KBin?`UYg6CdkgX4#MF-Vcu(_VjnJtb|P#jnj4if^Iw zHaa(Zf0q#zZi549=wMqG7OfsvwZ*mLK!$B-?u*(z!3{V`o{%3-X~`#n(cBL-#kC9H zn1ErQ55x>WXqk z8M+7EFoWCQ*W2GWwZCs#e_y_SDpe7t=cl_(;s{ow6U+8xKlpB!NP9(j3z6nqwyfy0oy*2##4Lus=PuIlgg8@!Vv1W*2}&!?-< z=wo04IFN^;31LHWyIEF*f<8Z8nqkH+XJ8^tP*I0$ol{DJZBrrP`EKYnOyBICM!g17 z-`Ab*mJ)O)(q?SB_e2F28@@<)dXx?}d?j5^B3;&|yFO0WtNEP~rGtfGN!N#piK+}M zZ>h83zBuJnO=+T(FcqvRJCi9pZOSL(l+!fjnNiAV`DvOG@9)HU+I9-Q9jDA|%Cn-B zcrZazrjsetnx~(^ZYR|&%tL75!t%?(#ffN%7C@AT5v8xMvU+--{|KGgdVpN|y7FE5 z=}qz}9N8urKc8(B!TSCAuFbf-lH{_!B%8qkuGAS2J_>}jJHh^an+pr01x6&>AMYOZ zq$^8#ta3Od$mIlaeB5owR4QQU!cH;gTt8x>n$Dd=@?sf?o`{1Pi4lTr%6xxw2X)tNA%^eq4jZ8twu$6xrm6&1<^06 z{u2macCPMSVP9+eh|$A%pF{+epLB!5bVHyjucQ(m{T9lIake+vJp(~6;A_O!1; z<6;LV+P|VaxE}(c{Q#CGXGXj@V`NI%ZAi-{X{#M%*7LO zjixXUVYRUfPV^v(5rg=v*wYt@H3rGfzm4(?l9*3PnaQaCE+f!G%pT2?vUde%^4Uc! zvEgTNissH}A!IhedDY3q5$p^}fv&_>EDX(H18NXa(RFW1n?&(K>^91^ z%?9DOWXu;MoW(0w;=r7`#tjPQw`a}c5~d~mPfDQ2TAxOVYrBRu^B<>k8(baO`Xa6W zH3st;3iLEXPSe)`k3;hD1Xs-piNG7$cXc$tsUQ)2yafMm&*cM(OJFtS8 zkis?8$>iNNwsZMH8~I6#-klMmC8Thj#AHj8JSp@j`UEIX89HR)R>lcY)PtB&%6t@w zWuFx161thj(-AD0&0-~$dENzbgnb{Qsyo^w4 zA`l3rNKsg%lj}OqA9nkU-fTV z6oA753M>;5MexER@ECoCctnA&MR*^@b(T7-FLSz4MB0?&qD*Y=@b1y4rOZq_IvYQ- zO}7n&*v|s*27(0c-_32hck`^MSnziMv0l9sLwpy^f&BrcEsk{K8d4Sz5vh|()Zsbe zuFk+As=vnh_6g+u8RRYNckJ`?xE%NHg6W-du!G}cTRxd+J;?f=%(6XMp+7y+g~{!6 zNQ6DlEW$Vq)F|uY95bE+GPSLtn@BYqsb{~2^(AytQLptoIRy~`a$Lv67b9_J^6&$S zcruR2%2-912}K#vU3H!9ocV9kse;<)xVIs)73G|hS@HPO*XQ|Wat`Avv>3R|7K`#N z+qJ7Q0-Xm6PdP7&CF^%jXT`YbJP`?Gg8)gSwZDi4gPKI#+FJT}=SQgxbte`$E6&h1 zS*3kICJtFSmVa%<$I)TXD}7*F_JPMi*#?3H?&Dam;@^v(1YeY&LQ?6J9Ps_=NM^;$ z2Dh=uF#INEUo;34q|6^#sW?5N7AnTpZ5XekS>mU&xivp9-Z}?gwjo1P2Fqa%q}GQ8 zs>~k@W2^8>@gE9iuD?A<;ZZ2@$?#I}kHOg{PRPzq0NsXU)L=ILQ4BvXwf;*GII8`r zb^Hoa{guO&Fq;gu_)c*9)o5@*hFKkJcP5XV;HFaI9Tx(V!mtC}9)Gz&X&u;?^nVGf z#b3%Q?eKTuC$_Td??ylD4DT-APJg9*J%3MpIj3&RI^mQh4ghdkssM2SFfRm%1Ay&9 zfH(l~Lx4B{m>&Yf!85(X!S`9tRsIrWT+O5mzhb&pAnG@_V&22d1(PGLzZ?;uM4K{n z_@|*B!w}9_DVep*4VW8pSe@{!ZWZ#t{fxZoWa2DDGs9s>aQ_mXfx!9&lj1NWSbq=! zLz;_fhNeF;)4WnUCBaR074$-n=ZOumWFffy7r4%~(;@$(lbzy*el>nt_ z%TZZJZ$x=KX$K-rycz-xE8db&4B}ikA9k}COG9LAb$#aSZ$M0+9E9uVWH8o$r?VO| z|L0Lxl}1P=iPg&&Yt6rqCYSQe2UBSG8E{-rM>iZFfMe++Ak6htiCS_Mg->PQxxx#@ zwaUbb9F3dA{u(I~-j=w9MaLz=3%i{P3mBEvN_{~{!3`oMWjY)}N)`^1f_E3R+-adE zL5HSS3wc_6sSYV&Vf)*YIW8aOYQ(lyl2BH|@LN_m2(Ikm+LEo&lFha8rD=r91O-w! zCCpMFU0do(DOl8}!CFB7AoQ5p%?grZMwvR7Uc!q0|D5mt@3h;lXuA`;gcNFM&EgM~ z%Pv(f_a~!qZTV@G;0xe0=#${RR6v6YPR#Wh;q2g62nl*cIeN07Fg#73ESOh@p%k*D ztUYH3dtI}IsE{cnE)~CJhhmxoO=L(z{(SsEB-sa;Fx9N$F2ufc8@9850DihUjP#QO z;f4(jjN|EyzXy^P^mQjahk6Uj@i@m8DQPXdt0=zWTG(l+?1;|> zrbEq_{d9Qh+Jzo3b5v$zhD#$E+%M`%&svzllk>dy_+=#g6QZHMQqI9Pp8`VXn;_cCA>LlyM&qUWL z)r{Wfa_ciu$xX)k#xop&FyQCvAH)wd?KVM9YgQ3toweAxK%6%+?Lu*4;>$I$06|=F zE}~PjukQuwn~NoE8qTnrBXlltK><)(x?aA>V7h!H#m-{E{I4f7))B0cAROf1?%hK_ZKAzYd2YZ@h6H*|D;8h z$cZA;k0S4sEHYv3MHZx$_eDjfKP)ocrQUHx7Bu!upYEd3BGVnLBq}X3{b7;mMv;$b zD>At#S!D4iicJ5cMV82kBGZo|uSph}u=XMg(x>7g(;pU@Zf)hkWGfRqXp2mDSY*0` z-^N9zKP)ocDDshQMP_d)VT^Y4=W)2?$rsD>3?4A=!Bp%v==Kw}LI0$+A(0ccA&5#? z6FbTJ5NHABZ4$~bg7%KK*>kB(~r`#kd9k?eqn&phT)GWv@67`Cn#uka~YuRGFSzwV|GKgWVC{+yNxG z{y9>P!_X~MuSdtL;Bdqcaaw8&I|W4_%uIu0abkMT_>jd!&sC8J8!UF)W=H1I(Zr=+ zZrkjP4`nCXRG@vgO_YNhj00iW{1A&&j4q6;cMIe;42%f64JOnOIm7c;@>T+NdL*fV z%4x#)WBN3YgOJC2WZg@0Qo1U~k<9SYK}ox=&h;NmF|i3>OQ_i^)T33Bp^H@N37 zg~NXebNW1Q0N!Phm)l3Sbc~GBF)B*OD3p0!k-Z_W=j}16+hD{i=1;*|f(oGWEJJYJ z{%9p|6f$rdL}9*++*-jzDd2f}JO^D|{=>yhXc?l>60T)#;~>Pw0;ZQOC3XBul>Z6T zG4Epcce|sIFm(g({Tv5xN4yOL3A}j#Q;)6*qkJG7DmM@$@aBOMWo;PcgHaTMM)}he z8mzk5bqIGGs{t<1(gxc0;DnoSo&|39J`_@e?TDJoG>oT@A6_4Z;p9NWm@XsfZV2D7)qcfcegY-veE#OZ?`?^!9wd6K-)=k@oc>+7gV0X+=2$*i@q zU|{qW8E#jij<8#|eg)9u6gQtqt)sKaa=MNE5o+$j0vNX=gU_SW%Scgw8r+-n@)@m- zmr(%*Td+B=bOdNL&ma_mo4xg+dWKnxQ7obRfu-HE>;OM)!PtdonHA&DLyYOt+7KfG zH+yGKhOw9yjBaBuP>korz3VNlczS$E=oY%WGho9TLw0JXY#<|e5?V=eM1`7Z2bt#~ z^Wg!H;jH2LRkf&J>Gi>x$WoW3tkOh?o?tY|9d2Vk*6w3?a*ahhhei7eYQ=mNKU9F= zS$aOx-y}yQBX^juAx0wyJ{uUR=aXUPIfOtF?X4~Gq0bhjD2}YmX9li>Ua?CHFJPdU z3PrpT)?ZqnHaXxzO69zk&?M@kaZ7&DkuAY^Gdjw9U}X0w?_56DnzxO(F`sMAU6KPT zd4oY%8`XuuhL%PZgOncBlTeZG2zi8Na-@ALZ*CzeCaAceJNR&j2%PeC=oU^9q-jNZ zZiJMNlC-fiA8jE&>s~?D*$=V<|FG%498K(Y)KA7+#?9U7?rg5$2L~GLd2X-QB*(hF z>E_<@%{2FsZ??IId^?+a@++;x?Ez`6P2d?f)td#JLu7B74@KLtw0=JVn~bKBdvT+b z(IutZcmo2=CnG>_#(X;RxQ$f|{kQWjgGy$O-=vY^#@DklL{c#=6@ z?SiXbH)p5Bc)tW^TNv*N-Ljr_oKD93$cV4eLf) z|7I7=NZdB^zkwq9-^5QMK+hEHaRQ_de;pFn(uJNEZU8=gA21o6S1lJ5Q&rk-Y@{JC z7W}iBq6hv{u^(Tj=V3Uc3WWjMR0Hq|I1?|=1i!<+X$jo8!R(8Y%){d^```-;`S{gR z%q#Yc&G4VcM1_}DxE!iX>6a2bpSAj+gU%a#0H)_*0R%?*ygf}%QSk1VhQ>b%6T84sw{sTmyC zX8p5J3q{x&9Sk2vdH|XNiC3p^b2ni#W;f^X>-5~8?fA2(9nS!k|CjApjN9>jlegnE zHehjr2K>Z-(SWq>Jz)cq{4F&g=u(~DLFbWY<2Ho!?L75w+wi*+wBh#v(>C-f4UDei z+fe4hqbF{fWFZO$7X40T*whvy(qvs_kji3KS5 z5ifODYApl}j%)=5_V0r$aGVm?7P`?erqN2qX8o0xtd-9PoTaNZU&_oEBVTNxV}9Y( zi&~Ybw!w+DF&$G_V+MZ0wJ4|MEk(gC&l#vqSeVAIR*p;noZ)p1>-o#ER&^UOBrOn$ ztg=BWx~tGpt6E_dfglfl$zuE6MDZh>4w$b@mP8W;CELcp7y&J`$o4rN!;a$@qo zPzZhr2`6P}-bl`P%@0t^#qk}HU9@LrGEwJe+E2LKM#^u4(1LS)$3?7uIDzH+$%_YIq53G z8exMn8rnSP|A@TP5M)@TNnhHNi$-WJu<^Nc6Cf^)in*Vtw-wEgku=fqZw6I~fr0(L z(^(JNo|W-)Utp74+Wxx`F&AtO1xVYZJWiCOSxopsX9b7tQu}`;oy+lqmm~v70=lx| z+w0H#|({=*z%inJ&Y0{yE|ndPHYdaOw=qcmAGx1xuPhvTj; z;bEhSveyaP!m8}0Lzq?k3fJIJOybtWG=RtzD1~0vq}*RYa%3 z;H3@@kuH2HmCz@_2nl@>%qD12t51@mMyW6~rBXf{>NdE95V}&Lr*kvM#FT#_Syn3< zrQ+CVZb3!XhID(0a=C2rBp&Crl$%|F+D@X-o#O-nB~$h=lsze@GyQluozN}I>2bQG zoIWlc)tcA^*|E8FDPIBr9lBIu33MS8t!o&QOCX6!M|;d@eZ-htib+galL@XECt`F6EhN{Y50m z)nCFd$`B2YqJ10-6~%;1pIh>GlnS?QD9vG$P9%#JuK<=2;bJM47}hEBMJ&-T#c<@n zsC=XaY_&Y^$Cx)`7n~>{+0TJ={jTU4s!}}vMvRx-T&wosLFqW~7l>9lyC3D2Wiq!` z%!Lqf`noDRPw(>IMJEJJ*=!r1p&-PoR*funR?NPb%X^?w+vQ(Ond@;VS$1tMpjoVe zf-EcvWHUJ5d`@fFfU@O6u@5t zSbGsUbZ;&!NnG6c4I}r!>Pe6PTRJ@``2G%#U@0m9?%%`h{{cVdRs0~q;PeS$jPaj^jZL87V$_dkZwMMfk z+{xmur!P&mU?IG^Ikjg#BeNd>QJo4vj3wxfcx84N9mZy0xHyif;mAcA;Jv7x-edzP z;kXR*4KTu%*xp%rK4ntJ`2+s%h5vjnu@_(d5xyG#vB-Czz^)4f3$MdJ2k!T`#lH{! z5x~dV;JCpd{rjW%hWKAhRr}n=8_^B9nZmCscgVg9?d8P#EB(4>lJeCe1ILRF=YyR4 z@n`iuh`^d>c#}Biqq{fRf^J=$?C=n;7_a^^b|{-~mN2|?nQL-tcI)Egtec$BSD+4) z6L!L{PMOx#DKoY>{W#iywe3KvLfZ~>w^}|RWFTqzfPi2%xY?)%2mP@SlaN1>#BCB{ zW5GcLlcKp4?5xpBkQ|-T+wqe;GbHZPOHO3uf&S3Q1Kpur1=eP0T$8@@3*rm-6g1`I;BI~3cwI+P+11{kVv+9l1TbP zBIyo^q`R0no@phLp)Eub5L_M;Nq8G8O$p%5{3i zOh5^{SWfA!ZB@*W(EbG(ELp9>a7qdbX-Oe8B!%u)QV0p|i0hF47E%Z({e%_SP6|UT zDHwzvUxA-Dt*n0*RpEb*^-=V3XD>RLmX7lT0l_24&XiCtRZY*OBlPC5E9A{v_fkqo;W!fEcoaZQ$ zsBRlm!juro(tNu(kHFyN-wsA`>ql}NJ651#qvkkq;(f`Se}_a6=SSkWC&qD4isRlD z$Gu0KlG|w#0lTs}|2~0UPv-;TTmkNE8i@c2E9XBXP;ovIJ0FXaeJplQrlgKQ_J9xgi2G!P&jza zD4oU(w{6W(k`~O{Vl-P3%>}4nMO!pSOBe|VMHISQ3M;%G>=_dvZG~9;D<; zP`p{2GuMy zAZhGLAi=Rw0mNSd!A|KI(322|B&2BmjNwD^SOG}N5mCWHg;dZTQbBh_g#@%vK}c|M zOa=Xe=58qf-KFbMFXJd;NJx>UP)%K7RjL1mj4E3HgtoB{LBT^&whj7Q*oOdRpPkwo zh9O1EK7wWw(Oe+xqhZQEBp_rTx?9`)L3c!i1hf!ANHF#0a1ik651EJV(oLw9aRf0WB#7=%3gxgKy>B98yq!v9R+?lg zkuaSu?j^2p_)oy^Cmib@;gA^K;0zZ{FEQNzDB}-~i|>D&@R{S_4Ni}Rp#;3tL$tI%g6p znBQ&V!%C=Hr?kAS2N2_I%WG_!!QrhFv$0Q5a9~s=;x9pTaE1%Xv5(QLHnGo!930*) ziG`rx?J*Ym70b*d7J{v9K*18!nMB46@fYn40ug#(@-#PiB?h!9RNV3(L|STm`45W& zcNZTOhdG!dzU86>O#%tdjc5|TR1s#-2iS}c3MVqJP-B>GO`PIE})53Xi*uGppg;}?GdKm9@HEfM|nx8s*M!;GW!vx^Q6zb#Sg(rbg2j3P@a@lU`B zOlcL8HOY}oqP5O2%L&rit(v*G2US3b6{iInoE&G!;bDRd365kvdc=;E&5{0)_e9Fx zMAq;>4X~Yj63|ah1Z{93l88H4x&nPDQ86++1s6ngieKo|mu1-hDVaw5fr3ujrf875;Z_tvm-ca9!awm(=tK5f62$1 zBkcb=)({+4YD3Z-8kMraY=X>8lv)N5@fU_+F^prCj2{gyRfl_R>FEheF9BA@l~|?2 zL1F3THXdZOz{F%qvh#*_NLGhMrPaZuTqxQ$=qZ|y%A$ZvCzw~q?|^w!#!gFK%fJIEq6Q!>o<6O3&Xfzxjd$jez{5H{{?cl|5yC9dml$3<50b9)Xk%K zMfS4})M!uSFU@AFm}H5W2Lv7|u`BbCAKrj)R${8%Fu^vGE8~v60l|hYLCIMqPagzf z@Yp1^!ba9%!2(!uEdbWH0_=r{qW?c!V(7Nlgx4GHL;dKERonH3uf*KMeC*znU4T9< z1aUnW?oUN)wH5$H>?9y`Q>YK!k(k~BNTy_rFpwfh(rum*Qbh1GN|wy{3g##m#%A>; z-I`LZ*SbFA^EB}o#479l|0*y8{}fn-ZY%?#lJo+`5ZyTa8*4Y!6u5*=80)QIN8*N3 zM~E8-C-SGj>Ra>+++U1v|1WV%8i1dQz%aKOgTEYs|B(bg9fAL;1TyC>WVJb&IL_){ zNpPGMb`N6;;;g0s%u=4fQu6#{V^l_hs(Wh?3iG9iJS`)G0sdYD)-qb~4m!Oult z+cpB1EGEoKi!&~()Wlh7+lVba+gR}TBd~27 zfeWq)acW`4;ncPnhcj%O(@C|qP0UjSG7o-1_u~;IrwG?t@Fs%S;uOSmNQGJO6H)9= zf>TX_3$6)q^5Ll{s~G1INpOtQ15WbP88O}QSVAC234THMw<1c?N{PTFbi!EsVnikG zGbh4LAXD)R+@FhZXB4-z$J9TSRwBEM7RlLDt>|c>k)2S-vXD=31fxzea=L<31ljMf&1I-xCJhu6UGX0 zpEnV10-1_m;QnztZh=eagt0>0=TC&2K&IjsxSwywEpQ2)FqYs}o29QnQu#V{t)OH8 z4K0(yXX$qV?C+}M-c+tz#JHXm&B+$m?(Jeq;Q#ILzp{_3+qU;%dh8la;iVe9wkLbM z&}hi58-T$^JYnj}7L?IQu14aXmx&_rZKA;BSwo?Hb(XS!3=>{P)mj4RWCKGgOIZY2j`?79h z6xG-Vv%`CL*y45J+mHXeIaZky;I1Uds|*Hz7CI}_EWs7nWfe$vZeMTpZTa3{%57G= zrUq-oK~Lzb?rC%EMUE25Ooa;%YLS8*UW@KDc{t(7tvisfKTd~F)8wqK0n@ZJplFj4fLjuZ2wlQC4)O z;!8Fwk4{H~>YSoPERXil*FRu={q%W*>Z6|EACcsnz&lE`OJ9L+^jTDJcZWFub6QV! z_AcKB%+~h+n$7nST*G_EvdJecG6=AZ(L|sau(AFj1TEMl5r|DUCNvC?uGN(YOosi5 zR8+P~gpN;|Rx0@}xhKPfCBw`38%RjZD%QN#Oyr8?=7A_$dA3$1nCCOQ)4VrMS20>5@{nZ#6U2|aaK$cSsVKd+t@bE8#E0ToNXBt#Y&5^%QDL@HqBfA zO_~-qLjAdN55uEQYdmmQM-m>}Jf8n7THnHFMyF@yRqT$KS!kW|W;+>hRIe_Al`x(` z#bdnxjHDN!rWa?N9-6nZ>2U$a%=eHBxUE=TWx>L*0?~O3x*X28q}^L59B@*UhuI3W z$h>4mfDl$5%j%P9rn7Q9%yx2)p~iSTfpldHY2k2tjbrz0a^AtS^mf`wrs;!?fGFE+ zH2cg#Ma@Gd@`%8-P{M<4(8OS@_bzsEf(LX6X1_iU<@z@JHK)^RPb>AXdbL_0X|ot~ z=e(G*ZV%5fi8&}huj8G0PKG^RAuDCUEdW*e?6&D=v&~=_>m)p{%dDh^ifb3$CjBbq z+yOdZ%OF2GMd{!tszuOojs!$>L^*bQg-mOX``DPwu^{q5TvKLi)KJ7?WRWaL>d7W* z(`wZlUL(o+ zNLTimo>svNwIRy3QPcM1J1sY5l$W-$LQM%}%y**Yg#XOe@OGihY32Ke!1w87nMJPL zKuOSwh8z#1ucpl$r0vU8_JL|D2Hf1b!yyaxd83Ssdu!VuR9Xn`ZQ)i`SZx5FS{h=q z@w6F$hnmH;hsJ98%=#RrT;AM)&-g<{X-vG6NhX^-H~1 zSTAVdH#{RKldzc!+A0IVtzlcWw(Z!=dBOK533AZ=Oi_=5%<;-=kCFT(V=HpRWqRxV$j@9a^|?zD_PJM{iXjGom-zY2{GOZxF( zXPY{b`Mab|Rp8H6)`xFX;@UYS{$w{yw-UIY4##-9@~>#vzKo1sXy&k2axjBeiH$~@ zs8Mm@cNL<)JQMj;y zvdd@=KTEg93RGM=AuZ3t@A`T$q|YPhVG!LCFZlF{m=J|S7VW7yn575|UXAFu97Ta% znQXvw6wxFyl#A2|4`EfC;hj;CoW$B79%lzPPZT7i2cMZJNLV`jxXuEoWaG8WG^8&JthAb(o4AKd{v(Ap# z>BY`;?99Z@ES;c<^YZ5~_WTIrd^|?aOU>=;TzV72aZ@QKdLQ^W3@HVx;ET!L3%;1{ zJ>ZK8UjbiC`SQxDnDojrb(8kW0(F!4${cl*`bt6FB)^hVH|Z~cucNtP>Hmr#5&6x7 zm@xXhB{u^MaY`gH?&eW;mc@cBpwdftOT>zcSPezHbKTi+Ekco6Cv#ocb4@a1c^S!I zGxww%YAUnTXC|3MO&tPXTvI2*7uVD%d{Ip;yNs2bi7RUv7w7;)^|fpx085_2&nVkE z6y8_BbZP{lq_Bj`ol(|f6y?1Mh(y^y0IN5QGICbvWq9S-QPy`9cu44#z*VDcfGBY1 z&?|xSN7*7#;85t5z-}u?FMFTv=e3B^XdH^S%MNGQjJ!92gzH^_-SsKK(7j+ij%i}D z+X@;h>{UsWjBgo%m7Uk|e;r!nBzQ!qfuHd2;QzybUj&Z`!SH{}j@fr(?!=2iiP_Tz z$m%{?;`u+q_)-3E6aA2hbWGS6d8&+Y8-NKRC|BLVOA0|=LI~cfbG9{UWQsp~sp4JS9#W&f7sSpB#d#yrG%tyv8^kGB z#x4@)L%7l2yjYxaXX4%Blw_CE*&ue+`g7qFy*P?(qIkeOdo^91@VdPN7RZ3`$m(pEY4_by>?w}DI z{COmzhW_FGTTQGI7Cv<>@u%#7_!q>LXw?~|;%s(wmtak%EjxmPG?Q!L>2J@Du+WI7 z#6Kan=t_U6BE|N=O@f<+4tkP2+GiN4SMIgy5hy(xPUm*jn8L1*gSW>2EJTVc}&niGLB}YjtbbBT{6# zu^9O+1`O5s;MtekV22EEp3z+xo|7ynLBWS&3g{O$DrM1H$)ZVOt1rf`9ab;h1@m_4 zqI9=vx)U-CH75)RZiAj+X58HLmmbELGdwGq6TzVkU%FAM-$$joC&C2qA0qI5N$~F? z@B;$o5EGJ1cQ~TZ9o`s{VTdD2%cv1S2j+~sM7ML<5W}?J&q>yyCVxnhlZvQk2uXHyrMvVg)_*R^69fl4#?2(r z*0A%o@H)ZaI3P)4Uf0po5B13=y_V=U*n_P;83(TtZ&yn>{KrYVRUaeonI{qesgWc= z21Nl_eX=&&xE}?JPpCZhy{I>VpZ-Y3iC6M~ycV*O|1PfWWq1x%vn0=Fq819lLYshF zG`7xj>)6`LHQ$4>gm!j+0_@@Y+0=ERRL4Kp|0zRK&C3|M!6YT_``TNvf?~7xYDk;h zitX?*4poXH^YQ%8gK#x3m$cG>8g!fOxRD5!sF;V*Eh<<<3g4OyAgj|1!<0d-r_&7L zt4C;Q*de@t%WP^S7Z))B76gQ*n%7l?0$5Z&V;2x&5pfI!(jDnF}3cW@D~=u%aOKGuQ3 zehAt`oYQ0h`zI2#Ah;>YazT)}Kg@nXaB0Hb^FRo{){aa+qt4``95Kul!{DP@hHHuDi5=SHkO%|h^K z^_emQr4}@LTeG>A9I49%VO?siJqFs>eH=zR@kA0@SBaC%T8eTf1X!u%D85o*3HTMu zuDOI}aAIT45sR zouP>w{}Ob^ve-m81~~X<`9oO6f1PDBzu_-B_n+|(zG7Ouw-h`Xaw-g({w;KC13apA zP~AqqriP+dLAw-qdR+EAoOWSxHL!AF!Ed;*7-IoIJI}6{V}Uisexnz*uR%1o&MVZ- z_lZ+(JzpnISuflm&fU?an>UMd0cdF67&~tgrzHD;IOR_Bdt>Ma#W|Z<+#=3}#Bi%P z&jPPCZ;Ru8NSu=K_2QI_-!D$Vdo7(JN!c|E3t*k3+B!+Kb&@FSBqi2KO3WK%%wnDv z$~@I+7eF%GZ35|TLo$+SO|nyL3C7HooQ~F@pSq(XxZF^zoMdBnJ>2O3ZX)Y)j#} zL|q4b9_;Qm*g|dD6BK4IY^*#dY^*#dF-o6lBZ|;qQA`y5O4N=?q6iKPuWr51Bgyw> zat>c^gZT~Fb-m<0P705p19OgAmv3e2|1j*z1wUF@zYY0?`vHr z6L1bb5t9-gGAZ4I!_$%tNKgPXm*KjR{-RMXrF%S=5?ac*khWU{dV<5+B*9Tz(lcNV zl2L{3@Nx{@a%K?C%|RV>@Eyb}qo~X8JbnCnz|SWa$15 z{UsV}D_z`H5Qc;Wp}S=S8!EiA#Xmv8nf(c|`Rd+q%9uaaCzAl0fnH?hdR%U$!_ot)E&DoKEz`P@J z7tFbl+ssEV8@RFpIlDUpag4Ie#tdXVN-`TW=Da9o*wCb)tw9J1u8ymM{-QZQN?I_@ z$UR_oj0i584H3Lxc8cHyvvb0|B;j5fxhHOLtsd<=bhkA4GD*x5>fJgN8Vn%*+e!Q( zk-umTPq^16+>n`VnwjQOA)XZldjcyZfSx3B@qZ#lPJf7;Qc1*lBDpE&iR7l7M`-Ez zDQ%obXz;bTx+T{A5j&1dcs+b z?r;F3TV^>OwD5GU4qDk_u&jsDk_ZlA3p)fvHZcJe1VusM#@m2M)5Cx}0zTq~5nMoU zSHuMb+;>I91x3M#`lyKefYP8Clh?0KfbSDVER^_I#qS*)Tyddr#3;N z)4+-QEcwUY4zb;%oxoX2k>7u5I%&6*xzSDxPQ^x^glOZuyQifk_ma^S*0?lP^~S;3r^=TMx!;@oaza&FhHI=9+=cvdX$}U?{UKX#3GIwBMlu zIty9wI6RLnXjgjSsBWgMdg1F?zjxG+U&9ox_GszL6@HW%$A)>93? z&VsEysQnX5v6C*=ubY%%zI}^6g`OriI9A-xB@3|Nyi?$oewT(Hgw=6knO9x|b? zgX7cAHfCE+vO$OJJm}=vLE`I>-r1(#H2Mz0Ic&;+_D9yNWm!Hqaf)LDf#W^FG%VmI z*MsqKaO4HtH+l$8E>~4*vVcb--*ho2BMt)$=rn8U{69WrHqoOT#rLGVoj zMc&T2n|Qcf-eh$sSxsKe4m^K*l^a0fOIN+12gbSSRrC`H^Q&NSa2UwWvKPNuaq_%N z?sfawHac?i;Z_EU@Nf{_{o)59D~}*6L;cO=*eBtOW>>bm&6!%p{MK8Lu;}mPk_l|? z4t98iGIZ6X_2KH8i5Po%kFcfY*tYVkS%-5Efo0=a4P2j&x}hqg8Xn27-W;w>?&A`R zxhBMbg`j%bUcxF#a*hVAzZ`H-y&k+)9Crk%=dygOYcTPozFwCe4~-Xy99-9lU^59< zf^|;Kx9EK?0=K?O=?;A3xzu2D2CqvJuziAF?sasbKT*50f>%RrU5bg{2%(wUccrX_ z#~9dkv<}-%F`Qf7T#||ra4hJRMY-T9e8b}`u2Ca6FUV)%szo>Wt8bgw=$fyyNQX}a z-};I|?hy)D24=29k2$Qs0*!thV4giaj;ProXfV~)L9R~X(b5pyKrfUp->#gKt1IQFN zcLFu3R(<=ywGxoWb;hkc)YqKBgxg;~oIT6o-+;AMHrFb7+pWCazd|P7Q;0}s^K?GF z#l?G~{HFa>(VB)68q&~ak;&V+VmY$~I>uI036CUveG6(cNo3`2N()g=R9zv0kEk{! zdQ*p4kmN7iq>?Nu1g}w9mQxdhm8q-5luEclKHcHG|NNLcI-zK>v`clGZod$2CVu@H zAjzC-EbK-?iH(t-4AL$M<9lr5%pMB<0#h$up{RWDz%HP76|0Ogw)G**r$?prV$eKX9e|fW-kpw z8czdl{n`IyPmgV#hqG}X&iTD#sQ_51_2EzWOKlW%ya_&n>}|g%1LI2e6Ow zhuPWwZF79d^maTTpogSpsH9}L$aE+?XCeF9#P3|+mg)4W+dUVlWfOigdbrLs2}t5T z=HiCWpopGfn=^POewouC2@i0v$1FOG+j#NNUe2L<>AtF&dksA9=X}GM0ReZcikqBQ(Rp zTI)GA_;~K`ojAp7l}R?=I+0C);kEQKG(nx>mw$pcOqT|yBjGmo_T*T{%>A6S85>?r zG0-Tj?@W)-WEyjA-65G!*R#f&a2jXYy3!q>)^{4TY+FX#qR?weLikqH$wgTR3!IhuDGs-BoC|Tj z)(J4f4S82n?B+TuzpoTSYPp}TI1mkced?E3oBS9^;o~<=e;TW*5 z*m@R#YPcJ3sq7f}P*OmPei@&}E~V)FBs0sgY-tBGNd|q>AA};`guYa3HmRcUY)X{W z$^LE>&eTb)|Bf5R#G7L&DtaAjz5yvWeCxL+^3lyFBw9jm^wJsJn%J-pV-;no z?uE~zv_0W&plM5V_W+|mG` zfpSdkNkV)vKaCfV**Il1ehgNk*CG|p0yWq-&{t)OIu7YK4fNFpO8gEFl=)p!;Adn& zVB7C7*sHfkcPAM>^c0ow1(b3;1@?yL$>C#}D!*EN>R(L^r@7s` z5YWu(!2{|Q-mhlyV`!Q-*W73-$+oX35f3evxHNca#KUVd~c z{5wsp8Z4%1wQtM9Y7X{c2Me-zw`XB7-bWm4RTl4~Sy+tsF$e26y!I!YZ-MiD-1&BQ zzB`<6H|M+4`A#xl^wy1WQ)%Dj;QP*o-z|7cCF*G3`@TUOXo>s`aK?b5wF7Ki;6;l* zigI8qiK=oMC!!HKjRDaLIj!6d*NW?Kt&|RGg>uoXL=I}jiB>8F@gR@oS{2bLSmPM4 zrKnC~`%p$iO50LvDWOh)sA*f;EhXCt5J7E$oW0`$WPouJ{Z5rXIu)~LwJ&>xN@r3O z{u4T4lpto7Ls3z8Kw0IrjCBr0<<6p{B|sNIPqus)>LIl2sla-V6*rsV{3i%o;25%M z(jT{q%EsH>GoH*Dwwq^cnKSGpuO$K6IYIk+ElJYO5zt&zfpeuEVxx3>{$1ZpcRt{C zUZo$)yh@+nD;@>>{8sCmS@+1kWj|S}+H>Lcq0F=P>u)R$hx@CK=3V>Yb;I_o{m1Dh z+V?;aZ;ozle-Z}|EjoZ5>UE$~(tf~D3l4g=*OIpZrxnozNlILG;=SP0Lrl7Z!4nSe zY6dYcI+aH@V*Jme^i53gTwqUd8k*6>5qbAk(|W|*bZ)0tZlY|jgco^xmXgu_ZJLtC zN&Dg3@r4)Ai!E8*1*?VcAS8~{DEanUR43X^il#9H{UV=Z;UxDMV_P#MAtdij^H55+ z;0|BN59j6gVo0==5m7YB78(O3&cHGATsaG zZd)xg=cnOZbfQW;12J*V7b{jFyc$UGUyKFKHJFetML3)uHJm%@jAWYY=bnE-Zne%! zC;j)c@}WoeUaNx6X=FNP$|m$m+Vrm}XFhxpS#ach!J<-d3C@Z?6mrVM$NOTulaHdr zm9|%pOXuJ*WtS>id1$bwc?}9Fho$a;a|1p`7ICMoEC+m-a|=LYWpp-W>y2U2-us|( zMHj2Mk5jntGH~((J-nFB#=UE$;kd!z6P%Vn7cS+N?Upn1gqOQFx8NaHw_fg` z+z*BmeYr93*h`$gta^MtT>p)9F(;|2mHzr6t`cY=#`Dfw3#jvY)q zlX53%3?~R|6ftJ1MG$Bl`5_!BWI5vbL%~WgvFn+D_8_1=mQa7W5Ue5uZz`b7GCIsG zg;$VrI@cJ=O&pl;^qIM3FLrM6?kUjyJGB8X{5zEytUyV^0?A1^9Z$ap-(;~EaKaJo zYq-f-Y^GdZ_zzH7OwtEgoHl=Sg@DcMxP(ut4f@K$_jT4B)|tdz*-7? ztOHz;0{_+lj^#FRBXE+$qK_r%O21J3Jq-Q&mv5;~oFc2PfSuwF)D}G7`Y(PBCP!O8 z`PQ!!m>g~Wg~WnGpJConnM`pKIp zTY8d16UKb&A4+dA8jHx_qZIil0(y~`(?ON@P)|*ket8qvGvW;ycbX1v)v^gNZV9hR zFm6e2TR*t}Ah&*Si#^68+$nExr{%&e*);*i{TI3QgZr;?>j$^Qr>!5{Y6xxp;QqVZ z`oS&9Z0iU2|H!Q$-2aqYKe$uA1N|TYOnjfu2{$luVS0Rd3^|-FQ-H3-7qF4}R z5v>W@qKL^TDV}JE2G1g@=DJh7zz_|dMO2M;BfiuS4W31u)jY`h217J>7E$%no#O3= zXz(ne7}t$>pCKANi|E>!A3Z{F+$+TG$B+Jyfk{f#dlWw2!E^1=kH#}F*Bay&P|3R-;OwvdZlxx;mEfmj-*>S z-!&ZhcEpi%3+JbXBj1iVl6v9%!*Jx=5l1buv5OxK-=T8J7p=t^e322Lt8i*&LOjqA z<=Y9O`UfGNYKZd9iReeuLa;t!x@5GW?`E=OZf^)`uhV5Ae4-n{wNGXBaYIx?o$eLl zUEPR`D~6z^9c-W<%;v&)uoT_ zddx?1}T>5Hhgaj2v*)pug`OERJj+oL<0DpY5D!7E_nK5&leOjKlVH*&w|+VSBf#ZF!uaLAp^1JAMz}UJqtg9XE634 z6kA4zV$TM77RR1v$dhp8Qh5@#d`kHwe7Ra731i+ZPr{jd&FU?;j^&sN=eF~wqt*=WIWF7Jox$Hr_?x<(A4KjDM9v1$ zsrO_68Y#Lk)PGOCqJt3)V%D;G@?@zTtVjCl^QxxsOg+1UWuxBI@fm759J~a1E_nM!W@wT)QwDWuU1mPxv5oGImN>n z-B=njP2-ume$F5b6;tgwgEV4HojGTa^qi?9736tU_Kuj!HBeeLShlw62xHR=BViDJ z^_mWr>w7uWQa4Sl{-QWT*X3f|sGG)AKixAG-^o{InqVe&Q_kx9yTIUJ20gqT)4gVOtWF=Sty@)^Tp258hZboAGjPldFs>W}J*NJ;(Pnhvx+zA04K!!X zEhg(8XEx+m>D8P=$2qCH+Me7mEyt2|MQ?=-7bS)oyN8)i?mGS`Wv)e6F^T)Hn02H} zVtt6`XllpHgI7{6c5%ImPov;hS68D)>4`jR<)%b6uOdj6G0n>g*4zA%am-dUl?3U92AbCb?k##Dt+dj94W4|_ zUM8+IUyCQaj-QIZcwII6GxQc)!pP8@_ruo#>09IlM`PJbv$c8bF68ki@_>ZbE15;C zLA(LS)t56?Z?Edt?emJuESml-n%)Q!G_~KvSL9sJx0{@$QRyy`BaEwGLPB%Xbd+ea zd9Lgin&;+?<5pTGw981uc*5!LVXIs}n##ax24g0vN_0BOC)JXqqPTR=CEdS3b62`m zTY?P#fe7>#`>TW8?!>*bTd@Ucq0#Bg)}9Bv(sYHi^qg_s^3wIRW(mCZoV8!iNGJrZ z2-hN^rsw2yo5>eh8?eN^K0yzSM^seLp)p-%eF4m6NkcbKy|X&$Q4Fgp)*Q@#;58=H7}biBAH^NnYxrK7Jh z8s!5S$gS1dJnIt-u&m1sL}w<*Gt!!(n^LdZdi2B8tIj6!?v7KQQLo~b6IkUP9lOz= zk+oywn$su)=X+kGZ#0RXRBOJKB3>bXvF5-hlge-gJnXCn%8`}V=o|f(V%C~(S8no`Y7TrJ@t0)4!w&p~eMLkEyZH_!E8Tc>;Weic zpAG-7(Kq@m3Tv%-lhT#HTyx-?0S{-u!w#(MMl#?f4m<;RMFu?Lz}ExjSYIdcr4If< z!N)T2We$E1@G&j4XM&cypnEL{O&}Ar!Ua8SLG+NBpwY4m`;CQ_y2C0i>>n1kusf{R zh4tMdO2)dw`drwAg>C2#>vv&CS=dZ>*nAhJ^>|X8*G1<77pD3m%*%!~Z&sbD-Hn#7 zVO!-=wc6@y@Zl_c*ukHU^o?ZUOB{R#{1sXFh=X4ToSMsI zu+#;-RRLq!fMqV=QwrFS4Os31)Z2Asy~4rOGj?auyhR1pyli59x{B5(ujXAFkc+?3 zrfVEG(483ynCy+Vk#F-aSV=BrLbZkS3k|O}(L9082EE0+ZI%cx!BdR z6X6v=^I?G)!R8|4vR9qJ0I!`6L*XW%eIb|*2eqjoP#+x!~Te(SvEP{{YP*B3|m))V@W<-Mh3V>Y<`I&sL^fr_cVqI!QO1B zknIj5{;~ANmHG(fb^fEw&to=(Jyq^}SRx_GMIk(jczKkdGLXD2kZxNbGjt*wLjQT14mXa@}K&0Q%Q>v6O+S)O-apR@HF_4SL% zx1urAUKY^sZI0kPwi+`G+5L&v^X2xz0h>ajWvJfs;bW933yY~%PfT*C~R02!EV>i(-E$?1bQO~ z-(wOxR4omKn?bKhCn)6JMEab^8Q{vABf!mvUqHEKs0#0-Av7VN(p&4RpXQgga_iy| zR7H3ZbRW5!Cil&Zv#TFS z0d6f}3u(TQGz-J4lf7Mq;muo(Hk7SSNz>5U=B=>!+lZ{=^JOp!z;9*&EQO>lGBEu1iTOuu!xbO{>vl zn}u7=(g&)Q=F{nBxcM1Pvr^kYt3s1C!TB44UTi%H^}|U-Dfl&YJh?I&QU20{+>;oc zZYg*@!14NS9CT0$B_5MUa!$zSkB_E^6U|>qMDgK-T4mdw{n2Y)6(eX(( z#qBFl+g|}h^8jl-m9zmDT#HWXf34R%yg(~2!WMS>2H12e7oAI56WhGzt&D^1LFz6Y z1?S6CXfM#Gr@c_0`Gxj?eS6xA_}bnKmdHiUK!8wH?*B3FfGJNUdO4*D38*xO`C-+Y z&Ht6&ZCrQc;|Am5V!UoWnkxsc{-Wr;#PV9o+G@r*o9}|SiI?XuQtFMG`x;V=x);f@ zuVt-|)lWy&9DK+vVQNk8OqG*= zta>gc2A`_?)ZAypeU`cp2XTb5!hJ^FXUu(eai5j$v#a~;rjOg3 zI`g8hNHE`}koYyvYVc+GEWjN(45A=ZEz@(pgWt+6y&K&=XidI{1sv$!Zx0; z4y(pHkk5zjf#cx`L>erx^?*GCmBOY<7rcjk1y2Ruv#Hl>o=&n121R!c_jE`sh3_Sa zeDFSg2Yn73oY7%XGSa7 z8}{eJKT)cFwxpEv;Ri^MKITRsrSOAz?4H)cDWm=+cgQ^x$~m0+B-Ls@{19k*38<2f zPjd&KCA+*`HIavXXCw>_Kdb~#^jeA-Ucyj2$wAr&;D<~T_Py9^iKfPo`=Xc5Czxx| z1f4i8A>er;Ah?8VCL%95%aQYBkyB{zV;`%|q>kP!+NmS2WjHONgs0H6vmwKVgx#Wt zB^w$NI=xk@qsFxP(QT(=#t(0&6pgyy{0QG(uNZ!mZ}1tSdaZp)xEOwccI(`ZgM&fRm;y_ULf@`Np?mr`Nn`)K<{c#8R!&~?In+~IiO1O;DLHqI z#%M{7*9*J*DkDLn%BShutU(y|*bU4R#%|#!d(PY9hIglBs)qNNTiJ%sg@E8}e!}PR z6BkLq*-to~(;Zw5&+P^T&!e8h7o@;icwXvGN}(J_!t+yjcZn1lJ@llsMDka|3sUUq z5NEh0^;g3ertYCIO5F~xnfj~Yg{gaP4k@SjBs^W!PG2&f71@c5wUwA}pOXy50CC-2 z*0RiXX3=g`R(wQW&a}UJZqmHs>mn`YSrUY}qhdn1MvW-n-j75l&bAko<=r1|JYpW8 z5VLPe_mGa9xAr2G#yR=$4g@wjN)%{}YCN5((Vc)AyY+;hP|%5K5a$6EDIfkp(%#QN zJ<$c34@COi(1hQ-i>O2S@NPcAJ^X+vLfEPqeiCo*w!!h}3{p14;8O<572SL&mwRDu z;L6;fbSLQ!S3~pf&>cKC*`cvs29ur)wSIJ=_~o3Jbex*aIB5Gwa&-~gN6T4jZ*-qy z+~-*L;fXYb9j8z8CG34_pCYFXcV4YpoqmJIUUyAZ+D{{Zu{&>L+5fL}<-_TOAg?8| zs^O~uB<@$^W_zrg`?<4G+FAkaJ-J8V>1V{#yq-ymOIv6^U4`~qDtma5;Kr92@FD?> zLowjR0vJ1EKuZ8)tV@EXhD5kIhRq*_Tvg~;i7Kt=>V&Z%ow-hLB5#{q&Pe)SO#__~ z$ly93Q=i_PU|b=LPa``s0vTMlzt)38`LUYU{;PV4-Xq=oF$YBaKoO_pnsb|}__wQQ z4>M4>a2~VC3(03T-1BYg{4!iPFS9Giin)N0&}H{ zlKvT)j-WA4^irZ-GWW-f8iUlT1(TbQNK%!O&tS(rm$Mo;3$CWXqTX3unG z))=Z=2lZkDyI=MPZ=ej{?}Vi2FvXH7D7F&BW-wlYt?J}XZ!Jc|Ic$?K97}Yvr#G>D z^_u0&MepXrCU{(NC-UCu9xtf4#|tJyH*Xo}afXG}3ow55xaY-;tK1!OKOAX4 zRWlar_MXQFjKeYa4cg5HI?^u|F>TTUslby7F`zVt-+Kn8AplMR4v1%za6v=ab zp*aX&Psp2`RjOEV{6a>|ineNt;G|;KU$%o##WhO`#n>4OK>-mBk0aaWk90%}aqMaB zLep!trn#duOH8SQ;Z} zUOqYBd1}@*SNpPQZt8{THKe=#AZ;FBJWzCXiLgPskKj zwuXi1zqwsEL2-2)DCkTg_oZ5UHI*7Obn=FO z!%Zu6hnw;`Zl0Xsrn#LAUy*zMuR6TMVvs8%i)hLethatXW1=Lh5}Zi^!mr@;qvN12 zd7fTqUxTAO6Why^&8mQdUP$*NWlH_TJ0OkiTe5FUo9e}$0t(mFq^-84wEQ)@(-lc_ zTf0&gzvQ59AalBb167KyDLYuwK5w7hKI3L!iMb(VxGVjPn&318@zu%sg4~JEPGrl^ zeH3^<^fQV}cL*-0mATy&SU99vL`Q!S9{v*H>Z|qFFD#X}nrYgN1S{C%RVdds^V*lH zajRPaxXI+Hw|=Mxb}&tf(F>J`HOm!6lvu!Rz${%@m(*J-Ta=sX3rpp$U~cK#)L$;K zk>lltQL-&oE*o?aF9$bG7s*F2QWk0iv*jI?MyKE>qI~q)o#B{XQ=rf1E}{XBNz%Sd zzpcj0m%N0|+FwP&_zDe+{>>YeuH0*N!`bXe&#{AY&&&!qfx(Zw7#yycXaZ``h4@RUgyhy`irl@yRQ-0NlHr!N1?IV0Qs=4L&o)&3cBB4?yB1tvezf9H&oos1cB9@+HMK1; zzszBtWtjTy#{9G}EigaY>rkI#sQR4))dKUQ`#aR<3N?78hDdZ1`MRSR$%d34-Ooii zTTwW4MoEJ~l$W-yy70Ja#e%EBD@d$;j)RRDtma_nTEx)<3>MwLM8;O0jjObu=K_w| zA>jE0&;hBvq9LQ><_7NnjqKD~x(U81fnvyC$gFqLD@=5P^1-XHKHnnLi8H;H>U?z2 zrT(ep5WgN7aRGT+N9iDI9SXH0-quIlN}dbV$Hlc}YIMbO6=I%VFXp-V`n*_J%-8S5 zQf59*>Bi#WyggZq$RY7kx0y%wF1ac&PvAN@8=4wyX2}Hcq;$t;cTwgUSDu7C>R(*A z^-j9uW9wGlW4)HdH4EZp4@qklg!(G+%Yc@7Es0qMGD=r3ams@BcT$uE?dP>5Ga1lQ zMh!{G)v6&IhMm}S{2AmCkR>{uKqpTfe+GH<0Iwx+qDsH$I=pZ3$s!!%wIo(^ARrOJ zs}Ww$?hOf#o+qbR=FZf!Y^NR}cs(du!xIxzk9d`O#HQ3E2070Pw}oS(;+aerauN0P zJM~w_SVJ-dyvo6eW0oz*C3o;F+wt4m5SxlZ%mqB9mvUMDCRg$BZh0lf?nhnYVV}kZwh5O;ij3z-0DqDc-(O3u6 z=)nnlA%|o9)O2UT0o_sejzMJ$a8Y+jqY63Pg&%YpLkJH{(mAL*9g!eV*?wn}ppbB- ziyE6`Dl!=K4HU7Ah8y6Q_Joi!vzs2yw&8Sg2s@Io#E+}{->=^9vSPi}nDX}5H z*y3*YS&=lZ)^{h8f?OosGEm*i4F~liOT?Cd5K}wPXzriO+?*l-3!T28E$p_p7;kl_fgyol5-|x+>PWPkvxy=l| zJf}7gJw$)%Y;e)95@#No0m#XS98a z)xlDAusro;M3I}3!XcF6L2j9BeW;8&@;I5e8Nfo1(BOLG?bPc*PEh83X%3Xa6v}mq z(wm|zNK@&bVy!;KSe#;H^6{q{pv*7qizz$BT#{f;o}N%Jnu3l^K&w*Fz6oeD1&t@5 zy;IO&0y-c8HA=O?($xFZ@JfvXvG^X1k;qxc`)P*Zub8tmDm|lnhFloz*K3l|PC%&# z^+N%0w|-8N_`ylylWBfOCZNWl$-P$jYJCy=HQi2n+3B=KSs%oB9lR2Op3GMV=_sUE z16fZ{qtr9d8{R-}17-HmbLA?AOX3~Wz&@R5Ev8&!UmYyW?{RyZQ0oVJno~5n6A(N4 zt9)*6zOoVLEq-ltA-SXm5!+;<(Yg(>U~U%B$xpI|q_vuOGn%DQ$c^%?kcMXsl_iz% z`^fru?B(_3@Im};zhDPfjWC02-W2y@ulWPwwAJ!srx4<;Fh8}oaGL>$oD;8Q zD{Z%y9bF_@vK58?_Qgrek0!tIQ<`m=S1NKW#_VOB0lT zr6>YT>!WnxibPy>!)p{n0`fq;tAzflwn37gSV|@ z)2~cW@@Yl_8N7W3E-zrYmMsQ1L944zo?oO&3kg0m?~~KIE?QVm62=b8gVHc=izJ?( zgfT}yAPsZZffp5~lCaETf?}dNP?(%g#F7G42Gau$C8~6mD(kSI5ug109@~Z+ZETy*B1KTe7}8(Fn8MK z*egCs3~kzrZb|yQ$-xBl`2^G`=Bwc#Z8aO=XGv%$!W&LbMxA25W)U3E^YaTKTYP+| zEwmPqTWfcInp{cgvp?VE|Afi)<(piJ%9htkabX@^OYI9{tgMsyq53=)_B6^S$uA}x zroT@T`hJbRH}K=S8Dj=v?^4(|xr-!xJz%Gw}Z$Y#6s)MJ_^ix<$G44wG~fio0Z#h%bcK)`zL)|jk+zgZUDuU_tCYR3az&! zzP-5lU6p809a^`7o~eD|5`|Feri<#^s!4ba>P5iuU-lMfF_heF3~q${5d|9ARI=}0 zmqfKMQ++b=#+NMW1c`6bbrW_b-!5y!HS7hbA@2H3yh~hs_ZsCuVZ&-6v=V}sv|+^6Yh8zr_ay6k2h@;g+eJKrEi`yQI) z$F^7Q27M>dwAbDXK8$OU^CHpqH^<4x^vLdG=0b-PK8MlU416vp&yRkzHIA`_(%(%N z(Oc{*E!%v!il;x$BjxIa>O^f~Slxo!x5nb0+2 zoIji7YEhl^t8NXSuW-_Hn^QST+8)v*NW89-?g-^;zQyLORSSvR)pq{|T^RN<5(!U0 z*!-47gD!Dj^hqE!VK#X@(e-66lV^FYDtTCl*IJA-WR=j}XYvyAWJBOU^F}vMZVNMS zf-MCA2U{$I55VQNB6_}yZ+m%KAh@18bc+aXewfAcf1Xw2j!N7L(ByUSo;ZvJCr*S7N=m< zpV#XoY%3_45h1UqML37Dzx^J<@6aM$ckp8xXErX^-*FG^=5RCR8MjWAvsZ=SqpBIC zP?^YTsTF4*5_TOhFU5H z^n3M+UtITNHwNUbpPwBM#r^*fPmO8E`~-dC{5tWn`ThHNQfGI}PtYgMuM;nu-xI~V z*7zyiIFldOf-Hrff|4Ke$sPGQJD%nDzlir@%TJ1SCchDvpP=MNHSd_;?0A;n&f=Zw z+An7oT|0gU?HJ4bZ19Z^%#qboq+WYZx@>8(jB>!rkyEQ zESG{lalLioW$SH+cpJUo4*DtA=?0IWyiOdK?}GhAFxewv4et=Bt)xAfI}XO4Ln)9} zJat&%;WV%Cbu@=+_>gYV`>7W^3PNKZ+Q}a+H$zkZ?~$2lX+K3diJd>g8Jw(aU;YFU zgOh||V@)CVWWKUJWbl=$Q*;7u$-v;v-k=?F_k&ZE%3ZVKg$Gg*ysNSUe(*G*UzI`M zp*+FUg_3mZEPsedjfW>fZNO4#-IW%6YabU=_$J839?RIWR zwE0xarc?149o$M%Vw03UJp^Nj=5va+Hs($YX<*UBIUhd4*p;eU8(9mamb}&yX%atC zP|VM9zN6A5-eI~#zAX%w1{by7r1Aczpoc%>XIz7v@}e`Z8lktc3Fc;Yb(V)ptF{-nD2nU`;V)GL zPBw4SD*gb=;cLHDA1(S_IG9i?*sESZr0}aqG;Vea`QgV&0QUuQbMa2al_vbKz~M*v z9f#sa$zc5n5VNYVsh% z98bJwz@JONbX9T8zY!;PQeuDlRvwjz^PbNkan-roC$c{G#ee1I;W$ z8e;P%%rH4#$Ql?L^oItELxZKE!E#)iW`Ed~X4QzYkQIWQ;aF=@1MhxJq9!vj*P^B_ z^068kUsuI)~V7!yO)u=6n6>UfyyxOQ?Hb-Ic= z&2R?7xJSq(oRIXCw2r8sg$X%hn-X@=$+=vxsrlS->bh3VMa+KA#kbs0W<8J}A>Uc5 zlP1U6piYw;NV7OJ$%4y*To#yio;ZtQ#G!?37Kx-WXmqkzlxA^Ck_A^MyDYGnaQ|~~ z2Td-ayQ`8*(QmtR=yZt-%5m0dZJZr&n1$o)&0o>CUK&rQq;;qf4%5zcmT^SWSy`U) zJZyUv2B(P=7vzG+h{4TD`h;)8@SyRjl+$~7&`0X9& zcPXaps{{Sp{da04{0+gu7f~@oiclGxUmqQqAN~$!A3OVw<_aX6O_o|4<$MGN5Ug$E zlMk{$IiCf}`SG^@I0xIGbM%m|nGcWW6aHSwE~tkC3&KChSx9J6={V5(M}T~+Oxl!e z<~2vm!uraAg+|O^k5CQgelj2E$>9o3=T}ajjmwPKrkwwodWq2NL)_I!q%A3wA7qjmcbS3F6vNooYOg_mU=v~woQ%AOmI1KbQH^cEjY#(q7 zrkNZEEyu~*82JaY*$w#9uc8CB6^yDH&0ol4Mj(TSf5pqKCX7oPWOzF~*LY!aC;Yc_ ztLG(m!rzd)EWICoYToUSx%=TgPWqg@*|Tw6V<*FMj(7P6IJ+lpun-=B)Y$8`SFuYV z-uYSWo5C=XTCh7TkoRybg zYtc{GDu-h@iCiYKE&KsoVh_~d80n;y4PP1^zPH7;12nz5lVj@29SGs71ZA>A2GQl} z<#lqWw|-0#D%xx7i1IQ56JVOBW0o+`R-=oKQ*r!S^y*{)!Z#eff6Bm1^7uxg4-tlAX^|gS@NKzrvH3Vc zkmzQ)+|lzEY?}A9MTkVw#kr%&S0OZ7y42S#U3Sjv7joa~fqVS(noB83TS#8>dO2Th zPR?If+E;g+*O>Dyf?jLRJ6Nf1zeY}%Me{!e_>T_SYvpVywQvK`yq1u|>~Uv>jl{2% z8yY`SLSkGIi&gaxx(g-u_N?mB6}^BX?Qq%r+F-W2Uh`?%mG(v z+4islzDkq6m!3&S#jaH|_{mbQaJrXz1&RK^xC*L((p@NK)OWPqUjKgm)TAVxQL%WJ$>M6Y33hztQ0= z(=5EnighKV24bY>V>Ifx!i6w)q)N7XmXQJv$CV>@^njvV(aC3F_&2%$*P=%IE| z2In)ijW08hzx&O4K_c&4Y4)xZh8O<5li=FXsVp@v{4QFz%Wz42v4G&o#R6*f9HTTG zxySxYp+feH6UVxQ?fz)WTej5$Ry$$$tdlxxG~s_64UQ^765bl>eoL~fwcspk1&BsE zWs~2rc0sl<0*}P3wI~ycVytytL+~t7M{l#!>r0%Z>O6AA%eJiGGlInXCsYWxe`1Nd z3!oZ&Nx{{COM|(-^bSSn6Ljr)nWQOKEoQ zIMM!->uAFImt4Ow4Er6^-LJh)?xw!3_=WZxNXn}P|4?>zQHN&+fv^WtK>IoZ&07t9 z{9c}I3AuUg*DDTh$_eFla<}YvyT2l>?(KSK$G|}kMg|5h&7o_e4V#xcUSap+DF2)M zfRo|2I`T%mTEEKYX21>5Q&?PMD*>{jTpL@wV3T~oU$O7>v-$1m_%;up7KeuxXsDqu z?1GmVg=6ZQwc}Cgg#Vpj7FNrPokr`A@o@zo{k*)^+l zVz27-`S3yi0&HM0OB*Z&?ZEMW8OIg5v6Lsk9fs|F)~dSD!;PI3h8@TXvS$*WS5d@! zo$qC>bzu5!M3cGMbITyirIz+xE+E$CVr)f!#MRdvam>{GL~-^YpI^!b+IoAOQM}&5 zW-hG{2ue=J&1J8j9nUh`S-j+}**&PdiCewtn@QNz?ZYIoKc_9u2xRc!D6$KV=7;;H zJi8NZ56uPVAp{j(9Hj;J)t4=bZwxF3>v^=2M-y09Ag#~?i!g3Ct4uzGqThXIpmca_ zOJ1%&x5qxtwsyqy{p=>lx7d4A2!D(&J^_UH#$w3V)G(yCe*#`jKu5K2`puxO>L-`4 z(FK^#V{06*Qdic$3at1Y&0@0-LF^QoNC>_|xx9 zxN^9#eoMzbBap$vRlxk|TN0EbQWSv|XADAJDcw z*C$N!ty8Y9ax|7ZZ`eaJ<9_P~@(6w0ez*@AD=poTb+{7YpVwT;#JK$yu)Jmww6-F6 z&61oqnzJnDTg_RK^Br=!3qkVjt$30&seSwBwFGsiV^qbHHAhkh?1-9oD8v>N+6Pqgye8V+fDebxT@ zE*uGD=h|a*zR@G=8J_jL61zf+cC`q5QQaZH9~cjnzRo#tv3}P%hvgV)bk1QJ-}sz^ zobH^%`)%#QYmEYFui(ebL$?66_N65T>YlzxQFylg=3>VDP$1174n*cRKoca$%@-7p|t{83a;;{9JHo$?U;gztUy;9(oei!e_<6IVe zFdNh2YpjkX0|kzjH??;aszdQw<}q~JhUEa8N8Gv6_EMn^8zo%-r`N}gdPk1>sP$*) z=tA%TxZqwNe=ja;tg2HMx^w^hXZkLPRs!eV|iaBmHXD(n>TT0GFNDep`5!Y~AHEi01wQCxnney{vd_mgj!qSaXXw?e#j7JNhsGryR^1%QuE`In7U02?WbB!VwgotYdF5)w(*ZR1C;gZy9 zR`hk@UY&|@{lT8OiOd;x$qIL)rDJ`g=2N<~k8M6*_VjHu1>&n-)erN)c~|@11D2?L z^PF+gzU8ES4_2F>Fur-M2_S9#P@fIC>vD_xw}U}jFXZkfZP(TnJ=4}{61f(CuGubb zTk0-Jt{wt6+)rKc2`Gl`J@L|@gi=3&qR1bfsE|p8wDcQZ!N@WFp!)ysAbyQKz!PaM zwE0JjYVF z$XUL@eTrO~Qqgi^X9UhqzbhFJkJ5NJi0IDOX zA&psV3a`aNyYCp7#jY@Az9=7#knMPRk|S4AkYWtrOMy4a`Es~Sba_Ml<;i8-*~CMv zxi*v!(UF;G&vmd3_nWkh2DeDPV zbRMZcXRK#$y%>2zUd|WmV?!uSjCUMDE3TJ-DuO4dKt{hCdn0~Hy4UCxQo?Y(= zuO>siul`!T+j8(x-Pro~>f)vOi+Zy?nZ}lbk7eNIdoq9OyDsK$K7Yx-`*Hk}zi*Jm zu6$*S6+Wrw&IiWzv?;#E%FBT7jhr<0tZBFz4&^ z^;4wV>0G?lTI5@O{TjZpE+?n!>%W9h!Nb-%AZ`8N-dpY`$*sQr(_q;AZ8P=Y`g%pD zua{CIy>2xDckvDQPEGJbPi8rA?X*@he+J&Tr-QG(Phb`4wDCGg9zEY5I6SB6XC47V+cS>#5dFM#jn zbq6nVx+3)Cj)#-_E6T$^b_0p(os3Ij_}t@?sM*Q5Wa)LrC9AZK=(Hs{rZ-xEu|3m3 z)V7mxNixT{6ibs6qEm#m??m$}6q8l)w(?*A+DhHGl}WX?(AXy*UMyL7jtul3LMU>n%CbZm_OI`Gvca{-kbky9r-?K8L2|;Lx-_p2PPH zR%~8_B2qDHPovkjZ+I0TzqH-|Dg@f4%Hi=klVp5|Gn1flp&$A9!5;kDb;RPYbWd5h z*Ta+Oi1~VyVw_I5(lfcTz@ZxJ^sXf}oxw4mA-U5BmFPCj3p*3oN-#m%y>4#BIm!pf zfGd<=LxO!JGrIKW!za`2T*&S=iq2-zODm}jCMB?q5U=d9-Gzf5dVI49D z3c)vV4|19F_Ua!Q5<?TsxG9uP$wq07^y<8~ zzAvnFtL(|$aL4B!opS5C8+p~4Dhl={rWen{)knV+_Us4Wo4ZlQ3hTSt!rv(u0Bve- ze*ubcYXeF9^K$pJzpM|JO@Gn8J?$^)%j%{Q=rF=M8ohOu4qaT3WbTXLRnfW`-+Gv$ z?Gs%MJ^MpXzEWT2htGpsAqFog857Q14Zn%M;$OrhdtT#V|3ZBy_G~s_=Zs8UZqML7 zq;ml2=nPnh|Lq|LgD>$AzCD`)_}!RPm2c%?q)xhx!DKN<7&tcj-@7g zOVQtmUkoD(I_?e*czNy)KZd~g{`uo`>t5pS_v@v;QXAIjbK37y%gh&owdBf4xp&J; zg}leUJ?-~8zm?2zx6L2-#;!*UoKIWVY+j(Z78hV&B!st5@@7Lm5Z-y=I#Ldv#7~8| z(J9}dr8yrg6vM_C^>XXn#U=gQ_V&WP0b)6C?!%YUgG(q@|F-3&2CA%d{D+GTOf=>i zcjv=dthRUTNhddder`SuAH8Tpu6(q!`FXs`w)7%t^A7v(XU8*p@Xq3m1jnmBHcr2v6uHLs$&@ZUU7*hyXuB^@ za|&>1X@E!_s&knGRErbqBRf1!QL#>XyzcD=#$azVB=ND>p_i@ z7aj_63(4m&zIkIA(BKquzT<-L9EB@&2=kDqIqg&2hw_9}f z_u`D5HjJGFW--8>oDQ2X!(N)rz|Hc=}vieS9HV= z{txK)MbGDJMHkAFWMq$+bs?@iDXyr z0IJ&8rK-IQnLrh zTxpgSSlvw|yM0CEy$O+A8`nkTh8<$CyH_#3k;FjV>x%I>F(#8TxJKBB$#PAD-P~JT z53_j9qHGz0%~@K-i&^PRb)|D^CY=@8bYd*mJQ7Y>B{BZbsw8$At2Fl|rRgtsmqy)k zWB0Dq3z$%d^35cQ_9S;lvYv-@O)}gwXlWIwRn1DU$0c}wnjk7ncYsBKbmg z6;#H)%(QvWB%_O(D&4#^C$+`K`Z&^sY0I3Ixy(tF=38mzGADIasM_bONHQ`J>Dy@} z8JW5wF&cV})mgqxe>fQ~&!n2IMa&3f@Fa3ft+fVgV=-X;8~&kpb3XunW5j*qwE3uo zhR=1fv)%uWh~ggYN^lhIf{|A9$|1&%XV6#+;n4sulxo9~gkX~*CH?nC9;78DuXQlL zE{Jh4Z{y-&^cT(Vk}~#0mN+w?0Bj0P$R_nlbpIe79w)gf(Yc7ZTNLo4%jDML++Yvy>eV-D zHpBv55HM{EB2sUxah|?n&;zW$6uev5I&xbpH-@H_3zMiqv3V)jA#aDVhm~VBHtXV8 z%?D-iZHp@(H{9?zFsAP!mZ?HbLYhw%xdItHxDUNAjrCR+yJ{DH1+O4)?q{(CYaI}l zEA63pD&^O|Oh$Jn8C{rWB+#^eETidr5)71mzj?e!5y;@0dxUuV2qdu1 zc>;)i7=FFrL|naS$Cnd79GugiOv-R^S_Xj(Ze=iJUH`s_3&2X@ z$xx>&2P(G7wHTg)bM4Rl=}#r;yh!Oh9q5ce1`jvk9cSA@Ol6^ zL>v+Qe}k$zxRP=oO}U+J()=DhNPpRDi;8l-E&2*-%-m?yedUTz%xjjFfQd?-3g{MGxcf+ix>#6%?iPdJ<3iG(sIW*)4YYAc-X z8(vfOtFLq2N1tDdU0j#pS)+3|@|ss-o$(&CHsh^Y`aQX)k$y$##~Vw6X{hGrn|l$v zLUf-5V>jz1xS=GTK}8P&HTzNf8(?{vkpE0W?jwXOtlXL-A49qGUFBvrmBYr@QW_Ip z%OZF!<(tIQxRk`>753mtG1LpL&<7jsw}q-Zeax}e3&iQ*r3$^yd8+PX^Ra~ZKO`i& zJz#9V${njZX?>IAR!uG*$Brx_>o`AcSuv2r7z0 z5Xc4a4vtls+KATh&LQ8YC|@@-bJx*Ln3bsFO@GId;(^nbQJUsCRKSct1`nPI-@?<7 z;=cNVQuquU>ay*c$@sa{Uv)i~YW6(w)b-T|3ljXHBCh-&QWzM1H;b6P1q6E@TsJCik^y-lV? zMJ4*Ps$5fSN2AwLVa?8FH>pd80@Ow=`UK<$vfDWX2&!8($3;t>NWS}G)?<^B$!<0bt9D#zlFycHHCyng5$M* zDCbi2ws1K=?rEo=0JG+34%zUuXKW9>hwJd44Xe7MvhkqGB6R1f&jObP7VMr+I^jLZ ziOUMotV-cB@*2lZei$JQIsgS_5R8`E=32M{JZ^Kcm{&{J9R)C`2NJcfw!iGJ@ya@# zY{t=RIU82MChE?fJRC6&rFgi!{{O9rF#TI^ox4>XQ<~<$AC0WSHKL+v)ejJXiPi!PlR{aKoyJyd;x>Vm= z_|~nyO;nD9jF_e0<3e z-v&z8v7;0^$MGc#yV(*IT|Aur&NPS6!9^q|RCj=j;%ahKDU*)KPmd&J;9@~_*^cR` zjMb4H;o@F;gh}ZnN0{X9KEfnO_6U>w%i|+Va)<8`Pu|NIy<=ElbJn3be{huA=Fw?* z^15d3;OdfU^CO~;_cr3l!H^O=CPn7>cIxJ6)?z|4xh!qoqUg7#(U)dV!dUHv)ig@< z>$6Zc-<2X)!(%ON70)HQJU;!Sn4CXLa~}IUMH>6bEVc+MIp!rd=ccyO-MTw7YL=}8 zE?NeY!L1L7ryn#n3A`dcC1lY*@*JXHk%lEF*%U_c-<%eoSriqe_M9GVk|$ea^Jj`I z|4xf+$eAL`KRkL$w!8+)me&%zxKm#Flk&yz(dIm7DTjKdZdz zr_%DulP$0LGv$?kr{y)|OnK!W9$k?wuYt1VwFGbIlvnXUl7#YR0}xymC|CH_R%p#+9_Z@?^_v{!Dr0-)VUbIa6NwdGI^ad<~Kz zPI2W=iYxaV#T7W|w=Md*PV<#NDX!cU_w}=i`v~B)xbh5-Mp+UKlqFGs=)XH8%0CBL z0*?;G)nIX!J(5;~{0UuhL)V+S>0(&h>6yg%)S->7pHnv#ttaXD*5>ZP&E48;noV+? z(4u`+(cBqAFOY`=X?b@qK=3vwL8p}t`&2s12Y4VaWihnIUn{V0P1`3}i zXDwtCcctuJL^?-K=F-8rIQqPNDY%&gOX17u%iX(`nY`ZN@{-<*KASs1dA)#mV4lY( zJfELlFJH7Yik8N49H%E$avQ0AwNx#p*{ z8g{m)%A?+{&IuYQEX$D*ZLhf_?Bd1ciAHsoZ#m7x5k1u=E`U!WCbS`6O+Td z^^p=qY`4Y}iKwGn%TZZTj8ojXC~^|l3GKhfbT*L>lkd|d6W@pRFh~8N7Dn~uG2{n< z`r!}w)!mXU^WTitovCcaZj@~*<1;u-5oK%Q6^3H*;U%2B{sE4 zwqmCVvdgH+GIpi?2Zgm1ugjhyKr%U$yBe;c&K%;B*tTMkWLt@6?{CK$zJs6fIKdt4 zE@_M|Ym7miWyKhnT+)((s|3Syz*U^oA|m|6A|iLUMMRLSMMVBuY!Q)rM~jG{W49p} zqsy|BP=S+qw&+b&Qh6ej=q+f34{n%cO;BJh#6k@da$Wa=SVBu`OPZY7O>SKgEc$4t(DIK~N2}RF zTfA5`ccN;szNA=CHho%iJoZ65my%%ny9AY35W@} zn}A$KM)3qBBinBFK~8riIRzKmu9iEu%n(lJD%nD1o6h0 zzVx#@R`ag^pq!_YZ}cU2u%gMXtIAA;+ajXxcKp5gN9=mMRrfFKWt#rqVpSi|=EX31 zhSiqB{Txt<-`ac;u!^q}_dL$36Ze;Bc-gfWzF6O-(?TzXpFj@_zDIGKGrW|*^bG!& z8Mo~c#C92Euc_mk?FDkWsg2j1W_x722xMYhQ?2h&?GxJTzKZhbAFr7K(t_#t`4$-6 z^1%;qZR7scV(gaQsWFqGDOVoJaWKv85wFb4<=zM|-i6y6{S;m_{{m|+Wl21EA4`WF zb%c94qQ0LZKQqussCFu4Li@eoZ)EGoo1TJSlgebCCnedi^=nZW{EOdAggyea%_+!n z3dajZ`E3jZ4c1J#%yOMJh5F4`0OWAeDn6N*+(7&Fr$ETKB94}$z4yWMPvtRsazkq92`U)g{g(!V_UHVLXHM!@kE|tXVCi!d6DO`Kbp14>soS*k! zTku~ipDh;>xb`;PZN=ndtUiGq^||>xdM#v zhqO^*UWt41lgzF-A&oIBo?VrrXC#@GqjPc6=ZHL+Vam~^2B>xbR~ulc1Gv=yBPqaa zHRbqMrm1a}&crFZx@+brU1=QiAbbh*Z9AOpjPWt(hqSFpn?ZFr%r=A${C~{737lL- zx&Pfc-E(@GCDSvL?wM>oED49{nS^9ml7N70vTw=~P(Va4ijDuGao@n}f*9ZL@2PW6pPo#V|9#*0^S*)UQ}xvLRMk^YJ@r)8 zQ}GSxd(sfyfYwpbIFG8|dLh0|c3;NB8vGL;$l3bP%UzTE=4lHcb*&*gxd)!=+_~H( z3+m5baHM$Q?%r7NfCz^;nk!m-ea6P-S8~4HF%4%;lQk^&MoHv5!_p%+BL(Z%0D9rJc# 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
fu5B=g6^Eb9YqKOg0kXGR=bR~ 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%0A>mPO#{N8I!nSWHSL-)%)KyX4l#ku4@1%*H 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

b8{11WIB}@M10!# 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 C4Uet> literal 1903104 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 z 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

o6Zw$k? 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 ny&2;0tgI8~Bfyc;4$%4i+J&TfP%8?9!9 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%0A7@-Ou2X}qg#1QtbJ>OG7M|7<{ zZZ3SLy$@5kDT-BgQkH#br1qp!)+3vd#7*g+{Fu})D$N>F!Vwl)GbY)L^&V>~Z!UFb zy6hA(H^j%=!Bhp`sOLiaN^I|nlX)Bj_53*N3`Xd*eaLBaX&ff(319=0-GYwI?q!oa z7rJo9=AqCRCGK~-QW8(qCDXt+Jl53WC$rOJvFWF$x?Eq>V^(W-8_l{V(BXp8?Y-kJ z>8#U@vMVe5W1%A)-0-t4Gt<=L!5>U4yth}L_W*=WB^DMsR+vUIg>MLg;N_us93T9s zW1Hw>;pdZUE~y1L(11IRe5nf*Ub{(h%TFLuxCnPhKK3**_T)4M~K!np&JgN@4R)XB}z zKk=uaY=>6q4LY8QOJD^)n^Z<54r_vpp^0N)Az?N{UrhQctY{h|2 z+Z_|!Y1w7-&K;a300M!7cr`2vL9Qofi<=FA-k>e{g*qLP1EBUecZA7;Ik*?pyz}6M zMwjGLKfpJn8|}NBaJQZ{736WA9!i|&g9Dq!wAG9D;-#jwyTQd06)+ym^p#5+<;CTE zN_N`1KV~%C$fZzXMDfl_2+&vxi6dlf=K+?EH30k$077ijj!urEJ5<-h!^~$61)~Kl zKnp#qn;O7v5d}3o>@QI%nA2T<{99n;ZZ>;yRP5xns}V8oEJkOyZYKOU6@GhEd-UZj zAF{b9g8g)O1lY~io^&`4j%O+Z)8VcpP;)JmMdxm1bGapfr+o~ zz)cHijT>*to8)(RQ$i!~5M68?qOi4N zrF0Z$0llAWX+Ud8SsP_?w>B`gz}fG}96DIskNRTS(~48O zu?}@$;^6|H5uyGZQ^9x%k2mRF{9;2!?VPHX{;u_GY$8VS{!Idhl8JvCu z4s-Kz%+Nc>%KQYAVSY3R>)|8i?^R>scXs03t%0Dh!%SNk-^T%=+kMy?Tuj668FnQO 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

VR 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ℜY{_hyIY(F=fka1p3hG|aSw_4d2^q* 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

w3bvaGLN&EiYn=53z#X-CzveIfSW{aNf>Zg1OW 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

_{NoG!dcQB}BLQQ^qe&4^{ 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 diff --git a/Src/FDO/FDOTests/ParatextHelperTests.cs b/Src/FDO/FDOTests/ParatextHelperTests.cs index bd39ca8c8e..5ca672ae37 100644 --- a/Src/FDO/FDOTests/ParatextHelperTests.cs +++ b/Src/FDO/FDOTests/ParatextHelperTests.cs @@ -11,7 +11,6 @@ using System.Linq; using NUnit.Framework; using Paratext; -using Paratext.LexicalClient; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.Resources; @@ -204,7 +203,7 @@ public void AddProject(string shortName, string associatedProject, string basePr scrText.Name = shortName; if (!string.IsNullOrEmpty(associatedProject)) - scrText.AssociatedLexicalProject = new AssociatedLexicalProject(LexicalAppType.FieldWorks, associatedProject); + scrText.AssociatedLexicalProject = new AssociatedLexicalProject(LexiconType.FieldWorks, associatedProject); // Don't know how to implement a test involving baseProject now that BaseTranslation is gone from the PT API. // However all clients I can find so far pass null. if (!string.IsNullOrEmpty(baseProject)) diff --git a/Src/TeDll/DockableUsfmBrowser.cs b/Src/TeDll/DockableUsfmBrowser.cs index c2d3beac0b..9845ef486a 100644 --- a/Src/TeDll/DockableUsfmBrowser.cs +++ b/Src/TeDll/DockableUsfmBrowser.cs @@ -55,7 +55,7 @@ public DockableUsfmBrowser() // are loaded string dummy = ParatextHelper.ProjectsDirectory; InitializeComponent(); - m_textCollection.Setup(new ScriptureViewSource(true)); + m_textCollection.Setup(ScriptureViewSource.Instance); } /// ------------------------------------------------------------------------------------ From 5e17f9189444683fff3400fd0d0efb57b8d2d1f4 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 21 Mar 2014 15:45:50 +0700 Subject: [PATCH 096/143] added FwParatextLexiconPlugin project Change-Id: Ibb32e230ada0d99427ac52f8f31a90130d996b19 --- Build/RegFree.targets | 1 - DistFiles/ParatextLexicalContracts.dll | Bin 0 -> 9728 bytes .../FwControls/ProgressDialogWithTask.cs | 16 +- .../BuildInclude.targets | 7 + .../ChooseFdoProjectForm.Designer.cs | 295 ++++++ .../ChooseFdoProjectForm.cs | 293 ++++++ .../ChooseFdoProjectForm.resx | 123 +++ .../FdoLanguageText.cs | 31 + .../FdoLexEntryLexeme.cs | 431 +++++++++ .../FdoLexicalRelation.cs | 26 + Src/FwParatextLexiconPlugin/FdoLexicon.cs | 868 ++++++++++++++++++ .../FdoSemanticDomain.cs | 40 + .../FdoWordAnalysis.cs | 78 ++ .../FdoWordformLexeme.cs | 289 ++++++ .../FwLexiconPlugin.cs | 244 +++++ .../FwParatextLexiconPlugin.csproj | 122 +++ .../DummyFdoUI.cs | 153 +++ .../FdoLexiconTests.cs | 539 +++++++++++ .../FwParatextLexiconPluginTests.csproj | 79 ++ .../Properties/AssemblyInfo.cs | 6 + Src/FwParatextLexiconPlugin/LexemeKey.cs | 93 ++ .../ParatextLexiconDirectoryFinder.cs | 141 +++ .../ParatextLexiconFdoUI.cs | 93 ++ .../ParatextLexiconProjectIdentifier.cs | 63 ++ .../ParatextLexiconThreadedProgress.cs | 89 ++ .../ProjectExistsForm.Designer.cs | 87 ++ .../ProjectExistsForm.cs | 35 + .../ProjectExistsForm.resx | 120 +++ .../Properties/AssemblyInfo.cs | 19 + .../gendarme-FwParatextLexiconPlugin.ignore | 7 + Src/LexText/ParserCore/HCParser.cs | 2 +- Src/LexText/ParserCore/IParser.cs | 5 +- Src/LexText/ParserCore/M3ToHCTransformer.cs | 3 +- .../ParserCore/M3ToParserTransformerBase.cs | 12 - .../ParserCore/M3ToXAmpleTransformer.cs | 3 +- Src/LexText/ParserCore/ParserWorker.cs | 5 +- Src/LexText/ParserCore/XAmpleParser.cs | 2 +- .../BasicUtils/ActivationContextHelper.cs | 122 +++ Src/Utilities/BasicUtils/BasicUtils.csproj | 2 +- .../CreateComObjectsFromManifestAttribute.cs | 14 +- Src/Utilities/BasicUtils/ManifestHelper.cs | 177 ---- 41 files changed, 4526 insertions(+), 209 deletions(-) create mode 100644 DistFiles/ParatextLexicalContracts.dll create mode 100644 Src/FwParatextLexiconPlugin/BuildInclude.targets create mode 100644 Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.Designer.cs create mode 100644 Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.cs create mode 100644 Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.resx create mode 100644 Src/FwParatextLexiconPlugin/FdoLanguageText.cs create mode 100644 Src/FwParatextLexiconPlugin/FdoLexEntryLexeme.cs create mode 100644 Src/FwParatextLexiconPlugin/FdoLexicalRelation.cs create mode 100644 Src/FwParatextLexiconPlugin/FdoLexicon.cs create mode 100644 Src/FwParatextLexiconPlugin/FdoSemanticDomain.cs create mode 100644 Src/FwParatextLexiconPlugin/FdoWordAnalysis.cs create mode 100644 Src/FwParatextLexiconPlugin/FdoWordformLexeme.cs create mode 100644 Src/FwParatextLexiconPlugin/FwLexiconPlugin.cs create mode 100644 Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj create mode 100644 Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/DummyFdoUI.cs create mode 100644 Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FdoLexiconTests.cs create mode 100644 Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FwParatextLexiconPluginTests.csproj create mode 100644 Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/Properties/AssemblyInfo.cs create mode 100644 Src/FwParatextLexiconPlugin/LexemeKey.cs create mode 100644 Src/FwParatextLexiconPlugin/ParatextLexiconDirectoryFinder.cs create mode 100644 Src/FwParatextLexiconPlugin/ParatextLexiconFdoUI.cs create mode 100644 Src/FwParatextLexiconPlugin/ParatextLexiconProjectIdentifier.cs create mode 100644 Src/FwParatextLexiconPlugin/ParatextLexiconThreadedProgress.cs create mode 100644 Src/FwParatextLexiconPlugin/ProjectExistsForm.Designer.cs create mode 100644 Src/FwParatextLexiconPlugin/ProjectExistsForm.cs create mode 100644 Src/FwParatextLexiconPlugin/ProjectExistsForm.resx create mode 100644 Src/FwParatextLexiconPlugin/Properties/AssemblyInfo.cs create mode 100644 Src/FwParatextLexiconPlugin/gendarme-FwParatextLexiconPlugin.ignore create mode 100644 Src/Utilities/BasicUtils/ActivationContextHelper.cs delete mode 100644 Src/Utilities/BasicUtils/ManifestHelper.cs diff --git a/Build/RegFree.targets b/Build/RegFree.targets index 88ee3c37c1..da8a2c6f8a 100644 --- a/Build/RegFree.targets +++ b/Build/RegFree.targets @@ -9,7 +9,6 @@ - diff --git a/DistFiles/ParatextLexicalContracts.dll b/DistFiles/ParatextLexicalContracts.dll new file mode 100644 index 0000000000000000000000000000000000000000..d7cd12c34ae642079d164c3f182d3f8ddda3f1d7 GIT binary patch literal 9728 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 + + + + + + diff --git a/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.Designer.cs b/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.Designer.cs new file mode 100644 index 0000000000..dbf7f3a588 --- /dev/null +++ b/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.Designer.cs @@ -0,0 +1,295 @@ +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + partial class ChooseFdoProjectForm : System.Windows.Forms.Form + { + + //Form overrides dispose to clean up the component list. + [System.Diagnostics.DebuggerNonUserCode()] + protected override void Dispose(bool disposing) + { + if (disposing && components != null) { + components.Dispose(); + } + base.Dispose(disposing); + } + + //Required by the Windows Form Designer + + private System.ComponentModel.IContainer components = null; + //NOTE: The following procedure is required by the Windows Form Designer + //It can be modified using the Windows Form Designer. + //Do not modify it using the code editor. + [System.Diagnostics.DebuggerStepThrough()] + private void InitializeComponent() + { + this.TableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.btnOk = new System.Windows.Forms.Button(); + this.btnCancel = new System.Windows.Forms.Button(); + this.openFileDialog = new System.Windows.Forms.OpenFileDialog(); + this.groupBoxRestore = new System.Windows.Forms.GroupBox(); + this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); + this.btnBrowse = new System.Windows.Forms.Button(); + this.labelSelectedBackupFile = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.textBoxProjectName = new System.Windows.Forms.TextBox(); + this.listBox = new System.Windows.Forms.ListBox(); + this.TableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); + this.groupBoxExisting = new System.Windows.Forms.GroupBox(); + this.panel1 = new System.Windows.Forms.Panel(); + this.radioExisting = new System.Windows.Forms.RadioButton(); + this.radioRestore = new System.Windows.Forms.RadioButton(); + this.TableLayoutPanel1.SuspendLayout(); + this.groupBoxRestore.SuspendLayout(); + this.tableLayoutPanel3.SuspendLayout(); + this.TableLayoutPanel2.SuspendLayout(); + this.groupBoxExisting.SuspendLayout(); + this.panel1.SuspendLayout(); + this.SuspendLayout(); + // + // TableLayoutPanel1 + // + this.TableLayoutPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.TableLayoutPanel1.ColumnCount = 2; + this.TableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.TableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.TableLayoutPanel1.Controls.Add(this.btnOk, 0, 0); + this.TableLayoutPanel1.Controls.Add(this.btnCancel, 1, 0); + this.TableLayoutPanel1.Location = new System.Drawing.Point(219, 341); + this.TableLayoutPanel1.Name = "TableLayoutPanel1"; + this.TableLayoutPanel1.RowCount = 1; + this.TableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.TableLayoutPanel1.Size = new System.Drawing.Size(194, 29); + this.TableLayoutPanel1.TabIndex = 0; + // + // btnOk + // + this.btnOk.Dock = System.Windows.Forms.DockStyle.Fill; + this.btnOk.Enabled = false; + this.btnOk.Location = new System.Drawing.Point(3, 3); + this.btnOk.Name = "btnOk"; + this.btnOk.Size = new System.Drawing.Size(91, 23); + this.btnOk.TabIndex = 0; + this.btnOk.Text = "OK"; + this.btnOk.Click += new System.EventHandler(this.btnOk_Click); + // + // btnCancel + // + this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.btnCancel.Dock = System.Windows.Forms.DockStyle.Fill; + this.btnCancel.Location = new System.Drawing.Point(100, 3); + this.btnCancel.Name = "btnCancel"; + this.btnCancel.Size = new System.Drawing.Size(91, 23); + this.btnCancel.TabIndex = 1; + this.btnCancel.Text = "Cancel"; + this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); + // + // openFileDialog + // + this.openFileDialog.FileName = "openFileDialog1"; + this.openFileDialog.Filter = "Backup files|*.fwbackup|All files|*.*"; + // + // groupBoxRestore + // + this.groupBoxRestore.Controls.Add(this.tableLayoutPanel3); + this.groupBoxRestore.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupBoxRestore.Enabled = false; + this.groupBoxRestore.Location = new System.Drawing.Point(23, 235); + this.groupBoxRestore.Name = "groupBoxRestore"; + this.groupBoxRestore.Size = new System.Drawing.Size(390, 94); + this.groupBoxRestore.TabIndex = 3; + this.groupBoxRestore.TabStop = false; + this.groupBoxRestore.Text = "Or select a project to restore:"; + // + // tableLayoutPanel3 + // + this.tableLayoutPanel3.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.tableLayoutPanel3.ColumnCount = 3; + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 82F)); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel3.Controls.Add(this.btnBrowse, 2, 0); + this.tableLayoutPanel3.Controls.Add(this.labelSelectedBackupFile, 1, 0); + this.tableLayoutPanel3.Controls.Add(this.label2, 0, 1); + this.tableLayoutPanel3.Controls.Add(this.textBoxProjectName, 1, 1); + this.tableLayoutPanel3.Controls.Add(this.label1, 0, 0); + this.tableLayoutPanel3.Location = new System.Drawing.Point(3, 16); + this.tableLayoutPanel3.Name = "tableLayoutPanel3"; + this.tableLayoutPanel3.RowCount = 2; + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel3.Size = new System.Drawing.Size(384, 75); + this.tableLayoutPanel3.TabIndex = 1; + // + // btnBrowse + // + this.btnBrowse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.btnBrowse.Location = new System.Drawing.Point(290, 7); + this.btnBrowse.Name = "btnBrowse"; + this.btnBrowse.Size = new System.Drawing.Size(91, 23); + this.btnBrowse.TabIndex = 0; + this.btnBrowse.Text = "Browse"; + this.btnBrowse.UseVisualStyleBackColor = true; + this.btnBrowse.Click += new System.EventHandler(this.btnBrowse_Click); + // + // labelSelectedBackupFile + // + this.labelSelectedBackupFile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.labelSelectedBackupFile.AutoSize = true; + this.labelSelectedBackupFile.Location = new System.Drawing.Point(85, 12); + this.labelSelectedBackupFile.Name = "labelSelectedBackupFile"; + this.labelSelectedBackupFile.Size = new System.Drawing.Size(199, 13); + this.labelSelectedBackupFile.TabIndex = 1; + // + // label1 + // + this.label1.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(3, 12); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(73, 13); + this.label1.TabIndex = 2; + this.label1.Text = "File to restore:"; + // + // label2 + // + this.label2.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(3, 49); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(72, 13); + this.label2.TabIndex = 3; + this.label2.Text = "Project name:"; + // + // textBoxProjectName + // + this.textBoxProjectName.Anchor = System.Windows.Forms.AnchorStyles.None; + this.textBoxProjectName.Enabled = false; + this.textBoxProjectName.Location = new System.Drawing.Point(85, 46); + this.textBoxProjectName.Name = "textBoxProjectName"; + this.textBoxProjectName.Size = new System.Drawing.Size(199, 20); + this.textBoxProjectName.TabIndex = 4; + this.textBoxProjectName.TextChanged += new System.EventHandler(this.textBoxProjectName_TextChanged); + // + // listBox + // + this.listBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.listBox.FormattingEnabled = true; + this.listBox.IntegralHeight = false; + this.listBox.Location = new System.Drawing.Point(3, 16); + this.listBox.Name = "listBox"; + this.listBox.Size = new System.Drawing.Size(384, 207); + this.listBox.TabIndex = 2; + this.listBox.SelectedIndexChanged += new System.EventHandler(this.ListBox_SelectedIndexChanged); + this.listBox.DoubleClick += new System.EventHandler(this.ListBox_DoubleClick); + // + // TableLayoutPanel2 + // + this.TableLayoutPanel2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TableLayoutPanel2.ColumnCount = 2; + this.TableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.TableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.TableLayoutPanel2.Controls.Add(this.groupBoxExisting, 1, 0); + this.TableLayoutPanel2.Controls.Add(this.groupBoxRestore, 1, 1); + this.TableLayoutPanel2.Controls.Add(this.panel1, 0, 0); + this.TableLayoutPanel2.Location = new System.Drawing.Point(3, 3); + this.TableLayoutPanel2.Name = "TableLayoutPanel2"; + this.TableLayoutPanel2.RowCount = 2; + this.TableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.TableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 100F)); + this.TableLayoutPanel2.Size = new System.Drawing.Size(416, 332); + this.TableLayoutPanel2.TabIndex = 1; + // + // groupBoxExisting + // + this.groupBoxExisting.Controls.Add(this.listBox); + this.groupBoxExisting.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupBoxExisting.Location = new System.Drawing.Point(23, 3); + this.groupBoxExisting.Name = "groupBoxExisting"; + this.groupBoxExisting.Size = new System.Drawing.Size(390, 226); + this.groupBoxExisting.TabIndex = 2; + this.groupBoxExisting.TabStop = false; + this.groupBoxExisting.Text = "Select an existing project:"; + // + // panel1 + // + this.panel1.Controls.Add(this.radioExisting); + this.panel1.Controls.Add(this.radioRestore); + this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panel1.Location = new System.Drawing.Point(3, 3); + this.panel1.Name = "panel1"; + this.TableLayoutPanel2.SetRowSpan(this.panel1, 2); + this.panel1.Size = new System.Drawing.Size(14, 326); + this.panel1.TabIndex = 6; + // + // radioExisting + // + this.radioExisting.AutoSize = true; + this.radioExisting.Checked = true; + this.radioExisting.Location = new System.Drawing.Point(0, 0); + this.radioExisting.Name = "radioExisting"; + this.radioExisting.Size = new System.Drawing.Size(14, 13); + this.radioExisting.TabIndex = 4; + this.radioExisting.TabStop = true; + this.radioExisting.UseVisualStyleBackColor = true; + this.radioExisting.CheckedChanged += new System.EventHandler(this.radio_CheckedChanged); + // + // radioRestore + // + this.radioRestore.AutoSize = true; + this.radioRestore.Location = new System.Drawing.Point(0, 232); + this.radioRestore.Name = "radioRestore"; + this.radioRestore.Size = new System.Drawing.Size(14, 13); + this.radioRestore.TabIndex = 5; + this.radioRestore.UseVisualStyleBackColor = true; + // + // ChooseFdoProjectForm + // + this.AcceptButton = this.btnOk; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.btnCancel; + this.ClientSize = new System.Drawing.Size(423, 373); + this.Controls.Add(this.TableLayoutPanel2); + this.Controls.Add(this.TableLayoutPanel1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "ChooseFdoProjectForm"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Select Lexical Project"; + this.TableLayoutPanel1.ResumeLayout(false); + this.groupBoxRestore.ResumeLayout(false); + this.tableLayoutPanel3.ResumeLayout(false); + this.tableLayoutPanel3.PerformLayout(); + this.TableLayoutPanel2.ResumeLayout(false); + this.groupBoxExisting.ResumeLayout(false); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + this.ResumeLayout(false); + + } + internal System.Windows.Forms.TableLayoutPanel TableLayoutPanel1; + internal System.Windows.Forms.Button btnOk; + internal System.Windows.Forms.Button btnCancel; + private System.Windows.Forms.OpenFileDialog openFileDialog; + private System.Windows.Forms.GroupBox groupBoxRestore; + private System.Windows.Forms.Button btnBrowse; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; + internal System.Windows.Forms.ListBox listBox; + internal System.Windows.Forms.TableLayoutPanel TableLayoutPanel2; + private System.Windows.Forms.GroupBox groupBoxExisting; + private System.Windows.Forms.Label labelSelectedBackupFile; + private System.Windows.Forms.RadioButton radioExisting; + private System.Windows.Forms.RadioButton radioRestore; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textBoxProjectName; + private System.Windows.Forms.Panel panel1; + } +} diff --git a/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.cs b/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.cs new file mode 100644 index 0000000000..64574f3de9 --- /dev/null +++ b/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.cs @@ -0,0 +1,293 @@ +using System; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Runtime.Remoting; +using System.Windows.Forms; +using SIL.FieldWorks.FDO.DomainServices; +using SIL.FieldWorks.FDO.DomainServices.BackupRestore; + +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + internal partial class ChooseFdoProjectForm + { + private LanguageProjectInfo m_selectedItem; + private string m_restoreFileFullPath; + private RestoreProjectSettings m_restoreSettings; + + public string SelectedProject + { + get { return m_selectedItem.ToString(); } + } + + #region Event handlers + private void btnOk_Click(Object sender, EventArgs e) + { + if (radioRestore.Checked) + { + textBoxProjectName.Text = textBoxProjectName.Text.Trim(); + if (!DoRestore()) + return; + } + else + { + m_selectedItem = (LanguageProjectInfo)listBox.SelectedItem; + } + DialogResult = DialogResult.OK; + + Close(); + } + + private void btnCancel_Click(Object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + } + + private void ListBox_DoubleClick(object sender, EventArgs e) + { + if (listBox.Items.Count > 0 && listBox.SelectedIndex > -1) { + btnOk.PerformClick(); + } + } + + private void ListBox_SelectedIndexChanged(object sender, EventArgs e) + { + btnOk.Enabled = listBox.SelectedIndex > -1; + } + + private void btnBrowse_Click(object sender, EventArgs e) + { + using (openFileDialog) + { + DialogResult result = openFileDialog.ShowDialog(); + if (result == DialogResult.OK) + { + m_restoreFileFullPath = openFileDialog.FileName; + if (SetupRestore()) + { + labelSelectedBackupFile.Text = openFileDialog.SafeFileName; + textBoxProjectName.Text = m_restoreSettings.Backup.ProjectName; + textBoxProjectName.Enabled = true; + } + else + { + m_restoreFileFullPath = null; + labelSelectedBackupFile.Text = ""; + textBoxProjectName.Text = ""; + textBoxProjectName.Enabled = false; + } + } + else + { + m_restoreFileFullPath = null; + labelSelectedBackupFile.Text = ""; + textBoxProjectName.Text = ""; + textBoxProjectName.Enabled = false; + } + } + } + + private void radio_CheckedChanged(object sender, EventArgs e) + { + btnOk.Enabled = (radioExisting.Checked && listBox.SelectedIndex > -1) || (radioRestore.Checked && textBoxProjectName.Text.Any()); + + groupBoxExisting.Enabled = radioExisting.Checked; + groupBoxRestore.Enabled = radioRestore.Checked; + } + + private void textBoxProjectName_TextChanged(object sender, EventArgs e) + { + btnOk.Enabled = textBoxProjectName.Text.Trim().Any() && labelSelectedBackupFile.Text.Any(); + } + #endregion + + public ChooseFdoProjectForm() + { + // This call is required by the Windows Form Designer. + InitializeComponent(); + + PopulateLanguageProjectsList(Dns.GetHostName(), true); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Queries a given host for avaiable Projects on a separate thread + /// + /// The host. + /// true if we want to show local fwdata projects + /// ------------------------------------------------------------------------------------ + private void PopulateLanguageProjectsList(string host, bool showLocalProjects) + { + // Need to end the previous project finder if the user clicks another host while + // searching the current host. + ClientServerServices.Current.ForceEndFindProjects(); + + btnOk.Enabled = false; + listBox.Items.Clear(); + listBox.Enabled = true; + + ClientServerServices.Current.BeginFindProjects(host, AddProject, + HandleProjectFindingExceptions, showLocalProjects); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Handles any exceptions thrown in the thread that looks for projects. + /// + /// ------------------------------------------------------------------------------------ + private void HandleProjectFindingExceptions(Exception e) + { + if (InvokeRequired) + { + Invoke((Action)HandleProjectFindingExceptions, e); + return; + } + + if (e is SocketException || e is RemotingException) + { + MessageBox.Show( + ActiveForm, + "Could not connect to server. Check service is running and that any running firewalls are configured to allow connections to the service.", + "Warning", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + else if (e is DirectoryNotFoundException) + { + MessageBox.Show(ActiveForm, e.Message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + else + throw e; + } + + /// ------------------------------------------------------------------------------------ + /// + /// Adds an entry to the languageProjectsList if it is not there already. + /// + /// ------------------------------------------------------------------------------------ + private void AddProject(string projectFile) + { + if (InvokeRequired) + { + BeginInvoke((Action)AddProject, projectFile); + return; + } + if (IsDisposed) return; + + var languageProjectInfo = new LanguageProjectInfo(projectFile); + + // Show file extensions for duplicate projects. + LanguageProjectInfo existingItem = listBox.Items.Cast().FirstOrDefault(item => item.ToString() == languageProjectInfo.ToString()); + + if (existingItem != null) + { + listBox.Items.Remove(existingItem); + existingItem.ShowExtenstion = true; + listBox.Items.Add(existingItem); + languageProjectInfo.ShowExtenstion = true; + } + + listBox.Items.Add(languageProjectInfo); + } + + private bool SetupRestore() + { + try + { + m_restoreSettings = new RestoreProjectSettings(ParatextLexiconDirectoryFinder.ProjectsDirectory) + { + Backup = new BackupFileSettings(m_restoreFileFullPath), + IncludeConfigurationSettings = true, + IncludeLinkedFiles = true, + IncludeSupportingFiles = true, + IncludeSpellCheckAdditions = true, + BackupOfExistingProjectRequested = false + }; + } + catch (InvalidBackupFileException ibfe) + { + MessageBox.Show(ibfe.Message, "Problem With Backup File", MessageBoxButtons.OK, MessageBoxIcon.Information); + return false; + } + catch + { + MessageBox.Show("An error occurred. Please select a different file.", "Problem With Backup File", MessageBoxButtons.OK, MessageBoxIcon.Information); + return false; + } + return true; + } + + private bool DoRestore() + { + m_restoreSettings.ProjectName = textBoxProjectName.Text; + + if (m_restoreSettings.ProjectExists) + { + using (var dlg = new ProjectExistsForm(m_restoreSettings.ProjectName)) + { + dlg.StartPosition = FormStartPosition.CenterParent; + DialogResult result = dlg.ShowDialog(); + if (result == DialogResult.Cancel) + { + textBoxProjectName.SelectAll(); + textBoxProjectName.Focus(); + return false; + } + } + } + + try + { + //ProgressUtils.Execute(string.Format(Localizer.Str("Restoring {0} project..."), m_restoreSettings.ProjectName), CancelModes.NonCancelable, () => + // { + var restoreService = new ProjectRestoreService(m_restoreSettings, ParatextLexiconFdoUI.Instance, null, null); + restoreService.RestoreProject(new ParatextLexiconThreadedProgress(ParatextLexiconFdoUI.Instance.SynchronizeInvoke)); + + m_selectedItem = new LanguageProjectInfo(m_restoreSettings.FullProjectPath); + // }); + } + catch + { + MessageBox.Show("An error occurred and the project could not be restored."); + return false; + } + + return true; + } + + #region LanguageProjectInfo class + /// type that is inserted in the Language Projects Listbox. + internal class LanguageProjectInfo + { + public string FullName { get; private set; } + + public bool ShowExtenstion + { + get { return m_showExtenstion; } + set + { + m_showExtenstion = value; + m_displayName = m_showExtenstion ? Path.GetFileName(FullName) : Path.GetFileNameWithoutExtension(FullName); + } + } + + protected string m_displayName; + + protected bool m_showExtenstion; + + public LanguageProjectInfo(string filename) + { + FullName = filename; + m_displayName = Path.GetFileNameWithoutExtension(filename); + } + + public override string ToString() + { + return m_displayName; + } + } + #endregion + + } +} diff --git a/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.resx b/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.resx new file mode 100644 index 0000000000..12048a9f5f --- /dev/null +++ b/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/Src/FwParatextLexiconPlugin/FdoLanguageText.cs b/Src/FwParatextLexiconPlugin/FdoLanguageText.cs new file mode 100644 index 0000000000..c94b88d1d0 --- /dev/null +++ b/Src/FwParatextLexiconPlugin/FdoLanguageText.cs @@ -0,0 +1,31 @@ +using System.Diagnostics; +using Paratext.LexicalContracts; + +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + internal class FdoLanguageText : LanguageText + { + /// + /// Creates a new LanguageText by wrapping the specified data + /// + public FdoLanguageText(string language, string text) + { + Debug.Assert(language.IsNormalized(), "We expect all strings to be normalized composed"); + Debug.Assert(text.IsNormalized(), "We expect all strings to be normalized composed"); + Language = language; + Text = text; + } + + #region Implementation of LanguageText + /// + /// Language of the text. + /// + public string Language { get; set; } + + /// + /// The actual text. + /// + public string Text { get; set; } + #endregion + } +} diff --git a/Src/FwParatextLexiconPlugin/FdoLexEntryLexeme.cs b/Src/FwParatextLexiconPlugin/FdoLexEntryLexeme.cs new file mode 100644 index 0000000000..dd052b0308 --- /dev/null +++ b/Src/FwParatextLexiconPlugin/FdoLexEntryLexeme.cs @@ -0,0 +1,431 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using Paratext.LexicalContracts; +using SIL.CoreImpl; +using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.FDO; +using SIL.FieldWorks.FDO.DomainServices; +using SIL.FieldWorks.FDO.Infrastructure; + +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + #region FdoLexEntryLexeme class + /// + /// + [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", + Justification="m_lexicon is a reference")] + internal class FdoLexEntryLexeme : Lexeme + { + private readonly LexemeKey m_key; + private readonly FdoLexicon m_lexicon; + + public FdoLexEntryLexeme(FdoLexicon lexicon, LexemeKey key) + { + m_lexicon = lexicon; + m_key = key; + } + + public LexemeKey Key + { + get { return m_key; } + } + + #region Lexeme Members + + public string Id + { + get { return m_key.Id; } + } + + public LexemeType Type + { + get { return m_key.Type; } + } + + public string LexicalForm + { + get { return m_key.LexicalForm; } + } + + /// + /// Gets a string that is suitable for display which may contain morphological abbreviations + /// + public string DisplayString + { + get + { + using (m_lexicon.ActivationContext.Activate()) + { + ILexEntry entry; + if (!m_lexicon.TryGetEntry(m_key, out entry)) + return null; + + return StringServices.CitationFormWithAffixTypeStaticForWs(entry, m_lexicon.DefaultVernWs); + } + } + } + + public string InterlinearDisplayString + { + get + { + using (m_lexicon.ActivationContext.Activate()) + { + // Add pre- post markers, if any. + string prefix = string.Empty; + string postfix = string.Empty; + if (Type == LexemeType.Stem) + { + prefix = "/"; + postfix = "/"; + } + else + { + ILexEntry entry; + if (m_lexicon.TryGetEntry(m_key, out entry)) + { + IMoMorphType mmt = entry.PrimaryMorphType; + if (mmt != null) // It may be null. + { + prefix = mmt.Prefix; + postfix = mmt.Postfix; + } + } + } + return prefix + LexicalForm + postfix; + } + } + } + + public string CitationForm + { + get + { + using (m_lexicon.ActivationContext.Activate()) + { + ILexEntry entry; + if (!m_lexicon.TryGetEntry(m_key, out entry)) + return null; + + ITsString tss = entry.CitationForm.StringOrNull(m_lexicon.DefaultVernWs); + return tss == null ? null : tss.Text; + } + } + } + + public int HomographNumber + { + get + { + using (m_lexicon.ActivationContext.Activate()) + { + ILexEntry entry; + if (!m_lexicon.TryGetEntry(m_key, out entry)) + return 0; + + return entry.HomographNumber; + } + } + } + + public IEnumerable Senses + { + get + { + using (m_lexicon.ActivationContext.Activate()) + { + ILexEntry entry; + if (!m_lexicon.TryGetEntry(m_key, out entry)) + return Enumerable.Empty(); + + if (entry.AllSenses.Count == 1 && entry.SensesOS[0].Gloss.StringCount == 0) + return Enumerable.Empty(); + + return entry.AllSenses.Select(s => new LexSenseLexiconSense(m_lexicon, m_key, s)).ToArray(); + } + } + } + + public IEnumerable LexicalRelations + { + get + { + using (m_lexicon.ActivationContext.Activate()) + { + ILexEntry entry; + if (!m_lexicon.TryGetEntry(m_key, out entry)) + return Enumerable.Empty(); + + var relations = new List(); + foreach (ILexReference lexRef in entry.LexEntryReferences.Union(entry.AllSenses.SelectMany(s => s.LexSenseReferences))) + { + string name = GetLexReferenceName(entry, lexRef.OwnerOfClass()).Normalize(); + foreach (ICmObject obj in lexRef.TargetsRS) + { + ILexEntry otherEntry = null; + switch (obj.ClassID) + { + case LexEntryTags.kClassId: + otherEntry = (ILexEntry) obj; + break; + case LexSenseTags.kClassId: + otherEntry = obj.OwnerOfClass(); + break; + } + if (otherEntry != null && otherEntry != entry) + relations.Add(new FdoLexicalRelation(m_lexicon.GetEntryLexeme(otherEntry), name)); + } + } + + return relations; + } + } + } + + private string GetLexReferenceName(ILexEntry lexEntry, ILexRefType lexRefType) + { + // The name we want to use for our lex reference is either the name or the reverse name + // (depending on the direction of the relationship, if relevant) of the owning lex ref type. + ITsString lexReferenceName = lexRefType.Name.BestVernacularAnalysisAlternative; + + if (lexRefType.MappingType == (int)MappingTypes.kmtEntryAsymmetricPair || + lexRefType.MappingType == (int)MappingTypes.kmtEntryOrSenseAsymmetricPair || + lexRefType.MappingType == (int)MappingTypes.kmtSenseAsymmetricPair || + lexRefType.MappingType == (int)MappingTypes.kmtEntryTree || + lexRefType.MappingType == (int)MappingTypes.kmtEntryOrSenseTree || + lexRefType.MappingType == (int)MappingTypes.kmtSenseTree) + { + if (lexEntry.OwnOrd == 0 && lexRefType.Name != null) // the original code had a check for name length as well. + lexReferenceName = lexRefType.ReverseName.BestAnalysisAlternative; + } + + return lexReferenceName.Text; + } + + public LexiconSense AddSense() + { + LexiconSense sense = null; + bool lexemeAdded = false; + m_lexicon.UpdatingEntries = true; + try + { + using (m_lexicon.ActivationContext.Activate()) + { + NonUndoableUnitOfWorkHelper.Do(m_lexicon.Cache.ActionHandlerAccessor, () => + { + ILexEntry entry; + if (!m_lexicon.TryGetEntry(m_key, out entry)) + { + entry = m_lexicon.CreateEntry(m_key); + lexemeAdded = true; + } + + if (entry.AllSenses.Count == 1 && entry.SensesOS[0].Gloss.StringCount == 0) + { + // An empty sense exists (probably was created during a call to AddLexeme) + sense = new LexSenseLexiconSense(m_lexicon, m_key, entry.SensesOS[0]); + } + else + { + ILexSense newSense = m_lexicon.Cache.ServiceLocator.GetInstance().Create( + entry, new SandboxGenericMSA(), (string)null); + sense = new LexSenseLexiconSense(m_lexicon, m_key, newSense); + } + }); + } + } + finally + { + m_lexicon.UpdatingEntries = false; + } + if (lexemeAdded) + m_lexicon.OnLexemeAdded(this); + m_lexicon.OnLexiconSenseAdded(this, sense); + return sense; + } + + public void RemoveSense(LexiconSense sense) + { + using (m_lexicon.ActivationContext.Activate()) + { + ILexEntry entry; + if (!m_lexicon.TryGetEntry(m_key, out entry)) + return; + + NonUndoableUnitOfWorkHelper.Do(m_lexicon.Cache.ActionHandlerAccessor, () => + { + var leSense = (LexSenseLexiconSense)sense; + if (entry.AllSenses.Count == 1) + { + foreach (int ws in leSense.Sense.Gloss.AvailableWritingSystemIds) + leSense.Sense.Gloss.set_String(ws, null); + } + else + { + leSense.Sense.Delete(); + } + }); + } + } + + #endregion + + public override string ToString() + { + return DisplayString; + } + + public override bool Equals(object obj) + { + var other = obj as FdoLexEntryLexeme; + return other != null && m_key.Equals(other.m_key); + } + + public override int GetHashCode() + { + return m_key.GetHashCode(); + } + + [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", + Justification="m_lexicon is a reference")] + private class LexSenseLexiconSense : LexiconSense + { + private readonly FdoLexicon m_lexicon; + private readonly LexemeKey m_lexemeKey; + private readonly ILexSense m_lexSense; + + public LexSenseLexiconSense(FdoLexicon lexicon, LexemeKey lexemeKey, ILexSense lexSense) + { + m_lexicon = lexicon; + m_lexemeKey = lexemeKey; + m_lexSense = lexSense; + } + + internal ILexSense Sense + { + get { return m_lexSense; } + } + + public string Id + { + get + { + using (m_lexicon.ActivationContext.Activate()) + return m_lexSense.Guid.ToString(); + } + } + + public string SenseNumber + { + get + { + using (m_lexicon.ActivationContext.Activate()) + return m_lexSense.LexSenseOutline.Text; + } + } + + public string Category + { + get + { + using (m_lexicon.ActivationContext.Activate()) + return m_lexSense.MorphoSyntaxAnalysisRA == null ? "" : m_lexSense.MorphoSyntaxAnalysisRA.PartOfSpeechForWsTSS(m_lexicon.Cache.DefaultAnalWs).Text; + } + } + + public IEnumerable Definitions + { + get + { + using (m_lexicon.ActivationContext.Activate()) + { + IMultiString definition = m_lexSense.Definition; + var defs = new List(); + foreach (IWritingSystem ws in m_lexicon.Cache.ServiceLocator.WritingSystems.CurrentAnalysisWritingSystems) + { + ITsString tss = definition.StringOrNull(ws.Handle); + if (tss != null) + defs.Add(new FdoLanguageText(ws.Id, tss.Text.Normalize())); + } + return defs; + } + } + } + + public IEnumerable Glosses + { + get + { + using (m_lexicon.ActivationContext.Activate()) + { + IMultiUnicode gloss = m_lexSense.Gloss; + var glosses = new List(); + foreach (IWritingSystem ws in m_lexicon.Cache.ServiceLocator.WritingSystems.CurrentAnalysisWritingSystems) + { + ITsString tss = gloss.StringOrNull(ws.Handle); + if (tss != null) + glosses.Add(new FdoLanguageText(ws.Id, tss.Text.Normalize())); + } + return glosses; + } + } + } + + public LanguageText AddGloss(string language, string text) + { + using (m_lexicon.ActivationContext.Activate()) + { + LanguageText lexGloss = null; + NonUndoableUnitOfWorkHelper.Do(m_lexSense.Cache.ActionHandlerAccessor, () => + { + IWritingSystem ws; + if (!m_lexicon.Cache.ServiceLocator.WritingSystemManager.TryGet(language, out ws)) + throw new ArgumentException("The specified language is unrecognized.", "language"); + m_lexSense.Gloss.set_String(ws.Handle, text.Normalize(NormalizationForm.FormD)); + lexGloss = new FdoLanguageText(language, text); + }); + m_lexicon.OnLexiconGlossAdded(new FdoLexEntryLexeme(m_lexicon, m_lexemeKey), this, lexGloss); + return lexGloss; + } + } + + public void RemoveGloss(string language) + { + using (m_lexicon.ActivationContext.Activate()) + { + NonUndoableUnitOfWorkHelper.Do(m_lexSense.Cache.ActionHandlerAccessor, () => + { + IWritingSystem ws; + if (!m_lexicon.Cache.ServiceLocator.WritingSystemManager.TryGet(language, out ws)) + throw new ArgumentException("The specified language is unrecognized.", "language"); + m_lexSense.Gloss.set_String(ws.Handle, (ITsString) null); + }); + } + } + + public IEnumerable SemanticDomains + { + get + { + using (m_lexicon.ActivationContext.Activate()) + return m_lexSense.SemanticDomainsRC.Select(sd => new FdoSemanticDomain(sd.ShortName.Normalize())).ToArray(); + } + } + + public override bool Equals(object obj) + { + var other = obj as LexSenseLexiconSense; + return other != null && m_lexSense == other.m_lexSense; + } + + public override int GetHashCode() + { + return m_lexSense.GetHashCode(); + } + } + } + #endregion +} diff --git a/Src/FwParatextLexiconPlugin/FdoLexicalRelation.cs b/Src/FwParatextLexiconPlugin/FdoLexicalRelation.cs new file mode 100644 index 0000000000..64c8ff582a --- /dev/null +++ b/Src/FwParatextLexiconPlugin/FdoLexicalRelation.cs @@ -0,0 +1,26 @@ +using Paratext.LexicalContracts; + +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + internal class FdoLexicalRelation : LexicalRelation + { + private readonly Lexeme m_lexeme; + private readonly string m_name; + + public FdoLexicalRelation(Lexeme lexeme, string name) + { + m_lexeme = lexeme; + m_name = name; + } + + public Lexeme Lexeme + { + get { return m_lexeme; } + } + + public string Name + { + get { return m_name; } + } + } +} diff --git a/Src/FwParatextLexiconPlugin/FdoLexicon.cs b/Src/FwParatextLexiconPlugin/FdoLexicon.cs new file mode 100644 index 0000000000..91eb29c1f6 --- /dev/null +++ b/Src/FwParatextLexiconPlugin/FdoLexicon.cs @@ -0,0 +1,868 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Web; +using Paratext.LexicalContracts; +using SIL.CoreImpl; +using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.FDO; +using SIL.FieldWorks.FDO.DomainImpl; +using SIL.FieldWorks.FDO.DomainServices; +using SIL.FieldWorks.FDO.Infrastructure; +using SIL.FieldWorks.WordWorks.Parser; +using SIL.Machine.Morphology; +using SIL.Utils; + +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + internal class FdoLexicon : FwDisposableBase, Lexicon, WordAnalyses, IVwNotifyChange + { + private IParser m_parser; + private readonly FdoCache m_cache; + private readonly string m_scrTextName; + private readonly ConditionalWeakTable m_homographNumbers; + private Dictionary> m_entryIndex; + private readonly LexEntryComparer m_entryComparer; + private readonly int m_defaultVernWs; + private PoorMansStemmer m_stemmer; + private readonly ActivationContextHelper m_activationContext; + + internal FdoLexicon(string scrTextName, FdoCache cache, int defaultVernWs, ActivationContextHelper activationContext) + { + m_scrTextName = scrTextName; + m_cache = cache; + m_homographNumbers = new ConditionalWeakTable(); + m_cache.DomainDataByFlid.AddNotification(this); + m_entryComparer = new LexEntryComparer(this); + m_defaultVernWs = defaultVernWs; + m_activationContext = activationContext; + } + + internal FdoCache Cache + { + get { return m_cache; } + } + + internal ActivationContextHelper ActivationContext + { + get { return m_activationContext; } + } + + internal string ScrTextName + { + get { return m_scrTextName; } + } + + internal bool UpdatingEntries { get; set; } + + internal int DefaultVernWs + { + get { return m_defaultVernWs; } + } + + protected override void DisposeManagedResources() + { + if (m_parser != null) + { + m_parser.Dispose(); + m_parser = null; + } + } + + #region Lexicon implementation + + public event EventHandler LexemeAdded; + + public event EventHandler LexiconSenseAdded; + + public event EventHandler LexiconGlossAdded; + + public bool RequiresLanguageId + { + get { return true; } + } + + public IEnumerable Lexemes + { + get + { + using (m_activationContext.Activate()) + { + var lexemes = new List(); + // Get all of the lexical entries in the database + foreach (ILexEntry entry in m_cache.ServiceLocator.GetInstance().AllInstances().Where(e => e.PrimaryMorphType != null)) + lexemes.Add(GetEntryLexeme(entry)); + + // Get all the wordforms in the database + foreach (IWfiWordform wordform in m_cache.ServiceLocator.GetInstance().AllInstances()) + { + string wordFormWs = wordform.Form.get_String(m_defaultVernWs).Text; + if (wordFormWs != null) + lexemes.Add(new FdoWordformLexeme(this, new LexemeKey(LexemeType.Word, wordFormWs.Normalize()))); + } + return lexemes; + } + } + } + + public Lexeme this[string id] + { + get + { + using (m_activationContext.Activate()) + { + Lexeme lexeme; + if (TryGetLexeme(new LexemeKey(id), out lexeme)) + return lexeme; + return null; + } + } + } + + private bool TryGetLexeme(LexemeKey key, out Lexeme lexeme) + { + if (key.Type == LexemeType.Word) + { + IWfiWordform wf; + if (TryGetWordform(key.LexicalForm, out wf)) + { + lexeme = new FdoWordformLexeme(this, key); + return true; + } + } + else + { + ILexEntry entry; + if (TryGetEntry(key, out entry)) + { + lexeme = new FdoLexEntryLexeme(this, key); + return true; + } + } + + lexeme = null; + return false; + } + + public Lexeme FindOrCreateLexeme(LexemeType type, string lexicalForm) + { + using (m_activationContext.Activate()) + { + Lexeme lexeme; + if (!TryGetLexeme(new LexemeKey(type, lexicalForm), out lexeme)) + lexeme = CreateLexeme(type, lexicalForm); + return lexeme; + } + } + + public Lexeme CreateLexeme(LexemeType type, string lexicalForm) + { + using (m_activationContext.Activate()) + { + if (type == LexemeType.Word) + return new FdoWordformLexeme(this, new LexemeKey(type, lexicalForm)); + + int num = 1; + foreach (ILexEntry entry in GetMatchingEntries(type, lexicalForm)) + { + if (m_homographNumbers.GetOrCreateValue(entry).Number != num) + break; + num++; + } + + return new FdoLexEntryLexeme(this, new LexemeKey(type, lexicalForm, num)); + } + } + + public void RemoveLexeme(Lexeme lexeme) + { + using (m_activationContext.Activate()) + { + if (lexeme.Type == LexemeType.Word) + { + IWfiWordform wordform; + if (TryGetWordform(lexeme.LexicalForm, out wordform)) + NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, () => wordform.Delete()); + } + else + { + var entryLexeme = (FdoLexEntryLexeme)lexeme; + ILexEntry entry; + if (TryGetEntry(entryLexeme.Key, out entry)) + { + var key = new LexemeKey(lexeme.Type, lexeme.LexicalForm); + SortedSet entries = m_entryIndex[key]; + entries.Remove(entry); + UpdatingEntries = true; + try + { + NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, () => entry.Delete()); + } + finally + { + UpdatingEntries = false; + } + } + } + } + } + + public void AddLexeme(Lexeme lexeme) + { + if (this[lexeme.Id] != null) + throw new ArgumentException("The specified lexeme has already been added.", "lexeme"); + + using (m_activationContext.Activate()) + { + if (lexeme.Type == LexemeType.Word) + { + NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, () => CreateWordform(lexeme.LexicalForm)); + } + else + { + UpdatingEntries = true; + try + { + var entryLexeme = (FdoLexEntryLexeme) lexeme; + NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, () => CreateEntry(entryLexeme.Key)); + } + finally + { + UpdatingEntries = false; + } + } + } + OnLexemeAdded(lexeme); + } + + public void Save() + { + // Comment copied from previous + + // ENHANCE: We could do a save on the cache here. It doesn't seem really important + // since the cache will be saved automatically with 10 seconds of inactivity anyways. + } + + public Lexeme FindClosestMatchingLexeme(string wordForm) + { + using (m_activationContext.Activate()) + { + wordForm = wordForm.Normalize(NormalizationForm.FormD); + ITsString tss = TsStringUtils.MakeTss(wordForm, DefaultVernWs); + ILexEntry matchingEntry = m_cache.ServiceLocator.GetInstance().FindEntryForWordform(m_cache, tss); + + if (matchingEntry == null) + matchingEntry = GetMatchingEntryFromParser(wordForm); + + if (matchingEntry == null) + matchingEntry = GetMatchingEntryFromStemmer(wordForm); + + if (matchingEntry == null) + return null; + + return GetEntryLexeme(matchingEntry); + } + } + + public IEnumerable FindMatchingLexemes(string wordForm) + { + using (m_activationContext.Activate()) + { + bool duplicates = false; + return m_cache.ServiceLocator.GetInstance() + .FindEntriesForWordform(m_cache, m_cache.TsStrFactory.MakeString(wordForm.Normalize(NormalizationForm.FormD), DefaultVernWs), null, ref duplicates).Select(GetEntryLexeme); + } + } + + public bool CanOpenInLexicon + { + get { return ParatextLexiconDirectoryFinder.IsFieldWorksInstalled; } + } + + public void OpenInLexicon(Lexeme lexeme) + { + if (m_cache.ProjectId.Type != FDOBackendProviderType.kDb4oClientServer) + throw new LexiconUnavailableException("Fieldworks and Paratext cannot access the same project at the same time unless the Fieldworks project is shared."); + + string guid = null, toolName; + using (m_activationContext.Activate()) + { + if (lexeme.Type == LexemeType.Word) + { + toolName = "Analyses"; + IWfiWordform wf; + if (TryGetWordform(lexeme.LexicalForm, out wf)) + guid = wf.Guid.ToString(); + } + else + { + toolName = "lexiconEdit"; + var entryLexeme = (FdoLexEntryLexeme)lexeme; + ILexEntry entry; + if (TryGetEntry(entryLexeme.Key, out entry)) + guid = entry.Guid.ToString(); + } + } + if (guid != null) + { + string url = string.Format("silfw://localhost/link?app=flex&database={0}&tool={1}&guid={2}", + HttpUtility.UrlEncode(m_cache.ProjectId.Name), HttpUtility.UrlEncode(toolName), HttpUtility.UrlEncode(guid)); + using (Process.Start(url)) {} + } + } + + public IEnumerable ValidLanguages + { + get + { + using (m_activationContext.Activate()) + return m_cache.ServiceLocator.WritingSystems.CurrentAnalysisWritingSystems.Select(writingSystem => writingSystem.Id); + } + } + #endregion + + #region WordAnalyses implementation + public IEnumerable GetWordAnalyses(string word) + { + using (m_activationContext.Activate()) + { + IWfiWordform wordform; + if (!TryGetWordform(word, out wordform)) + return Enumerable.Empty(); + + var analyses = new HashSet(); + foreach (IWfiAnalysis analysis in wordform.AnalysesOC.Where(a => a.MorphBundlesOS.Count > 0 && a.ApprovalStatusIcon == (int) Opinions.approves)) + { + FdoWordAnalysis lexemes; + if (GetMorpologySegment(analysis, out lexemes)) + analyses.Add(lexemes); + } + return analyses; + } + } + + public void AddWordAnalysis(string word, WordAnalysis lexemes) + { + using (m_activationContext.Activate()) + { + NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, () => + { + IWfiWordform wordform; + if (!TryGetWordform(word, out wordform)) + { + wordform = m_cache.ServiceLocator.GetInstance().Create( + m_cache.TsStrFactory.MakeString(word.Normalize(NormalizationForm.FormD), DefaultVernWs)); + } + + IWfiAnalysis analysis = m_cache.ServiceLocator.GetInstance().Create(); + wordform.AnalysesOC.Add(analysis); + analysis.ApprovalStatusIcon = (int) Opinions.approves; + + foreach (Lexeme lexeme in lexemes) + { + var entryLexeme = (FdoLexEntryLexeme) lexeme; + ILexEntry entry; + if (TryGetEntry(entryLexeme.Key, out entry)) + { + IWfiMorphBundle mb = m_cache.ServiceLocator.GetInstance().Create(); + analysis.MorphBundlesOS.Add(mb); + mb.MorphRA = entry.LexemeFormOA; + mb.SenseRA = entry.SensesOS[0]; + mb.MsaRA = entry.SensesOS[0].MorphoSyntaxAnalysisRA; + } + } + }); + } + } + + public void RemoveWordAnalysis(string word, WordAnalysis lexemes) + { + using (m_activationContext.Activate()) + { + IWfiWordform wordform; + if (!TryGetWordform(word, out wordform)) + return; + + foreach (IWfiAnalysis analysis in wordform.AnalysesOC.Where(a => a.MorphBundlesOS.Count > 0 && a.ApprovalStatusIcon == (int) Opinions.approves)) + { + bool match = true; + int i = 0; + foreach (Lexeme lexeme in lexemes) + { + if (i == analysis.MorphBundlesOS.Count || analysis.MorphBundlesOS[i].MorphRA == null) + { + match = false; + break; + } + + var entry = analysis.MorphBundlesOS[i].MorphRA.OwnerOfClass(); + if (!GetEntryLexeme(entry).Equals(lexeme)) + { + match = false; + break; + } + i++; + } + if (match && !analysis.OccurrencesInTexts.Any()) + { + NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, () => wordform.AnalysesOC.Remove(analysis)); + break; + } + } + } + } + + public IEnumerable> GetWordAnalyses() + { + using (m_activationContext.Activate()) + { + var analyses = new HashSet>(); + foreach (IWfiAnalysis analysis in m_cache.ServiceLocator.GetInstance().AllInstances().Where(a => a.MorphBundlesOS.Count > 0 && a.ApprovalStatusIcon == (int) Opinions.approves)) + { + FdoWordAnalysis lexemes; + string wordFormWs = analysis.Wordform.Form.get_String(m_defaultVernWs).Text; + if (wordFormWs != null && GetMorpologySegment(analysis, out lexemes)) + analyses.Add(new KeyValuePair(wordFormWs.Normalize(), lexemes)); + } + return analyses; + } + } + #endregion + + private bool GetMorpologySegment(IWfiAnalysis analysis, out FdoWordAnalysis lexemes) + { + var lexemeArray = new Lexeme[analysis.MorphBundlesOS.Count]; + for (int i = 0; i < analysis.MorphBundlesOS.Count; i++) + { + IWfiMorphBundle mb = analysis.MorphBundlesOS[i]; + if (mb.MorphRA == null) + { + lexemes = null; + return false; + } + var entry = mb.MorphRA.OwnerOfClass(); + if (entry.LexemeFormOA != mb.MorphRA) + { + lexemes = null; + return false; + } + lexemeArray[i] = GetEntryLexeme(entry); + } + + lexemes = new FdoWordAnalysis(lexemeArray); + return true; + } + + private ILexEntry GetMatchingEntryFromParser(string wordForm) + { + ILexEntry matchingEntry = null; + if (m_parser == null) + InstantiateParser(); + + if (m_parser == null) + return null; + + if (!m_parser.IsUpToDate()) + { + m_parser.Update(); + //ProgressUtils.Execute(Localizer.Str("Updating Data for Parser"), CancelModes.NonCancelable, () => m_parser.Update() ); + } + + ParseResult parseResult = m_parser.ParseWord(wordForm); + if (parseResult != null && parseResult.Analyses != null && parseResult.Analyses.Any()) + { + foreach (ParseMorph morph in parseResult.Analyses.First().Morphs) + { + if (morph.Form is IMoStemAllomorph) + { + matchingEntry = morph.Form.OwnerOfClass(); + break; + } + } + } + return matchingEntry; + } + + private void InstantiateParser() + { + string parserDataDir = Path.Combine(ParatextLexiconDirectoryFinder.DataDirectory, "Language Explorer"); + switch (m_cache.LanguageProject.MorphologicalDataOA.ActiveParser) + { + case "XAmple": + m_parser = new XAmpleParser(m_cache, parserDataDir); + break; + case "HC": + m_parser = new HCParser(m_cache, parserDataDir); + break; + default: + throw new InvalidOperationException("The language project is set to use an unrecognized parser."); + } + } + + private ILexEntry GetMatchingEntryFromStemmer(string wordForm) + { + var repo = m_cache.ServiceLocator.GetInstance(); + if (m_stemmer == null) + { + m_stemmer = new PoorMansStemmer(s => s) {NormalizeScores = true, WeightScores = false, Threshold = 0.12}; + var forms = new HashSet(); + foreach (ILexEntry entry in repo.AllInstances()) + { + if (!(entry.LexemeFormOA is IMoStemAllomorph)) + continue; + + forms.UnionWith(GetForms(entry)); + } + m_stemmer.Train(forms); + } + + int bestLen = 0; + double bestScore = 0; + ILexEntry bestMatch = null; + foreach (ILexEntry entry in repo.AllInstances()) + { + if (!(entry.LexemeFormOA is IMoStemAllomorph)) + continue; + + foreach (string form in GetForms(entry)) + { + double formScore; + if (m_stemmer.HaveSameStem(wordForm, form, out formScore)) + { + if (formScore > bestScore) + { + bestMatch = entry; + bestScore = formScore; + bestLen = LongestCommonSubstringLength(wordForm, form); + } + else if (Math.Abs(formScore - bestScore) < double.Epsilon) + { + int len = LongestCommonSubstringLength(wordForm, form); + if (len > bestLen) + { + bestMatch = entry; + bestScore = formScore; + bestLen = len; + } + } + } + } + } + return bestMatch; + } + + private IEnumerable GetForms(ILexEntry entry) + { + ITsString citationFormTss = entry.CitationForm.StringOrNull(m_defaultVernWs); + if (citationFormTss != null) + yield return citationFormTss.Text; + + ITsString lexemeFormTss = entry.LexemeFormOA.Form.StringOrNull(m_defaultVernWs); + if (lexemeFormTss != null) + yield return lexemeFormTss.Text; + } + + private static int LongestCommonSubstringLength(string str1, string str2) + { + if (String.IsNullOrEmpty(str1) || String.IsNullOrEmpty(str2)) + return 0; + + var num = new int[str1.Length, str2.Length]; + int maxlen = 0; + + for (int i = 0; i < str1.Length; i++) + { + for (int j = 0; j < str2.Length; j++) + { + if (str1[i] != str2[j]) + { + num[i, j] = 0; + } + else + { + if ((i == 0) || (j == 0)) + num[i, j] = 1; + else + num[i, j] = 1 + num[i - 1, j - 1]; + + if (num[i, j] > maxlen) + maxlen = num[i, j]; + } + } + } + return maxlen; + } + + private IEnumerable GetMatchingEntries(LexemeType type, string lexicalForm) + { + CreateEntryIndexIfNeeded(); + SortedSet entries; + if (m_entryIndex.TryGetValue(new LexemeKey(type, lexicalForm), out entries)) + return entries; + return Enumerable.Empty(); + } + + private void CreateEntryIndexIfNeeded() + { + if (m_entryIndex != null) + return; + + m_entryIndex = new Dictionary>(); + foreach (ILexEntry entry in m_cache.ServiceLocator.GetInstance().AllInstances()) + { + LexemeType type = GetLexemeTypeForMorphType(entry.PrimaryMorphType); + string form = entry.LexemeFormOA.Form.VernacularDefaultWritingSystem.Text.Normalize(); + var key = new LexemeKey(type, form); + + SortedSet entries; + if (!m_entryIndex.TryGetValue(key, out entries)) + { + entries = new SortedSet(m_entryComparer); + m_entryIndex[key] = entries; + } + + HomographNumber hn = m_homographNumbers.GetOrCreateValue(entry); + if (hn.Number == 0) + { + int num = 1; + foreach (ILexEntry e in entries) + { + if (m_homographNumbers.GetOrCreateValue(e).Number != num) + break; + num++; + } + hn.Number = num; + } + + entries.Add(entry); + } + } + + internal bool TryGetWordform(string lexicalForm, out IWfiWordform wordform) + { + return m_cache.ServiceLocator.GetInstance().TryGetObject( + TsStringUtils.MakeTss(lexicalForm.Normalize(NormalizationForm.FormD), DefaultVernWs), true, out wordform); + } + + internal IWfiWordform CreateWordform(string lexicalForm) + { + ITsString tss = m_cache.TsStrFactory.MakeString(lexicalForm.Normalize(NormalizationForm.FormD), DefaultVernWs); + IWfiWordform wordform = m_cache.ServiceLocator.GetInstance().Create(tss); + return wordform; + } + + internal bool TryGetEntry(LexemeKey key, out ILexEntry entry) + { + entry = GetMatchingEntries(key.Type, key.LexicalForm).FirstOrDefault(e => m_homographNumbers.GetOrCreateValue(e).Number == key.Homograph); + return entry != null; + } + + internal ILexEntry CreateEntry(LexemeKey key) + { + CreateEntryIndexIfNeeded(); + + ITsString tss = m_cache.TsStrFactory.MakeString(key.LexicalForm.Normalize(NormalizationForm.FormD), DefaultVernWs); + var msa = new SandboxGenericMSA {MsaType = (key.Type == LexemeType.Stem) ? MsaType.kStem : MsaType.kUnclassified}; + ILexEntry entry = m_cache.ServiceLocator.GetInstance().Create(GetMorphTypeForLexemeType(key.Type), tss, (ITsString) null, msa); + m_homographNumbers.GetOrCreateValue(entry).Number = key.Homograph; + + var homographKey = new LexemeKey(key.Type, key.LexicalForm); + SortedSet entries; + if (!m_entryIndex.TryGetValue(homographKey, out entries)) + { + entries = new SortedSet(m_entryComparer); + m_entryIndex[homographKey] = entries; + } + entries.Add(entry); + + return entry; + } + + internal FdoLexEntryLexeme GetEntryLexeme(ILexEntry entry) + { + CreateEntryIndexIfNeeded(); + LexemeType type = GetLexemeTypeForMorphType(entry.PrimaryMorphType); + HomographNumber hn = m_homographNumbers.GetOrCreateValue(entry); + return new FdoLexEntryLexeme(this, new LexemeKey(type, entry.LexemeFormOA.Form.VernacularDefaultWritingSystem.Text.Normalize(), hn.Number)); + } + + internal void OnLexemeAdded(Lexeme lexeme) + { + if (LexemeAdded != null) + LexemeAdded(this, new LexemeAddedEventArgs(lexeme)); + } + + internal void OnLexiconSenseAdded(Lexeme lexeme, LexiconSense sense) + { + if (LexiconSenseAdded != null) + LexiconSenseAdded(this, new LexiconSenseAddedEventArgs(lexeme, sense)); + } + + internal void OnLexiconGlossAdded(Lexeme lexeme, LexiconSense sense, LanguageText gloss) + { + if (LexiconGlossAdded != null) + LexiconGlossAdded(this, new LexiconGlossAddedEventArgs(lexeme, sense, gloss)); + } + + /// ------------------------------------------------------------------------------------ + /// + /// Gets the lexeme type that most closely represents the specified morph type. + /// + /// This method attempts to do it's best to get the correct lexeme type. + /// However, the FW database contains many more morph types then can be represented with + /// the few lexeme types. This creates some ambiguous mappings which are commented + /// inside this method body. + /// ------------------------------------------------------------------------------------ + private static LexemeType GetLexemeTypeForMorphType(IMoMorphType type) + { + switch (type.Guid.ToString()) + { + case MoMorphTypeTags.kMorphCircumfix: + case MoMorphTypeTags.kMorphInfix: + case MoMorphTypeTags.kMorphInfixingInterfix: + case MoMorphTypeTags.kMorphSimulfix: + case MoMorphTypeTags.kMorphSuprafix: + case MoMorphTypeTags.kMorphClitic: + case MoMorphTypeTags.kMorphProclitic: + // These don't map neatly to a lexeme type, so we just return prefix + return LexemeType.Prefix; + + case MoMorphTypeTags.kMorphEnclitic: + // This one also isn't a great match, but there is no better choice + return LexemeType.Suffix; + + case MoMorphTypeTags.kMorphPrefix: + case MoMorphTypeTags.kMorphPrefixingInterfix: + return LexemeType.Prefix; + + case MoMorphTypeTags.kMorphSuffix: + case MoMorphTypeTags.kMorphSuffixingInterfix: + return LexemeType.Suffix; + + case MoMorphTypeTags.kMorphPhrase: + case MoMorphTypeTags.kMorphDiscontiguousPhrase: + return LexemeType.Phrase; + + case MoMorphTypeTags.kMorphStem: + case MoMorphTypeTags.kMorphRoot: + case MoMorphTypeTags.kMorphBoundRoot: + case MoMorphTypeTags.kMorphBoundStem: + case MoMorphTypeTags.kMorphParticle: + return LexemeType.Stem; + } + + // Shouldn't ever get here, but since we don't know what type it is just return + // a random default and hope for the best. + return LexemeType.Stem; + } + + /// ------------------------------------------------------------------------------------ + /// + /// Gets the morph type for the specified lexeme type. + /// + /// ------------------------------------------------------------------------------------ + private IMoMorphType GetMorphTypeForLexemeType(LexemeType type) + { + if (type == LexemeType.Word || type == LexemeType.Lemma) + throw new ArgumentException("Morph type can never be of the specified lexeme type"); + + var repo = m_cache.ServiceLocator.GetInstance(); + switch (type) + { + case LexemeType.Prefix: return repo.GetObject(MoMorphTypeTags.kguidMorphPrefix); + case LexemeType.Suffix: return repo.GetObject(MoMorphTypeTags.kguidMorphSuffix); + case LexemeType.Phrase: return repo.GetObject(MoMorphTypeTags.kguidMorphPhrase); + case LexemeType.Stem: return repo.GetObject(MoMorphTypeTags.kguidMorphStem); + } + return null; + } + + void IVwNotifyChange.PropChanged(int hvo, int tag, int ivMin, int cvIns, int cvDel) + { + ICmObject obj = m_cache.ServiceLocator.GetObject(hvo); + switch (obj.ClassID) + { + case LexDbTags.kClassId: + if (tag == m_cache.ServiceLocator.GetInstance().LexDbEntries) + { + if (!UpdatingEntries) + m_entryIndex = null; + m_stemmer = null; + } + break; + + case MoStemAllomorphTags.kClassId: + if (tag == MoFormTags.kflidForm) + { + if (!UpdatingEntries && obj.OwningFlid == LexEntryTags.kflidLexemeForm) + m_entryIndex = null; + m_stemmer = null; + } + break; + + case MoAffixAllomorphTags.kClassId: + if (!UpdatingEntries && obj.OwningFlid == LexEntryTags.kflidLexemeForm && tag == MoFormTags.kflidForm) + m_entryIndex = null; + break; + + case LexEntryTags.kClassId: + var entry = (ILexEntry) obj; + switch (tag) + { + case LexEntryTags.kflidLexemeForm: + if (!UpdatingEntries) + m_entryIndex = null; + if (entry.LexemeFormOA is IMoStemAllomorph) + m_stemmer = null; + break; + + case LexEntryTags.kflidAlternateForms: + if (entry.LexemeFormOA is IMoStemAllomorph) + m_stemmer = null; + break; + } + break; + + case MoMorphDataTags.kClassId: + if (tag == MoMorphDataTags.kflidParserParameters) + { + if (m_parser != null) + { + m_parser.Dispose(); + m_parser = null; + } + } + break; + } + } + + internal class HomographNumber + { + public int Number { get; set; } + } + + [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", + Justification="m_lexicon is a reference")] + private class LexEntryComparer : IComparer + { + private readonly FdoLexicon m_lexicon; + + public LexEntryComparer(FdoLexicon lexicon) + { + m_lexicon = lexicon; + } + + public int Compare(ILexEntry x, ILexEntry y) + { + HomographNumber hnx = m_lexicon.m_homographNumbers.GetOrCreateValue(x); + HomographNumber hny = m_lexicon.m_homographNumbers.GetOrCreateValue(y); + return hnx.Number.CompareTo(hny.Number); + } + } + } +} diff --git a/Src/FwParatextLexiconPlugin/FdoSemanticDomain.cs b/Src/FwParatextLexiconPlugin/FdoSemanticDomain.cs new file mode 100644 index 0000000000..347cf1366c --- /dev/null +++ b/Src/FwParatextLexiconPlugin/FdoSemanticDomain.cs @@ -0,0 +1,40 @@ +using System.Diagnostics; +using Paratext.LexicalContracts; + +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + internal class FdoSemanticDomain : LexiconSemanticDomain + { + private readonly string m_name; + + /// + /// Creates a new LexiconSemanticDomain by wrapping the specified data + /// + public FdoSemanticDomain(string name) + { + Debug.Assert(name.IsNormalized(), "We expect all strings to be normalized composed"); + m_name = name; + } + + #region Implementation of LexiconSemanticDomain + /// + /// The name of the semantic domain + /// + public string Name + { + get { return m_name; } + } + #endregion + + public override bool Equals(object obj) + { + var other = obj as FdoSemanticDomain; + return other != null && m_name == other.m_name; + } + + public override int GetHashCode() + { + return m_name.GetHashCode(); + } + } +} diff --git a/Src/FwParatextLexiconPlugin/FdoWordAnalysis.cs b/Src/FwParatextLexiconPlugin/FdoWordAnalysis.cs new file mode 100644 index 0000000000..e37dd9cc9c --- /dev/null +++ b/Src/FwParatextLexiconPlugin/FdoWordAnalysis.cs @@ -0,0 +1,78 @@ +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using Paratext.LexicalContracts; + +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + internal class FdoWordAnalysis : WordAnalysis + { + private readonly Lexeme[] m_lexemes; + + public FdoWordAnalysis(Lexeme[] lexemes) + { + m_lexemes = lexemes; + } + + public string DisplayString + { + get + { + var sb = new StringBuilder(); + foreach (Lexeme lex in m_lexemes) + { + switch (lex.Type) + { + case LexemeType.Prefix: sb.Append(lex.LexicalForm + "+ "); break; + case LexemeType.Suffix: sb.Append("+" + lex.LexicalForm + " "); break; + default: sb.Append(lex.LexicalForm + " "); break; + } + } + return sb.ToString().TrimEnd(); + } + } + + public Lexeme this[int index] + { + get { return m_lexemes[index]; } + } + + public override bool Equals(object obj) + { + var other = obj as FdoWordAnalysis; + if (other == null || m_lexemes.Length != other.m_lexemes.Length) + return false; + + for (int i = 0; i < m_lexemes.Length; i++) + { + if (!m_lexemes[i].Equals(other.m_lexemes[i])) + return false; + } + return true; + } + + public override int GetHashCode() + { + return m_lexemes.Aggregate(23, (code, lexeme) => code * 31 + lexeme.GetHashCode()); + } + + public override string ToString() + { + return DisplayString; + } + + public IEnumerator GetEnumerator() + { + return ((IEnumerable)m_lexemes).GetEnumerator(); + } + + [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", + Justification = "Don't need to dispose an IEnumerator.")] + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} diff --git a/Src/FwParatextLexiconPlugin/FdoWordformLexeme.cs b/Src/FwParatextLexiconPlugin/FdoWordformLexeme.cs new file mode 100644 index 0000000000..4eb43973f3 --- /dev/null +++ b/Src/FwParatextLexiconPlugin/FdoWordformLexeme.cs @@ -0,0 +1,289 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using Paratext.LexicalContracts; +using SIL.CoreImpl; +using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.FDO; +using SIL.FieldWorks.FDO.Infrastructure; + +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + #region FdoWordformLexeme class + /// + /// + [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", + Justification="m_lexicon is a reference")] + internal class FdoWordformLexeme : Lexeme + { + private readonly LexemeKey m_key; + private readonly FdoLexicon m_lexicon; + + public FdoWordformLexeme(FdoLexicon lexicon, LexemeKey key) + { + m_lexicon = lexicon; + m_key = key; + } + + #region Lexeme Members + + public string Id + { + get { return m_key.Id; } + } + + public LexemeType Type + { + get { return LexemeType.Word; } + } + + public string LexicalForm + { + get { return m_key.LexicalForm; } + } + + /// + /// Gets a string that is suitable for display which may contain morphological abbreviations + /// + public string DisplayString + { + get { return LexicalForm; } + } + + public string InterlinearDisplayString + { + get { return DisplayString; } + } + + public string CitationForm + { + get { return null; } + } + + public int HomographNumber + { + get { return 0; } + } + + public IEnumerable Senses + { + get + { + using (m_lexicon.ActivationContext.Activate()) + { + IWfiWordform wf; + if (!m_lexicon.TryGetWordform(m_key.LexicalForm, out wf)) + return Enumerable.Empty(); + + return wf.AnalysesOC.Where(a => a.ApprovalStatusIcon == (int) Opinions.approves).SelectMany(a => a.MeaningsOC) + .Select(gloss => new WfiGlossLexiconSense(m_lexicon, m_key, gloss)).ToArray(); + } + } + } + + public IEnumerable LexicalRelations + { + get { return Enumerable.Empty(); } + } + + public LexiconSense AddSense() + { + LexiconSense sense = null; + bool lexemeAdded = false; + using (m_lexicon.ActivationContext.Activate()) + { + NonUndoableUnitOfWorkHelper.Do(m_lexicon.Cache.ActionHandlerAccessor, () => + { + IWfiWordform wordform; + if (!m_lexicon.TryGetWordform(m_key.LexicalForm, out wordform)) + { + wordform = m_lexicon.CreateWordform(m_key.LexicalForm); + lexemeAdded = true; + } + // For wordforms, our "senses" could be new meanings of an analysis for the word + // or it could be a brand new analysis. Because we have no idea what the user actually + // wanted, we just assume the worst (they want to create a new analysis for the word + // with a new meaning). + IWfiAnalysis analysis = m_lexicon.Cache.ServiceLocator.GetInstance().Create(); + wordform.AnalysesOC.Add(analysis); + analysis.ApprovalStatusIcon = (int) Opinions.approves; // Assume the analysis from the external application is user approved + IMoStemAllomorph morph = m_lexicon.Cache.ServiceLocator.GetInstance().AllInstances().FirstOrDefault(allo => + { + ITsString tss = allo.Form.StringOrNull(m_lexicon.DefaultVernWs); + if (tss != null) + return tss.Text == LexicalForm.Normalize(NormalizationForm.FormD); + return false; + }); + if (morph != null) + { + IWfiMorphBundle mb = m_lexicon.Cache.ServiceLocator.GetInstance().Create(); + analysis.MorphBundlesOS.Add(mb); + mb.MorphRA = morph; + var entry = morph.OwnerOfClass(); + mb.SenseRA = entry.SensesOS[0]; + mb.MsaRA = entry.SensesOS[0].MorphoSyntaxAnalysisRA; + } + IWfiGloss gloss = m_lexicon.Cache.ServiceLocator.GetInstance().Create(); + analysis.MeaningsOC.Add(gloss); + sense = new WfiGlossLexiconSense(m_lexicon, m_key, gloss); + }); + } + if (lexemeAdded) + m_lexicon.OnLexemeAdded(this); + m_lexicon.OnLexiconSenseAdded(this, sense); + return sense; + } + + public void RemoveSense(LexiconSense sense) + { + using (m_lexicon.ActivationContext.Activate()) + { + NonUndoableUnitOfWorkHelper.Do(m_lexicon.Cache.ActionHandlerAccessor, () => + { + var glossSense = (WfiGlossLexiconSense) sense; + if (!glossSense.Gloss.Analysis.OccurrencesInTexts.Any(seg => seg.AnalysesRS.Contains(glossSense.Gloss))) + { + IWfiAnalysis analysis = glossSense.Gloss.Analysis; + if (analysis.MeaningsOC.Count == 1 && !analysis.OccurrencesInTexts.Any()) + analysis.Delete(); + else + glossSense.Gloss.Delete(); + } + }); + } + } + + #endregion + + public override bool Equals(object obj) + { + var other = obj as FdoWordformLexeme; + return other != null && m_key.Equals(other.m_key); + } + + public override int GetHashCode() + { + return m_key.GetHashCode(); + } + + public override string ToString() + { + return DisplayString; + } + + [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", + Justification="m_lexicon is a reference")] + private class WfiGlossLexiconSense : LexiconSense + { + private readonly FdoLexicon m_lexicon; + private readonly LexemeKey m_lexemeKey; + private readonly IWfiGloss m_gloss; + + public WfiGlossLexiconSense(FdoLexicon lexicon, LexemeKey lexemeKey, IWfiGloss gloss) + { + m_lexicon = lexicon; + m_lexemeKey = lexemeKey; + m_gloss = gloss; + } + + internal IWfiGloss Gloss + { + get { return m_gloss; } + } + + public string Id + { + get + { + using (m_lexicon.ActivationContext.Activate()) + return m_gloss.Guid.ToString(); + } + } + + public string SenseNumber + { + get { return null; } + } + + public string Category + { + get { return null; } + } + + public IEnumerable Definitions + { + get { return Enumerable.Empty(); } + } + + public IEnumerable Glosses + { + get + { + using (m_lexicon.ActivationContext.Activate()) + { + var glosses = new List(); + IMultiUnicode fdoGlosses = m_gloss.Form; + foreach (IWritingSystem ws in m_lexicon.Cache.ServiceLocator.WritingSystems.CurrentAnalysisWritingSystems) + { + ITsString tssGloss = fdoGlosses.StringOrNull(ws.Handle); + if (tssGloss != null) + glosses.Add(new FdoLanguageText(ws.Id, tssGloss.Text.Normalize())); + } + return glosses; + } + } + } + + public LanguageText AddGloss(string language, string text) + { + LanguageText lexGloss = null; + using (m_lexicon.ActivationContext.Activate()) + { + NonUndoableUnitOfWorkHelper.Do(m_gloss.Cache.ActionHandlerAccessor, () => + { + IWritingSystem ws; + if (!m_lexicon.Cache.ServiceLocator.WritingSystemManager.TryGet(language, out ws)) + throw new ArgumentException("The specified language is unrecognized.", "language"); + m_gloss.Form.set_String(ws.Handle, text.Normalize(NormalizationForm.FormD)); + lexGloss = new FdoLanguageText(language, text); + }); + } + m_lexicon.OnLexiconGlossAdded(new FdoWordformLexeme(m_lexicon, m_lexemeKey), this, lexGloss); + return lexGloss; + } + + public void RemoveGloss(string language) + { + using (m_lexicon.ActivationContext.Activate()) + { + NonUndoableUnitOfWorkHelper.Do(m_gloss.Cache.ActionHandlerAccessor, () => + { + IWritingSystem ws; + if (!m_lexicon.Cache.ServiceLocator.WritingSystemManager.TryGet(language, out ws)) + throw new ArgumentException("The specified language is unrecognized.", "language"); + m_gloss.Form.set_String(ws.Handle, (ITsString) null); + }); + } + } + + public IEnumerable SemanticDomains + { + get { return Enumerable.Empty(); } + } + + public override bool Equals(object obj) + { + var other = obj as WfiGlossLexiconSense; + return other != null && m_gloss == other.m_gloss; + } + + public override int GetHashCode() + { + return m_gloss.GetHashCode(); + } + } + } + #endregion +} diff --git a/Src/FwParatextLexiconPlugin/FwLexiconPlugin.cs b/Src/FwParatextLexiconPlugin/FwLexiconPlugin.cs new file mode 100644 index 0000000000..401aa8dce3 --- /dev/null +++ b/Src/FwParatextLexiconPlugin/FwLexiconPlugin.cs @@ -0,0 +1,244 @@ +using System; +using System.Collections.ObjectModel; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using System.Threading; +using System.Windows.Forms; +using Paratext.LexicalContracts; +using SIL.CoreImpl; +using SIL.FieldWorks.FDO; +using SIL.Utils; + +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + /// + /// This is the main Paratext lexicon plugin class + /// + [LexiconPlugin(ID = "FieldWorks", DisplayName = "FieldWorks Language Explorer")] + public class FwLexiconPlugin : FwDisposableBase, LexiconPlugin + { + private const int CacheSize = 5; + private readonly FdoLexiconCollection m_lexiconCache; + private readonly FdoCacheCollection m_fdoCacheCache; + private readonly object m_syncRoot; + private ActivationContextHelper m_activationContext; + + /// + /// Initializes a new instance of the class. + /// + public FwLexiconPlugin() + { + m_syncRoot = new object(); + m_lexiconCache = new FdoLexiconCollection(); + m_fdoCacheCache = new FdoCacheCollection(); + m_activationContext = new ActivationContextHelper("FwParatextLexiconPlugin.dll.manifest"); + } + + /// + /// Validates the lexical project. + /// + /// The project identifier. + /// The language identifier. + /// + [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", + Justification = "FdoCache is diposed when the plugin is diposed.")] + public bool ValidateLexicalProject(string projectId, string langId) + { + using (m_activationContext.Activate()) + { + lock (m_syncRoot) + { + FdoCache fdoCache = GetFdoCache(projectId); + + if (fdoCache.ServiceLocator.WritingSystems.CurrentVernacularWritingSystems.Any(ws => ws.Id == langId)) + return true; + + DiscardFdoCache(fdoCache); + } + return false; + } + } + + /// + /// Chooses the lexical project. + /// + /// The project identifier. + /// + public bool ChooseLexicalProject(out string projectId) + { + using (m_activationContext.Activate()) + using (var dialog = new ChooseFdoProjectForm()) + { + if (dialog.ShowDialog() == DialogResult.OK) + { + projectId = dialog.SelectedProject; + return true; + } + + projectId = null; + return false; + } + } + + /// + /// Gets the lexicon. + /// + /// Name of the SCR text. + /// The project identifier. + /// The language identifier. + /// + [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", + Justification = "FdoLexicon is diposed when the plugin is diposed.")] + public Lexicon GetLexicon(string scrTextName, string projectId, string langId) + { + using (m_activationContext.Activate()) + return GetFdoLexicon(scrTextName, projectId, langId); + } + + /// + /// Gets the word analyses. + /// + /// Name of the SCR text. + /// The project identifier. + /// The language identifier. + /// + [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", + Justification = "FdoLexicon is diposed when the plugin is diposed.")] + public WordAnalyses GetWordAnalyses(string scrTextName, string projectId, string langId) + { + using (m_activationContext.Activate()) + return GetFdoLexicon(scrTextName, projectId, langId); + } + + private FdoLexicon GetFdoLexicon(string scrTextName, string projectId, string langId) + { + lock (m_syncRoot) + { + if (m_lexiconCache.Contains(scrTextName)) + { + FdoLexicon lexicon = m_lexiconCache[scrTextName]; + m_lexiconCache.Remove(scrTextName); + m_lexiconCache.Insert(0, lexicon); + return lexicon; + } + + FdoCache fdoCache = GetFdoCache(projectId); + + IWritingSystem writingSystem; + if (!fdoCache.ServiceLocator.WritingSystemManager.TryGet(langId, out writingSystem)) + throw new ArgumentException("Could not find a matching vernacular writing system.", "langId"); + + if (m_lexiconCache.Count == CacheSize) + { + FdoLexicon oldLexicon = m_lexiconCache[CacheSize - 1]; + m_lexiconCache.RemoveAt(CacheSize - 1); + + DiscardFdoCache(oldLexicon.Cache); + } + + var newLexicon = new FdoLexicon(scrTextName, fdoCache, writingSystem.Handle, m_activationContext); + m_lexiconCache.Insert(0, newLexicon); + return newLexicon; + } + } + + private FdoCache GetFdoCache(string projectId) + { + FdoCache fdoCache; + if (m_fdoCacheCache.Contains(projectId)) + { + fdoCache = m_fdoCacheCache[projectId]; + } + else + { + var backendProviderType = FDOBackendProviderType.kXML; + string path = Path.Combine(ParatextLexiconDirectoryFinder.ProjectsDirectory, projectId, projectId + FdoFileHelper.ksFwDataXmlFileExtension); + if (!File.Exists(path)) + { + backendProviderType = FDOBackendProviderType.kDb4oClientServer; + path = Path.Combine(ParatextLexiconDirectoryFinder.ProjectsDirectory, projectId, projectId + FdoFileHelper.ksFwDataDb4oFileExtension); + if (!File.Exists(path)) + throw new LexiconUnavailableException("The associated Fieldworks project has been moved, renamed, or does not exist."); + } + + var progress = new ParatextLexiconThreadedProgress(ParatextLexiconFdoUI.Instance.SynchronizeInvoke) { IsIndeterminate = true, Title = string.Format("Opening {0}", projectId) }; + fdoCache = (FdoCache) progress.RunTask(CreateFdoCache, new ParatextLexiconProjectIdentifier(backendProviderType, path)); + + m_fdoCacheCache.Add(fdoCache); + } + return fdoCache; + } + + private static FdoCache CreateFdoCache(IThreadedProgress progress, object[] parameters) + { + var projectId = (ParatextLexiconProjectIdentifier) parameters[0]; + try + { + return FdoCache.CreateCacheFromExistingData(projectId, Thread.CurrentThread.CurrentUICulture.Name, ParatextLexiconFdoUI.Instance, ParatextLexiconDirectoryFinder.FdoDirectories, progress, true); + } + catch (FdoDataMigrationForbiddenException) + { + throw new LexiconUnavailableException("The current version of Paratext is not compatible with the associated Fieldworks lexicon. Please open the lexicon using a compatible version of Fieldworks first."); + } + catch (FdoFileLockedException) + { + throw new LexiconUnavailableException("Fieldworks and Paratext cannot access the same project at the same time unless the Fieldworks project is shared."); + } + catch (StartupException se) + { + throw new LexiconUnavailableException(se.Message); + } + } + + private void DiscardFdoCache(FdoCache fdoCache) + { + if (m_lexiconCache.All(lexicon => lexicon.Cache != fdoCache)) + { + m_fdoCacheCache.Remove(fdoCache.ProjectId.Name); + fdoCache.Dispose(); + } + } + + /// + /// Override to dispose managed resources. + /// + protected override void DisposeManagedResources() + { + if (m_activationContext != null) + { + using (m_activationContext.Activate()) + { + lock (m_syncRoot) + { + foreach (FdoLexicon lexicon in m_lexiconCache) + lexicon.Dispose(); + m_lexiconCache.Clear(); + foreach (FdoCache fdoCache in m_fdoCacheCache) + fdoCache.Dispose(); + m_fdoCacheCache.Clear(); + } + } + + m_activationContext.Dispose(); + m_activationContext = null; + } + } + + private class FdoLexiconCollection : KeyedCollection + { + protected override string GetKeyForItem(FdoLexicon item) + { + return item.ScrTextName; + } + } + + private class FdoCacheCollection : KeyedCollection + { + protected override string GetKeyForItem(FdoCache item) + { + return item.ProjectId.Name; + } + } + } +} diff --git a/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj b/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj new file mode 100644 index 0000000000..362601923a --- /dev/null +++ b/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj @@ -0,0 +1,122 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {41FE243C-4D03-45E3-B556-CF361272B3BA} + Library + Properties + SIL.FieldWorks.ParatextLexiconPlugin + FwParatextLexiconPlugin + v4.0 + 512 + + + true + full + false + ..\..\Output\Debug\ + DEBUG;TRACE + prompt + 4 + x86 + true + ..\..\Output\Debug\FwParatextLexiconPlugin.xml + 67 + + + pdbonly + true + ..\..\Output\Release\ + TRACE + prompt + 4 + x86 + 67 + + + + ..\..\Output\Debug\BasicUtils.dll + + + ..\..\Output\Debug\COMInterfaces.dll + + + ..\..\Output\Debug\CoreImpl.dll + + + ..\..\Output\Debug\FDO.dll + + + ..\..\DistFiles\Microsoft.Practices.ServiceLocation.dll + + + ..\..\DistFiles\ParatextLexicalContracts.dll + + + ..\..\Output\Debug\ParserCore.dll + + + ..\..\Lib\debug\SIL.Machine.dll + + + ..\..\Output\Debug\SilUtils.dll + + + + + + + + + + + Properties\CommonAssemblyInfo.cs + + + Form + + + ChooseFdoProjectForm.cs + + + + + + + + + + + + + + + + Form + + + ProjectExistsForm.cs + + + + + + ChooseFdoProjectForm.cs + + + ProjectExistsForm.cs + + + + + + \ No newline at end of file diff --git a/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/DummyFdoUI.cs b/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/DummyFdoUI.cs new file mode 100644 index 0000000000..27268912a9 --- /dev/null +++ b/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/DummyFdoUI.cs @@ -0,0 +1,153 @@ +using System; +using System.ComponentModel; +using SIL.FieldWorks.FDO; + +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + internal class DummyFdoUI : IFdoUI + { + private readonly ISynchronizeInvoke m_synchronizeInvoke; + + public DummyFdoUI(ISynchronizeInvoke synchronizeInvoke) + { + m_synchronizeInvoke = synchronizeInvoke; + } + + /// + /// Gets the object that is used to invoke methods on the main UI thread. + /// + public ISynchronizeInvoke SynchronizeInvoke + { + get { return m_synchronizeInvoke; } + } + + /// + /// Gets the error message. + /// + /// + /// The error message. + /// + public string ErrorMessage { get; private set; } + + /// + /// Check with user regarding conflicting changes + /// + /// True if user wishes to revert to saved state. False otherwise. + public bool ConflictingSave() + { + throw new NotImplementedException(); + } + + /// + /// Inform the user of a lost connection + /// + /// True if user wishes to attempt reconnect. False otherwise. + public bool ConnectionLost() + { + throw new NotImplementedException(); + } + + /// + /// Gets the last time that there was user activity. + /// + public DateTime LastActivityTime + { + get { return DateTime.Now; } + } + + /// + /// Check with user regarding which files to use + /// + /// + public FileSelection ChooseFilesToUse() + { + throw new NotImplementedException(); + } + + /// + /// Check with user regarding restoring linked files in the project folder or original path + /// + /// True if user wishes to restore linked files in project folder. False to leave them in the original location. + public bool RestoreLinkedFilesInProjectFolder() + { + throw new NotImplementedException(); + } + + /// + /// Cannot restore linked files to original path. + /// Check with user regarding restoring linked files in the project folder or not at all + /// + /// OkYes to restore to project folder, OkNo to skip restoring linked files, Cancel otherwise + public YesNoCancel CannotRestoreLinkedFilesToOriginalLocation() + { + throw new NotImplementedException(); + } + + /// + /// Displays information to the user + /// + /// + /// + /// + /// + public void DisplayMessage(MessageType type, string message, string caption, string helpTopic) + { + throw new NotImplementedException(); + } + + /// + /// Show a dialog or output to the error log, as appropriate. + /// + /// the exception you want to report + /// set to true if the error is lethal, otherwise + /// false. + /// True if the error was lethal and the user chose to exit the application, + /// false otherwise. + public void ReportException(Exception error, bool isLethal) + { + // Store the message so we can check it later + ErrorMessage = error.Message; + } + + /// + /// Reports duplicate guids to the user + /// + /// The error text. + public void ReportDuplicateGuids(string errorText) + { + throw new NotImplementedException(); + } + + /// + /// Ask user if they wish to restore an XML project from a backup project file. + /// + /// The project path. + /// The backup path. + /// + /// + public bool OfferToRestore(string projectPath, string backupPath) + { + throw new NotImplementedException(); + } + + /// + /// Exits the application. + /// + /// + public void Exit() + { + throw new NotImplementedException(); + } + + /// + /// Present a message to the user and allow the options to Retry or Cancel + /// + /// The message. + /// The caption. + /// True to retry. False otherwise + public bool Retry(string msg, string caption) + { + throw new NotImplementedException(); + } + } +} diff --git a/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FdoLexiconTests.cs b/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FdoLexiconTests.cs new file mode 100644 index 0000000000..75bd1c9e7c --- /dev/null +++ b/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FdoLexiconTests.cs @@ -0,0 +1,539 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using NUnit.Framework; +using Paratext.LexicalContracts; +using SIL.FieldWorks.FDO; +using SIL.FieldWorks.FDO.Infrastructure; +using SIL.Utils; + +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + /// + /// FDO lexicon tests + /// + [TestFixture] + [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", + Justification="Fields are diposed in test teardown")] + public class FdoLexiconTests + { + private ThreadHelper m_threadHelper; + private FdoLexicon m_lexicon; + private FdoCache m_cache; + private ActivationContextHelper m_activationContext; + + /// + /// Set up the unit tests + /// + [SetUp] + public void SetUp() + { + m_activationContext = new ActivationContextHelper("FwParatextLexiconPlugin.dll.manifest"); + using (m_activationContext.Activate()) + { + m_threadHelper = new ThreadHelper(); + var ui = new DummyFdoUI(m_threadHelper); + var projectId = new ParatextLexiconProjectIdentifier(FDOBackendProviderType.kMemoryOnly, "Test.fwdata"); + m_cache = FdoCache.CreateCacheWithNewBlankLangProj(projectId, "en", "fr", "en", ui, ParatextLexiconDirectoryFinder.FdoDirectories); + NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, () => + { + m_cache.ServiceLocator.WritingSystems.AddToCurrentAnalysisWritingSystems(m_cache.ServiceLocator.WritingSystemManager.Get("fr")); + m_cache.LangProject.MorphologicalDataOA.ParserParameters = "1515010XAmple"; + }); + } + m_lexicon = new FdoLexicon("Test", m_cache, m_cache.DefaultVernWs, m_activationContext); + } + + /// + /// Cleans up the unit tests + /// + [TearDown] + public void TearDown() + { + m_lexicon.Dispose(); + m_cache.Dispose(); + m_activationContext.Dispose(); + m_threadHelper.Dispose(); + } + + #region Tests + /// + /// Test multiple lexeme creates where the IDs match + /// + [Test] + public void MultipleCreatesIdsMatch() + { + Lexeme lex = m_lexicon.CreateLexeme(LexemeType.Word, "a"); + Lexeme lex2 = m_lexicon.CreateLexeme(LexemeType.Word, "a"); + Assert.AreEqual(lex.Id, lex2.Id); + Assert.AreEqual(LexemeType.Word, lex.Type); + Assert.AreEqual("a", lex.LexicalForm); + Assert.AreEqual(LexemeType.Word, lex2.Type); + Assert.AreEqual("a", lex2.LexicalForm); + } + + /// + /// Test multiple lexeme creates that refer to the same sense + /// + [Test] + public void MultipleCreatesReferToSameSenses() + { + Lexeme lex = m_lexicon.CreateLexeme(LexemeType.Word, "a"); + Lexeme lex2 = m_lexicon.CreateLexeme(LexemeType.Word, "a"); + + m_lexicon.AddLexeme(lex); + LexiconSense sense = lex.AddSense(); + sense.AddGloss("en", "test"); + + Assert.AreEqual(1, lex2.Senses.Count()); + + // Make sure the one that was added has the right sense now + lex = m_lexicon[lex.Id]; + Assert.AreEqual(LexemeType.Word, lex.Type); + Assert.AreEqual("a", lex.LexicalForm); + Assert.AreEqual(1, lex.Senses.Count()); + Assert.AreEqual("en", lex.Senses.First().Glosses.First().Language); + Assert.AreEqual("test", lex.Senses.First().Glosses.First().Text); + } + + /// + /// Test that adding sense also adds lexeme + /// + [Test] + public void AddingSenseAddsLexeme() + { + Lexeme lex = m_lexicon.CreateLexeme(LexemeType.Word, "a"); + LexiconSense sense = lex.AddSense(); + sense.AddGloss("en", "test"); + + Assert.AreEqual(1, m_lexicon.Lexemes.Count()); + + lex = m_lexicon[lex.Id]; // Make sure we're using the one stored in the lexicon + Assert.AreEqual(LexemeType.Word, lex.Type); + Assert.AreEqual("a", lex.LexicalForm); + Assert.AreEqual(1, lex.Senses.Count()); + Assert.AreEqual("en", lex.Senses.First().Glosses.First().Language); + Assert.AreEqual("test", lex.Senses.First().Glosses.First().Text); + } + + /// + /// Test that homograph increments + /// + [Test] + public void HomographsIncrement() + { + Lexeme lex = m_lexicon.CreateLexeme(LexemeType.Stem, "a"); + Lexeme lex2 = m_lexicon.CreateLexeme(LexemeType.Stem, "a"); + + m_lexicon.AddLexeme(lex); + + Assert.AreEqual(lex.Id, lex2.Id); + + Lexeme lex3 = m_lexicon.CreateLexeme(LexemeType.Stem, "a"); + Assert.AreNotEqual(lex.Id, lex3.Id); + Assert.AreNotEqual(lex2.Id, lex3.Id); + } + + /// + /// + /// + [Test] + public void HomographsFind() + { + Lexeme lex = m_lexicon.CreateLexeme(LexemeType.Stem, "a"); + m_lexicon.AddLexeme(lex); + Lexeme lex2 = m_lexicon.CreateLexeme(LexemeType.Stem, "a"); + m_lexicon.AddLexeme(lex2); + Assert.AreNotEqual(lex.Id, lex2.Id); + + List found = new List(m_lexicon.Lexemes); + Assert.AreEqual(2, found.Count); + Assert.AreEqual(lex.Id, found[0].Id); + Assert.AreEqual(lex2.Id, found[1].Id); + } + + /// + /// Test find or create lexeme + /// + [Test] + public void FindOrCreate() + { + Lexeme lex = m_lexicon.CreateLexeme(LexemeType.Word, "a"); + LexiconSense sense = lex.AddSense(); + sense.AddGloss("en", "monkey"); + + Lexeme lex2 = m_lexicon.FindOrCreateLexeme(LexemeType.Word, "a"); + Assert.AreEqual(lex.Id, lex2.Id); + Assert.AreEqual(LexemeType.Word, lex2.Type); + Assert.AreEqual("a", lex2.LexicalForm); + Assert.AreEqual(1, lex2.Senses.Count()); + Assert.AreEqual(1, lex2.Senses.First().Glosses.Count()); + Assert.AreEqual("en", lex2.Senses.First().Glosses.First().Language); + Assert.AreEqual("monkey", lex2.Senses.First().Glosses.First().Text); + + Lexeme lex3 = m_lexicon.FindOrCreateLexeme(LexemeType.Suffix, "bob"); + Assert.AreNotEqual(lex.Id, lex3.Id); + Assert.AreNotEqual(lex2.Id, lex3.Id); + Assert.AreEqual(LexemeType.Suffix, lex3.Type); + Assert.AreEqual("bob", lex3.LexicalForm); + Assert.AreEqual(0, lex3.Senses.Count()); + } + + /// + /// Test indexer + /// + [Test] + public void Indexer() + { + Lexeme lex = m_lexicon.CreateLexeme(LexemeType.Stem, "a"); + m_lexicon.AddLexeme(lex); + + lex = m_lexicon[lex.Id]; + Assert.IsNotNull(lex); + Assert.AreEqual(LexemeType.Stem, lex.Type); + Assert.AreEqual("a", lex.LexicalForm); + + Lexeme lex2 = m_lexicon.CreateLexeme(LexemeType.Suffix, "monkey"); + Assert.IsNull(m_lexicon[lex2.Id]); + } + + /// + /// Test that creating a lexeme does not add it + /// + [Test] + public void CreatingDoesNotAdd() + { + m_lexicon.CreateLexeme(LexemeType.Word, "a"); + Assert.AreEqual(0, m_lexicon.Lexemes.Count()); + } + + /// + /// Test that getting a sense from a created lexeme does not add it + /// + [Test] + public void GettingSensesDoesNotAdd() + { + Lexeme lexeme = m_lexicon.CreateLexeme(LexemeType.Word, "a"); + lexeme.Senses.Count(); + Assert.AreEqual(0, m_lexicon.Lexemes.Count()); + } + + /// + /// + /// + [Test] + public void AddSucceeds() + { + Lexeme lex = m_lexicon.CreateLexeme(LexemeType.Word, "a"); + m_lexicon.AddLexeme(lex); + Assert.AreEqual(1, m_lexicon.Lexemes.Count()); + + lex = m_lexicon[lex.Id]; // Make sure we're using the one stored in the lexicon + Assert.AreEqual(LexemeType.Word, lex.Type); + Assert.AreEqual("a", lex.LexicalForm); + } + + /// + /// Test that adding the same lexeme multiple times fails + /// + [Test] + public virtual void MultipleAddsFail() + { + Lexeme lex = m_lexicon.CreateLexeme(LexemeType.Word, "a"); + Lexeme lex2 = m_lexicon.CreateLexeme(LexemeType.Word, "a"); + m_lexicon.AddLexeme(lex); + Assert.Throws(typeof (ArgumentException), () => m_lexicon.AddLexeme(lex2)); + } + + /// + /// + /// + [Test] + public void SensesRetained() + { + Lexeme lex = m_lexicon.CreateLexeme(LexemeType.Word, "a"); + m_lexicon.AddLexeme(lex); + LexiconSense sense = lex.AddSense(); + sense.AddGloss("en", "glossen"); + sense.AddGloss("fr", "glossfr"); + + Assert.AreEqual(1, lex.Senses.Count()); + Assert.AreEqual(2, lex.Senses.First().Glosses.Count()); + + sense = m_lexicon[lex.Id].Senses.First(); // Make sure we're working with the one stored in the lexicon + Assert.AreEqual("en", sense.Glosses.First().Language); + Assert.AreEqual("glossen", sense.Glosses.First().Text); + Assert.AreEqual("fr", sense.Glosses.ElementAt(1).Language); + Assert.AreEqual("glossfr", sense.Glosses.ElementAt(1).Text); + + sense.RemoveGloss("en"); + + sense = m_lexicon[lex.Id].Senses.First(); // Make sure we're working with the one stored in the lexicon + Assert.AreEqual(1, sense.Glosses.Count()); + Assert.AreEqual("fr", sense.Glosses.First().Language); + Assert.AreEqual("glossfr", sense.Glosses.First().Text); + } + + /// + /// + /// + [Test] + public void MorphTypeRetained() + { + Lexeme lex = m_lexicon.CreateLexeme(LexemeType.Word, "a"); + m_lexicon.AddLexeme(lex); + Lexeme lex2 = m_lexicon.CreateLexeme(LexemeType.Prefix, "a"); + m_lexicon.AddLexeme(lex2); + Lexeme lex3 = m_lexicon.CreateLexeme(LexemeType.Suffix, "a"); + m_lexicon.AddLexeme(lex3); + Lexeme lex4 = m_lexicon.CreateLexeme(LexemeType.Stem, "a"); + m_lexicon.AddLexeme(lex4); + + Assert.AreEqual(4, m_lexicon.Lexemes.Count()); + Assert.IsTrue(m_lexicon.Lexemes.Contains(lex)); + Assert.IsTrue(m_lexicon.Lexemes.Contains(lex2)); + Assert.IsTrue(m_lexicon.Lexemes.Contains(lex3)); + Assert.IsTrue(m_lexicon.Lexemes.Contains(lex4)); + } + + /// + /// Test removing lexemes + /// + [Test] + public void RemoveLexemeSucceeds() + { + Lexeme lex = m_lexicon.CreateLexeme(LexemeType.Word, "a"); + m_lexicon.AddLexeme(lex); + Lexeme lex2 = m_lexicon.CreateLexeme(LexemeType.Prefix, "a"); + + Assert.IsTrue(m_lexicon.Lexemes.Contains(lex)); + Assert.IsFalse(m_lexicon.Lexemes.Contains(lex2)); + + m_lexicon.RemoveLexeme(lex); + Assert.IsFalse(m_lexicon.Lexemes.Contains(lex)); + + m_lexicon.RemoveLexeme(lex2); + Assert.IsFalse(m_lexicon.Lexemes.Contains(lex2)); + + m_lexicon.AddLexeme(lex2); + Lexeme lex3 = m_lexicon.CreateLexeme(LexemeType.Prefix, "a"); + m_lexicon.AddLexeme(lex3); + + m_lexicon.RemoveLexeme(lex2); + Assert.IsFalse(m_lexicon.Lexemes.Contains(lex2)); + Assert.IsTrue(m_lexicon.Lexemes.Contains(lex3)); + } + + /// + /// Test removing senses + /// + [Test] + public void RemoveSenseSucceeds() + { + Lexeme lex = m_lexicon.CreateLexeme(LexemeType.Word, "a"); + m_lexicon.AddLexeme(lex); + + LexiconSense sense = lex.AddSense(); + sense.AddGloss("en", "gloss1"); + + LexiconSense sense2 = lex.AddSense(); + sense.AddGloss("en", "gloss1"); + + // Test remove at + lex.RemoveSense(sense2); + + Assert.AreEqual(1, lex.Senses.Count()); + Assert.AreEqual(sense, lex.Senses.First()); + } + + /// + /// Test unusual characters in the lexical form + /// + [Test] + public void UnusualCharactersSupported() + { + var stems = new[] { "a:b:c", "a:b:", "a:2", "123-4", "!@#$%^&*()" }; + + foreach (string stem in stems) + { + Lexeme lexeme = m_lexicon.FindOrCreateLexeme(LexemeType.Stem, stem); + Assert.IsFalse(m_lexicon.Lexemes.Contains(lexeme)); + m_lexicon.AddLexeme(lexeme); + Assert.IsTrue(m_lexicon.Lexemes.Contains(lexeme)); + + // Add homomorph + Lexeme lexeme2 = m_lexicon.CreateLexeme(LexemeType.Stem, stem); + Assert.IsFalse(m_lexicon.Lexemes.Contains(lexeme2)); + m_lexicon.AddLexeme(lexeme2); + Assert.IsTrue(m_lexicon.Lexemes.Contains(lexeme2)); + } + } + + /// + /// Tests that the lexicon correctly normalizes strings + /// + [Test] + public void NormalizeStrings() + { + Lexeme lex = m_lexicon.CreateLexeme(LexemeType.Stem, "Vacaci\u00f3n"); // Uses composed accented letter 'o' + m_lexicon.AddLexeme(lex); + + lex = m_lexicon[new LexemeKey(LexemeType.Stem, "Vacaci\u00f3n").Id]; + Assert.IsNotNull(lex); + Assert.AreEqual(LexemeType.Stem, lex.Type); + Assert.AreEqual("Vacaci\u00f3n", lex.LexicalForm); + + LexiconSense sense = lex.AddSense(); + Assert.IsNotNull(sense); + + LanguageText gloss = sense.AddGloss("en", "D\u00f3nde"); + + Lexeme reGetLex = m_lexicon[lex.Id]; + Assert.AreEqual(gloss.Text, reGetLex.Senses.First().Glosses.First().Text); + } + + #region Lexicon Events + + /// + /// Test lexeme added event + /// + [Test] + public void LexemeAddedEvent() + { + // Listen for events + int lexemeAddedCount = 0; + int senseAddedCount = 0; + int glossAddedCount = 0; + m_lexicon.LexemeAdded += (sender, e) => lexemeAddedCount++; + m_lexicon.LexiconSenseAdded += (sender, e) => senseAddedCount++; + m_lexicon.LexiconGlossAdded += (sender, e) => glossAddedCount++; + + Lexeme lexeme = m_lexicon.FindOrCreateLexeme(LexemeType.Word, "word"); + Assert.AreEqual(0, lexemeAddedCount); + + m_lexicon.AddLexeme(lexeme); + Assert.AreEqual(1, lexemeAddedCount); + Assert.AreEqual(0, senseAddedCount); + Assert.AreEqual(0, glossAddedCount); + + // Adding sense adds lexeme + Lexeme lexeme2 = m_lexicon.FindOrCreateLexeme(LexemeType.Word, "word2"); + lexeme2.AddSense(); + Assert.AreEqual(2, lexemeAddedCount); + } + + /// + /// Test sense added event + /// + [Test] + public void SenseAddedEvent() + { + // Listen for events + int lexemeAddedCount = 0; + int senseAddedCount = 0; + int glossAddedCount = 0; + m_lexicon.LexemeAdded += (sender, e) => lexemeAddedCount++; + m_lexicon.LexiconSenseAdded += (sender, e) => senseAddedCount++; + m_lexicon.LexiconGlossAdded += (sender, e) => glossAddedCount++; + + Lexeme lexeme = m_lexicon.FindOrCreateLexeme(LexemeType.Word, "word"); + m_lexicon.AddLexeme(lexeme); + lexeme.AddSense(); + Assert.AreEqual(1, senseAddedCount); + } + + /// + /// Test gloss added event + /// + [Test] + public void GlossAddedEvent() + { + // Listen for events + int lexemeAddedCount = 0; + int senseAddedCount = 0; + int glossAddedCount = 0; + string glossText = ""; + m_lexicon.LexemeAdded += (sender, e) => lexemeAddedCount++; + m_lexicon.LexiconSenseAdded += (sender, e) => senseAddedCount++; + m_lexicon.LexiconGlossAdded += (sender, e) => + { + glossAddedCount++; + glossText = e.Gloss.Text; + }; + + Lexeme lexeme = m_lexicon.FindOrCreateLexeme(LexemeType.Word, "word"); + m_lexicon.AddLexeme(lexeme); + LexiconSense sense = lexeme.AddSense(); + sense.AddGloss("en", "somegloss"); + + Assert.AreEqual(1, glossAddedCount); + Assert.AreEqual("somegloss", glossText); + } + + #endregion + + /// + /// Test find matching lexemes + /// + [Test] + public void FindMatchingLexemes() + { + Lexeme[] matchingLexemes = m_lexicon.FindMatchingLexemes("a").ToArray(); + Assert.That(matchingLexemes, Is.Empty); + + // Just the stem + Lexeme lexemeA = m_lexicon.CreateLexeme(LexemeType.Stem, "a"); + m_lexicon.AddLexeme(lexemeA); + matchingLexemes = m_lexicon.FindMatchingLexemes("a").ToArray(); + Assert.That(matchingLexemes[0].LexicalForm, Is.EqualTo("a")); + + // Other parts, too + Lexeme lexemePre = m_lexicon.CreateLexeme(LexemeType.Prefix, "pre"); + m_lexicon.AddLexeme(lexemePre); + Lexeme lexemeSuf = m_lexicon.CreateLexeme(LexemeType.Suffix, "suf"); + m_lexicon.AddLexeme(lexemeSuf); + m_lexicon.AddWordAnalysis("preasuf", new FdoWordAnalysis(new[] { lexemePre, lexemeA, lexemeSuf })); + matchingLexemes = m_lexicon.FindMatchingLexemes("preasuf").ToArray(); + Assert.That(matchingLexemes.Length, Is.EqualTo(3)); + Assert.IsTrue(matchingLexemes.Contains(lexemePre)); + Assert.IsTrue(matchingLexemes.Contains(lexemeA)); + Assert.IsTrue(matchingLexemes.Contains(lexemeSuf)); + } + + /// + /// Test find closest matching lexeme + /// + [Test] + public void FindClosestMatchingLexeme() + { + // Nothing found + Lexeme matchingLexeme = m_lexicon.FindClosestMatchingLexeme("a"); + Assert.IsNull(matchingLexeme); + + // Found by simple lexicon lookup + Lexeme lexeme = m_lexicon.CreateLexeme(LexemeType.Stem, "a"); + m_lexicon.AddLexeme(lexeme); + matchingLexeme = m_lexicon.FindClosestMatchingLexeme("a"); + Assert.IsTrue(matchingLexeme.LexicalForm == "a"); + + // Found by parser + lexeme = m_lexicon.CreateLexeme(LexemeType.Prefix, "pre"); + m_lexicon.AddLexeme(lexeme); + matchingLexeme = m_lexicon.FindClosestMatchingLexeme("prea"); + Assert.IsTrue(matchingLexeme.LexicalForm == "a"); + + // Found by unsupervised stemmer + m_lexicon.AddLexeme(m_lexicon.CreateLexeme(LexemeType.Stem, "b")); + m_lexicon.AddLexeme(m_lexicon.CreateLexeme(LexemeType.Stem, "c")); + m_lexicon.AddLexeme(m_lexicon.CreateLexeme(LexemeType.Stem, "d")); + m_lexicon.AddLexeme(m_lexicon.CreateLexeme(LexemeType.Stem, "bpos")); + m_lexicon.AddLexeme(m_lexicon.CreateLexeme(LexemeType.Stem, "cpos")); + m_lexicon.AddLexeme(m_lexicon.CreateLexeme(LexemeType.Stem, "dpos")); + matchingLexeme = m_lexicon.FindClosestMatchingLexeme("apos"); + Assert.IsTrue(matchingLexeme.LexicalForm == "a"); + } + + #endregion + } +} diff --git a/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FwParatextLexiconPluginTests.csproj b/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FwParatextLexiconPluginTests.csproj new file mode 100644 index 0000000000..6b349380ea --- /dev/null +++ b/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FwParatextLexiconPluginTests.csproj @@ -0,0 +1,79 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {04DB1DD6-082B-4453-8B83-0B40C019F149} + Library + Properties + SIL.FieldWorks.ParatextLexiconPlugin + FwParatextLexiconPluginTests + v4.0 + 512 + + + true + full + false + ..\..\..\Output\Debug\ + DEBUG;TRACE + prompt + 4 + x86 + ..\..\..\Output\Debug\FwParatextLexiconPluginTests.xml + true + + + pdbonly + true + ..\..\..\Output\Release\ + TRACE + prompt + 4 + x86 + + + + ..\..\..\Output\Debug\BasicUtils.dll + + + ..\..\..\Output\Debug\COMInterfaces.dll + + + ..\..\..\Output\Debug\CoreImpl.dll + + + ..\..\..\Output\Debug\FDO.dll + + + False + ..\..\..\Output\Debug\FwParatextLexiconPlugin.dll + + + ..\..\..\DistFiles\Microsoft.Practices.ServiceLocation.dll + + + ..\..\..\Bin\NUnit\bin\nunit.framework.dll + + + ..\..\..\DistFiles\ParatextLexicalContracts.dll + + + + + + + + + + + + \ No newline at end of file diff --git a/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/Properties/AssemblyInfo.cs b/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..e38add4f9b --- /dev/null +++ b/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/Properties/AssemblyInfo.cs @@ -0,0 +1,6 @@ +using System.Reflection; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("FwParatextLexiconPluginTests")] diff --git a/Src/FwParatextLexiconPlugin/LexemeKey.cs b/Src/FwParatextLexiconPlugin/LexemeKey.cs new file mode 100644 index 0000000000..4fc23754b2 --- /dev/null +++ b/Src/FwParatextLexiconPlugin/LexemeKey.cs @@ -0,0 +1,93 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.Text.RegularExpressions; +using Paratext.LexicalContracts; + +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + internal class LexemeKey + { + private static readonly Regex s_idRegex = new Regex("^(\\w+):(.*?)(:\\d+)?$", RegexOptions.Compiled); + + private readonly LexemeType m_type; + private readonly string m_lexicalForm; + private readonly int m_homograph; + + public LexemeKey(LexemeType type, string lexicalForm) : this(type, lexicalForm, 1) + { + } + + public LexemeKey(LexemeType type, string lexicalForm, int homograph) + { + Debug.Assert(lexicalForm.IsNormalized(), "Key lexical forms should always be in composed form"); + + m_type = type; + m_lexicalForm = lexicalForm; + m_homograph = homograph; + } + + public LexemeKey(string id) + { + Match match = s_idRegex.Match(id); + Debug.Assert(match.Groups[2].Value.IsNormalized(), "Key lexical forms should always be in composed form"); + m_type = (LexemeType)Enum.Parse(typeof(LexemeType), match.Groups[1].Value); + m_lexicalForm = match.Groups[2].Value; + m_homograph = match.Groups[3].Length > 0 ? Int32.Parse(match.Groups[3].Value.Substring(1), CultureInfo.InvariantCulture) : 1; + } + + /// + /// Unique string identifier of the lexeme string. Unique within this lexicon type. + /// + public string Id + { + get + { + if (m_homograph == 1) + return string.Format("{0}:{1}", Type, LexicalForm); + + return string.Format("{0}:{1}:{2}", Type, LexicalForm, m_homograph); + } + } + + public LexemeType Type + { + get { return m_type; } + } + + public string LexicalForm + { + get { return m_lexicalForm; } + } + + public int Homograph + { + get { return m_homograph; } + } + + public override bool Equals(object obj) + { + var other = obj as LexemeKey; + + return other != null + && m_type == other.m_type + && m_lexicalForm == other.m_lexicalForm + && m_homograph == other.m_homograph; + } + + public override int GetHashCode() + { + int code = 23; + code = code * 31 + m_type.GetHashCode(); + code = code * 31 + m_lexicalForm.GetHashCode(); + code = code * 31 + m_homograph.GetHashCode(); + return code; + } + + public override string ToString() + { + return Id; + } + } + +} diff --git a/Src/FwParatextLexiconPlugin/ParatextLexiconDirectoryFinder.cs b/Src/FwParatextLexiconPlugin/ParatextLexiconDirectoryFinder.cs new file mode 100644 index 0000000000..1b97cf2f99 --- /dev/null +++ b/Src/FwParatextLexiconPlugin/ParatextLexiconDirectoryFinder.cs @@ -0,0 +1,141 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using Microsoft.Win32; +using SIL.CoreImpl; +using SIL.FieldWorks.FDO; +using SIL.Utils; + +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + internal static class ParatextLexiconDirectoryFinder + { + private static readonly IFdoDirectories s_fdoDirs = new ParatextLexiconFdoDirectories(); + + static ParatextLexiconDirectoryFinder() + { + RegistryHelper.CompanyName = DirectoryFinder.CompanyName; + RegistryHelper.ProductName = ProductName; + } + + private const string ProjectsDir = "ProjectsDir"; + private const string ProductName = "FieldWorks"; + private const string RootDataDir = "RootDataDir"; + private const string RootCodeDir = "RootCodeDir"; + private const string Projects = "Projects"; + private const string Templates = "Templates"; + private const string FdoVersion = "8"; + + public static string ProjectsDirectory + { + get { return GetDirectory(ProjectsDir, Path.Combine(DataDirectory, Projects)); } + } + + public static string ProjectsDirectoryLocalMachine + { + get { return GetDirectoryLocalMachine(ProjectsDir, Path.Combine(DataDirectoryLocalMachine, Projects)); } + } + + public static string TemplateDirectory + { + get { return Path.Combine(CodeDirectory, Templates); } + } + + public static bool IsFieldWorksInstalled + { + get + { + using (RegistryKey machineKey = FieldWorksRegistryKeyLocalMachine) + { + return machineKey != null; + } + } + } + + public static IFdoDirectories FdoDirectories + { + get { return s_fdoDirs; } + } + + public static string DataDirectory + { + get { return GetDirectory(RootDataDir, DirectoryFinder.CommonAppDataFolder(ProductName)); } + } + + public static string DataDirectoryLocalMachine + { + get { return GetDirectoryLocalMachine(RootDataDir, DirectoryFinder.CommonAppDataFolder(ProductName)); } + } + + public static string CodeDirectory + { + get { return GetDirectory(RootCodeDir, DirectoryFinder.CommonAppDataFolder(ProductName)); } + } + + [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", + Justification = "Disposed in caller.")] + private static RegistryKey FieldWorksRegistryKey + { + get { return RegistryHelper.SettingsKey(FdoVersion); } + } + + [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", + Justification = "Disposed in caller.")] + private static RegistryKey FieldWorksRegistryKeyLocalMachine + { + get { return RegistryHelper.SettingsKeyLocalMachine(FdoVersion); } + } + + private static string GetDirectory(string registryValue, string defaultDir) + { + using (RegistryKey userKey = FieldWorksRegistryKey) + using (RegistryKey machineKey = FieldWorksRegistryKeyLocalMachine) + { + var registryKey = userKey; + if (userKey == null || userKey.GetValue(registryValue) == null) + { + registryKey = machineKey; + } + + return GetDirectory(registryKey, registryValue, defaultDir); + } + } + + private static string GetDirectory(RegistryKey registryKey, string registryValue, string defaultDir) + { + string rootDir = (registryKey == null) ? null : registryKey.GetValue(registryValue, null) as string; + + if (string.IsNullOrEmpty(rootDir) && !string.IsNullOrEmpty(defaultDir)) + rootDir = defaultDir; + if (string.IsNullOrEmpty(rootDir)) + { + throw new ApplicationException(); + } + // Hundreds of callers of this method are using Path.Combine with the results. + // Combine only works with a root directory if it is followed by \ (e.g., c:\) + // so we don't want to trim the \ in this situation. + string dir = rootDir.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + return dir.Length > 2 ? dir : dir + Path.DirectorySeparatorChar; + } + + private static string GetDirectoryLocalMachine(string registryValue, string defaultDir) + { + using (RegistryKey machineKey = FieldWorksRegistryKeyLocalMachine) + { + return GetDirectory(machineKey, registryValue, defaultDir); + } + } + + private class ParatextLexiconFdoDirectories : IFdoDirectories + { + public string ProjectsDirectory + { + get { return ParatextLexiconDirectoryFinder.ProjectsDirectory; } + } + public string TemplateDirectory + { + get { return ParatextLexiconDirectoryFinder.TemplateDirectory; } + } + } + } +} diff --git a/Src/FwParatextLexiconPlugin/ParatextLexiconFdoUI.cs b/Src/FwParatextLexiconPlugin/ParatextLexiconFdoUI.cs new file mode 100644 index 0000000000..808c736661 --- /dev/null +++ b/Src/FwParatextLexiconPlugin/ParatextLexiconFdoUI.cs @@ -0,0 +1,93 @@ +using System; +using System.ComponentModel; +using System.Windows.Forms; +using SIL.FieldWorks.FDO; + +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + internal class ParatextLexiconFdoUI : IFdoUI + { + // Singleton + private static readonly ParatextLexiconFdoUI s_instance = new ParatextLexiconFdoUI(); + private ParatextLexiconFdoUI(){} + public static ParatextLexiconFdoUI Instance + { + get { return s_instance; } + } + + public bool ConflictingSave() + { + throw new NotImplementedException(); + } + + /// + /// Inform the user of a lost connection + /// + /// True if user wishes to attempt reconnect. False otherwise. + public bool ConnectionLost() + { + return (bool)SynchronizeInvoke.Invoke(new Func(() => MessageBox.Show( + "There is a problem with the connection to the lexicon. Usually, this occurs when there is a problem with the FwRemoteDatabaseConnectorService. Would you like to attempt to reestablish the connection?", + "Lexicon Connection Lost", MessageBoxButtons.YesNo) == DialogResult.Yes), null); + } + + public FileSelection ChooseFilesToUse() + { + throw new NotImplementedException(); + } + + public bool RestoreLinkedFilesInProjectFolder() + { + throw new NotImplementedException(); + } + + public YesNoCancel CannotRestoreLinkedFilesToOriginalLocation() + { + throw new NotImplementedException(); + } + + public void DisplayMessage(MessageType type, string message, string caption, string helpTopic) + { + throw new NotImplementedException(); + } + + public void ReportException(Exception error, bool isLethal) + { + throw new NotImplementedException(); + } + + public void ReportDuplicateGuids(string errorText) + { + throw new NotImplementedException(); + } + + public bool Retry(string msg, string caption) + { + throw new NotImplementedException(); + } + + public bool OfferToRestore(string projectPath, string backupPath) + { + throw new NotImplementedException(); + } + + public void Exit() + { + System.Windows.Forms.Application.Exit(); + } + + public ISynchronizeInvoke SynchronizeInvoke + { + get + { + Form form = Form.ActiveForm; + if (form != null) + return form; + if (System.Windows.Forms.Application.OpenForms.Count > 0) + return System.Windows.Forms.Application.OpenForms[0]; + return null; + } + } + public DateTime LastActivityTime { get; private set; } + } +} diff --git a/Src/FwParatextLexiconPlugin/ParatextLexiconProjectIdentifier.cs b/Src/FwParatextLexiconPlugin/ParatextLexiconProjectIdentifier.cs new file mode 100644 index 0000000000..1cf832c91b --- /dev/null +++ b/Src/FwParatextLexiconPlugin/ParatextLexiconProjectIdentifier.cs @@ -0,0 +1,63 @@ +using System; +using SIL.FieldWorks.FDO; + +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + internal class ParatextLexiconProjectIdentifier : IProjectIdentifier + { + private readonly FDOBackendProviderType m_backendProviderType; + + public ParatextLexiconProjectIdentifier(FDOBackendProviderType backendProviderType, string projectPath) + { + m_backendProviderType = backendProviderType; + Path = projectPath; + } + + public bool IsLocal + { + get { return true; } + } + + public string Path { get; set; } + + public string ProjectFolder + { + get { return System.IO.Path.GetDirectoryName(Path); } + } + + public string SharedProjectFolder + { + get { return ProjectFolder; } + } + + public string ServerName + { + get { return null; } + } + + public string Handle + { + get { return Name; } + } + + public string PipeHandle + { + get { throw new NotImplementedException(); } + } + + public string Name + { + get { return System.IO.Path.GetFileNameWithoutExtension(Path); } + } + + public FDOBackendProviderType Type + { + get { return m_backendProviderType; } + } + + public string UiName + { + get { return Name; } + } + } +} diff --git a/Src/FwParatextLexiconPlugin/ParatextLexiconThreadedProgress.cs b/Src/FwParatextLexiconPlugin/ParatextLexiconThreadedProgress.cs new file mode 100644 index 0000000000..6d5548b47f --- /dev/null +++ b/Src/FwParatextLexiconPlugin/ParatextLexiconThreadedProgress.cs @@ -0,0 +1,89 @@ +using System; +using System.ComponentModel; +using SIL.Utils; + +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + internal class ParatextLexiconThreadedProgress : IThreadedProgress + { + private readonly ISynchronizeInvoke m_synchronizeInvoke; + + public ParatextLexiconThreadedProgress(ISynchronizeInvoke synchronizeInvoke) + { + m_synchronizeInvoke = synchronizeInvoke; + } + + public void Step(int amount) + { + Position += amount * StepSize; + //Progress.Mgr.Incr(amount * StepSize); + } + + public string Title { get; set; } + + public string Message + { + //get { return Progress.Mgr.Text; } + //set { Progress.Mgr.Text = value; } + get; set; + } + + public int Position + { + //get { return Progress.Mgr.Value; } + //set { Progress.Mgr.Value = value; } + get; set; + } + + public int StepSize { get; set; } + + public int Minimum { get; set; } + + public int Maximum { get; set; } + + public ISynchronizeInvoke SynchronizeInvoke + { + get { return m_synchronizeInvoke; } + } + + public bool IsIndeterminate { get; set; } + + public bool AllowCancel { get; set; } + + public event CancelEventHandler Canceling; + + public object RunTask(Func backgroundTask, params object[] parameters) + { + return RunTask(true, backgroundTask, parameters); + } + + public object RunTask(bool fDisplayUi, Func backgroundTask, params object[] parameters) + { + object result = backgroundTask(this, parameters); + //if (Progress.Mgr.InProgress) + //{ + // result = backgroundTask(this, parameters); + //} + //else + //{ + // ProgressUtils.Execute(Title, AllowCancel ? CancelModes.Cancelable : CancelModes.NonCancelable, () => + // { + // if (!IsIndeterminate) + // Progress.Mgr.Begin(Minimum, Maximum); + + // result = backgroundTask(this, parameters); + + // if (!IsIndeterminate) + // Progress.Mgr.End(); + // }); + //} + return result; + } + + public bool Canceled + { + //get { return Progress.Mgr.Cancelled; } + get; set; + } + } +} diff --git a/Src/FwParatextLexiconPlugin/ProjectExistsForm.Designer.cs b/Src/FwParatextLexiconPlugin/ProjectExistsForm.Designer.cs new file mode 100644 index 0000000000..af58e5ad42 --- /dev/null +++ b/Src/FwParatextLexiconPlugin/ProjectExistsForm.Designer.cs @@ -0,0 +1,87 @@ +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + partial class ProjectExistsForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + System.Diagnostics.Debug.WriteLineIf(!disposing, "****** Missing Dispose() call for " + GetType() + ". ****** "); + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.btnOverwrite = new System.Windows.Forms.Button(); + this.btnRename = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // btnOverwrite + // + this.btnOverwrite.Location = new System.Drawing.Point(189, 85); + this.btnOverwrite.Name = "btnOverwrite"; + this.btnOverwrite.Size = new System.Drawing.Size(75, 23); + this.btnOverwrite.TabIndex = 0; + this.btnOverwrite.Text = "Overwrite"; + this.btnOverwrite.UseVisualStyleBackColor = true; + this.btnOverwrite.Click += new System.EventHandler(this.btnOverwrite_Click); + // + // btnRename + // + this.btnRename.Location = new System.Drawing.Point(271, 84); + this.btnRename.Name = "btnRename"; + this.btnRename.Size = new System.Drawing.Size(75, 23); + this.btnRename.TabIndex = 1; + this.btnRename.Text = "Rename"; + this.btnRename.UseVisualStyleBackColor = true; + this.btnRename.Click += new System.EventHandler(this.btnRename_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(13, 13); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(50, 13); + this.label1.TabIndex = 2; + this.label1.Text = "labelText"; + // + // ProjectExistsForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(360, 121); + this.Controls.Add(this.label1); + this.Controls.Add(this.btnRename); + this.Controls.Add(this.btnOverwrite); + this.Name = "ProjectExistsForm"; + this.Text = "Project Already Exists"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button btnOverwrite; + private System.Windows.Forms.Button btnRename; + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/Src/FwParatextLexiconPlugin/ProjectExistsForm.cs b/Src/FwParatextLexiconPlugin/ProjectExistsForm.cs new file mode 100644 index 0000000000..d0c87ea5bd --- /dev/null +++ b/Src/FwParatextLexiconPlugin/ProjectExistsForm.cs @@ -0,0 +1,35 @@ +using System; +using System.Windows.Forms; + +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + internal partial class ProjectExistsForm : Form + { + private const string labelText1 = "The {0} project already exists."; + private const string labelText2 = "You may overwrite the existing project or select a different name."; + + private ProjectExistsForm() + { + InitializeComponent(); + + Icon = System.Drawing.SystemIcons.Warning; + } + + public ProjectExistsForm(string projectName) : this() + { + label1.Text = string.Format(labelText1, projectName) + Environment.NewLine + labelText2; + DialogResult = DialogResult.Cancel; + } + + private void btnOverwrite_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.OK; + Close(); + } + + private void btnRename_Click(object sender, EventArgs e) + { + Close(); + } + } +} diff --git a/Src/FwParatextLexiconPlugin/ProjectExistsForm.resx b/Src/FwParatextLexiconPlugin/ProjectExistsForm.resx new file mode 100644 index 0000000000..1af7de150c --- /dev/null +++ b/Src/FwParatextLexiconPlugin/ProjectExistsForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Src/FwParatextLexiconPlugin/Properties/AssemblyInfo.cs b/Src/FwParatextLexiconPlugin/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..78ff41fa5a --- /dev/null +++ b/Src/FwParatextLexiconPlugin/Properties/AssemblyInfo.cs @@ -0,0 +1,19 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("FwParatextLexiconPlugin")] +[assembly: AssemblyDescription("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a787fc88-0ff6-4982-9305-8da92ef8fc7f")] + +[assembly: InternalsVisibleTo("FwParatextLexiconPluginTests")] diff --git a/Src/FwParatextLexiconPlugin/gendarme-FwParatextLexiconPlugin.ignore b/Src/FwParatextLexiconPlugin/gendarme-FwParatextLexiconPlugin.ignore new file mode 100644 index 0000000000..7d65c093e9 --- /dev/null +++ b/Src/FwParatextLexiconPlugin/gendarme-FwParatextLexiconPlugin.ignore @@ -0,0 +1,7 @@ +# Gendarme filter file to suppress reporting of defects + +#----------------------------------------------------------------------------------------------- +R: Gendarme.Rules.Correctness.EnsureLocalDisposalRule + +# Don't need to dipose IEnumerator +M: System.Collections.IEnumerator SIL.FieldWorks.ParatextLexiconPlugin.FdoLexicon/d__25::System.Collections.IEnumerable.GetEnumerator() diff --git a/Src/LexText/ParserCore/HCParser.cs b/Src/LexText/ParserCore/HCParser.cs index e64abd1b29..ab5dc01d63 100644 --- a/Src/LexText/ParserCore/HCParser.cs +++ b/Src/LexText/ParserCore/HCParser.cs @@ -52,7 +52,7 @@ public HCParser(FdoCache cache, string dataDir) m_outputDirectory = Path.GetTempPath(); m_projectName = ParserHelper.ConvertNameToUseAnsiCharacters(cache.ProjectId.Name); - m_transformer = new M3ToHCTransformer(m_projectName, dataDir); + m_transformer = new M3ToHCTransformer(m_projectName); } #region IParser implementation diff --git a/Src/LexText/ParserCore/IParser.cs b/Src/LexText/ParserCore/IParser.cs index f19ebf0c6d..c96a3774d5 100644 --- a/Src/LexText/ParserCore/IParser.cs +++ b/Src/LexText/ParserCore/IParser.cs @@ -1,8 +1,9 @@ -using System.Xml.Linq; +using System; +using System.Xml.Linq; namespace SIL.FieldWorks.WordWorks.Parser { - public interface IParser + public interface IParser : IDisposable { // Warning: This method is not thread-safe. // The parser could end up using stale data. diff --git a/Src/LexText/ParserCore/M3ToHCTransformer.cs b/Src/LexText/ParserCore/M3ToHCTransformer.cs index b660259b47..9236ca1016 100644 --- a/Src/LexText/ParserCore/M3ToHCTransformer.cs +++ b/Src/LexText/ParserCore/M3ToHCTransformer.cs @@ -27,8 +27,7 @@ internal class M3ToHCTransformer : M3ToParserTransformerBase /// Initializes a new instance of the class. ///

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

/// ----------------------------------------------------------------------------------- - public M3ToHCTransformer(string database, string dataDir) - : base(dataDir) + public M3ToHCTransformer(string database) { m_database = database; } diff --git a/Src/LexText/ParserCore/M3ToParserTransformerBase.cs b/Src/LexText/ParserCore/M3ToParserTransformerBase.cs index e269a96607..d21847c0ec 100644 --- a/Src/LexText/ParserCore/M3ToParserTransformerBase.cs +++ b/Src/LexText/ParserCore/M3ToParserTransformerBase.cs @@ -8,21 +8,9 @@ namespace SIL.FieldWorks.WordWorks.Parser ///
internal abstract class M3ToParserTransformerBase { - private readonly string m_dataDir; - private XslCompiledTransform m_grammarTransform; private XslCompiledTransform m_grammarDebuggingTransform; - /// ----------------------------------------------------------------------------------- - /// - /// Initializes a new instance of the class. - /// - /// ----------------------------------------------------------------------------------- - protected M3ToParserTransformerBase(string dataDir) - { - m_dataDir = dataDir; - } - protected XslCompiledTransform GrammarTransform { get diff --git a/Src/LexText/ParserCore/M3ToXAmpleTransformer.cs b/Src/LexText/ParserCore/M3ToXAmpleTransformer.cs index 4f45a63c5b..43136ddfcc 100644 --- a/Src/LexText/ParserCore/M3ToXAmpleTransformer.cs +++ b/Src/LexText/ParserCore/M3ToXAmpleTransformer.cs @@ -33,8 +33,7 @@ internal class M3ToXAmpleTransformer : M3ToParserTransformerBase /// Initializes a new instance of the class. ///
/// ----------------------------------------------------------------------------------- - public M3ToXAmpleTransformer(string dataDir, string database) - : base(dataDir) + public M3ToXAmpleTransformer(string database) { m_database = database; } diff --git a/Src/LexText/ParserCore/ParserWorker.cs b/Src/LexText/ParserCore/ParserWorker.cs index 48bc3b8b80..bdf0ad76cf 100644 --- a/Src/LexText/ParserCore/ParserWorker.cs +++ b/Src/LexText/ParserCore/ParserWorker.cs @@ -75,10 +75,9 @@ public ParserWorker(FdoCache cache, Action taskUpdateHandler, IdleQu protected override void DisposeManagedResources() { - var disposeParser = m_parser as IDisposable; - if (disposeParser != null) + if (m_parser != null) { - disposeParser.Dispose(); + m_parser.Dispose(); m_parser = null; } } diff --git a/Src/LexText/ParserCore/XAmpleParser.cs b/Src/LexText/ParserCore/XAmpleParser.cs index e9ff45e9f0..f8ccad37c8 100644 --- a/Src/LexText/ParserCore/XAmpleParser.cs +++ b/Src/LexText/ParserCore/XAmpleParser.cs @@ -33,7 +33,7 @@ public XAmpleParser(FdoCache cache, string dataDir) m_dataDir = dataDir; m_retriever = new M3ParserModelRetriever(m_cache); m_database = ParserHelper.ConvertNameToUseAnsiCharacters(m_cache.ProjectId.Name); - m_transformer = new M3ToXAmpleTransformer(dataDir, m_database); + m_transformer = new M3ToXAmpleTransformer(m_database); } public bool IsUpToDate() diff --git a/Src/Utilities/BasicUtils/ActivationContextHelper.cs b/Src/Utilities/BasicUtils/ActivationContextHelper.cs new file mode 100644 index 0000000000..5643f953d6 --- /dev/null +++ b/Src/Utilities/BasicUtils/ActivationContextHelper.cs @@ -0,0 +1,122 @@ +using System; +using System.ComponentModel; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Security; + +namespace SIL.Utils +{ + /// + /// Used to create an activation context + /// + [SuppressUnmanagedCodeSecurity] + public class ActivationContextHelper : FwDisposableBase + { +#if !__MonoCS__ + #region Unmanaged structs and methods + [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] + private struct ActCtx + { + public int cbSize; + public uint dwFlags; + public string lpSource; + public ushort wProcessorArchitecture; + public short wLangId; + public string lpAssemblyDirectory; + public string lpResourceName; + public string lpApplicationName; + public IntPtr hModule; + } + + [DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "CreateActCtxW")] + private static extern IntPtr CreateActCtx(ref ActCtx actCtx); + + [DllImport("Kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool ActivateActCtx(IntPtr hActCtx, out IntPtr lpCookie); + + [DllImport("Kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool DeactivateActCtx(int dwFlags, IntPtr lpCookie); + + [DllImport("Kernel32.dll", SetLastError = true)] + private static extern void ReleaseActCtx(IntPtr hActCtx); + #endregion // Unmanaged structs and methods + + private IntPtr m_activationContext; +#endif + + /// + /// Initializes a new instance of the class. + /// + /// The manifest file. + public ActivationContextHelper(string manifestFile) + { +#if !__MonoCS__ + // Specifying a full path to the manifest file like this allows our unit tests to work even with a + // test runner like Resharper 8 which does not set the current directory to the one containing the DLLs. + // Note that we have to use CodeBase here because NUnit runs the tests from a shadow copy directory + // that doesn't contain the manifest file. + var uri = new Uri(Assembly.GetExecutingAssembly().CodeBase); + string location = Path.GetDirectoryName(uri.AbsolutePath); + var context = new ActCtx + { + cbSize = Marshal.SizeOf(typeof(ActCtx)), + lpSource = Path.Combine(location, manifestFile) + }; + + IntPtr handle = CreateActCtx(ref context); + if (handle == (IntPtr)(-1)) + throw new Win32Exception(Marshal.GetLastWin32Error(), "Error creating activation context"); + m_activationContext = handle; +#endif + } + + /// + /// Override to dispose unmanaged resources. + /// + protected override void DisposeUnmanagedResources() + { +#if !__MonoCS__ + // dispose managed and unmanaged objects + if (m_activationContext != IntPtr.Zero) + ReleaseActCtx(m_activationContext); + m_activationContext = IntPtr.Zero; +#endif + } + + /// + /// Activates this instance. + /// + /// Error activating context + public IDisposable Activate() + { + IntPtr cookie; +#if !__MonoCS__ + if (!ActivateActCtx(m_activationContext, out cookie)) + throw new Win32Exception(Marshal.GetLastWin32Error(), "Error activating context"); +#endif + return new Activation(cookie); + } + + private class Activation : FwDisposableBase + { + private IntPtr m_cookie; + + public Activation(IntPtr cookie) + { + m_cookie = cookie; + } + + protected override void DisposeUnmanagedResources() + { +#if !__MonoCS__ + if (m_cookie != IntPtr.Zero) + DeactivateActCtx(0, m_cookie); + m_cookie = IntPtr.Zero; +#endif + } + } + } +} diff --git a/Src/Utilities/BasicUtils/BasicUtils.csproj b/Src/Utilities/BasicUtils/BasicUtils.csproj index 01571e48ac..fcd02bb0df 100644 --- a/Src/Utilities/BasicUtils/BasicUtils.csproj +++ b/Src/Utilities/BasicUtils/BasicUtils.csproj @@ -84,10 +84,10 @@ Properties\CommonAssemblyInfo.cs + - diff --git a/Src/Utilities/BasicUtils/BasicUtilsTests/Attributes/CreateComObjectsFromManifestAttribute.cs b/Src/Utilities/BasicUtils/BasicUtilsTests/Attributes/CreateComObjectsFromManifestAttribute.cs index 34416f2604..e78a6cbdd7 100644 --- a/Src/Utilities/BasicUtils/BasicUtilsTests/Attributes/CreateComObjectsFromManifestAttribute.cs +++ b/Src/Utilities/BasicUtils/BasicUtilsTests/Attributes/CreateComObjectsFromManifestAttribute.cs @@ -3,6 +3,7 @@ // (http://www.gnu.org/licenses/lgpl-2.1.html) using System; +using System.Diagnostics.CodeAnalysis; using System.Security; using NUnit.Framework; @@ -16,8 +17,15 @@ namespace SIL.Utils.Attributes [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Interface)] [SuppressUnmanagedCodeSecurity] + [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", + Justification="m_activationContext and m_currentActivation are disposed in AfterTest method")] public class CreateComObjectsFromManifestAttribute : TestActionAttribute { +#if !__MonoCS__ + private ActivationContextHelper m_activationContext; + private IDisposable m_currentActivation; +#endif + /// public override ActionTargets Targets { @@ -30,7 +38,8 @@ public override void BeforeTest(TestDetails testDetails) base.BeforeTest(testDetails); #if !__MonoCS__ - ManifestHelper.CreateActivationContext("FieldWorks.Tests.manifest"); + m_activationContext = new ActivationContextHelper("FieldWorks.Tests.manifest"); + m_currentActivation = m_activationContext.Activate(); #endif } @@ -38,7 +47,8 @@ public override void BeforeTest(TestDetails testDetails) public override void AfterTest(TestDetails testDetails) { #if !__MonoCS__ - ManifestHelper.DestroyActivationContext(); + m_currentActivation.Dispose(); + m_activationContext.Dispose(); #endif base.AfterTest(testDetails); diff --git a/Src/Utilities/BasicUtils/ManifestHelper.cs b/Src/Utilities/BasicUtils/ManifestHelper.cs deleted file mode 100644 index 4371c78118..0000000000 --- a/Src/Utilities/BasicUtils/ManifestHelper.cs +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) 2012-2013 SIL International -// This software is licensed under the LGPL, version 2.1 or later -// (http://www.gnu.org/licenses/lgpl-2.1.html) - -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.IO; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Security; - -namespace SIL.Utils -{ - /// ---------------------------------------------------------------------------------------- - /// - /// Allows to create COM objects from a manifest file when running unit tests. - /// - /// Registration-free activation of native COM components reads the information - /// about what COM objects implement which interface etc from a manifest file. This manifest - /// file is usually embedded as a resource in the executable (as we do with the unmanaged - /// tests). However, when running unit tests with NUnit this doesn't work since we can't - /// modify the NUnit executable for each test assembly. Therefore we have to make use - /// of activation contexts which tells the OS which manifest file to use. Note that - /// activation contexts are thread specific. - /// - /// - /// ---------------------------------------------------------------------------------------- - public static class ManifestHelper - { -#if !__MonoCS__ - [SuppressUnmanagedCodeSecurity] - private sealed class ManifestHelperImpl: IDisposable - { - #region Unmanaged structs and methods - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] - private struct ActCtx - { - public int cbSize; - public uint dwFlags; - public string lpSource; - public ushort wProcessorArchitecture; - public short wLangId; - public string lpAssemblyDirectory; - public string lpResourceName; - public string lpApplicationName; - public IntPtr hModule; - } - - [DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "CreateActCtxW")] - private static extern IntPtr CreateActCtx(ref ActCtx actCtx); - - [DllImport("Kernel32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool ActivateActCtx(IntPtr hActCtx, out IntPtr lpCookie); - - [DllImport("Kernel32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DeactivateActCtx(int dwFlags, IntPtr lpCookie); - - [DllImport("Kernel32.dll", SetLastError = true)] - private static extern void ReleaseActCtx(IntPtr hActCtx); - #endregion // Unmanaged structs and methods - - [ThreadStatic] - private static IntPtr m_ActivationContext; - [ThreadStatic] - private static IntPtr m_Cookie; - [ThreadStatic] - private static int m_Count; - - #region Disposable stuff -#if DEBUG - /// - ~ManifestHelperImpl() - { - Dispose(false); - } -#endif - - /// - public bool IsDisposed { get; private set; } - - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - private void Dispose(bool fDisposing) - { - Debug.WriteLineIf(!fDisposing, "****** Missing Dispose() call for " + GetType() + ". *******"); - if (fDisposing && !IsDisposed) - { - // dispose managed and unmanaged objects - m_Count = 0; - DestroyActivationContext(); - } - IsDisposed = true; - } - #endregion - - /// - /// Creates and activates an activation context on the current thread - /// - public void CreateContext(string manifestFile) - { - if (m_Cookie == IntPtr.Zero) - { - if (m_ActivationContext == IntPtr.Zero) - { - // Specifying a full path to the manifest file like this allows our unit tests to work even with a - // test runner like Resharper 8 which does not set the current directory to the one containing the DLLs. - // Note that we have to use CodeBase here because NUnit runs the tests from a shadow copy directory - // that doesn't contain the manifest file. - var uri = new Uri(Assembly.GetExecutingAssembly().CodeBase); - string location = Path.GetDirectoryName(uri.AbsolutePath); - var context = new ActCtx - { - cbSize = Marshal.SizeOf(typeof(ActCtx)), - lpSource = Path.Combine(location, manifestFile) - }; - - IntPtr handle = CreateActCtx(ref context); - if (handle == (IntPtr)(-1)) - throw new Win32Exception(Marshal.GetLastWin32Error(), "Error creating activation context"); - m_ActivationContext = handle; - } - if (!ActivateActCtx(m_ActivationContext, out m_Cookie)) - throw new Win32Exception(Marshal.GetLastWin32Error(), "Error activating context"); - } - m_Count++; - } - - /// - /// Releases the current activation context - /// - public void DestroyContext() - { - m_Count--; - if (m_Count <= 0) - { - if (m_Cookie != IntPtr.Zero) - DeactivateActCtx(0, m_Cookie); - m_Cookie = IntPtr.Zero; - - if (m_ActivationContext != IntPtr.Zero) - ReleaseActCtx(m_ActivationContext); - m_ActivationContext = IntPtr.Zero; - } - } - } -#endif - - /// - /// Creates and activates an activation context on the current thread - /// - public static void CreateActivationContext(string manifestFile) - { -#if !__MonoCS__ - SingletonsContainer.Get().CreateContext(manifestFile); -#endif - } - - /// - /// Releases the current activation context - /// - public static void DestroyActivationContext() - { -#if !__MonoCS__ - SingletonsContainer.Get().DestroyContext(); -#endif - } - } -} From 811ad9350f6344049c3314f97f73882a5ab06260 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Mon, 24 Mar 2014 09:45:09 +0700 Subject: [PATCH 097/143] fixed build issues Change-Id: I493b80261f81dad336c91d03f99b0b45a5ca13e9 --- Src/FwParatextLexiconPlugin/FdoLexicon.cs | 2 +- Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj | 4 ++-- .../ParatextLexiconDirectoryFinder.cs | 7 ++++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Src/FwParatextLexiconPlugin/FdoLexicon.cs b/Src/FwParatextLexiconPlugin/FdoLexicon.cs index 91eb29c1f6..5ec9ad4978 100644 --- a/Src/FwParatextLexiconPlugin/FdoLexicon.cs +++ b/Src/FwParatextLexiconPlugin/FdoLexicon.cs @@ -490,7 +490,7 @@ private ILexEntry GetMatchingEntryFromParser(string wordForm) private void InstantiateParser() { - string parserDataDir = Path.Combine(ParatextLexiconDirectoryFinder.DataDirectory, "Language Explorer"); + string parserDataDir = Path.Combine(ParatextLexiconDirectoryFinder.CodeDirectory, "Language Explorer"); switch (m_cache.LanguageProject.MorphologicalDataOA.ActiveParser) { case "XAmple": diff --git a/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj b/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj index 362601923a..6ca8db8105 100644 --- a/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj +++ b/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj @@ -78,7 +78,7 @@ Form - + ChooseFdoProjectForm.cs @@ -97,7 +97,7 @@ Form - + ProjectExistsForm.cs diff --git a/Src/FwParatextLexiconPlugin/ParatextLexiconDirectoryFinder.cs b/Src/FwParatextLexiconPlugin/ParatextLexiconDirectoryFinder.cs index 1b97cf2f99..a8bbadfa0e 100644 --- a/Src/FwParatextLexiconPlugin/ParatextLexiconDirectoryFinder.cs +++ b/Src/FwParatextLexiconPlugin/ParatextLexiconDirectoryFinder.cs @@ -69,7 +69,12 @@ public static string DataDirectoryLocalMachine public static string CodeDirectory { - get { return GetDirectory(RootCodeDir, DirectoryFinder.CommonAppDataFolder(ProductName)); } + get + { + string defaultDir = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), DirectoryFinder.CompanyName), + string.Format("FieldWorks {0}", FdoVersion)); + return GetDirectory(RootCodeDir, defaultDir); + } } [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", From 67a6072b4a45cece6ff589754a46803e9b74ba5b Mon Sep 17 00:00:00 2001 From: Andrew Polk Date: Mon, 24 Mar 2014 11:32:01 +0700 Subject: [PATCH 098/143] Initialize FwLexiconPlugin to allow DB4O Change-Id: I15609ce6d19a8633701c4fdf441840d4eb0519ad --- Src/FwParatextLexiconPlugin/FwLexiconPlugin.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Src/FwParatextLexiconPlugin/FwLexiconPlugin.cs b/Src/FwParatextLexiconPlugin/FwLexiconPlugin.cs index 401aa8dce3..97bb6a5209 100644 --- a/Src/FwParatextLexiconPlugin/FwLexiconPlugin.cs +++ b/Src/FwParatextLexiconPlugin/FwLexiconPlugin.cs @@ -8,6 +8,7 @@ using Paratext.LexicalContracts; using SIL.CoreImpl; using SIL.FieldWorks.FDO; +using SIL.FieldWorks.FDO.DomainServices; using SIL.Utils; namespace SIL.FieldWorks.ParatextLexiconPlugin @@ -33,6 +34,12 @@ public FwLexiconPlugin() m_lexiconCache = new FdoLexiconCollection(); m_fdoCacheCache = new FdoCacheCollection(); m_activationContext = new ActivationContextHelper("FwParatextLexiconPlugin.dll.manifest"); + + // initialize client-server services to use Db4O backend for FDO + var ui = ParatextLexiconFdoUI.Instance; + var dirs = ParatextLexiconDirectoryFinder.FdoDirectories; + ClientServerServices.SetCurrentToDb4OBackend(ui, dirs, + () => dirs.ProjectsDirectory == ParatextLexiconDirectoryFinder.ProjectsDirectoryLocalMachine); } /// From 75f0a20656899420403ca938f46aaaa349dacc00 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Mon, 24 Mar 2014 17:11:52 +0700 Subject: [PATCH 099/143] fixed build on Linux Change-Id: If4a0bdaf4eab7ede01527c463ffe5331df754733 --- Src/FwParatextLexiconPlugin/BuildInclude.targets | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Src/FwParatextLexiconPlugin/BuildInclude.targets b/Src/FwParatextLexiconPlugin/BuildInclude.targets index c2a14a9583..9a053ab3f8 100644 --- a/Src/FwParatextLexiconPlugin/BuildInclude.targets +++ b/Src/FwParatextLexiconPlugin/BuildInclude.targets @@ -1,7 +1,7 @@  - - + + From 41b31de859c18c7bf12344ef79c3c642c707c7ae Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Mon, 21 Apr 2014 11:32:54 +0700 Subject: [PATCH 100/143] removed ParatextShared.dll dependency from FDO Change-Id: If582857d0aaa0a84bd48f5dce90b67f1bf7b94f1 --- .../Controls/FwControls/FwControls.csproj | 11 +- .../FwControls/TextsTriStateTreeView.cs | 2 +- Src/Common/FwUtils/FwUtils.csproj | 4 - .../ScriptureUtils}/ParatextHelper.cs | 57 +- .../ScriptureUtils/ScriptureUtils.csproj | 360 +++++---- .../ParatextHelperTests.cs | 45 +- .../ScriptureUtilsTests.csproj | 54 +- Src/FDO/DomainImpl/ScrImportSet.cs | 196 +---- Src/FDO/DomainServices/IScrImportFileInfo.cs | 15 +- Src/FDO/DomainServices/ScrImportFileInfo.cs | 2 +- Src/FDO/FDO.csproj | 8 - Src/FDO/FDOTests/FDOTests.csproj | 1 - Src/FDO/FDOTests/ScrImportSetTests.cs | 228 ------ Src/FDO/FdoInterfaceAdditions.cs | 37 - Src/FwCoreDlgs/FwCoreDlgs.csproj | 4 + Src/FwCoreDlgs/ValidCharactersDlg.cs | 2 +- Src/LexText/Interlinear/ITextDll.csproj | 8 + .../InterlinearTextsRecordClerk.cs | 7 +- Src/TE/TeImportExport/ImportDialog.cs | 22 +- Src/TE/TeImportExport/ImportWizard.cs | 12 +- Src/TE/TeImportExport/ScrObjWrapper.cs | 2 +- Src/TE/TeImportExport/TeImportExport.csproj | 745 +++++++++--------- .../TeImportExportExtensions.cs | 162 ++++ .../ExportTests/ExportParatextDlgTests.cs | 1 + .../ImportWizardTests.cs | 26 +- .../ImportTests/TeImportTests.cs | 10 - .../TeImportExportExtensionsTests.cs | 213 +++++ .../TeImportExportTests.csproj | 5 + Src/TE/TeImportExport/TeImportManager.cs | 1 + Src/TeDll/DockableUsfmBrowser.cs | 1 + 30 files changed, 1135 insertions(+), 1106 deletions(-) rename Src/{FDO/DomainServices => Common/ScriptureUtils}/ParatextHelper.cs (92%) rename Src/{FDO/FDOTests => Common/ScriptureUtils/ScriptureUtilsTests}/ParatextHelperTests.cs (90%) create mode 100644 Src/TE/TeImportExport/TeImportExportExtensions.cs create mode 100644 Src/TE/TeImportExport/TeImportExportTests/TeImportExportExtensionsTests.cs diff --git a/Src/Common/Controls/FwControls/FwControls.csproj b/Src/Common/Controls/FwControls/FwControls.csproj index 6823a44abe..48cb1eed64 100644 --- a/Src/Common/Controls/FwControls/FwControls.csproj +++ b/Src/Common/Controls/FwControls/FwControls.csproj @@ -95,11 +95,19 @@ False + + False + ..\..\..\..\Output\Debug\FwUtils.dll + False ..\..\..\..\Output\Debug\ManagedLgIcuCollator.dll + + False + ..\..\..\..\Output\Debug\ScriptureUtils.dll + System @@ -127,9 +135,6 @@ ..\..\..\..\Output\Debug\FwResources.dll - - ..\..\..\..\Output\Debug\FwUtils.dll - ..\..\..\..\Output\Debug\SilUtils.dll diff --git a/Src/Common/Controls/FwControls/TextsTriStateTreeView.cs b/Src/Common/Controls/FwControls/TextsTriStateTreeView.cs index fa3697c9a9..c44e646bea 100644 --- a/Src/Common/Controls/FwControls/TextsTriStateTreeView.cs +++ b/Src/Common/Controls/FwControls/TextsTriStateTreeView.cs @@ -12,8 +12,8 @@ using System.Windows.Forms; using Paratext; using SIL.FieldWorks.Common.COMInterfaces; +using SIL.FieldWorks.Common.ScriptureUtils; using SIL.FieldWorks.FDO; -using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.Language; using SIL.FieldWorks.Resources; using SILUBS.SharedScrUtils; diff --git a/Src/Common/FwUtils/FwUtils.csproj b/Src/Common/FwUtils/FwUtils.csproj index 5d445de217..e0f9bd534e 100644 --- a/Src/Common/FwUtils/FwUtils.csproj +++ b/Src/Common/FwUtils/FwUtils.csproj @@ -134,10 +134,6 @@ False ..\..\..\Downloads\Palaso.Lift.dll - - False - ..\..\..\DistFiles\ParatextShared.dll - False ..\..\..\Output\Debug\SharedScrUtils.dll diff --git a/Src/FDO/DomainServices/ParatextHelper.cs b/Src/Common/ScriptureUtils/ParatextHelper.cs similarity index 92% rename from Src/FDO/DomainServices/ParatextHelper.cs rename to Src/Common/ScriptureUtils/ParatextHelper.cs index 5cd404d72b..73815c4beb 100644 --- a/Src/FDO/DomainServices/ParatextHelper.cs +++ b/Src/Common/ScriptureUtils/ParatextHelper.cs @@ -12,10 +12,12 @@ using System.Linq; using Microsoft.Win32; using Paratext; +using SIL.FieldWorks.FDO; +using SIL.FieldWorks.FDO.DomainServices; using SIL.Utils; using SILUBS.SharedScrUtils; -namespace SIL.FieldWorks.FDO.DomainServices +namespace SIL.FieldWorks.Common.ScriptureUtils { #region IParatextHelper interface /// ---------------------------------------------------------------------------------------- @@ -64,13 +66,8 @@ public interface IParatextHelper /// /// Load the mappings for a Paratext 6/7 project into the specified list. /// - /// Paratext project ID - /// ScrMappingList to which new mappings will be added - /// The import domain for which this project is the source - /// true if the Paratext mappings were loaded successfully; false - /// otherwise /// ------------------------------------------------------------------------------------ - bool LoadProjectMappings(string project, ScrMappingList mappingList, ImportDomain domain); + void LoadProjectMappings(IScrImportSet importSettings); } #endregion @@ -292,20 +289,36 @@ public IEnumerable GetProjects() /// /// Load the mappings for a Paratext 6/7 project into the specified list. /// - /// Paratext project ID - /// ScrMappingList to which new mappings will be added - /// The import domain for which this project is the source /// true if the Paratext mappings were loaded successfully; false /// otherwise /// ------------------------------------------------------------------------------------ - [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", - Justification = "See REVIEW comment")] - public bool LoadProjectMappings(string project, ScrMappingList mappingList, ImportDomain domain) + public void LoadProjectMappings(IScrImportSet importSettings) { RefreshProjects(); + if (!m_IsParatextInitialized) + { + importSettings.ParatextScrProj = null; + importSettings.ParatextBTProj = null; + importSettings.ParatextNotesProj = null; + return; + } + + if (!LoadProjectMappings(importSettings.ParatextScrProj, importSettings.GetMappingListForDomain(ImportDomain.Main), ImportDomain.Main)) + importSettings.ParatextScrProj = null; + + if (!LoadProjectMappings(importSettings.ParatextBTProj, importSettings.GetMappingListForDomain(ImportDomain.BackTrans), ImportDomain.BackTrans)) + importSettings.ParatextBTProj = null; - // If Paratext is not initialized or the new project ID is null, then do not load mappings. - if (!m_IsParatextInitialized || project == null) + if (!LoadProjectMappings(importSettings.ParatextNotesProj, importSettings.GetMappingListForDomain(ImportDomain.Annotations), ImportDomain.Annotations)) + importSettings.ParatextNotesProj = null; + } + + [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", + Justification = "See REVIEW comment")] + private bool LoadProjectMappings(string project, ScrMappingList mappingList, ImportDomain domain) + { + // If the new project ID is null, then do not load mappings. + if (string.IsNullOrEmpty(project)) return false; // Load the tags from the paratext project and create mappings for them. @@ -324,7 +337,8 @@ public bool LoadProjectMappings(string project, ScrMappingList mappingList, Impo return false; } - mappingList.ResetInUseFlags(domain); + foreach (ImportMappingInfo mapping in mappingList) + mapping.SetIsInUse(domain, false); try { foreach (ScrTag tag in scParatextText.DefaultStylesheet.Tags) @@ -497,17 +511,12 @@ public static IEnumerable GetProjectBooks(string projShortName) /// ------------------------------------------------------------------------------------ /// - /// Load the mappings for a Paratext 6/7 project into the specified list. + /// Load the mappings for a Paratext 6/7 project into the specified import settings. /// - /// Paratext project ID - /// ScrMappingList to which new mappings will be added - /// The import domain for which this project is the source - /// true if the Paratext mappings were loaded successfully; false - /// otherwise /// ------------------------------------------------------------------------------------ - public static bool LoadProjectMappings(string project, ScrMappingList mappingList, ImportDomain domain) + public static void LoadProjectMappings(IScrImportSet importSettings) { - return s_ptHelper.LoadProjectMappings(project, mappingList, domain); + s_ptHelper.LoadProjectMappings(importSettings); } #endregion diff --git a/Src/Common/ScriptureUtils/ScriptureUtils.csproj b/Src/Common/ScriptureUtils/ScriptureUtils.csproj index eeeefc15a0..e08dbfcf77 100644 --- a/Src/Common/ScriptureUtils/ScriptureUtils.csproj +++ b/Src/Common/ScriptureUtils/ScriptureUtils.csproj @@ -1,186 +1,208 @@ - + - Local - 9.0.30729 - 2.0 - {C98A0201-B55C-4B8C-9408-5F5FC2FD22B6} - - - - Debug - AnyCPU - - - - - ScriptureUtils - - - JScript - Grid - IE50 - false - Library - SIL.FieldWorks.Common.ScriptureUtils - OnBuildSuccess - - - - - - - - - 3.5 - false - v4.0 - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - true - + Local + 9.0.30729 + 2.0 + {C98A0201-B55C-4B8C-9408-5F5FC2FD22B6} + + + + + + + Debug + AnyCPU + + + + + ScriptureUtils + + + JScript + Grid + IE50 + false + Library + SIL.FieldWorks.Common.ScriptureUtils + OnBuildSuccess + + + + + + + + + 3.5 + false + v4.0 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + - ..\..\..\Output\Debug\ - false - 285212672 - false - - - DEBUG;TRACE - ..\..\..\Output\Debug\ScriptureUtils.xml - true - 4096 - false - 168,169,219,414,649,1635,1702,1701 - false - false - false - true - 4 - full - prompt - AllRules.ruleset - x86 + ..\..\..\Output\Debug\ + false + 285212672 + false + + + DEBUG;TRACE + ..\..\..\Output\Debug\ScriptureUtils.xml + true + 4096 + false + 168,169,219,414,649,1635,1702,1701 + false + false + false + true + 4 + full + prompt + AllRules.ruleset + x86 - ..\..\..\Output\Release\ - false - 285212672 - false - - - TRACE - - - true - 4096 - true - false - false - true - 4 - full - prompt - AllRules.ruleset - x86 + ..\..\..\Output\Release\ + false + 285212672 + false + + + TRACE + + + true + 4096 + true + false + false + true + 4 + full + prompt + AllRules.ruleset + x86 - - False - ..\..\..\Output\Debug\BasicUtils.dll - - - False - ..\..\..\Output\Debug\COMInterfaces.dll - - - False - ..\..\..\Output\Debug\FwResources.dll - - - False - ..\..\..\Output\Debug\FwUtils.dll - - - False - ..\..\..\Output\Debug\ScrUtilsInterfaces.dll - - - False - ..\..\..\Output\Debug\SharedScrUtils.dll - - - False - ..\..\..\Output\Debug\SilEncConverters40.dll - - - System - - - - System.Data - - - System.XML - + + False + ..\..\..\Output\Debug\BasicUtils.dll + + + False + ..\..\..\Output\Debug\COMInterfaces.dll + + + False + ..\..\..\Output\Debug\FDO.dll + + + False + ..\..\..\Output\Debug\FwResources.dll + + + False + ..\..\..\Output\Debug\FwUtils.dll + + + ..\..\..\DistFiles\NetLoc.dll + + + False + ..\..\..\DistFiles\ParatextShared.dll + + + False + ..\..\..\Output\Debug\ScrUtilsInterfaces.dll + + + False + ..\..\..\Output\Debug\SharedScrUtils.dll + + + False + ..\..\..\Output\Debug\SilEncConverters40.dll + + + System + + + + System.Data + + + System.XML + + + False + ..\..\..\DistFiles\Utilities.dll + - - CommonAssemblyInfo.cs - - - Code - - - - - Code - + + CommonAssemblyInfo.cs + + + Code + + + + + + Code + - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 2.0 %28x86%29 - true - - - False - .NET Framework 3.0 %28x86%29 - false - - - False - .NET Framework 3.5 - false - - - False - .NET Framework 3.5 SP1 - false - + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + true + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + False + .NET Framework 3.5 SP1 + false + + + + - - - - + + + + \ No newline at end of file diff --git a/Src/FDO/FDOTests/ParatextHelperTests.cs b/Src/Common/ScriptureUtils/ScriptureUtilsTests/ParatextHelperTests.cs similarity index 90% rename from Src/FDO/FDOTests/ParatextHelperTests.cs rename to Src/Common/ScriptureUtils/ScriptureUtilsTests/ParatextHelperTests.cs index 5ca672ae37..0aa09b1730 100644 --- a/Src/FDO/FDOTests/ParatextHelperTests.cs +++ b/Src/Common/ScriptureUtils/ScriptureUtilsTests/ParatextHelperTests.cs @@ -12,13 +12,15 @@ using NUnit.Framework; using Paratext; using SIL.FieldWorks.Common.FwUtils; +using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices; +using SIL.FieldWorks.FDO.FDOTests; using SIL.FieldWorks.Resources; using SIL.FieldWorks.Test.ProjectUnpacker; using SIL.FieldWorks.Test.TestUtils; using SIL.Utils; -namespace SIL.FieldWorks.FDO.FDOTests +namespace SIL.FieldWorks.Common.ScriptureUtils { #region MockParatextHelper class /// ---------------------------------------------------------------------------------------- @@ -126,11 +128,11 @@ public IEnumerable GetProjects() /// We never use this method; for tests, we use Rhino.Mocks.MockRepository /// /// ------------------------------------------------------------------------------------ - public bool LoadProjectMappings(string project, ScrMappingList mappingList, ImportDomain domain) + public void LoadProjectMappings(IScrImportSet importSettings) { if (m_loadProjectMappingsImpl == null) throw new NotImplementedException(); - return m_loadProjectMappingsImpl.LoadProjectMappings(project, mappingList, domain); + m_loadProjectMappingsImpl.LoadProjectMappings(importSettings); } #endregion @@ -409,7 +411,9 @@ public class ParatextHelperTests : ScrInMemoryFdoTestBase [Test] public void LoadParatextMappings_NullProjectName() { - Assert.IsFalse(ParatextHelper.LoadProjectMappings(null, null, ImportDomain.Main)); + IScrImportSet importSettings = Cache.ServiceLocator.GetInstance().Create(ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); + ParatextHelper.LoadProjectMappings(importSettings); + Assert.That(importSettings.ParatextScrProj, Is.Null); } /// ------------------------------------------------------------------------------------ @@ -423,12 +427,13 @@ public void LoadParatextMappings_Normal() { Unpacker.UnPackParatextTestProjects(); - FwStyleSheet stylesheet = new FwStyleSheet(); + var stylesheet = new FwStyleSheet(); stylesheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); - ScrMappingList mappingList = new ScrMappingList(MappingSet.Main, stylesheet, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); - - Assert.IsTrue(ParatextHelper.LoadProjectMappings("KAM", mappingList, ImportDomain.Main)); + IScrImportSet importSettings = Cache.ServiceLocator.GetInstance().Create(ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); + importSettings.ParatextScrProj = "KAM"; + ParatextHelper.LoadProjectMappings(importSettings); + ScrMappingList mappingList = importSettings.GetMappingListForDomain(ImportDomain.Main); // Test to see that the projects are set correctly Assert.AreEqual(44, mappingList.Count); @@ -452,9 +457,11 @@ public void LoadParatextMappings_Normal() [Ignore("Has not been run for a while and no longer works; possibly obsolete")] public void LoadParatextMappings_MarkMappingsInUse() { - FwStyleSheet stylesheet = new FwStyleSheet(); + var stylesheet = new FwStyleSheet(); stylesheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); - ScrMappingList mappingList = new ScrMappingList(MappingSet.Main, stylesheet, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); + IScrImportSet importSettings = Cache.ServiceLocator.GetInstance().Create(ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); + importSettings.ParatextScrProj = "TEV"; + ScrMappingList mappingList = importSettings.GetMappingListForDomain(ImportDomain.Main); mappingList.Add(new ImportMappingInfo(@"\hahaha", @"\*hahaha", false, MappingTargetType.TEStyle, MarkerDomain.Default, "laughing", null, null, true, ImportDomain.Main)); @@ -463,7 +470,8 @@ public void LoadParatextMappings_MarkMappingsInUse() "en", null, true, ImportDomain.Main)); Unpacker.UnPackParatextTestProjects(); - Assert.IsTrue(ParatextHelper.LoadProjectMappings("TEV", mappingList, ImportDomain.Main)); + + ParatextHelper.LoadProjectMappings(importSettings); Assert.IsTrue(mappingList[@"\c"].IsInUse); Assert.IsTrue(mappingList[@"\p"].IsInUse); @@ -484,12 +492,15 @@ public void LoadParatextMappings_MarkMappingsInUse() [Category("LongRunning")] public void LoadParatextMappings_MissingEncodingFile() { - FwStyleSheet stylesheet = new FwStyleSheet(); + var stylesheet = new FwStyleSheet(); stylesheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); - ScrMappingList mappingList = new ScrMappingList(MappingSet.Main, stylesheet, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); + IScrImportSet importSettings = Cache.ServiceLocator.GetInstance().Create(ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); + importSettings.ParatextScrProj = "NEC"; Unpacker.UnPackMissingFileParatextTestProjects(); - Assert.IsFalse(ParatextHelper.LoadProjectMappings("NEC", mappingList, ImportDomain.Main)); + + ParatextHelper.LoadProjectMappings(importSettings); + Assert.That(importSettings.ParatextScrProj, Is.Null); } /// ------------------------------------------------------------------------------------ @@ -504,10 +515,12 @@ public void LoadParatextMappings_MissingStyleFile() { FwStyleSheet stylesheet = new FwStyleSheet(); stylesheet.Init(Cache, m_scr.Hvo, ScriptureTags.kflidStyles, ResourceHelper.DefaultParaCharsStyleName); - ScrMappingList mappingList = new ScrMappingList(MappingSet.Main, stylesheet, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); + IScrImportSet importSettings = Cache.ServiceLocator.GetInstance().Create(ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); + importSettings.ParatextScrProj = "NSF"; Unpacker.UnPackMissingFileParatextTestProjects(); - Assert.IsFalse(ParatextHelper.LoadProjectMappings("NSF", mappingList, ImportDomain.Main)); + ParatextHelper.LoadProjectMappings(importSettings); + Assert.That(importSettings.ParatextScrProj, Is.Null); } #endregion } diff --git a/Src/Common/ScriptureUtils/ScriptureUtilsTests/ScriptureUtilsTests.csproj b/Src/Common/ScriptureUtils/ScriptureUtilsTests/ScriptureUtilsTests.csproj index 14decc95f7..0bf0023c13 100644 --- a/Src/Common/ScriptureUtils/ScriptureUtilsTests/ScriptureUtilsTests.csproj +++ b/Src/Common/ScriptureUtils/ScriptureUtilsTests/ScriptureUtilsTests.csproj @@ -5,9 +5,12 @@ 9.0.30729 2.0 {C79E699C-2766-4D5B-9661-3BCE7C9679A6} - SAK - SAK - SAK + + + + + + Debug AnyCPU @@ -30,7 +33,8 @@ - SAK + + 3.5 false v4.0 @@ -98,18 +102,54 @@ x86 + + False + ..\..\..\..\Output\Debug\BasicUtils.dll + False ..\..\..\..\Output\Debug\BasicUtilsTests.dll + + False + ..\..\..\..\Output\Debug\COMInterfaces.dll + False ..\..\..\..\Output\Debug\COMInterfacesTests.dll + + False + ..\..\..\..\Output\Debug\FDO.dll + + + False + ..\..\..\..\Output\Debug\FDOTests.dll + + + False + ..\..\..\..\Output\Debug\FwResources.dll + + + False + ..\..\..\..\Output\Debug\FwUtils.dll + + + False + ..\..\..\..\DistFiles\Microsoft.Practices.ServiceLocation.dll + nunit.framework ..\..\..\..\Bin\NUnit\bin\nunit.framework.dll + + False + ..\..\..\..\DistFiles\ParatextShared.dll + + + False + ..\..\..\..\Output\Debug\ProjectUnpacker.dll + ScriptureUtils ..\..\..\..\Output\Debug\ScriptureUtils.dll @@ -126,16 +166,22 @@ System + TestUtils ..\..\..\..\Output\Debug\TestUtils.dll + + False + ..\..\..\..\DistFiles\Utilities.dll + AssemblyInfoForTests.cs + diff --git a/Src/FDO/DomainImpl/ScrImportSet.cs b/Src/FDO/DomainImpl/ScrImportSet.cs index bf9ad0d369..b7286aa209 100644 --- a/Src/FDO/DomainImpl/ScrImportSet.cs +++ b/Src/FDO/DomainImpl/ScrImportSet.cs @@ -6,14 +6,10 @@ // Responsibility: TE Team using System; -using System.IO; using System.Collections; -using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; -using System.Linq; using SIL.FieldWorks.Common.COMInterfaces; -using SIL.Utils; using SILUBS.SharedScrUtils; using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.FDO.DomainServices; @@ -261,104 +257,7 @@ public TypeOfImport ImportTypeEnum #endregion #region Import Project Accessibility Methods - /// ----------------------------------------------------------------------------------- - /// - /// Indicates whether the in-memory import projects/files are currently accessible from - /// this machine. - /// - /// A list of Paratext project IDs or file paths that - /// could not be found. - /// - /// For Paratext projects, this will only return true if all projects are accessible. - /// For Standard Format, this will return true if any of the files are accessible. - /// We think this might make sense, but we aren't sure why. - /// - /// ----------------------------------------------------------------------------------- - public bool ImportProjectIsAccessible(out StringCollection thingsNotFound) - { - lock (SyncRoot) - { - if (ImportTypeEnum == TypeOfImport.Paratext6) - return ParatextProjectsAccessible(out thingsNotFound); - else if (ImportTypeEnum == TypeOfImport.Other || ImportTypeEnum == TypeOfImport.Paratext5) - return SFProjectFilesAccessible(out thingsNotFound); - thingsNotFound = null; - return false; - } - } - - /// ------------------------------------------------------------------------------------ - /// - /// Determines whether or not a set of paratext projects can be found and are - /// accessible. - /// - /// A list of the Paratext projects that couldn't - /// be found or are inaccessible. - /// A value indicating whether or not the projects are accessible. True if - /// all are. Otherwise, false. - /// ------------------------------------------------------------------------------------ - private bool ParatextProjectsAccessible(out StringCollection projectsNotFound) - { - projectsNotFound = new StringCollection(); - - if (m_ParatextScrProject == null) - return false; - - // Paratext seems to want to have write access to do an import... - string filename = Path.Combine(ParatextHelper.ProjectsDirectory, m_ParatextScrProject + ".ssf"); - if (!FileUtils.IsFileReadableAndWritable(filename) || - !ParatextHelper.GetProjectBooks(m_ParatextScrProject).Any()) - { - projectsNotFound.Add(m_ParatextScrProject); - } - - if (m_ParatextBTProject != null) - { - filename = Path.Combine(ParatextHelper.ProjectsDirectory, m_ParatextBTProject + ".ssf"); - if (!FileUtils.IsFileReadableAndWritable(filename) || - !ParatextHelper.GetProjectBooks(m_ParatextBTProject).Any()) - { - projectsNotFound.Add(m_ParatextBTProject); - } - } - - if (m_ParatextNotesProject != null) - { - filename = Path.Combine(ParatextHelper.ProjectsDirectory, m_ParatextNotesProject + ".ssf"); - if (!FileUtils.IsFileReadableAndWritable(filename) || - !ParatextHelper.GetProjectBooks(m_ParatextNotesProject).Any()) - { - projectsNotFound.Add(m_ParatextNotesProject); - } - } - - return (projectsNotFound.Count == 0); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Determines whether or not a set of SFM project files can be found and are - /// accessible. - /// - /// A list of files that couldn't be found. - /// true if any SFM files are accessible. Otherwise, false. - /// ------------------------------------------------------------------------------------ - private bool SFProjectFilesAccessible(out StringCollection filesNotFound) - { - filesNotFound = new StringCollection(); - bool fProjectFileFound = false; - - fProjectFileFound |= m_scrFileInfoList.FilesAreAccessible(ref filesNotFound); - - foreach (ScrSfFileList list in m_btFileInfoLists.Values) - fProjectFileFound |= list.FilesAreAccessible(ref filesNotFound); - - foreach (ScrSfFileList list in m_notesFileInfoLists.Values) - fProjectFileFound |= list.FilesAreAccessible(ref filesNotFound); - - return (fProjectFileFound); - } #endregion #region Public Properties @@ -646,18 +545,6 @@ public bool Valid } } - /// ------------------------------------------------------------------------------------ - /// - /// Sets the StartRef and EndRef based on the requested canonical book numbers. - /// - /// ------------------------------------------------------------------------------------ - public void IncludeBooks(int startBook, int endBook, Paratext.ScrVers versification) - { - StartRef = new BCVRef(startBook, 0, 0); - int chapter = versification.LastChapter(endBook); - EndRef = new BCVRef(endBook, chapter, versification.LastVerse(endBook, chapter)); - } - /// ------------------------------------------------------------------------------------ /// /// Gets/sets stylesheet for settings. @@ -897,7 +784,7 @@ public virtual string ParatextScrProj if (value != null && (value == ParatextNotesProj || value == ParatextBTProj)) throw new ArgumentException(ScrFdoResources.kstidPtScrAlreadyUsed); - m_ParatextScrProject = SetParatextProject(value, ImportDomain.Main); + m_ParatextScrProject = value; } } } @@ -923,7 +810,7 @@ public virtual string ParatextBTProj if (value != null && (value == ParatextScrProj || value == ParatextNotesProj)) throw new ArgumentException(ScrFdoResources.kstidPtBtAlreadyUsed); - m_ParatextBTProject = SetParatextProject(value, ImportDomain.BackTrans); + m_ParatextBTProject = value; } } } @@ -949,34 +836,11 @@ public virtual string ParatextNotesProj if (value != null && (value == ParatextScrProj || value == ParatextBTProj)) throw new ArgumentException(ScrFdoResources.kstidPtNotesAlreadyUsed); - m_ParatextNotesProject = SetParatextProject(value, ImportDomain.Annotations); + m_ParatextNotesProject = value; } } } - /// ------------------------------------------------------------------------------------ - /// - /// Sets the Paratext project name for the specified domain. - /// - /// The name of the Paratext project. - /// The domain (Scripture, back translation or annotations). - /// name of the project, if not empty and the project loads without error; - /// otherwise null - /// ------------------------------------------------------------------------------------ - private string SetParatextProject(string value, ImportDomain domain) - { - string projName = (value == string.Empty) ? null : value; - if (projName != null) - { - // use notes list for the annotations domain, otherwise use the scripture list. - ScrMappingList loadedList = domain == ImportDomain.Annotations ? m_notesMappingsList : m_scrMappingsList; - bool fValidProj = ParatextHelper.LoadProjectMappings(value, loadedList, domain); - return fValidProj ? value : null; - } - - return null; - } - /// ------------------------------------------------------------------------------------ /// /// Commit the "temporary" in-memory settings to the permanent properties @@ -1063,60 +927,6 @@ private string StartsWithMarker(string line, StringCollection markersList) return null; } - /// ------------------------------------------------------------------------------------ - /// - /// Gets a list of books that exist for all of the files in this project. - /// - /// A List of integers representing 1-based canonical book numbers that exist - /// in any source represented by these import settings - /// If project is not a supported type - /// ------------------------------------------------------------------------------------ - public List BooksForProject - { - get - { - Debug.Assert(BasicSettingsExist, "Vernacular Scripture project not defined."); - switch (ImportTypeEnum) - { - case TypeOfImport.Paratext6: - // TODO (TE-5903): Check BT and Notes projects as well. - return ParatextHelper.GetProjectBooks(ParatextScrProj).ToList(); - case TypeOfImport.Paratext5: - case TypeOfImport.Other: - lock (SyncRoot) - { - List booksPresent = new List(); - foreach (IScrImportFileInfo file in m_scrFileInfoList) - foreach (int iBook in file.BooksInFile) - { - if (!booksPresent.Contains(iBook)) - booksPresent.Add(iBook); - } - - foreach (ScrSfFileList fileList in m_btFileInfoLists.Values) - foreach (IScrImportFileInfo file in fileList) - foreach (int iBook in file.BooksInFile) - { - if (!booksPresent.Contains(iBook)) - booksPresent.Add(iBook); - } - - foreach (ScrSfFileList fileList in m_notesFileInfoLists.Values) - foreach (IScrImportFileInfo file in fileList) - foreach (int iBook in file.BooksInFile) - { - if (!booksPresent.Contains(iBook)) - booksPresent.Add(iBook); - } - booksPresent.Sort(); - return booksPresent; - } - default: - throw new NotSupportedException("Unexpected type of Import Project"); - } - } - } - /// ------------------------------------------------------------------------------------ /// /// Get a MappingSet that is appropriate for the ImportDomain diff --git a/Src/FDO/DomainServices/IScrImportFileInfo.cs b/Src/FDO/DomainServices/IScrImportFileInfo.cs index 1691fa296a..5dcd066994 100644 --- a/Src/FDO/DomainServices/IScrImportFileInfo.cs +++ b/Src/FDO/DomainServices/IScrImportFileInfo.cs @@ -75,7 +75,7 @@ public interface IScrImportFileInfo /// (only used for Note sources) /// /// ------------------------------------------------------------------------------------ - SIL.FieldWorks.FDO.ICmAnnotationDefn NoteType { get; } + ICmAnnotationDefn NoteType { get; } /// ------------------------------------------------------------------------------------ /// @@ -111,5 +111,18 @@ public interface IScrImportFileInfo /// /// ------------------------------------------------------------------------------------ SILUBS.SharedScrUtils.ScrReference StartRef { get; } + + /// ------------------------------------------------------------------------------------ + /// + /// Rechecks the accessibility of a file that might have been initially determined to + /// be inaccessible. If the file was inaccessible but is now accessible, it will be + /// properly initialized so all the cached info will be valid. + /// + /// Use to recheck accessibility of a file + /// that was initially determined to be accessible. Use to + /// access the cached value. + /// true if the file is currently accessible + /// ------------------------------------------------------------------------------------ + bool RecheckAccessibility(); } } diff --git a/Src/FDO/DomainServices/ScrImportFileInfo.cs b/Src/FDO/DomainServices/ScrImportFileInfo.cs index c483f7fb8f..498db95f43 100644 --- a/Src/FDO/DomainServices/ScrImportFileInfo.cs +++ b/Src/FDO/DomainServices/ScrImportFileInfo.cs @@ -495,7 +495,7 @@ protected virtual void GuessFileEncoding() /// access the cached value. /// true if the file is currently accessible /// ------------------------------------------------------------------------------------ - internal bool RecheckAccessibility() + public bool RecheckAccessibility() { if (IsReadable) return IsStillReadable; diff --git a/Src/FDO/FDO.csproj b/Src/FDO/FDO.csproj index 36dba37da8..11e95aad13 100644 --- a/Src/FDO/FDO.csproj +++ b/Src/FDO/FDO.csproj @@ -114,10 +114,6 @@ System.XML - - False - ..\..\DistFiles\Utilities.dll - XMLUtils ..\..\Output\Debug\XMLUtils.dll @@ -143,9 +139,6 @@ ..\..\DistFiles\Microsoft.Practices.ServiceLocation.dll - - ..\..\DistFiles\ParatextShared.dll - ..\..\Output\Debug\PhraseTranslationHelper.dll @@ -185,7 +178,6 @@ - diff --git a/Src/FDO/FDOTests/FDOTests.csproj b/Src/FDO/FDOTests/FDOTests.csproj index dfc199db0d..1851442407 100644 --- a/Src/FDO/FDOTests/FDOTests.csproj +++ b/Src/FDO/FDOTests/FDOTests.csproj @@ -354,7 +354,6 @@ - diff --git a/Src/FDO/FDOTests/ScrImportSetTests.cs b/Src/FDO/FDOTests/ScrImportSetTests.cs index e361133e5e..6269fcf6d8 100644 --- a/Src/FDO/FDOTests/ScrImportSetTests.cs +++ b/Src/FDO/FDOTests/ScrImportSetTests.cs @@ -8,11 +8,7 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Collections.Specialized; using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Text; - using NUnit.Framework; using Rhino.Mocks; using SIL.FieldWorks.Common.FwUtils; @@ -124,39 +120,13 @@ public override IScrImportFileInfo Create(string fileName, ScrMappingList mappin public class ScrImportSetTests : ScrInMemoryFdoTestBase { #region data members - private MockParatextHelper m_ptHelper; private IScrImportSet m_importSettings; private ICmAnnotationDefn m_translatorNoteDefn; private ICmAnnotationDefn m_consultantNoteDefn; - private IParatextHelper m_mockParatextHelper; private MockFileOS m_fileOs; #endregion #region Setup & Teardown - /// ------------------------------------------------------------------------------------ - /// - /// - /// - /// ------------------------------------------------------------------------------------ - public override void FixtureSetup() - { - base.FixtureSetup(); - m_ptHelper = new MockParatextHelper(); - ParatextHelper.Manager.SetParatextHelperAdapter(m_ptHelper); - } - - /// ------------------------------------------------------------------------------------ - /// - /// - /// - /// ------------------------------------------------------------------------------------ - public override void FixtureTeardown() - { - base.FixtureTeardown(); - m_ptHelper.Dispose(); - ParatextHelper.Manager.Reset(); - } - /// ------------------------------------------------------------------------------------ /// /// Test setup stuff @@ -165,12 +135,9 @@ public override void FixtureTeardown() public override void TestSetup() { base.TestSetup(); - m_ptHelper.Projects.Clear(); m_importSettings = Cache.ServiceLocator.GetInstance().Create(ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); - m_mockParatextHelper = MockRepository.GenerateMock(); m_scr.ImportSettingsOC.Add(m_importSettings); - m_ptHelper.m_loadProjectMappingsImpl = m_mockParatextHelper; m_translatorNoteDefn = Cache.ServiceLocator.GetInstance().TranslatorAnnotationDefn; m_consultantNoteDefn = Cache.ServiceLocator.GetInstance().ConsultantAnnotationDefn; @@ -689,8 +656,6 @@ public void SaveAndReloadSources_SaveSeparateSourcesWhenImportTypeChanges() // Now that we've saved the settings, we'll "revert" in order to re-load from the DB m_importSettings.RevertToSaved(); - m_mockParatextHelper.Stub(x => x.LoadProjectMappings(Arg.Is.Equal("KAM"), - Arg.Is.Anything, Arg.Is.Equal(ImportDomain.Main))).Return(true); m_importSettings.ImportTypeEnum = TypeOfImport.Paratext6; m_importSettings.ParatextScrProj = "KAM"; m_importSettings.SaveSettings(); @@ -795,11 +760,6 @@ public void SaveAndReloadParatext6Projects() ScrMappingList mappingList = (ScrMappingList)m_importSettings.Mappings(MappingSet.Main); - m_mockParatextHelper.Stub(x => x.LoadProjectMappings(Arg.Is.Equal("KAM"), - Arg.Is.Equal(mappingList), Arg.Is.Equal(ImportDomain.Main))).Return(true); - m_mockParatextHelper.Stub(x => x.LoadProjectMappings(Arg.Is.Equal("TEV"), - Arg.Is.Equal(mappingList), Arg.Is.Equal(ImportDomain.BackTrans))).Return(true); - // add Scripture files m_importSettings.ParatextScrProj = "KAM"; m_importSettings.ParatextBTProj = "TEV"; @@ -852,32 +812,6 @@ public void AddFile_Main() ((ScrSfFileList)ReflectionHelper.GetField(m_importSettings, "m_scrFileInfoList"))[0]); } - /// ------------------------------------------------------------------------------------ - /// - /// Test adding a file that is locked - /// - /// ------------------------------------------------------------------------------------ - [Test] - public void AddFileAndCheckAccessibility_Locked() - { - m_importSettings.ImportTypeEnum = TypeOfImport.Other; - - string filename = m_fileOs.MakeSfFile("EPH", @"\c 1", @"\v 1"); - m_fileOs.LockFile(filename); - - // Lock the file - //using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite)) - //{ - IScrImportFileInfo info = m_importSettings.AddFile(filename, ImportDomain.Main, null, null); - Assert.AreEqual(Encoding.ASCII, info.FileEncoding); - Assert.AreEqual(1, m_importSettings.GetImportFiles(ImportDomain.Main).Count); - StringCollection notFound; - Assert.IsFalse(m_importSettings.ImportProjectIsAccessible(out notFound)); - Assert.AreEqual(1, notFound.Count); - Assert.AreEqual(filename, (string)notFound[0]); - //} - } - /// ------------------------------------------------------------------------------------ /// /// Try to add non-existent file to the SF Project. This should be allowed because @@ -974,11 +908,6 @@ public void MarkMappingsInUse_SwitchFromParatext6ToOther() ScrMappingList mappingListMain = (ScrMappingList)m_importSettings.Mappings(MappingSet.Main); ScrMappingList mappingListNotes = (ScrMappingList)m_importSettings.Mappings(MappingSet.Notes); - m_mockParatextHelper.Stub(x => x.LoadProjectMappings(Arg.Is.Equal("KAM"), - Arg.Is.Equal(mappingListMain), Arg.Is.Equal(ImportDomain.Main))).Return(true); - m_mockParatextHelper.Stub(x => x.LoadProjectMappings(Arg.Is.Equal("TEV"), - Arg.Is.Equal(mappingListNotes), Arg.Is.Equal(ImportDomain.Annotations))).Return(true); - // set Scripture project m_importSettings.ParatextScrProj = "TEV"; m_importSettings.ParatextNotesProj = "KAM"; @@ -1056,9 +985,6 @@ public void AttemptToUseSameParatextProjectTwice() { m_importSettings.ImportTypeEnum = TypeOfImport.Paratext6; - m_mockParatextHelper.Stub(x => x.LoadProjectMappings(Arg.Is.Equal("KAM"), - Arg.Is.Anything, Arg.Is.Equal(ImportDomain.BackTrans))).Return(true); - m_importSettings.ParatextBTProj = "KAM"; m_importSettings.ParatextNotesProj = "KAM"; } @@ -1074,9 +1000,6 @@ public void SwitchFromParatext6ToParatext5Project() { m_importSettings.ImportTypeEnum = TypeOfImport.Paratext6; - m_mockParatextHelper.Stub(x => x.LoadProjectMappings(Arg.Is.Equal("KAM"), - Arg.Is.Anything, Arg.Is.Equal(ImportDomain.BackTrans))).Return(true); - ScrMappingList mappings = m_importSettings.GetMappingListForDomain(ImportDomain.Main); m_importSettings.SetMapping(MappingSet.Main, new ImportMappingInfo(@"\q", null, "Qute")); @@ -1143,9 +1066,6 @@ public void BasicSettingsExist_Paratext6() { m_importSettings.ImportTypeEnum = TypeOfImport.Paratext6; - m_mockParatextHelper.Stub(x => x.LoadProjectMappings(Arg.Is.Anything, - Arg.Is.Anything, Arg.Is.Anything)).Return(true); - Assert.IsFalse(m_importSettings.BasicSettingsExist, "No project settings set yet"); m_importSettings.ParatextBTProj = "KAM"; @@ -1210,83 +1130,6 @@ public void BasicSettingsExist_Paretxt5() } #endregion - #region Attempting to load Paratext project with missing files - /// ------------------------------------------------------------------------------------ - /// - /// Attempting to set the Paratext project to a project that can't be loaded should not - /// set the value. - /// - /// ------------------------------------------------------------------------------------ - [Test] - public void ParatextScrProj_Set_FailureToLoadProject() - { - m_importSettings.ImportTypeEnum = TypeOfImport.Paratext6; - - m_mockParatextHelper.Stub(x => x.LoadProjectMappings(Arg.Is.Equal("NEC"), - Arg.Is.Anything, Arg.Is.Anything)).Return(false); - - m_importSettings.ParatextScrProj = "NEC"; - - Assert.IsNull(m_importSettings.ParatextScrProj); - } - #endregion - - #region ImportProjectIsAccessible tests - /// ------------------------------------------------------------------------------------ - /// - /// Test to see if the ImportProjectIsAccessible method works for Paratext 6 projects. - /// - /// ------------------------------------------------------------------------------------ - [Test] - public void ImportProjectIsAccessible_Paratext6() - { - m_importSettings.ImportTypeEnum = TypeOfImport.Paratext6; - - string paratextDir = ParatextHelper.ProjectsDirectory; - m_mockParatextHelper.Stub(x => x.LoadProjectMappings(Arg.Is.Anything, - Arg.Is.Anything, Arg.Is.Anything)).Return(true); - m_ptHelper.AddProject("TEV", null, null, true, false, "100001"); - - m_fileOs.AddExistingFile(Path.Combine(paratextDir, "TEV.ssf")); - - m_importSettings.ParatextScrProj = "KAM"; - m_importSettings.ParatextBTProj = "TEV"; - - StringCollection projectsNotFound; - Assert.IsFalse(m_importSettings.ImportProjectIsAccessible(out projectsNotFound)); - Assert.AreEqual(1, projectsNotFound.Count); - Assert.AreEqual("KAM", projectsNotFound[0]); - - m_fileOs.AddExistingFile(Path.Combine(paratextDir, "KAM.ssf")); - m_ptHelper.AddProject("KAM", null, null, true, false, "000101"); - Assert.IsTrue(m_importSettings.ImportProjectIsAccessible(out projectsNotFound)); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Test to see if the ImportProjectIsAccessible method works for Paratext 5 projects. - /// - /// ------------------------------------------------------------------------------------ - [Test] - public void ImportProjectIsAccessible_Paratext5() - { - m_importSettings.ImportTypeEnum = TypeOfImport.Paratext5; - ImportProjectIsAccessible_helper(); - } - - /// ------------------------------------------------------------------------------------ - /// - /// Test to see if the ImportProjectIsAccessible method works for Other projects. - /// - /// ------------------------------------------------------------------------------------ - [Test] - public void ImportProjectIsAccessible_Other() - { - m_importSettings.ImportTypeEnum = TypeOfImport.Other; - ImportProjectIsAccessible_helper(); - } - #endregion - #region Helper methods /// ------------------------------------------------------------------------------------ /// @@ -1339,77 +1182,6 @@ private void CheckFileListContents(string[] files, ImportDomain domain) for (int index = 0; index < found.Length; index++) Assert.IsTrue(found[index], "File not found in " + domain + " source: " + files[index]); } - - /// ------------------------------------------------------------------------------------ - /// - /// Test to see if the ImportProjectIsAccessible method works for projects other than - /// Paratext 6. - /// - /// ------------------------------------------------------------------------------------ - private void ImportProjectIsAccessible_helper() - { - string scrFile1 = m_fileOs.MakeSfFile("GEN", @"\p", @"\c 1", @"\v 1", @"\v 2"); - string scrFile2 = m_fileOs.MakeSfFile("EXO", @"\p", @"\c 1", @"\v 1", @"\v 2"); - string scrFile3 = m_fileOs.MakeSfFile("LEV", @"\p", @"\c 1", @"\v 1", @"\v 2"); - string btFileDef = m_fileOs.MakeSfFile("GEN", @"\p", @"\c 3", @"\v 1"); - string btFileSpan = m_fileOs.MakeSfFile("GEN", @"\p", @"\c 3", @"\v 1"); - string annotFileCons = m_fileOs.MakeSfFile("GEN", @"\p", @"\c 3", @"\v 1"); - string annotFileTrans = m_fileOs.MakeSfFile("GEN", @"\p", @"\c 3", @"\v 1"); - - m_importSettings.AddFile(scrFile1, ImportDomain.Main, null, null); - m_importSettings.AddFile(scrFile2, ImportDomain.Main, null, null); - m_importSettings.AddFile(scrFile3, ImportDomain.Main, null, null); - m_importSettings.AddFile(btFileDef, ImportDomain.BackTrans, null, null); - m_importSettings.AddFile(btFileSpan, ImportDomain.BackTrans, "es", null); - m_importSettings.AddFile(annotFileCons, ImportDomain.Annotations, null, m_consultantNoteDefn); - m_importSettings.AddFile(annotFileTrans, ImportDomain.Annotations, null, m_translatorNoteDefn); - - StringCollection filesNotFound; - Assert.IsTrue(m_importSettings.ImportProjectIsAccessible(out filesNotFound)); - Assert.AreEqual(0, filesNotFound.Count); - m_importSettings.SaveSettings(); - - // Blow away some project files: should still return true, but should - // report missing files. - FileUtils.Delete(scrFile2); - FileUtils.Delete(scrFile3); - FileUtils.Delete(btFileDef); - FileUtils.Delete(annotFileCons); - FileUtils.Delete(annotFileTrans); - - // Now that we've saved the settings, we'll "revert" in order to re-load from the DB - m_importSettings.RevertToSaved(); - - Assert.IsTrue(m_importSettings.ImportProjectIsAccessible(out filesNotFound)); - Assert.AreEqual(5, filesNotFound.Count); - - Assert.IsTrue(filesNotFound.Contains(scrFile2)); - Assert.IsTrue(filesNotFound.Contains(scrFile3)); - Assert.IsTrue(filesNotFound.Contains(btFileDef)); - Assert.IsTrue(filesNotFound.Contains(annotFileCons)); - Assert.IsTrue(filesNotFound.Contains(annotFileTrans)); - - m_importSettings.SaveSettings(); - - // Blow away the rest of the project files: should return false and report - // missing files. - FileUtils.Delete(scrFile1); - FileUtils.Delete(btFileSpan); - - // Now that we've saved the settings, we'll "revert" in order to re-load from the DB - m_importSettings.RevertToSaved(); - - Assert.IsFalse(m_importSettings.ImportProjectIsAccessible(out filesNotFound)); - Assert.AreEqual(7, filesNotFound.Count); - - Assert.IsTrue(filesNotFound.Contains(scrFile1)); - Assert.IsTrue(filesNotFound.Contains(scrFile2)); - Assert.IsTrue(filesNotFound.Contains(scrFile3)); - Assert.IsTrue(filesNotFound.Contains(btFileDef)); - Assert.IsTrue(filesNotFound.Contains(btFileSpan)); - Assert.IsTrue(filesNotFound.Contains(annotFileCons)); - Assert.IsTrue(filesNotFound.Contains(annotFileTrans)); - } #endregion } } diff --git a/Src/FDO/FdoInterfaceAdditions.cs b/Src/FDO/FdoInterfaceAdditions.cs index 9434d07077..d66e2b36a2 100644 --- a/Src/FDO/FdoInterfaceAdditions.cs +++ b/Src/FDO/FdoInterfaceAdditions.cs @@ -14,7 +14,6 @@ using System.Collections.Generic; using System.Xml; using System.Collections; -using System.Collections.Specialized; using SIL.FieldWorks.Common.COMInterfaces; using SIL.FieldWorks.FDO.DomainImpl; @@ -4165,21 +4164,6 @@ string ParatextNotesProj set; } - /// ----------------------------------------------------------------------------------- - /// - /// Indicates whether the in-memory import projects/files are currently accessible from - /// this machine. - /// - /// A list of Paratext project IDs or file paths that - /// could not be found. - /// - /// For Paratext projects, this will only return true if all projects are accessible. - /// For Standard Format, this will return true if any of the files are accessible. - /// We think this might make sense, but we aren't sure why. - /// - /// ----------------------------------------------------------------------------------- - bool ImportProjectIsAccessible(out StringCollection thingsNotFound); - /// ------------------------------------------------------------------------------------ /// /// Gets whether to import back translations @@ -4349,20 +4333,6 @@ IScrImportFileInfo AddFile(string fileName, ImportDomain domain, string wsId, /// ------------------------------------------------------------------------------------ void RevertToSaved(); - /// ------------------------------------------------------------------------------------ - /// - /// Gets a list of books that exist for all of the files in this project. - /// - /// A List of integers representing 1-based canonical book numbers that exist - /// in any source represented by these import settings - /// If project is not a supported type - /// ------------------------------------------------------------------------------------ - List BooksForProject - { - get; - } - - /// ------------------------------------------------------------------------------------ /// /// Starting reference for the import; for now, we ignore the @@ -4422,13 +4392,6 @@ bool Valid { get; } - - /// ------------------------------------------------------------------------------------ - /// - /// Sets the StartRef and EndRef based on the requested canonical book numbers. - /// - /// ------------------------------------------------------------------------------------ - void IncludeBooks(int startBook, int endBook, Paratext.ScrVers versification); } /// ---------------------------------------------------------------------------------------- diff --git a/Src/FwCoreDlgs/FwCoreDlgs.csproj b/Src/FwCoreDlgs/FwCoreDlgs.csproj index af203a4a0f..804edd037e 100644 --- a/Src/FwCoreDlgs/FwCoreDlgs.csproj +++ b/Src/FwCoreDlgs/FwCoreDlgs.csproj @@ -175,6 +175,10 @@ False ..\..\Output\Debug\RootSite.dll + + False + ..\..\Output\Debug\ScriptureUtils.dll + False ..\..\Output\Debug\SharedScrUtils.dll diff --git a/Src/FwCoreDlgs/ValidCharactersDlg.cs b/Src/FwCoreDlgs/ValidCharactersDlg.cs index a4364f50ba..a6b83139dc 100644 --- a/Src/FwCoreDlgs/ValidCharactersDlg.cs +++ b/Src/FwCoreDlgs/ValidCharactersDlg.cs @@ -24,6 +24,7 @@ using SIL.FieldWorks.Common.Controls; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Common.RootSites; +using SIL.FieldWorks.Common.ScriptureUtils; using SIL.FieldWorks.Common.Widgets; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices; @@ -33,7 +34,6 @@ using SILUBS.SharedScrUtils; using XCore; - namespace SIL.FieldWorks.FwCoreDlgs { /// ---------------------------------------------------------------------------------------- diff --git a/Src/LexText/Interlinear/ITextDll.csproj b/Src/LexText/Interlinear/ITextDll.csproj index d737acb469..5564f2bd7a 100644 --- a/Src/LexText/Interlinear/ITextDll.csproj +++ b/Src/LexText/Interlinear/ITextDll.csproj @@ -148,9 +148,17 @@ False ..\..\..\Output\Debug\ScrControls.dll + + False + ..\..\..\Output\Debug\ScriptureUtils.dll + False + + False + ..\..\..\Output\Debug\SharedScrUtils.dll + False ..\..\..\Lib\debug\SIL.Collections.dll diff --git a/Src/LexText/Interlinear/InterlinearTextsRecordClerk.cs b/Src/LexText/Interlinear/InterlinearTextsRecordClerk.cs index fc17aceed3..a08084e24a 100644 --- a/Src/LexText/Interlinear/InterlinearTextsRecordClerk.cs +++ b/Src/LexText/Interlinear/InterlinearTextsRecordClerk.cs @@ -9,12 +9,14 @@ using SIL.FieldWorks.Common.Framework; using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Common.RootSites; +using SIL.FieldWorks.Common.ScriptureUtils; using SIL.FieldWorks.FDO; using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.Infrastructure; using SIL.FieldWorks.Resources; using SIL.FieldWorks.XWorks; using SIL.Utils; +using SILUBS.SharedScrUtils; using XCore; namespace SIL.FieldWorks.IText @@ -433,7 +435,9 @@ public IScrBook Import(int bookNum, Form owningForm, bool importBt) IScrImportSet importSettings = scr.FindOrCreateDefaultImportSettings(TypeOfImport.Paratext6, ResourceHelper.DefaultParaCharsStyleName, FwDirectoryFinder.TeStylesPath); ScrText paratextProj = ParatextHelper.GetAssociatedProject(Cache.ProjectId); importSettings.ParatextScrProj = paratextProj.Name; - importSettings.IncludeBooks(bookNum, bookNum, paratextProj.Versification); + importSettings.StartRef = new BCVRef(bookNum, 0, 0); + int chapter = paratextProj.Versification.LastChapter(bookNum); + importSettings.EndRef = new BCVRef(bookNum, chapter, paratextProj.Versification.LastVerse(bookNum, chapter)); if (!importBt) { importSettings.ImportTranslation = true; @@ -452,6 +456,7 @@ public IScrBook Import(int bookNum, Form owningForm, bool importBt) importSettings.ImportTranslation = false; importSettings.ImportBackTranslation = true; } + ParatextHelper.LoadProjectMappings(importSettings); return true; }); diff --git a/Src/TE/TeImportExport/ImportDialog.cs b/Src/TE/TeImportExport/ImportDialog.cs index 4db13ffdae..fb967bd00e 100644 --- a/Src/TE/TeImportExport/ImportDialog.cs +++ b/Src/TE/TeImportExport/ImportDialog.cs @@ -139,7 +139,7 @@ private int InitBookNameList() List booksPresent = null; try { - booksPresent = m_importSettings.BooksForProject; + booksPresent = m_importSettings.BooksForProject(); } catch { @@ -479,8 +479,8 @@ private void btnSource_Click(object sender, System.EventArgs e) /// ------------------------------------------------------------------------------------ private void InitializeStartAndEndRefControls() { - scrPsgFrom.Initialize(StartRef.Book, m_importSettings.BooksForProject.ToArray()); - scrPsgTo.Initialize(EndRef.Book, m_importSettings.BooksForProject.ToArray()); + scrPsgFrom.Initialize(StartRef.Book, m_importSettings.BooksForProject().ToArray()); + scrPsgTo.Initialize(EndRef.Book, m_importSettings.BooksForProject().ToArray()); } /// ------------------------------------------------------------------------------------ @@ -599,8 +599,12 @@ private int FirstImportableBook { get { - if (m_importSettings != null && m_importSettings.BooksForProject.Count > 0) - return m_importSettings.BooksForProject[0]; + if (m_importSettings != null) + { + List books = m_importSettings.BooksForProject(); + if (books.Count > 0) + return books[0]; + } return ScrReference.StartOfBible(m_scr.Versification).Book; } @@ -615,8 +619,12 @@ private int LastImportableBook { get { - if (m_importSettings != null && m_importSettings.BooksForProject.Count > 0) - return m_importSettings.BooksForProject[m_importSettings.BooksForProject.Count - 1]; + if (m_importSettings != null) + { + List books = m_importSettings.BooksForProject(); + if (books.Count > 0) + return books[books.Count - 1]; + } return ScrReference.EndOfBible(m_scr.Versification).Book; } diff --git a/Src/TE/TeImportExport/ImportWizard.cs b/Src/TE/TeImportExport/ImportWizard.cs index 251febdbe3..7a2b2e3b3e 100644 --- a/Src/TE/TeImportExport/ImportWizard.cs +++ b/Src/TE/TeImportExport/ImportWizard.cs @@ -1155,6 +1155,7 @@ private void LoadParatextProjectCombos() ScrText assocProj = ParatextHelper.GetAssociatedProject(m_cache.ProjectId); //Ignore the case that there is information already in the combobox. //Solution for TE - 4441) + bool loadMappings = false; if (cboPTLangProj.Items.Count == 0) { if (assocProj != null) @@ -1163,6 +1164,7 @@ private void LoadParatextProjectCombos() cboPTLangProj.Items.Add(assocProj); cboPTLangProj.SelectedIndex = 0; cboPTLangProj.Enabled = false; + loadMappings = true; } else { @@ -1181,6 +1183,7 @@ private void LoadParatextProjectCombos() cboPTBackTrans.Items.Add(btText); cboPTBackTrans.SelectedIndex = 0; cboPTBackTrans.Enabled = (btProjects.Count() > 1); + loadMappings = true; } else { @@ -1198,6 +1201,9 @@ private void LoadParatextProjectCombos() cboPTTransNotes.Items.Add(s_noneProject); LoadParatextProjectCombo(cboPTTransNotes, m_settings.ParatextNotesProj); } + + if (loadMappings) + ParatextHelper.LoadProjectMappings(m_settings); } /// ------------------------------------------------------------------------------------ @@ -1243,10 +1249,12 @@ private bool SetParatextProjectIds() // The projects will only be assigned if the project can be loaded (part of the set // property). m_settings.ParatextScrProj = GetPTShortName(cboPTLangProj); - CheckProjectCombo(m_settings.ParatextScrProj, cboPTLangProj, ImportDomain.Main); m_settings.ParatextBTProj = GetPTShortName(cboPTBackTrans); - CheckProjectCombo(m_settings.ParatextBTProj, cboPTBackTrans, ImportDomain.BackTrans); m_settings.ParatextNotesProj = GetPTShortName(cboPTTransNotes); + ParatextHelper.LoadProjectMappings(m_settings); + + CheckProjectCombo(m_settings.ParatextScrProj, cboPTLangProj, ImportDomain.Main); + CheckProjectCombo(m_settings.ParatextBTProj, cboPTBackTrans, ImportDomain.BackTrans); CheckProjectCombo(m_settings.ParatextNotesProj, cboPTTransNotes, ImportDomain.Annotations); diff --git a/Src/TE/TeImportExport/ScrObjWrapper.cs b/Src/TE/TeImportExport/ScrObjWrapper.cs index 042d8a7a54..f36619089a 100644 --- a/Src/TE/TeImportExport/ScrObjWrapper.cs +++ b/Src/TE/TeImportExport/ScrObjWrapper.cs @@ -410,7 +410,7 @@ public virtual int CurrentLineNumber /// ------------------------------------------------------------------------------------ public List BooksPresent { - get { return m_settings.BooksForProject; } + get { return m_settings.BooksForProject(); } } /// ------------------------------------------------------------------------------------ diff --git a/Src/TE/TeImportExport/TeImportExport.csproj b/Src/TE/TeImportExport/TeImportExport.csproj index fadca36b6f..3a6151ae69 100644 --- a/Src/TE/TeImportExport/TeImportExport.csproj +++ b/Src/TE/TeImportExport/TeImportExport.csproj @@ -1,389 +1,390 @@ - + - Debug - AnyCPU - 9.0.30729 - 2.0 - {1C23DE94-04CC-470A-9D1E-E236E23B9C8A} - Library - Properties - SIL.FieldWorks.TE - TeImportExport - v4.0 - 512 - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - + Debug + AnyCPU + 9.0.30729 + 2.0 + {1C23DE94-04CC-470A-9D1E-E236E23B9C8A} + Library + Properties + SIL.FieldWorks.TE + TeImportExport + v4.0 + 512 + + + 3.5 + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + - true - full - false - 168,169,219,414,649,1635,1702,1701 - ..\..\..\Output\Debug\ - DEBUG;TRACE - prompt - 4 - ..\..\..\Output\Debug\TeImportExport.xml - true - 4096 - AllRules.ruleset - x86 + true + full + false + 168,169,219,414,649,1635,1702,1701 + ..\..\..\Output\Debug\ + DEBUG;TRACE + prompt + 4 + ..\..\..\Output\Debug\TeImportExport.xml + true + 4096 + AllRules.ruleset + x86 - pdbonly - true - 168,169,219,414,649,1635,1702,1701 - ..\..\..\Output\Release\ - TRACE - prompt - 4 - AllRules.ruleset - x86 + pdbonly + true + 168,169,219,414,649,1635,1702,1701 + ..\..\..\Output\Release\ + TRACE + prompt + 4 + AllRules.ruleset + x86 - - ..\..\..\Output\Debug\BasicUtils.dll - False - - - ..\..\..\Output\Debug\COMInterfaces.dll - False - - - False - ..\..\..\Output\Debug\CoreImpl.dll - - - False - ..\..\..\Output\Debug\DiffView.dll - - - False - ..\..\..\Output\Debug\ECInterfaces.dll - - - ..\..\..\Output\Debug\FDO.dll - False - - - ..\..\..\Output\Debug\Framework.dll - False - - - ..\..\..\Output\Debug\FwControls.dll - False - - - False - ..\..\..\Output\Debug\FwCoreDlgControls.dll - - - False - ..\..\..\Output\Debug\FwCoreDlgs.dll - - - ..\..\..\Output\Debug\FwResources.dll - False - - - ..\..\..\Output\Debug\FwUtils.dll - False - - - False - ..\..\..\Output\Debug\ITextDll.dll - - - False - ..\..\..\DistFiles\Microsoft.Practices.ServiceLocation.dll - - - False - ..\..\..\Output\Debug\OxesIO.dll - - - ..\..\..\Output\Debug\ParatextShared.dll - False - - - False - ..\..\..\Output\Debug\Reporting.dll - - - ..\..\..\Output\Debug\RootSite.dll - False - - - ..\..\..\Output\Debug\ScrControls.dll - False - - - ..\..\..\Output\Debug\ScriptureUtils.dll - False - - - ..\..\..\Output\Debug\ScrUtilsInterfaces.dll - False - - - False - - - ..\..\..\Output\Debug\SharedScrUtils.dll - False - - - False - ..\..\..\Output\Debug\SilEncConverters40.dll - - - False - ..\..\..\Output\Debug\SilUtils.dll - - - False - ..\..\..\Output\Debug\SimpleRootSite.dll - - - False - - - - False - - - - - False - - - ..\..\..\Output\Debug\TeDialogs.dll - False - - - False - ..\..\..\Output\Debug\TeEditing.dll - - - False - ..\..\..\Output\Debug\TeEditorialChecks.dll - - - ..\..\..\Output\Debug\TeRegistrySettings.dll - False - - - ..\..\..\Output\Debug\TeResources.dll - False - - - ..\..\..\Output\Debug\Widgets.dll - False - - - ..\..\..\Output\Debug\xCoreInterfaces.dll - False - - - False - ..\..\..\Output\Debug\XMLUtils.dll - + + ..\..\..\Output\Debug\BasicUtils.dll + False + + + ..\..\..\Output\Debug\COMInterfaces.dll + False + + + False + ..\..\..\Output\Debug\CoreImpl.dll + + + False + ..\..\..\Output\Debug\DiffView.dll + + + False + ..\..\..\Output\Debug\ECInterfaces.dll + + + ..\..\..\Output\Debug\FDO.dll + False + + + ..\..\..\Output\Debug\Framework.dll + False + + + ..\..\..\Output\Debug\FwControls.dll + False + + + False + ..\..\..\Output\Debug\FwCoreDlgControls.dll + + + False + ..\..\..\Output\Debug\FwCoreDlgs.dll + + + ..\..\..\Output\Debug\FwResources.dll + False + + + ..\..\..\Output\Debug\FwUtils.dll + False + + + False + ..\..\..\Output\Debug\ITextDll.dll + + + False + ..\..\..\DistFiles\Microsoft.Practices.ServiceLocation.dll + + + False + ..\..\..\Output\Debug\OxesIO.dll + + + ..\..\..\Output\Debug\ParatextShared.dll + False + + + False + ..\..\..\Output\Debug\Reporting.dll + + + ..\..\..\Output\Debug\RootSite.dll + False + + + ..\..\..\Output\Debug\ScrControls.dll + False + + + ..\..\..\Output\Debug\ScriptureUtils.dll + False + + + ..\..\..\Output\Debug\ScrUtilsInterfaces.dll + False + + + False + + + ..\..\..\Output\Debug\SharedScrUtils.dll + False + + + False + ..\..\..\Output\Debug\SilEncConverters40.dll + + + False + ..\..\..\Output\Debug\SilUtils.dll + + + False + ..\..\..\Output\Debug\SimpleRootSite.dll + + + False + + + + False + + + + + False + + + ..\..\..\Output\Debug\TeDialogs.dll + False + + + False + ..\..\..\Output\Debug\TeEditing.dll + + + False + ..\..\..\Output\Debug\TeEditorialChecks.dll + + + ..\..\..\Output\Debug\TeRegistrySettings.dll + False + + + ..\..\..\Output\Debug\TeResources.dll + False + + + ..\..\..\Output\Debug\Widgets.dll + False + + + ..\..\..\Output\Debug\xCoreInterfaces.dll + False + + + False + ..\..\..\Output\Debug\XMLUtils.dll + - - Properties\CommonAssemblyInfo.cs - - - Form - - - Form - - - - Form - - - ExportPtxDialog.cs - - - - Form - - - Form - - - ExportTbxDialog.cs - - - - Form - - - - - Form - - - UserControl - - - Form - - - - Form - - - Form - - - ImportXmlDialog.cs - - - UserControl - - - Form - - - - Form - - - - - - - True - True - ScrImportComponents.resx - - - Form - - - - - - - UserControl - - - - - - - - - - - - - - - - - + + Properties\CommonAssemblyInfo.cs + + + Form + + + Form + + + + Form + + + ExportPtxDialog.cs + + + + Form + + + Form + + + ExportTbxDialog.cs + + + + Form + + + + + Form + + + UserControl + + + Form + + + + Form + + + Form + + + ImportXmlDialog.cs + + + UserControl + + + Form + + + + Form + + + + + + + True + True + ScrImportComponents.resx + + + Form + + + + + + + UserControl + + + + + + + + + + + + + + + + + + - - CharacterMappingSettings.cs - - - ConfirmOverlappingFileReplaceDialog.cs - - - ExportPtxDialog.cs - Designer - - - ExportRtfDialog.cs - Designer - - - ExportTbxDialog.cs - Designer - - - ExportUsfmDialog.cs - Designer - - - ExportXmlDialog.cs - Designer - - - FileNameSchemeCtrl.cs - Designer - - - ImportDialog.cs - Designer - - - ImportWizard.cs - - - ImportXmlDialog.cs - Designer - - - MappingDetailsCtrl.cs - - - ModifyMapping.cs - - - Paratext5LocationUnknown.cs - - - ResXFileCodeGenerator - ScrImportComponents.Designer.cs - - - ScrImportSetMessage.cs - - - SFFileListBuilder.cs - + + CharacterMappingSettings.cs + + + ConfirmOverlappingFileReplaceDialog.cs + + + ExportPtxDialog.cs + Designer + + + ExportRtfDialog.cs + Designer + + + ExportTbxDialog.cs + Designer + + + ExportUsfmDialog.cs + Designer + + + ExportXmlDialog.cs + Designer + + + FileNameSchemeCtrl.cs + Designer + + + ImportDialog.cs + Designer + + + ImportWizard.cs + + + ImportXmlDialog.cs + Designer + + + MappingDetailsCtrl.cs + + + ModifyMapping.cs + + + Paratext5LocationUnknown.cs + + + ResXFileCodeGenerator + ScrImportComponents.Designer.cs + + + ScrImportSetMessage.cs + + + SFFileListBuilder.cs + - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 60, 12 + + + 488, 52 + + + + 3 + + + Some files in the Linked Files folder are newer than the ones which will be restored, and these may not be files that this FieldWorks project links to yet. + + + label_message + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 6 + + + 60, 64 + + + 488, 41 + + + 4 + + + Would you like to keep the newer files in the folder or replace them with the older ones from the backup? + + + label_Question + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 5 + + + 12, 12 + + + 42, 38 + + + 5 + + + pictureBox1 + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + True + + + + NoControl + + + 64, 132 + + + 192, 17 + + + 13 + + + Use the older files from the backup. + + + radio_Overwrite + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + NoControl + + + 64, 109 + + + 164, 17 + + + 12 + + + Keep newer files in the folder. + + + radio_Keep + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + NoControl + + + 473, 157 + + + 75, 23 + + + 10 + + + Cancel + + + button_Cancel + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + NoControl + + + 392, 157 + + + 75, 23 + + + 9 + + + OK + + + button_OK + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + True + + + 6, 13 + + + 561, 192 + + + Linked files in backup are older + + + FilesToRestoreAreOlder + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Src/FwParatextLexiconPlugin/FwLexiconPlugin.cs b/Src/FwParatextLexiconPlugin/FwLexiconPlugin.cs index 40f333a67b..3cd21580fe 100644 --- a/Src/FwParatextLexiconPlugin/FwLexiconPlugin.cs +++ b/Src/FwParatextLexiconPlugin/FwLexiconPlugin.cs @@ -36,10 +36,10 @@ public FwLexiconPlugin() m_activationContext = new ActivationContextHelper("FwParatextLexiconPlugin.dll.manifest"); // initialize client-server services to use Db4O backend for FDO - var ui = ParatextLexiconFdoUI.Instance; - var dirs = ParatextLexiconDirectoryFinder.FdoDirectories; + var ui = ParatextLexiconPluginFdoUI.Instance; + var dirs = ParatextLexiconPluginDirectoryFinder.FdoDirectories; ClientServerServices.SetCurrentToDb4OBackend(ui, dirs, - () => dirs.ProjectsDirectory == ParatextLexiconDirectoryFinder.ProjectsDirectoryLocalMachine); + () => dirs.ProjectsDirectory == ParatextLexiconPluginDirectoryFinder.ProjectsDirectoryLocalMachine); } /// @@ -160,17 +160,17 @@ private FdoCache GetFdoCache(string projectId) else { var backendProviderType = FDOBackendProviderType.kSharedXML; - string path = Path.Combine(ParatextLexiconDirectoryFinder.ProjectsDirectory, projectId, projectId + FdoFileHelper.ksFwDataXmlFileExtension); + string path = Path.Combine(ParatextLexiconPluginDirectoryFinder.ProjectsDirectory, projectId, projectId + FdoFileHelper.ksFwDataXmlFileExtension); if (!File.Exists(path)) { backendProviderType = FDOBackendProviderType.kDb4oClientServer; - path = Path.Combine(ParatextLexiconDirectoryFinder.ProjectsDirectory, projectId, projectId + FdoFileHelper.ksFwDataDb4oFileExtension); + path = Path.Combine(ParatextLexiconPluginDirectoryFinder.ProjectsDirectory, projectId, projectId + FdoFileHelper.ksFwDataDb4oFileExtension); if (!File.Exists(path)) throw new LexiconUnavailableException("The associated Fieldworks project has been moved, renamed, or does not exist."); } - var progress = new ParatextLexiconThreadedProgress(ParatextLexiconFdoUI.Instance.SynchronizeInvoke) { IsIndeterminate = true, Title = string.Format("Opening {0}", projectId) }; - fdoCache = (FdoCache) progress.RunTask(CreateFdoCache, new ParatextLexiconProjectIdentifier(backendProviderType, path)); + var progress = new ParatextLexiconPluginThreadedProgress(ParatextLexiconPluginFdoUI.Instance.SynchronizeInvoke) { IsIndeterminate = true, Title = string.Format("Opening {0}", projectId) }; + fdoCache = (FdoCache) progress.RunTask(CreateFdoCache, new ParatextLexiconPluginProjectID(backendProviderType, path)); m_fdoCacheCache.Add(fdoCache); } @@ -179,10 +179,10 @@ private FdoCache GetFdoCache(string projectId) private static FdoCache CreateFdoCache(IThreadedProgress progress, object[] parameters) { - var projectId = (ParatextLexiconProjectIdentifier) parameters[0]; + var projectId = (ParatextLexiconPluginProjectID) parameters[0]; try { - return FdoCache.CreateCacheFromExistingData(projectId, Thread.CurrentThread.CurrentUICulture.Name, ParatextLexiconFdoUI.Instance, ParatextLexiconDirectoryFinder.FdoDirectories, progress, true); + return FdoCache.CreateCacheFromExistingData(projectId, Thread.CurrentThread.CurrentUICulture.Name, ParatextLexiconPluginFdoUI.Instance, ParatextLexiconPluginDirectoryFinder.FdoDirectories, progress, true); } catch (FdoDataMigrationForbiddenException) { @@ -190,7 +190,7 @@ private static FdoCache CreateFdoCache(IThreadedProgress progress, object[] para } catch (FdoFileLockedException) { - throw new LexiconUnavailableException("Fieldworks and Paratext cannot access the same project at the same time unless the Fieldworks project is shared."); + throw new LexiconUnavailableException("Paratext cannot currently access the lexicon. Please close FieldWorks."); } catch (StartupException se) { diff --git a/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj b/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj index 6ca8db8105..03ec0770b4 100644 --- a/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj +++ b/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj @@ -85,15 +85,21 @@ + + Form + + + FilesToRestoreAreOlder.cs + - - - - + + + + Form @@ -101,14 +107,39 @@ ProjectExistsForm.cs + + True + True + Resources.resx + + + True + True + Strings.resx + ChooseFdoProjectForm.cs + + FilesToRestoreAreOlder.cs + Designer + ProjectExistsForm.cs + + ResXFileCodeGenerator + Resources.Designer.cs + + + ResXFileCodeGenerator + Strings.Designer.cs + + + + diff --git a/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FdoLexiconTests.cs b/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FdoLexiconTests.cs index 75bd1c9e7c..2159279815 100644 --- a/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FdoLexiconTests.cs +++ b/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FdoLexiconTests.cs @@ -34,8 +34,8 @@ public void SetUp() { m_threadHelper = new ThreadHelper(); var ui = new DummyFdoUI(m_threadHelper); - var projectId = new ParatextLexiconProjectIdentifier(FDOBackendProviderType.kMemoryOnly, "Test.fwdata"); - m_cache = FdoCache.CreateCacheWithNewBlankLangProj(projectId, "en", "fr", "en", ui, ParatextLexiconDirectoryFinder.FdoDirectories); + var projectId = new ParatextLexiconPluginProjectID(FDOBackendProviderType.kMemoryOnly, "Test.fwdata"); + m_cache = FdoCache.CreateCacheWithNewBlankLangProj(projectId, "en", "fr", "en", ui, ParatextLexiconPluginDirectoryFinder.FdoDirectories); NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, () => { m_cache.ServiceLocator.WritingSystems.AddToCurrentAnalysisWritingSystems(m_cache.ServiceLocator.WritingSystemManager.Get("fr")); diff --git a/Src/FwParatextLexiconPlugin/ParatextLexiconFdoUI.cs b/Src/FwParatextLexiconPlugin/ParatextLexiconFdoUI.cs deleted file mode 100644 index 808c736661..0000000000 --- a/Src/FwParatextLexiconPlugin/ParatextLexiconFdoUI.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using System.ComponentModel; -using System.Windows.Forms; -using SIL.FieldWorks.FDO; - -namespace SIL.FieldWorks.ParatextLexiconPlugin -{ - internal class ParatextLexiconFdoUI : IFdoUI - { - // Singleton - private static readonly ParatextLexiconFdoUI s_instance = new ParatextLexiconFdoUI(); - private ParatextLexiconFdoUI(){} - public static ParatextLexiconFdoUI Instance - { - get { return s_instance; } - } - - public bool ConflictingSave() - { - throw new NotImplementedException(); - } - - /// - /// Inform the user of a lost connection - /// - /// True if user wishes to attempt reconnect. False otherwise. - public bool ConnectionLost() - { - return (bool)SynchronizeInvoke.Invoke(new Func(() => MessageBox.Show( - "There is a problem with the connection to the lexicon. Usually, this occurs when there is a problem with the FwRemoteDatabaseConnectorService. Would you like to attempt to reestablish the connection?", - "Lexicon Connection Lost", MessageBoxButtons.YesNo) == DialogResult.Yes), null); - } - - public FileSelection ChooseFilesToUse() - { - throw new NotImplementedException(); - } - - public bool RestoreLinkedFilesInProjectFolder() - { - throw new NotImplementedException(); - } - - public YesNoCancel CannotRestoreLinkedFilesToOriginalLocation() - { - throw new NotImplementedException(); - } - - public void DisplayMessage(MessageType type, string message, string caption, string helpTopic) - { - throw new NotImplementedException(); - } - - public void ReportException(Exception error, bool isLethal) - { - throw new NotImplementedException(); - } - - public void ReportDuplicateGuids(string errorText) - { - throw new NotImplementedException(); - } - - public bool Retry(string msg, string caption) - { - throw new NotImplementedException(); - } - - public bool OfferToRestore(string projectPath, string backupPath) - { - throw new NotImplementedException(); - } - - public void Exit() - { - System.Windows.Forms.Application.Exit(); - } - - public ISynchronizeInvoke SynchronizeInvoke - { - get - { - Form form = Form.ActiveForm; - if (form != null) - return form; - if (System.Windows.Forms.Application.OpenForms.Count > 0) - return System.Windows.Forms.Application.OpenForms[0]; - return null; - } - } - public DateTime LastActivityTime { get; private set; } - } -} diff --git a/Src/FwParatextLexiconPlugin/ParatextLexiconDirectoryFinder.cs b/Src/FwParatextLexiconPlugin/ParatextLexiconPluginDirectoryFinder.cs similarity index 91% rename from Src/FwParatextLexiconPlugin/ParatextLexiconDirectoryFinder.cs rename to Src/FwParatextLexiconPlugin/ParatextLexiconPluginDirectoryFinder.cs index a8bbadfa0e..40b56b0728 100644 --- a/Src/FwParatextLexiconPlugin/ParatextLexiconDirectoryFinder.cs +++ b/Src/FwParatextLexiconPlugin/ParatextLexiconPluginDirectoryFinder.cs @@ -8,11 +8,11 @@ namespace SIL.FieldWorks.ParatextLexiconPlugin { - internal static class ParatextLexiconDirectoryFinder + internal static class ParatextLexiconPluginDirectoryFinder { - private static readonly IFdoDirectories s_fdoDirs = new ParatextLexiconFdoDirectories(); + private static readonly IFdoDirectories s_fdoDirs = new ParatextLexiconPluginFdoDirectories(); - static ParatextLexiconDirectoryFinder() + static ParatextLexiconPluginDirectoryFinder() { RegistryHelper.CompanyName = DirectoryFinder.CompanyName; RegistryHelper.ProductName = ProductName; @@ -131,15 +131,15 @@ private static string GetDirectoryLocalMachine(string registryValue, string defa } } - private class ParatextLexiconFdoDirectories : IFdoDirectories + private class ParatextLexiconPluginFdoDirectories : IFdoDirectories { public string ProjectsDirectory { - get { return ParatextLexiconDirectoryFinder.ProjectsDirectory; } + get { return ParatextLexiconPluginDirectoryFinder.ProjectsDirectory; } } public string TemplateDirectory { - get { return ParatextLexiconDirectoryFinder.TemplateDirectory; } + get { return ParatextLexiconPluginDirectoryFinder.TemplateDirectory; } } } } diff --git a/Src/FwParatextLexiconPlugin/ParatextLexiconPluginFdoUI.cs b/Src/FwParatextLexiconPlugin/ParatextLexiconPluginFdoUI.cs new file mode 100644 index 0000000000..41ce1e3a85 --- /dev/null +++ b/Src/FwParatextLexiconPlugin/ParatextLexiconPluginFdoUI.cs @@ -0,0 +1,147 @@ +using System; +using System.ComponentModel; +using System.IO; +using System.Windows.Forms; +using SIL.FieldWorks.FDO; + +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + internal class ParatextLexiconPluginFdoUI : IFdoUI + { + // Singleton + private static readonly ParatextLexiconPluginFdoUI s_instance = new ParatextLexiconPluginFdoUI(); + private ParatextLexiconPluginFdoUI(){} + public static ParatextLexiconPluginFdoUI Instance + { + get { return s_instance; } + } + + public bool ConflictingSave() + { + SynchronizeInvoke.Invoke(new Action(() => MessageBox.Show(Strings.ksConflictingSaveText, + Strings.ksConflictingSaveCaption, MessageBoxButtons.OK, MessageBoxIcon.Warning)), null); + return true; + } + + /// + /// Inform the user of a lost connection + /// + /// True if user wishes to attempt reconnect. False otherwise. + public bool ConnectionLost() + { + return (bool) SynchronizeInvoke.Invoke(new Func(() => MessageBox.Show(Strings.ksConnectionLostText, + Strings.ksConnectionLostCaption, MessageBoxButtons.YesNo) == DialogResult.Yes), null); + } + + public FileSelection ChooseFilesToUse() + { + using (var dlg = new FilesToRestoreAreOlder()) + { + if (dlg.ShowDialog() == DialogResult.OK) + { + if (dlg.fKeepFilesThatAreNewer) + { + return FileSelection.OkKeepNewer; + } + if (dlg.fOverWriteThatAreNewer) + { + return FileSelection.OkUseOlder; + } + } + return FileSelection.Cancel; + } + } + + public bool RestoreLinkedFilesInProjectFolder() + { + return (bool) SynchronizeInvoke.Invoke(new Func(() => MessageBox.Show( + Strings.ksRestoreLinkedFilesInProjectFolderText, Strings.ksRestoreLinkedFilesInProjectFolderCaption, + MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes), null); + } + + public YesNoCancel CannotRestoreLinkedFilesToOriginalLocation() + { + var result = (DialogResult) SynchronizeInvoke.Invoke(new Func(() => MessageBox.Show( + Strings.ksCannotRestoreLinkedFilesToOriginalLocationText, Strings.ksCannotRestoreLinkedFilesToOriginalLocationCaption, + MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)), null); + switch (result) + { + case DialogResult.Yes: + return YesNoCancel.OkYes; + case DialogResult.No: + return YesNoCancel.OkNo; + } + return YesNoCancel.Cancel; + } + + public void DisplayMessage(MessageType type, string message, string caption, string helpTopic) + { + var icon = MessageBoxIcon.Information; + switch (type) + { + case MessageType.Error: + icon = MessageBoxIcon.Error; + break; + case MessageType.Info: + icon = MessageBoxIcon.Information; + break; + case MessageType.Warning: + icon = MessageBoxIcon.Warning; + break; + } + SynchronizeInvoke.Invoke(new Action(() => MessageBox.Show(message, caption, MessageBoxButtons.OK, icon)), null); + } + + public void ReportException(Exception error, bool isLethal) + { + // do nothing + } + + public void ReportDuplicateGuids(string errorText) + { + // do nothing + } + + public bool Retry(string msg, string caption) + { + return (bool) SynchronizeInvoke.Invoke(new Func(() => MessageBox.Show(msg, caption, + MessageBoxButtons.RetryCancel, MessageBoxIcon.None) == DialogResult.Retry), null); + } + + public bool OfferToRestore(string projectPath, string backupPath) + { + return (bool) SynchronizeInvoke.Invoke(new Func(() => MessageBox.Show( + String.Format(Strings.ksOfferToRestoreText, projectPath, File.GetLastWriteTime(projectPath), + backupPath, File.GetLastWriteTime(backupPath)), + Strings.ksOfferToRestoreCaption, MessageBoxButtons.YesNo, + MessageBoxIcon.Error) == DialogResult.Yes), null); + } + + public void Exit() + { + Application.Exit(); + } + + public ISynchronizeInvoke SynchronizeInvoke + { + get + { + Form form = Form.ActiveForm; + if (form != null) + return form; + if (Application.OpenForms.Count > 0) + return Application.OpenForms[0]; + return null; + } + } + + public DateTime LastActivityTime + { + get + { + // this effectively disables saving on idle + return DateTime.Now; + } + } + } +} diff --git a/Src/FwParatextLexiconPlugin/ParatextLexiconProjectIdentifier.cs b/Src/FwParatextLexiconPlugin/ParatextLexiconPluginProjectID.cs similarity index 84% rename from Src/FwParatextLexiconPlugin/ParatextLexiconProjectIdentifier.cs rename to Src/FwParatextLexiconPlugin/ParatextLexiconPluginProjectID.cs index 1cf832c91b..4b31f28663 100644 --- a/Src/FwParatextLexiconPlugin/ParatextLexiconProjectIdentifier.cs +++ b/Src/FwParatextLexiconPlugin/ParatextLexiconPluginProjectID.cs @@ -3,11 +3,11 @@ namespace SIL.FieldWorks.ParatextLexiconPlugin { - internal class ParatextLexiconProjectIdentifier : IProjectIdentifier + internal class ParatextLexiconPluginProjectID : IProjectIdentifier { private readonly FDOBackendProviderType m_backendProviderType; - public ParatextLexiconProjectIdentifier(FDOBackendProviderType backendProviderType, string projectPath) + public ParatextLexiconPluginProjectID(FDOBackendProviderType backendProviderType, string projectPath) { m_backendProviderType = backendProviderType; Path = projectPath; diff --git a/Src/FwParatextLexiconPlugin/ParatextLexiconThreadedProgress.cs b/Src/FwParatextLexiconPlugin/ParatextLexiconPluginThreadedProgress.cs similarity index 92% rename from Src/FwParatextLexiconPlugin/ParatextLexiconThreadedProgress.cs rename to Src/FwParatextLexiconPlugin/ParatextLexiconPluginThreadedProgress.cs index 6d5548b47f..06cbfb644b 100644 --- a/Src/FwParatextLexiconPlugin/ParatextLexiconThreadedProgress.cs +++ b/Src/FwParatextLexiconPlugin/ParatextLexiconPluginThreadedProgress.cs @@ -4,11 +4,11 @@ namespace SIL.FieldWorks.ParatextLexiconPlugin { - internal class ParatextLexiconThreadedProgress : IThreadedProgress + internal class ParatextLexiconPluginThreadedProgress : IThreadedProgress { private readonly ISynchronizeInvoke m_synchronizeInvoke; - public ParatextLexiconThreadedProgress(ISynchronizeInvoke synchronizeInvoke) + public ParatextLexiconPluginThreadedProgress(ISynchronizeInvoke synchronizeInvoke) { m_synchronizeInvoke = synchronizeInvoke; } diff --git a/Src/FwParatextLexiconPlugin/ProjectExistsForm.Designer.cs b/Src/FwParatextLexiconPlugin/ProjectExistsForm.Designer.cs index af58e5ad42..13f6e97efa 100644 --- a/Src/FwParatextLexiconPlugin/ProjectExistsForm.Designer.cs +++ b/Src/FwParatextLexiconPlugin/ProjectExistsForm.Designer.cs @@ -29,52 +29,41 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.btnOverwrite = new System.Windows.Forms.Button(); - this.btnRename = new System.Windows.Forms.Button(); - this.label1 = new System.Windows.Forms.Label(); - this.SuspendLayout(); - // - // btnOverwrite - // - this.btnOverwrite.Location = new System.Drawing.Point(189, 85); - this.btnOverwrite.Name = "btnOverwrite"; - this.btnOverwrite.Size = new System.Drawing.Size(75, 23); - this.btnOverwrite.TabIndex = 0; - this.btnOverwrite.Text = "Overwrite"; - this.btnOverwrite.UseVisualStyleBackColor = true; - this.btnOverwrite.Click += new System.EventHandler(this.btnOverwrite_Click); - // - // btnRename - // - this.btnRename.Location = new System.Drawing.Point(271, 84); - this.btnRename.Name = "btnRename"; - this.btnRename.Size = new System.Drawing.Size(75, 23); - this.btnRename.TabIndex = 1; - this.btnRename.Text = "Rename"; - this.btnRename.UseVisualStyleBackColor = true; - this.btnRename.Click += new System.EventHandler(this.btnRename_Click); - // - // label1 - // - this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(13, 13); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(50, 13); - this.label1.TabIndex = 2; - this.label1.Text = "labelText"; - // - // ProjectExistsForm - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(360, 121); - this.Controls.Add(this.label1); - this.Controls.Add(this.btnRename); - this.Controls.Add(this.btnOverwrite); - this.Name = "ProjectExistsForm"; - this.Text = "Project Already Exists"; - this.ResumeLayout(false); - this.PerformLayout(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ProjectExistsForm)); + this.btnOverwrite = new System.Windows.Forms.Button(); + this.btnRename = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // btnOverwrite + // + resources.ApplyResources(this.btnOverwrite, "btnOverwrite"); + this.btnOverwrite.Name = "btnOverwrite"; + this.btnOverwrite.UseVisualStyleBackColor = true; + this.btnOverwrite.Click += new System.EventHandler(this.btnOverwrite_Click); + // + // btnRename + // + resources.ApplyResources(this.btnRename, "btnRename"); + this.btnRename.Name = "btnRename"; + this.btnRename.UseVisualStyleBackColor = true; + this.btnRename.Click += new System.EventHandler(this.btnRename_Click); + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // ProjectExistsForm + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.label1); + this.Controls.Add(this.btnRename); + this.Controls.Add(this.btnOverwrite); + this.Name = "ProjectExistsForm"; + this.ResumeLayout(false); + this.PerformLayout(); } diff --git a/Src/FwParatextLexiconPlugin/ProjectExistsForm.cs b/Src/FwParatextLexiconPlugin/ProjectExistsForm.cs index d0c87ea5bd..48cbd46ca1 100644 --- a/Src/FwParatextLexiconPlugin/ProjectExistsForm.cs +++ b/Src/FwParatextLexiconPlugin/ProjectExistsForm.cs @@ -5,9 +5,6 @@ namespace SIL.FieldWorks.ParatextLexiconPlugin { internal partial class ProjectExistsForm : Form { - private const string labelText1 = "The {0} project already exists."; - private const string labelText2 = "You may overwrite the existing project or select a different name."; - private ProjectExistsForm() { InitializeComponent(); @@ -17,7 +14,7 @@ private ProjectExistsForm() public ProjectExistsForm(string projectName) : this() { - label1.Text = string.Format(labelText1, projectName) + Environment.NewLine + labelText2; + label1.Text = string.Format(Strings.ksProjectExistsText1, projectName) + Environment.NewLine + Strings.ksProjectExistsText2; DialogResult = DialogResult.Cancel; } diff --git a/Src/FwParatextLexiconPlugin/ProjectExistsForm.resx b/Src/FwParatextLexiconPlugin/ProjectExistsForm.resx index 1af7de150c..2f8844c58e 100644 --- a/Src/FwParatextLexiconPlugin/ProjectExistsForm.resx +++ b/Src/FwParatextLexiconPlugin/ProjectExistsForm.resx @@ -117,4 +117,99 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 189, 85 + + + 75, 23 + + + + 0 + + + Overwrite + + + btnOverwrite + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + 271, 84 + + + 75, 23 + + + 1 + + + Rename + + + btnRename + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + True + + + 13, 13 + + + 50, 13 + + + 2 + + + labelText + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 6, 13 + + + 360, 121 + + + Project Already Exists + + + ProjectExistsForm + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + \ No newline at end of file diff --git a/Src/FwParatextLexiconPlugin/Properties/Resources.Designer.cs b/Src/FwParatextLexiconPlugin/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..68d5661ba1 --- /dev/null +++ b/Src/FwParatextLexiconPlugin/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.18444 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SIL.FieldWorks.ParatextLexiconPlugin.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SIL.FieldWorks.ParatextLexiconPlugin.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap question { + get { + object obj = ResourceManager.GetObject("question", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/Src/FwParatextLexiconPlugin/Properties/Resources.resx b/Src/FwParatextLexiconPlugin/Properties/Resources.resx new file mode 100644 index 0000000000..465338dcd5 --- /dev/null +++ b/Src/FwParatextLexiconPlugin/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\question.ico;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/Src/FwParatextLexiconPlugin/Resources/question.ico b/Src/FwParatextLexiconPlugin/Resources/question.ico new file mode 100644 index 0000000000000000000000000000000000000000..b16ecb8719d9350bc8d949401c2a90cab0d4a7ad GIT binary patch literal 23566 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 AQ2+n{ literal 0 HcmV?d00001 diff --git a/Src/FwParatextLexiconPlugin/Strings.Designer.cs b/Src/FwParatextLexiconPlugin/Strings.Designer.cs new file mode 100644 index 0000000000..4fac61bb7c --- /dev/null +++ b/Src/FwParatextLexiconPlugin/Strings.Designer.cs @@ -0,0 +1,216 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.18444 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SIL.FieldWorks.ParatextLexiconPlugin { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Strings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Strings() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SIL.FieldWorks.ParatextLexiconPlugin.Strings", typeof(Strings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Problem With Backup File. + /// + internal static string ksBackupFileProblemCaption { + get { + return ResourceManager.GetString("ksBackupFileProblemCaption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to An error occurred. Please select a different file.. + /// + internal static string ksBackupFileProblemText { + get { + return ResourceManager.GetString("ksBackupFileProblemText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot Restore Linked Files. + /// + internal static string ksCannotRestoreLinkedFilesToOriginalLocationCaption { + get { + return ResourceManager.GetString("ksCannotRestoreLinkedFilesToOriginalLocationCaption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ParaTExt cannot restore the linked files to their original location. If you choose to restore the linked files, they will be placed inside the project folder. Do you wish to restore the linked files anyway? . + /// + internal static string ksCannotRestoreLinkedFilesToOriginalLocationText { + get { + return ResourceManager.GetString("ksCannotRestoreLinkedFilesToOriginalLocationText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot Save Lexicon. + /// + internal static string ksConflictingSaveCaption { + get { + return ResourceManager.GetString("ksConflictingSaveCaption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ParaTExt cannot save changes to the lexicon, because they conflict with changes made by another user or application. The conflicting changes will be reverted.. + /// + internal static string ksConflictingSaveText { + get { + return ResourceManager.GetString("ksConflictingSaveText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Lexicon Connection Lost. + /// + internal static string ksConnectionLostCaption { + get { + return ResourceManager.GetString("ksConnectionLostCaption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There is a problem with the connection to the lexicon. Usually, this occurs when there is a problem with the FwRemoteDatabaseConnectorService. Would you like to attempt to reestablish the connection?. + /// + internal static string ksConnectionLostText { + get { + return ResourceManager.GetString("ksConnectionLostText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Could not connect to server. Check service is running and that any running firewalls are configured to allow connections to the service.. + /// + internal static string ksCouldNotConnectText { + get { + return ResourceManager.GetString("ksCouldNotConnectText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Problem opening file. + /// + internal static string ksOfferToRestoreCaption { + get { + return ResourceManager.GetString("ksOfferToRestoreCaption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There was a problem opening the current version of the file {0}, dated {1}. Would you like to open the automatic backup, {2}, dated {3}?. + /// + internal static string ksOfferToRestoreText { + get { + return ResourceManager.GetString("ksOfferToRestoreText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The {0} project already exists.. + /// + internal static string ksProjectExistsText1 { + get { + return ResourceManager.GetString("ksProjectExistsText1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You may overwrite the existing project or select a different name.. + /// + internal static string ksProjectExistsText2 { + get { + return ResourceManager.GetString("ksProjectExistsText2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Linked Files Folder. + /// + internal static string ksRestoreLinkedFilesInProjectFolderCaption { + get { + return ResourceManager.GetString("ksRestoreLinkedFilesInProjectFolderCaption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Linked Files folder was not previously stored in the project folder. Would you like ParaTExt to restore the linked files within the project folder?. + /// + internal static string ksRestoreLinkedFilesInProjectFolderText { + get { + return ResourceManager.GetString("ksRestoreLinkedFilesInProjectFolderText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to An error occurred and the project could not be restored.. + /// + internal static string ksRestoreProblemText { + get { + return ResourceManager.GetString("ksRestoreProblemText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Warning. + /// + internal static string ksWarningCaption { + get { + return ResourceManager.GetString("ksWarningCaption", resourceCulture); + } + } + } +} diff --git a/Src/FwParatextLexiconPlugin/Strings.resx b/Src/FwParatextLexiconPlugin/Strings.resx new file mode 100644 index 0000000000..ca81e5a929 --- /dev/null +++ b/Src/FwParatextLexiconPlugin/Strings.resx @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ParaTExt cannot save changes to the lexicon, because they conflict with changes made by another user or application. The conflicting changes will be reverted. + + + Cannot Save Lexicon + + + There is a problem with the connection to the lexicon. Usually, this occurs when there is a problem with the FwRemoteDatabaseConnectorService. Would you like to attempt to reestablish the connection? + + + Lexicon Connection Lost + + + Problem opening file + + + There was a problem opening the current version of the file {0}, dated {1}. Would you like to open the automatic backup, {2}, dated {3}? + + + The {0} project already exists. + + + You may overwrite the existing project or select a different name. + + + Warning + + + Could not connect to server. Check service is running and that any running firewalls are configured to allow connections to the service. + + + Problem With Backup File + + + An error occurred. Please select a different file. + + + An error occurred and the project could not be restored. + + + Cannot Restore Linked Files + + + ParaTExt cannot restore the linked files to their original location. If you choose to restore the linked files, they will be placed inside the project folder. Do you wish to restore the linked files anyway? + + + Linked Files Folder + + + The Linked Files folder was not previously stored in the project folder. Would you like ParaTExt to restore the linked files within the project folder? + + \ No newline at end of file diff --git a/Src/FwParatextLexiconPlugin/question.ico b/Src/FwParatextLexiconPlugin/question.ico new file mode 100644 index 0000000000000000000000000000000000000000..b16ecb8719d9350bc8d949401c2a90cab0d4a7ad GIT binary patch literal 23566 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 AQ2+n{ literal 0 HcmV?d00001 From be4365520ead897194922654653e7e2e8a098d80 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 2 May 2014 15:15:41 +0700 Subject: [PATCH 107/143] restricted changing custom fields when using shared XML backend Change-Id: I6566de4fb9e12024724f7534b8b764fc6331a941 --- Src/xWorks/XWorksViewBase.cs | 7 +++++++ Src/xWorks/xWorksStrings.Designer.cs | 22 ++++++++++++++++++++-- Src/xWorks/xWorksStrings.resx | 6 ++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/Src/xWorks/XWorksViewBase.cs b/Src/xWorks/XWorksViewBase.cs index c58398cb10..86b2c631b8 100644 --- a/Src/xWorks/XWorksViewBase.cs +++ b/Src/xWorks/XWorksViewBase.cs @@ -14,6 +14,7 @@ using System.ComponentModel; using System.Windows.Forms; using System.Xml; +using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.Infrastructure; using XCore; using SIL.Utils; @@ -580,6 +581,12 @@ public bool OnAddCustomField(object argument) xWorksStrings.ksCustomFieldsCanNotBeAddedDueToRemoteClientsCaption, MessageBoxButtons.OK, MessageBoxIcon.Warning); return true; } + if (SharedBackendServices.AreMultipleApplicationsConnected(Cache)) + { + MessageBoxUtils.Show(ParentForm, xWorksStrings.ksCustomFieldsCanNotBeAddedDueToOtherAppsText, + xWorksStrings.ksCustomFieldsCanNotBeAddedDueToOtherAppsCaption, MessageBoxButtons.OK, MessageBoxIcon.Warning); + return true; + } AddCustomFieldDlg.LocationType locationType = AddCustomFieldDlg.LocationType.Lexicon; string areaChoice = m_mediator.PropertyTable.GetStringProperty("areaChoice", string.Empty); diff --git a/Src/xWorks/xWorksStrings.Designer.cs b/Src/xWorks/xWorksStrings.Designer.cs index 17d31fdd86..c78a404670 100644 --- a/Src/xWorks/xWorksStrings.Designer.cs +++ b/Src/xWorks/xWorksStrings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.18052 +// Runtime Version:4.0.30319.18444 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -689,6 +689,24 @@ internal static string ksCustomFieldMatchesNonCustomField { } } + /// + /// Looks up a localized string similar to Cannot Add Custom Fields. + /// + internal static string ksCustomFieldsCanNotBeAddedDueToOtherAppsCaption { + get { + return ResourceManager.GetString("ksCustomFieldsCanNotBeAddedDueToOtherAppsCaption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Custom Fields cannot be added when there is more than one application using this project.. + /// + internal static string ksCustomFieldsCanNotBeAddedDueToOtherAppsText { + get { + return ResourceManager.GetString("ksCustomFieldsCanNotBeAddedDueToOtherAppsText", resourceCulture); + } + } + /// /// Looks up a localized string similar to Custom Fields cannot be added.. /// @@ -880,7 +898,7 @@ internal static string ksLexicalRelationTypes { } /// - /// Looks up a localized string similar to This will overwrite the lexicon in that project. Click “Cancel” if you have not already imported that LIFT file into FLEx.. + /// Looks up a localized string similar to There is already a project in that folder. Click “OK” to overwrite the lexicon in that project, or “Cancel” to abort.. /// internal static string ksLIFTAlreadyExists { get { diff --git a/Src/xWorks/xWorksStrings.resx b/Src/xWorks/xWorksStrings.resx index b14265bc87..ffb4908435 100644 --- a/Src/xWorks/xWorksStrings.resx +++ b/Src/xWorks/xWorksStrings.resx @@ -788,4 +788,10 @@ If you are not the one designated user who adds fields, or you are making some o (There is one other special case. If you are adding a temporary custom field for a special purpose and will delete it before you next Send/Receive, you may proceed safely.) + + Cannot Add Custom Fields + + + Custom Fields cannot be added when there is more than one application using this project. + \ No newline at end of file From 0df66aa8e980a13d171afafe2971110a07d9c7b6 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Mon, 5 May 2014 14:23:42 +0700 Subject: [PATCH 108/143] updated Paratext lexical contracts Change-Id: I4545e2943e03f91119652336fdca7c343a9b312d --- DistFiles/ParatextLexicalContracts.dll | Bin 9728 -> 9728 bytes .../FdoLexEntryLexeme.cs | 32 ------------------ Src/FwParatextLexiconPlugin/FdoLexicon.cs | 15 +++++--- .../FdoWordAnalysis.cs | 31 ++++------------- .../FdoWordformLexeme.cs | 5 --- .../FdoLexiconTests.cs | 2 +- 6 files changed, 17 insertions(+), 68 deletions(-) diff --git a/DistFiles/ParatextLexicalContracts.dll b/DistFiles/ParatextLexicalContracts.dll index d7cd12c34ae642079d164c3f182d3f8ddda3f1d7..01d55963d4f2a605c4a0e1b2075ba16f9061e0d7 100644 GIT binary patch delta 2275 zcmaKu4QLcc7>3`O-P!xe-FbKUF~*$9CC2!ZL?vo4AvPLgv<mVpRg|H*@ChY-#7XXWsXl zZ)bLPcV@S{p}S${cH_(Wt&yGpyBImN#M4~`yZ|aSfY*!!(_Kw~i~NI1AXf%?iCoHx z*;Tofh1pTbc)GYV3SiP#P$3ucpQ^jlfWo(cJ5+Z$NryVySGBF|pf1pw1=y)BTpYrB z(q5(O7cZDgbvOAna+OiRO65KyPmHBli9B!Ag}cnP%)*P-HDaS}md(O-+gYOB{*V~d zoTa%~vt2Wy*{69{^JmS+ntq4sXPjoeW16EG%N&4(9gfuw3w=Z zYGjft*KPUaRNHjzraW~Oa*NoKHz-P25OLlUmH*IonQ2`QcN**TJ)=$#b8j~~l1@mY zE5-F1Ta(Ux(0C7Sbr6-9JHtGj;wG8>DXzjCNIFqto}xL&OH72qWYw)zB_^8882oWV zZY{a=gxhFNrfJ4Y%-v&tlj8P}%S^N#F|UE15M5&KbL2)Q+;wvh*$H>wd~Fc)Na_+3 zE-`?dgc~PrWAw0dSBk^P9d_a+5lcFEqj-P--p*Ie?`ALJF>*5Q>^FsMvgdejiYY7~ z$Dalt3Aw|b6HviI{FVrIp%8bUI*&YKuM4XT^>nKebC2OZB%H{$nv-o}h_|t#cp_c8 zN!BJdF5#-kjZe5C9%d60PF>c7b2nPP6t_D3jGbzvHg0{UE%J=}#QGpPg!@RU6DO>X zl5OIwRgRM3lW||N_OjB1t1!a@DK^)(4rSEHP-cshlb)uvBFAd2-_Tk`jQ@<>6RL+d zb$++bf9GF%P#{c6RHY30e>$SOh%<9#L2j!d5d_JJw}D|0rQa_lDpHEE^p^$ zn1nE~2MtCUZRKB(-iBJz>2Q%Q$6jKUW-ShoUZ!;j-;#b^>kfD+e+w#&CPYz$Zq04j zgCAwcRT$>HmVXY;?R2)lPC?r|dWG5njtD=^jKL(@h<4gt9JC`kX$wfB#qFYH>!H=@ zrB&#o73HVZ0Tgq!(2r>z*F0&c$Z2CI@x0cTHGffj9(Rmg)G%c1CK~2`;(9Se+$Pi+ z^#}*?w2oXBV@ZFA=?QXcUQ)|CcVW20QiFAA#s~gY>)$mWS)WqAX;XCB`iVW_6tUR0 zi>4Q#iFz@HsHSa@&ezk<)0e=2Iw6zjMFG8D>7Kwcq|Y-luLyY* zDW)ur33O>V-OM6l3B@?dWW6U)H=S-F#|(NoaC(JQ5NBZ~@j1GwoL<}2#M$IH=1|R1 zOFxczs3X?Xk7GU-$bQdg_LcnFQx^Tx(`v{r|E8!reJ1zSwzn+rY+16deZ}myQg-yStcyGwMm}9hpkRaV!l8!j zIqzp=9?QzUax2<9s+pxZ^O=8srhgRk=SKg^Vf47smq$qDbNaW@-%DQ~-T?4&Xm054 z?Tz!E^iHnX+nRm5apCuKM#$2@GXFu!7%r!j&W{AM_|YnPBJhf=Vcw``%oD-CtBU#x J{$PiCdnZq6#mL=VHUk=T?Sk2<+ep5_9bwf z%XV2bRdc!K2F>l7eVS)9FKPa%>2a&Gf^OAMwdM=%kh_UCyNN97b$7ZgIsj{7Z) z=oEU?@FkkVhKi@__(hLu`kKdf$>U~gQzkLY=Mc>yA9<-vTfep^Xri_swfU%m4q|R2 zFrp`Es?M2g4rRce(YXSc%1zfc`Jv5_ouV^8(<*0$6ypSI*1zH!nPClwyA7XyX6S^X zPLHuA$v!vQ6DCd>T}d`zY)zOmWV}y~>H;O|EH+Oh*?RMfBx^DI6DD2{n`dzgVkIg* zfT;(qN>uDOqvVeX><}zHZYRx3OgdJg&Y<~Sl3j#l#B2nJZvT zW_i>b&(-8Yzf4LN(7;2huw<7jC!o#<(v5g!7X@kLp)HURSBM8J`M{ME9_3A}m|`U= zmRT)KZ3|VRVlAvRCa_W7!OG&M?quAYZp)WsyC1PBSSpE@habtE4nLxU*0#hD&c$RC z!`7}uPTa7nu;ybW>fEvRvhuh!V8Dd6m?w3P(Oet9A|MAtIu6-kB2JxJwt-wHjQ_2f zV5u%X*6n+A`~8o_nYvAkV?)LU{tt%HU7zkE#^jS#%qccxA~vW-4{$=C6^WBm|6}nv z)Nnel>s8F?f-SI*{P-R6V|_J{EKXTGWq=J(1Fxb%@GQFse#@?am2^$>CU~CxO^ZA? znGf-8c_3xg`i;B-kDvqGMe~dbT0*B0Z>JfE(}^LjqP^g3&06{t@oF76(l>}-)^R%t zwC|)!V;x1Pgt|4iQ!jllSEUBS_gO7JL-&~r7q8YNe(&iAq4xfD;m70{nV=22Ffli# z<-zDF*vYBbqF!vpG;A^-Yuf79`Z=BVNd$}m;B$ovGH zYJLXJH2c6KViX(@>beGn8@#7$Y^xaYKAINi3~ON`mLVq?-fyWs4`{}Qw`^78*UYth z(Y{o((msqhc0q$8g4>XX>84RWs3vb9F4U7R&^N*$bwMVWh8=I=rWAo3Zlm4;Ii<+o zoigT^K5tfjw(jXE^nsOzGdMkshrqFaO2J98&Kp=#g$K#;PcaRw#)sp7WhPjIN6Tq0 zjN`w2E;tV#PV=c2tfdgRkm|rXss|U*5_!y<%dW^FZ$;!U?*=2KzO|#dZS$tq=Jjo| z-v42;M~3`$T;^xomPMHzsc&p)dxSky2W}XTmJxWmsv3Y diff --git a/Src/FwParatextLexiconPlugin/FdoLexEntryLexeme.cs b/Src/FwParatextLexiconPlugin/FdoLexEntryLexeme.cs index dd052b0308..79eb94bbcb 100644 --- a/Src/FwParatextLexiconPlugin/FdoLexEntryLexeme.cs +++ b/Src/FwParatextLexiconPlugin/FdoLexEntryLexeme.cs @@ -68,38 +68,6 @@ public string DisplayString } } - public string InterlinearDisplayString - { - get - { - using (m_lexicon.ActivationContext.Activate()) - { - // Add pre- post markers, if any. - string prefix = string.Empty; - string postfix = string.Empty; - if (Type == LexemeType.Stem) - { - prefix = "/"; - postfix = "/"; - } - else - { - ILexEntry entry; - if (m_lexicon.TryGetEntry(m_key, out entry)) - { - IMoMorphType mmt = entry.PrimaryMorphType; - if (mmt != null) // It may be null. - { - prefix = mmt.Prefix; - postfix = mmt.Postfix; - } - } - } - return prefix + LexicalForm + postfix; - } - } - } - public string CitationForm { get diff --git a/Src/FwParatextLexiconPlugin/FdoLexicon.cs b/Src/FwParatextLexiconPlugin/FdoLexicon.cs index 9731d069af..aa2677bc68 100644 --- a/Src/FwParatextLexiconPlugin/FdoLexicon.cs +++ b/Src/FwParatextLexiconPlugin/FdoLexicon.cs @@ -324,6 +324,11 @@ public IEnumerable ValidLanguages #endregion #region WordAnalyses implementation + public WordAnalysis CreateWordAnalysis(IEnumerable lexemes) + { + return new FdoWordAnalysis(lexemes); + } + public IEnumerable GetWordAnalyses(string word) { using (m_activationContext.Activate()) @@ -335,8 +340,8 @@ public IEnumerable GetWordAnalyses(string word) var analyses = new HashSet(); foreach (IWfiAnalysis analysis in wordform.AnalysesOC.Where(a => a.MorphBundlesOS.Count > 0 && a.ApprovalStatusIcon == (int) Opinions.approves)) { - FdoWordAnalysis lexemes; - if (GetMorpologySegment(analysis, out lexemes)) + WordAnalysis lexemes; + if (GetWordAnalysis(analysis, out lexemes)) analyses.Add(lexemes); } return analyses; @@ -421,9 +426,9 @@ public IEnumerable> GetWordAnalyses() var analyses = new HashSet>(); foreach (IWfiAnalysis analysis in m_cache.ServiceLocator.GetInstance().AllInstances().Where(a => a.MorphBundlesOS.Count > 0 && a.ApprovalStatusIcon == (int) Opinions.approves)) { - FdoWordAnalysis lexemes; + WordAnalysis lexemes; string wordFormWs = analysis.Wordform.Form.get_String(m_defaultVernWs).Text; - if (wordFormWs != null && GetMorpologySegment(analysis, out lexemes)) + if (wordFormWs != null && GetWordAnalysis(analysis, out lexemes)) analyses.Add(new KeyValuePair(wordFormWs.Normalize(), lexemes)); } return analyses; @@ -431,7 +436,7 @@ public IEnumerable> GetWordAnalyses() } #endregion - private bool GetMorpologySegment(IWfiAnalysis analysis, out FdoWordAnalysis lexemes) + private bool GetWordAnalysis(IWfiAnalysis analysis, out WordAnalysis lexemes) { var lexemeArray = new Lexeme[analysis.MorphBundlesOS.Count]; for (int i = 0; i < analysis.MorphBundlesOS.Count; i++) diff --git a/Src/FwParatextLexiconPlugin/FdoWordAnalysis.cs b/Src/FwParatextLexiconPlugin/FdoWordAnalysis.cs index e37dd9cc9c..122fabfa8e 100644 --- a/Src/FwParatextLexiconPlugin/FdoWordAnalysis.cs +++ b/Src/FwParatextLexiconPlugin/FdoWordAnalysis.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; -using System.Text; using Paratext.LexicalContracts; namespace SIL.FieldWorks.ParatextLexiconPlugin @@ -11,32 +10,19 @@ internal class FdoWordAnalysis : WordAnalysis { private readonly Lexeme[] m_lexemes; - public FdoWordAnalysis(Lexeme[] lexemes) + public FdoWordAnalysis(IEnumerable lexemes) { - m_lexemes = lexemes; + m_lexemes = lexemes.ToArray(); } - public string DisplayString + public Lexeme this[int index] { - get - { - var sb = new StringBuilder(); - foreach (Lexeme lex in m_lexemes) - { - switch (lex.Type) - { - case LexemeType.Prefix: sb.Append(lex.LexicalForm + "+ "); break; - case LexemeType.Suffix: sb.Append("+" + lex.LexicalForm + " "); break; - default: sb.Append(lex.LexicalForm + " "); break; - } - } - return sb.ToString().TrimEnd(); - } + get { return m_lexemes[index]; } } - public Lexeme this[int index] + public int Length { - get { return m_lexemes[index]; } + get { return m_lexemes.Length; } } public override bool Equals(object obj) @@ -58,11 +44,6 @@ public override int GetHashCode() return m_lexemes.Aggregate(23, (code, lexeme) => code * 31 + lexeme.GetHashCode()); } - public override string ToString() - { - return DisplayString; - } - public IEnumerator GetEnumerator() { return ((IEnumerable)m_lexemes).GetEnumerator(); diff --git a/Src/FwParatextLexiconPlugin/FdoWordformLexeme.cs b/Src/FwParatextLexiconPlugin/FdoWordformLexeme.cs index 4eb43973f3..7b29f2c71a 100644 --- a/Src/FwParatextLexiconPlugin/FdoWordformLexeme.cs +++ b/Src/FwParatextLexiconPlugin/FdoWordformLexeme.cs @@ -52,11 +52,6 @@ public string DisplayString get { return LexicalForm; } } - public string InterlinearDisplayString - { - get { return DisplayString; } - } - public string CitationForm { get { return null; } diff --git a/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FdoLexiconTests.cs b/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FdoLexiconTests.cs index 2159279815..6a412821cf 100644 --- a/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FdoLexiconTests.cs +++ b/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FdoLexiconTests.cs @@ -493,7 +493,7 @@ public void FindMatchingLexemes() m_lexicon.AddLexeme(lexemePre); Lexeme lexemeSuf = m_lexicon.CreateLexeme(LexemeType.Suffix, "suf"); m_lexicon.AddLexeme(lexemeSuf); - m_lexicon.AddWordAnalysis("preasuf", new FdoWordAnalysis(new[] { lexemePre, lexemeA, lexemeSuf })); + m_lexicon.AddWordAnalysis("preasuf", m_lexicon.CreateWordAnalysis(new[] { lexemePre, lexemeA, lexemeSuf })); matchingLexemes = m_lexicon.FindMatchingLexemes("preasuf").ToArray(); Assert.That(matchingLexemes.Length, Is.EqualTo(3)); Assert.IsTrue(matchingLexemes.Contains(lexemePre)); From d0ed05f921b24109d150924d736c940fbd385f67 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Mon, 12 May 2014 15:14:30 +0700 Subject: [PATCH 109/143] updated Paratext plugin for new contracts Change-Id: Ib5f50e0440e24f27f7d5dee39d011d05201b83cb --- DistFiles/Paratext.LexicalContracts.dll | Bin 0 -> 10752 bytes DistFiles/ParatextLexicalContracts.dll | Bin 9728 -> 0 bytes .../FdoLexemeAddedEventArgs.cs | 20 +++++++ Src/FwParatextLexiconPlugin/FdoLexicon.cs | 49 ++++++++++-------- .../FdoLexiconGlossAddedEventArgs.cs | 34 ++++++++++++ .../FdoLexiconSenseAddedEventArgs.cs | 27 ++++++++++ .../FdoWordAnalysis.cs | 14 ++++- .../FwLexiconPlugin.cs | 4 ++ .../FwParatextLexiconPlugin.csproj | 7 ++- .../FdoLexiconTests.cs | 2 +- .../FwParatextLexiconPluginTests.csproj | 4 +- 11 files changed, 131 insertions(+), 30 deletions(-) create mode 100644 DistFiles/Paratext.LexicalContracts.dll delete mode 100644 DistFiles/ParatextLexicalContracts.dll create mode 100644 Src/FwParatextLexiconPlugin/FdoLexemeAddedEventArgs.cs create mode 100644 Src/FwParatextLexiconPlugin/FdoLexiconGlossAddedEventArgs.cs create mode 100644 Src/FwParatextLexiconPlugin/FdoLexiconSenseAddedEventArgs.cs diff --git a/DistFiles/Paratext.LexicalContracts.dll b/DistFiles/Paratext.LexicalContracts.dll new file mode 100644 index 0000000000000000000000000000000000000000..1d2034cd79a251094fc01354eafca77d86c57f80 GIT binary patch literal 10752 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 eca`JzK24t>4iVZ$CHi0PMAdWv literal 0 HcmV?d00001 diff --git a/DistFiles/ParatextLexicalContracts.dll b/DistFiles/ParatextLexicalContracts.dll deleted file mode 100644 index 01d55963d4f2a605c4a0e1b2075ba16f9061e0d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9728 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 LexemeAdded; + public event LexemeAddedEventHandler LexemeAdded; - public event EventHandler LexiconSenseAdded; + public event LexiconSenseAddedEventHandler LexiconSenseAdded; - public event EventHandler LexiconGlossAdded; + public event LexiconGlossAddedEventHandler LexiconGlossAdded; public bool RequiresLanguageId { @@ -324,9 +324,9 @@ public IEnumerable ValidLanguages #endregion #region WordAnalyses implementation - public WordAnalysis CreateWordAnalysis(IEnumerable lexemes) + public WordAnalysis CreateWordAnalysis(string word, IEnumerable lexemes) { - return new FdoWordAnalysis(lexemes); + return new FdoWordAnalysis(word, lexemes); } public IEnumerable GetWordAnalyses(string word) @@ -348,17 +348,17 @@ public IEnumerable GetWordAnalyses(string word) } } - public void AddWordAnalysis(string word, WordAnalysis lexemes) + public void AddWordAnalysis(WordAnalysis lexemes) { using (m_activationContext.Activate()) { NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, () => { IWfiWordform wordform; - if (!TryGetWordform(word, out wordform)) + if (!TryGetWordform(lexemes.Word, out wordform)) { wordform = m_cache.ServiceLocator.GetInstance().Create( - m_cache.TsStrFactory.MakeString(word.Normalize(NormalizationForm.FormD), DefaultVernWs)); + m_cache.TsStrFactory.MakeString(lexemes.Word.Normalize(NormalizationForm.FormD), DefaultVernWs)); } IWfiAnalysis analysis = m_cache.ServiceLocator.GetInstance().Create(); @@ -382,12 +382,12 @@ public void AddWordAnalysis(string word, WordAnalysis lexemes) } } - public void RemoveWordAnalysis(string word, WordAnalysis lexemes) + public void RemoveWordAnalysis(WordAnalysis lexemes) { using (m_activationContext.Activate()) { IWfiWordform wordform; - if (!TryGetWordform(word, out wordform)) + if (!TryGetWordform(lexemes.Word, out wordform)) return; foreach (IWfiAnalysis analysis in wordform.AnalysesOC.Where(a => a.MorphBundlesOS.Count > 0 && a.ApprovalStatusIcon == (int) Opinions.approves)) @@ -419,19 +419,22 @@ public void RemoveWordAnalysis(string word, WordAnalysis lexemes) } } - public IEnumerable> GetWordAnalyses() + public IEnumerable WordAnalyses { - using (m_activationContext.Activate()) + get { - var analyses = new HashSet>(); - foreach (IWfiAnalysis analysis in m_cache.ServiceLocator.GetInstance().AllInstances().Where(a => a.MorphBundlesOS.Count > 0 && a.ApprovalStatusIcon == (int) Opinions.approves)) + using (m_activationContext.Activate()) { - WordAnalysis lexemes; - string wordFormWs = analysis.Wordform.Form.get_String(m_defaultVernWs).Text; - if (wordFormWs != null && GetWordAnalysis(analysis, out lexemes)) - analyses.Add(new KeyValuePair(wordFormWs.Normalize(), lexemes)); + var analyses = new HashSet(); + foreach (IWfiAnalysis analysis in m_cache.ServiceLocator.GetInstance().AllInstances().Where(a => a.MorphBundlesOS.Count > 0 && a.ApprovalStatusIcon == (int) Opinions.approves)) + { + WordAnalysis lexemes; + string wordFormWs = analysis.Wordform.Form.get_String(m_defaultVernWs).Text; + if (wordFormWs != null && GetWordAnalysis(analysis, out lexemes)) + analyses.Add(lexemes); + } + return analyses; } - return analyses; } } #endregion @@ -456,7 +459,7 @@ private bool GetWordAnalysis(IWfiAnalysis analysis, out WordAnalysis lexemes) lexemeArray[i] = GetEntryLexeme(entry); } - lexemes = new FdoWordAnalysis(lexemeArray); + lexemes = new FdoWordAnalysis(analysis.Wordform.Form.get_String(DefaultVernWs).Text.Normalize(), lexemeArray); return true; } @@ -696,19 +699,19 @@ internal FdoLexEntryLexeme GetEntryLexeme(ILexEntry entry) internal void OnLexemeAdded(Lexeme lexeme) { if (LexemeAdded != null) - LexemeAdded(this, new LexemeAddedEventArgs(lexeme)); + LexemeAdded(this, new FdoLexemeAddedEventArgs(lexeme)); } internal void OnLexiconSenseAdded(Lexeme lexeme, LexiconSense sense) { if (LexiconSenseAdded != null) - LexiconSenseAdded(this, new LexiconSenseAddedEventArgs(lexeme, sense)); + LexiconSenseAdded(this, new FdoLexiconSenseAddedEventArgs(lexeme, sense)); } internal void OnLexiconGlossAdded(Lexeme lexeme, LexiconSense sense, LanguageText gloss) { if (LexiconGlossAdded != null) - LexiconGlossAdded(this, new LexiconGlossAddedEventArgs(lexeme, sense, gloss)); + LexiconGlossAdded(this, new FdoLexiconGlossAddedEventArgs(lexeme, sense, gloss)); } /// ------------------------------------------------------------------------------------ diff --git a/Src/FwParatextLexiconPlugin/FdoLexiconGlossAddedEventArgs.cs b/Src/FwParatextLexiconPlugin/FdoLexiconGlossAddedEventArgs.cs new file mode 100644 index 0000000000..5b620f72ae --- /dev/null +++ b/Src/FwParatextLexiconPlugin/FdoLexiconGlossAddedEventArgs.cs @@ -0,0 +1,34 @@ +using System; +using Paratext.LexicalContracts; + +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + internal class FdoLexiconGlossAddedEventArgs : EventArgs, LexiconGlossAddedEventArgs + { + private readonly Lexeme m_lexeme; + private readonly LexiconSense m_sense; + private readonly LanguageText m_gloss; + + public FdoLexiconGlossAddedEventArgs(Lexeme lexeme, LexiconSense sense, LanguageText gloss) + { + m_lexeme = lexeme; + m_sense = sense; + m_gloss = gloss; + } + + public Lexeme Lexeme + { + get { return m_lexeme; } + } + + public LexiconSense Sense + { + get { return m_sense; } + } + + public LanguageText Gloss + { + get { return m_gloss; } + } + } +} diff --git a/Src/FwParatextLexiconPlugin/FdoLexiconSenseAddedEventArgs.cs b/Src/FwParatextLexiconPlugin/FdoLexiconSenseAddedEventArgs.cs new file mode 100644 index 0000000000..79123b55da --- /dev/null +++ b/Src/FwParatextLexiconPlugin/FdoLexiconSenseAddedEventArgs.cs @@ -0,0 +1,27 @@ +using System; +using Paratext.LexicalContracts; + +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + internal class FdoLexiconSenseAddedEventArgs : EventArgs, LexiconSenseAddedEventArgs + { + private readonly Lexeme m_lexeme; + private readonly LexiconSense m_sense; + + public FdoLexiconSenseAddedEventArgs(Lexeme lexeme, LexiconSense sense) + { + m_lexeme = lexeme; + m_sense = sense; + } + + public Lexeme Lexeme + { + get { return m_lexeme; } + } + + public LexiconSense Sense + { + get { return m_sense; } + } + } +} diff --git a/Src/FwParatextLexiconPlugin/FdoWordAnalysis.cs b/Src/FwParatextLexiconPlugin/FdoWordAnalysis.cs index 122fabfa8e..e4132869f5 100644 --- a/Src/FwParatextLexiconPlugin/FdoWordAnalysis.cs +++ b/Src/FwParatextLexiconPlugin/FdoWordAnalysis.cs @@ -1,4 +1,5 @@ -using System.Collections; +using System; +using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; @@ -8,13 +9,22 @@ namespace SIL.FieldWorks.ParatextLexiconPlugin { internal class FdoWordAnalysis : WordAnalysis { + private readonly string m_word; private readonly Lexeme[] m_lexemes; - public FdoWordAnalysis(IEnumerable lexemes) + public FdoWordAnalysis(string word, IEnumerable lexemes) { + if (!word.IsNormalized()) + throw new ArgumentException("The word is not normalized.", "word"); + m_word = word; m_lexemes = lexemes.ToArray(); } + public string Word + { + get { return m_word; } + } + public Lexeme this[int index] { get { return m_lexemes[index]; } diff --git a/Src/FwParatextLexiconPlugin/FwLexiconPlugin.cs b/Src/FwParatextLexiconPlugin/FwLexiconPlugin.cs index 3cd21580fe..2f0846f855 100644 --- a/Src/FwParatextLexiconPlugin/FwLexiconPlugin.cs +++ b/Src/FwParatextLexiconPlugin/FwLexiconPlugin.cs @@ -203,6 +203,7 @@ private void DiscardFdoCache(FdoCache fdoCache) if (m_lexiconCache.All(lexicon => lexicon.Cache != fdoCache)) { m_fdoCacheCache.Remove(fdoCache.ProjectId.Name); + fdoCache.ServiceLocator.GetInstance().Save(); fdoCache.Dispose(); } } @@ -222,7 +223,10 @@ protected override void DisposeManagedResources() lexicon.Dispose(); m_lexiconCache.Clear(); foreach (FdoCache fdoCache in m_fdoCacheCache) + { + fdoCache.ServiceLocator.GetInstance().Save(); fdoCache.Dispose(); + } m_fdoCacheCache.Clear(); } } diff --git a/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj b/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj index 03ec0770b4..993131f863 100644 --- a/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj +++ b/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj @@ -52,8 +52,8 @@ ..\..\DistFiles\Microsoft.Practices.ServiceLocation.dll - - ..\..\DistFiles\ParatextLexicalContracts.dll + + ..\..\DistFiles\Paratext.LexicalContracts.dll ..\..\Output\Debug\ParserCore.dll @@ -82,9 +82,12 @@ ChooseFdoProjectForm.cs + + + Form diff --git a/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FdoLexiconTests.cs b/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FdoLexiconTests.cs index 6a412821cf..c0bba53c70 100644 --- a/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FdoLexiconTests.cs +++ b/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FdoLexiconTests.cs @@ -493,7 +493,7 @@ public void FindMatchingLexemes() m_lexicon.AddLexeme(lexemePre); Lexeme lexemeSuf = m_lexicon.CreateLexeme(LexemeType.Suffix, "suf"); m_lexicon.AddLexeme(lexemeSuf); - m_lexicon.AddWordAnalysis("preasuf", m_lexicon.CreateWordAnalysis(new[] { lexemePre, lexemeA, lexemeSuf })); + m_lexicon.AddWordAnalysis(m_lexicon.CreateWordAnalysis("preasuf", new[] { lexemePre, lexemeA, lexemeSuf })); matchingLexemes = m_lexicon.FindMatchingLexemes("preasuf").ToArray(); Assert.That(matchingLexemes.Length, Is.EqualTo(3)); Assert.IsTrue(matchingLexemes.Contains(lexemePre)); diff --git a/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FwParatextLexiconPluginTests.csproj b/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FwParatextLexiconPluginTests.csproj index 6b349380ea..9fc7c6cb3a 100644 --- a/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FwParatextLexiconPluginTests.csproj +++ b/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FwParatextLexiconPluginTests.csproj @@ -57,8 +57,8 @@ ..\..\..\Bin\NUnit\bin\nunit.framework.dll - - ..\..\..\DistFiles\ParatextLexicalContracts.dll + + ..\..\..\DistFiles\Paratext.LexicalContracts.dll From 5dc411b2e642ea0450406ef335ad5ef722ce8397 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Tue, 13 May 2014 11:58:43 +0700 Subject: [PATCH 110/143] added alternate forms to lexeme interface in Paratext plugin Change-Id: Iddf52aa9736941370b427ca84d6dd71e9acb1633 --- DistFiles/Paratext.LexicalContracts.dll | Bin 10752 -> 10752 bytes .../FdoLexEntryLexeme.cs | 23 ++++++++++++++++++ .../FdoWordformLexeme.cs | 5 ++++ 3 files changed, 28 insertions(+) diff --git a/DistFiles/Paratext.LexicalContracts.dll b/DistFiles/Paratext.LexicalContracts.dll index 1d2034cd79a251094fc01354eafca77d86c57f80..d2f45e82875d4936a7a53a16adafa007d134abc4 100644 GIT binary patch delta 4508 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 ML}2Pa#Q1FU-*#NtBme*a delta 4369 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 LexicalRelations } } + public IEnumerable AlternateForms + { + get + { + using (m_lexicon.ActivationContext.Activate()) + { + ILexEntry entry; + if (!m_lexicon.TryGetEntry(m_key, out entry)) + return Enumerable.Empty(); + + var forms = new List(); + foreach (IMoForm form in entry.AlternateFormsOS) + { + ITsString tss = form.Form.StringOrNull(m_lexicon.DefaultVernWs); + if (tss != null) + forms.Add(tss.Text.Normalize()); + } + + return forms; + } + } + } + private string GetLexReferenceName(ILexEntry lexEntry, ILexRefType lexRefType) { // The name we want to use for our lex reference is either the name or the reverse name diff --git a/Src/FwParatextLexiconPlugin/FdoWordformLexeme.cs b/Src/FwParatextLexiconPlugin/FdoWordformLexeme.cs index 7b29f2c71a..d6a9e7a169 100644 --- a/Src/FwParatextLexiconPlugin/FdoWordformLexeme.cs +++ b/Src/FwParatextLexiconPlugin/FdoWordformLexeme.cs @@ -83,6 +83,11 @@ public IEnumerable LexicalRelations get { return Enumerable.Empty(); } } + public IEnumerable AlternateForms + { + get { return Enumerable.Empty(); } + } + public LexiconSense AddSense() { LexiconSense sense = null; From aef6b60b5665d7dde12ae90cc5d90148516b44a5 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Tue, 13 May 2014 13:39:25 +0700 Subject: [PATCH 111/143] Paratext plugin now saves when idle Change-Id: I5dce3e8ee41a13f53feb0c1f204c1ce5ee775642 --- Src/FdoUi/FwFdoUI.cs | 48 ++------ .../ChooseFdoProjectForm.cs | 14 +-- .../FwLexiconPlugin.cs | 13 ++- .../ParatextLexiconPluginFdoUI.cs | 105 +++++++++++++----- Src/Utilities/BasicUtils/BasicUtils.csproj | 1 + .../BasicUtils/UserActivityMonitor.cs | 61 ++++++++++ 6 files changed, 157 insertions(+), 85 deletions(-) create mode 100644 Src/Utilities/BasicUtils/UserActivityMonitor.cs diff --git a/Src/FdoUi/FwFdoUI.cs b/Src/FdoUi/FwFdoUI.cs index add28e9e47..916e3406db 100644 --- a/Src/FdoUi/FwFdoUI.cs +++ b/Src/FdoUi/FwFdoUI.cs @@ -4,7 +4,6 @@ using System; using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; using System.IO; using System.Windows.Forms; using SIL.FieldWorks.Common.FwUtils; @@ -22,12 +21,14 @@ public class FwFdoUI : IFdoUI { private readonly IHelpTopicProvider m_helpTopicProvider; private readonly ISynchronizeInvoke m_synchronizeInvoke; + private readonly UserActivityMonitor m_activityMonitor; public FwFdoUI(IHelpTopicProvider helpTopicProvider, ISynchronizeInvoke synchronizeInvoke) { m_helpTopicProvider = helpTopicProvider; m_synchronizeInvoke = synchronizeInvoke; - Application.AddMessageFilter(new UserActivityMonitor(this)); + m_activityMonitor = new UserActivityMonitor(); + m_activityMonitor.StartMonitoring(); } /// @@ -170,7 +171,10 @@ public void ReportException(Exception error, bool isLethal) m_synchronizeInvoke.Invoke(() => ErrorReporter.ReportException(error, null, null, null, isLethal)); } - public DateTime LastActivityTime { get; private set; } + public DateTime LastActivityTime + { + get { return m_activityMonitor.LastActivityTime; } + } /// /// Reports duplicate guids to the user @@ -216,43 +220,5 @@ public bool Retry(string msg, string caption) return m_synchronizeInvoke.Invoke(() => MessageBox.Show(msg, caption, MessageBoxButtons.RetryCancel, MessageBoxIcon.None) == DialogResult.Retry); } - - /// - /// This class is a message filter which can be installed in order to track when the user last - /// pressed a key or did any mouse action, including moving the mouse. - /// - [SuppressMessage("Gendarme.Rules.Design", "TypesWithNativeFieldsShouldBeDisposableRule", Justification="No unmanaged resources to release")] - class UserActivityMonitor : IMessageFilter - { - private readonly FwFdoUI m_ui; - - public UserActivityMonitor(FwFdoUI ui) - { - m_ui = ui; - } - - private IntPtr m_lastMousePosition; - - public bool PreFilterMessage(ref Message m) - { - if(m.Msg == (int)Win32.WinMsgs.WM_MOUSEMOVE) - { - // For mouse move, we get spurious ones when it didn't really move. So check the actual position. - if (m.LParam != m_lastMousePosition) - { - m_ui.LastActivityTime = DateTime.Now; - m_lastMousePosition = m.LParam; - // Enhance JohnT: suppress ones where it doesn't move?? - } - return false; - } - if ((m.Msg >= (int)Win32.WinMsgs.WM_MOUSE_Min && m.Msg <= (int)Win32.WinMsgs.WM_MOUSE_Max) - || (m.Msg >= (int)Win32.WinMsgs.WM_KEY_Min && m.Msg <= (int)Win32.WinMsgs.WM_KEY_Max)) - { - m_ui.LastActivityTime = DateTime.Now; - } - return false; // don't want to block any messages. - } - } } } diff --git a/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.cs b/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.cs index 9c895784c9..de2267e6d7 100644 --- a/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.cs +++ b/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.cs @@ -15,6 +15,7 @@ internal partial class ChooseFdoProjectForm private LanguageProjectInfo m_selectedItem; private string m_restoreFileFullPath; private RestoreProjectSettings m_restoreSettings; + private readonly ParatextLexiconPluginFdoUI m_ui; public string SelectedProject { @@ -103,11 +104,11 @@ private void textBoxProjectName_TextChanged(object sender, EventArgs e) } #endregion - public ChooseFdoProjectForm() + public ChooseFdoProjectForm(ParatextLexiconPluginFdoUI ui) { // This call is required by the Windows Form Designer. InitializeComponent(); - + m_ui = ui; PopulateLanguageProjectsList(Dns.GetHostName(), true); } @@ -239,13 +240,10 @@ private bool DoRestore() try { - //ProgressUtils.Execute(string.Format(Localizer.Str("Restoring {0} project..."), m_restoreSettings.ProjectName), CancelModes.NonCancelable, () => - // { - var restoreService = new ProjectRestoreService(m_restoreSettings, ParatextLexiconPluginFdoUI.Instance, null, null); - restoreService.RestoreProject(new ParatextLexiconPluginThreadedProgress(ParatextLexiconPluginFdoUI.Instance.SynchronizeInvoke)); + var restoreService = new ProjectRestoreService(m_restoreSettings, m_ui, null, null); + restoreService.RestoreProject(new ParatextLexiconPluginThreadedProgress(m_ui.SynchronizeInvoke)); - m_selectedItem = new LanguageProjectInfo(m_restoreSettings.FullProjectPath); - // }); + m_selectedItem = new LanguageProjectInfo(m_restoreSettings.FullProjectPath); } catch { diff --git a/Src/FwParatextLexiconPlugin/FwLexiconPlugin.cs b/Src/FwParatextLexiconPlugin/FwLexiconPlugin.cs index 2f0846f855..0d9b869abd 100644 --- a/Src/FwParatextLexiconPlugin/FwLexiconPlugin.cs +++ b/Src/FwParatextLexiconPlugin/FwLexiconPlugin.cs @@ -24,6 +24,7 @@ public class FwLexiconPlugin : FwDisposableBase, LexiconPlugin private readonly FdoCacheCollection m_fdoCacheCache; private readonly object m_syncRoot; private ActivationContextHelper m_activationContext; + private readonly ParatextLexiconPluginFdoUI m_ui; /// /// Initializes a new instance of the class. @@ -36,9 +37,9 @@ public FwLexiconPlugin() m_activationContext = new ActivationContextHelper("FwParatextLexiconPlugin.dll.manifest"); // initialize client-server services to use Db4O backend for FDO - var ui = ParatextLexiconPluginFdoUI.Instance; + m_ui = new ParatextLexiconPluginFdoUI(m_activationContext); var dirs = ParatextLexiconPluginDirectoryFinder.FdoDirectories; - ClientServerServices.SetCurrentToDb4OBackend(ui, dirs, + ClientServerServices.SetCurrentToDb4OBackend(m_ui, dirs, () => dirs.ProjectsDirectory == ParatextLexiconPluginDirectoryFinder.ProjectsDirectoryLocalMachine); } @@ -75,7 +76,7 @@ public bool ValidateLexicalProject(string projectId, string langId) public bool ChooseLexicalProject(out string projectId) { using (m_activationContext.Activate()) - using (var dialog = new ChooseFdoProjectForm()) + using (var dialog = new ChooseFdoProjectForm(m_ui)) { if (dialog.ShowDialog() == DialogResult.OK) { @@ -169,7 +170,7 @@ private FdoCache GetFdoCache(string projectId) throw new LexiconUnavailableException("The associated Fieldworks project has been moved, renamed, or does not exist."); } - var progress = new ParatextLexiconPluginThreadedProgress(ParatextLexiconPluginFdoUI.Instance.SynchronizeInvoke) { IsIndeterminate = true, Title = string.Format("Opening {0}", projectId) }; + var progress = new ParatextLexiconPluginThreadedProgress(m_ui.SynchronizeInvoke) { IsIndeterminate = true, Title = string.Format("Opening {0}", projectId) }; fdoCache = (FdoCache) progress.RunTask(CreateFdoCache, new ParatextLexiconPluginProjectID(backendProviderType, path)); m_fdoCacheCache.Add(fdoCache); @@ -177,12 +178,12 @@ private FdoCache GetFdoCache(string projectId) return fdoCache; } - private static FdoCache CreateFdoCache(IThreadedProgress progress, object[] parameters) + private FdoCache CreateFdoCache(IThreadedProgress progress, object[] parameters) { var projectId = (ParatextLexiconPluginProjectID) parameters[0]; try { - return FdoCache.CreateCacheFromExistingData(projectId, Thread.CurrentThread.CurrentUICulture.Name, ParatextLexiconPluginFdoUI.Instance, ParatextLexiconPluginDirectoryFinder.FdoDirectories, progress, true); + return FdoCache.CreateCacheFromExistingData(projectId, Thread.CurrentThread.CurrentUICulture.Name, m_ui, ParatextLexiconPluginDirectoryFinder.FdoDirectories, progress, true); } catch (FdoDataMigrationForbiddenException) { diff --git a/Src/FwParatextLexiconPlugin/ParatextLexiconPluginFdoUI.cs b/Src/FwParatextLexiconPlugin/ParatextLexiconPluginFdoUI.cs index 41ce1e3a85..eaeea93df7 100644 --- a/Src/FwParatextLexiconPlugin/ParatextLexiconPluginFdoUI.cs +++ b/Src/FwParatextLexiconPlugin/ParatextLexiconPluginFdoUI.cs @@ -1,25 +1,29 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Windows.Forms; using SIL.FieldWorks.FDO; +using SIL.Utils; namespace SIL.FieldWorks.ParatextLexiconPlugin { internal class ParatextLexiconPluginFdoUI : IFdoUI { - // Singleton - private static readonly ParatextLexiconPluginFdoUI s_instance = new ParatextLexiconPluginFdoUI(); - private ParatextLexiconPluginFdoUI(){} - public static ParatextLexiconPluginFdoUI Instance + private readonly SynchronizeInvokeWrapper m_synchronizeInvoke; + private readonly UserActivityMonitor m_activityMonitor; + + public ParatextLexiconPluginFdoUI(ActivationContextHelper activationContext) { - get { return s_instance; } + m_synchronizeInvoke = new SynchronizeInvokeWrapper(activationContext); + m_activityMonitor = new UserActivityMonitor(); + m_activityMonitor.StartMonitoring(); } public bool ConflictingSave() { - SynchronizeInvoke.Invoke(new Action(() => MessageBox.Show(Strings.ksConflictingSaveText, - Strings.ksConflictingSaveCaption, MessageBoxButtons.OK, MessageBoxIcon.Warning)), null); + SynchronizeInvoke.Invoke(() => MessageBox.Show(Strings.ksConflictingSaveText, + Strings.ksConflictingSaveCaption, MessageBoxButtons.OK, MessageBoxIcon.Warning)); return true; } @@ -29,8 +33,8 @@ public bool ConflictingSave() /// True if user wishes to attempt reconnect. False otherwise. public bool ConnectionLost() { - return (bool) SynchronizeInvoke.Invoke(new Func(() => MessageBox.Show(Strings.ksConnectionLostText, - Strings.ksConnectionLostCaption, MessageBoxButtons.YesNo) == DialogResult.Yes), null); + return SynchronizeInvoke.Invoke(() => MessageBox.Show(Strings.ksConnectionLostText, + Strings.ksConnectionLostCaption, MessageBoxButtons.YesNo) == DialogResult.Yes); } public FileSelection ChooseFilesToUse() @@ -54,16 +58,16 @@ public FileSelection ChooseFilesToUse() public bool RestoreLinkedFilesInProjectFolder() { - return (bool) SynchronizeInvoke.Invoke(new Func(() => MessageBox.Show( + return SynchronizeInvoke.Invoke(() => MessageBox.Show( Strings.ksRestoreLinkedFilesInProjectFolderText, Strings.ksRestoreLinkedFilesInProjectFolderCaption, - MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes), null); + MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes); } public YesNoCancel CannotRestoreLinkedFilesToOriginalLocation() { - var result = (DialogResult) SynchronizeInvoke.Invoke(new Func(() => MessageBox.Show( + DialogResult result = SynchronizeInvoke.Invoke(() => MessageBox.Show( Strings.ksCannotRestoreLinkedFilesToOriginalLocationText, Strings.ksCannotRestoreLinkedFilesToOriginalLocationCaption, - MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)), null); + MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)); switch (result) { case DialogResult.Yes: @@ -89,7 +93,7 @@ public void DisplayMessage(MessageType type, string message, string caption, str icon = MessageBoxIcon.Warning; break; } - SynchronizeInvoke.Invoke(new Action(() => MessageBox.Show(message, caption, MessageBoxButtons.OK, icon)), null); + SynchronizeInvoke.Invoke(() => MessageBox.Show(message, caption, MessageBoxButtons.OK, icon)); } public void ReportException(Exception error, bool isLethal) @@ -104,17 +108,17 @@ public void ReportDuplicateGuids(string errorText) public bool Retry(string msg, string caption) { - return (bool) SynchronizeInvoke.Invoke(new Func(() => MessageBox.Show(msg, caption, - MessageBoxButtons.RetryCancel, MessageBoxIcon.None) == DialogResult.Retry), null); + return SynchronizeInvoke.Invoke(() => MessageBox.Show(msg, caption, + MessageBoxButtons.RetryCancel, MessageBoxIcon.None) == DialogResult.Retry); } public bool OfferToRestore(string projectPath, string backupPath) { - return (bool) SynchronizeInvoke.Invoke(new Func(() => MessageBox.Show( + return SynchronizeInvoke.Invoke(() => MessageBox.Show( String.Format(Strings.ksOfferToRestoreText, projectPath, File.GetLastWriteTime(projectPath), backupPath, File.GetLastWriteTime(backupPath)), Strings.ksOfferToRestoreCaption, MessageBoxButtons.YesNo, - MessageBoxIcon.Error) == DialogResult.Yes), null); + MessageBoxIcon.Error) == DialogResult.Yes); } public void Exit() @@ -124,23 +128,64 @@ public void Exit() public ISynchronizeInvoke SynchronizeInvoke { - get - { - Form form = Form.ActiveForm; - if (form != null) - return form; - if (Application.OpenForms.Count > 0) - return Application.OpenForms[0]; - return null; - } + get { return m_synchronizeInvoke; } } public DateTime LastActivityTime { - get + get { return m_activityMonitor.LastActivityTime; } + } + + [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", + Justification="m_activationContext is a reference")] + private class SynchronizeInvokeWrapper : ISynchronizeInvoke + { + private readonly ActivationContextHelper m_activationContext; + + public SynchronizeInvokeWrapper(ActivationContextHelper activationContext) + { + m_activationContext = activationContext; + } + + private ISynchronizeInvoke SynchronizeInvoke + { + get + { + Form form = Form.ActiveForm; + if (form != null) + return form; + if (Application.OpenForms.Count > 0) + return Application.OpenForms[0]; + return null; + } + } + + public IAsyncResult BeginInvoke(Delegate method, object[] args) + { + return SynchronizeInvoke.BeginInvoke(new Func(() => + { + using (m_activationContext.Activate()) + return method.DynamicInvoke(args); + }), null); + } + + public object EndInvoke(IAsyncResult result) + { + return SynchronizeInvoke.EndInvoke(result); + } + + public object Invoke(Delegate method, object[] args) + { + return SynchronizeInvoke.Invoke(new Func(() => + { + using (m_activationContext) + return method.DynamicInvoke(args); + }), null); + } + + public bool InvokeRequired { - // this effectively disables saving on idle - return DateTime.Now; + get { return SynchronizeInvoke.InvokeRequired; } } } } diff --git a/Src/Utilities/BasicUtils/BasicUtils.csproj b/Src/Utilities/BasicUtils/BasicUtils.csproj index fcd02bb0df..825d395115 100644 --- a/Src/Utilities/BasicUtils/BasicUtils.csproj +++ b/Src/Utilities/BasicUtils/BasicUtils.csproj @@ -143,6 +143,7 @@ + diff --git a/Src/Utilities/BasicUtils/UserActivityMonitor.cs b/Src/Utilities/BasicUtils/UserActivityMonitor.cs new file mode 100644 index 0000000000..68f2e7f23f --- /dev/null +++ b/Src/Utilities/BasicUtils/UserActivityMonitor.cs @@ -0,0 +1,61 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Windows.Forms; + +namespace SIL.Utils +{ + /// + /// This class is a message filter which can be installed in order to track when the user last + /// pressed a key or did any mouse action, including moving the mouse. + /// + [SuppressMessage("Gendarme.Rules.Design", "TypesWithNativeFieldsShouldBeDisposableRule", Justification="No unmanaged resources to release")] + public class UserActivityMonitor : IMessageFilter + { + private IntPtr m_lastMousePosition; + + /// + /// Starts monitoring user activity. + /// + public void StartMonitoring() + { + Application.AddMessageFilter(this); + } + + /// + /// Stops monitoring user activity. + /// + public void StopMonitoring() + { + Application.RemoveMessageFilter(this); + } + + /// + /// Gets the last user activity time. + /// + /// + /// The last activity user time. + /// + public DateTime LastActivityTime { get; private set; } + + bool IMessageFilter.PreFilterMessage(ref Message m) + { + if(m.Msg == (int) Win32.WinMsgs.WM_MOUSEMOVE) + { + // For mouse move, we get spurious ones when it didn't really move. So check the actual position. + if (m.LParam != m_lastMousePosition) + { + LastActivityTime = DateTime.Now; + m_lastMousePosition = m.LParam; + // Enhance JohnT: suppress ones where it doesn't move?? + } + return false; + } + if ((m.Msg >= (int) Win32.WinMsgs.WM_MOUSE_Min && m.Msg <= (int) Win32.WinMsgs.WM_MOUSE_Max) + || (m.Msg >= (int) Win32.WinMsgs.WM_KEY_Min && m.Msg <= (int) Win32.WinMsgs.WM_KEY_Max)) + { + LastActivityTime = DateTime.Now; + } + return false; // don't want to block any messages. + } + } +} From ab3b43779a2c1e7fbdca38bb5ffbe9a30036fff2 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Thu, 15 May 2014 16:22:30 +0700 Subject: [PATCH 112/143] Fixed SharedXMLBackendProvider on Linux Change-Id: I517661cc07fea831511e82a5db4909e58faf5876 --- .../Impl/SharedXMLBackendProvider.cs | 99 ++++++++++++++----- 1 file changed, 77 insertions(+), 22 deletions(-) diff --git a/Src/FDO/Infrastructure/Impl/SharedXMLBackendProvider.cs b/Src/FDO/Infrastructure/Impl/SharedXMLBackendProvider.cs index 9e69c04de0..657e67fe49 100644 --- a/Src/FDO/Infrastructure/Impl/SharedXMLBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/SharedXMLBackendProvider.cs @@ -8,6 +8,7 @@ using System.IO.MemoryMappedFiles; using System.Linq; using System.Threading; +using System.Diagnostics.CodeAnalysis; using ProtoBuf; using SIL.FieldWorks.FDO.DomainServices.DataMigration; @@ -15,7 +16,9 @@ namespace SIL.FieldWorks.FDO.Infrastructure.Impl { internal class SharedXMLBackendProvider : XMLBackendProvider { - private const int CommitLogSize = 10000 * 4096; + private const int PageSize = 4096; + private const int CommitLogSize = 2500 * PageSize; + private const int CommitLogMetadataSize = 1 * PageSize; private Mutex m_mutex; private MemoryMappedFile m_commitLogMetadata; @@ -50,15 +53,18 @@ internal int OtherApplicationsConnectedCount protected override int StartupInternal(int currentModelVersion) { - BasicInit(); - m_mutex.WaitOne(); + bool createdNew; + m_mutex = new Mutex(true, MutexName, out createdNew); + if (!createdNew) + m_mutex.WaitOne(); try { + CreateSharedMemory(createdNew); using (MemoryMappedViewStream stream = m_commitLogMetadata.CreateViewStream()) { CommitLogMetadata metadata; int length; - if (Serializer.TryReadLengthPrefix(stream, PrefixStyle.Base128, out length) && length > 0) + if (!createdNew && Serializer.TryReadLengthPrefix(stream, PrefixStyle.Base128, out length) && length > 0) { stream.Seek(0, SeekOrigin.Begin); metadata = Serializer.DeserializeWithLengthPrefix(stream, PrefixStyle.Base128, 1); @@ -109,6 +115,9 @@ protected override void ShutdownInternal() m_mutex.WaitOne(); try { +#if __MonoCS__ + bool delete = false; +#endif using (MemoryMappedViewStream stream = m_commitLogMetadata.CreateViewStream()) { int length; @@ -119,12 +128,29 @@ protected override void ShutdownInternal() metadata.Slots[m_slotIndex] = -1; if (metadata.Master == m_slotIndex) metadata.Master = -1; +#if __MonoCS__ + delete = metadata.Slots.All(s => s == -1); +#endif stream.Seek(0, SeekOrigin.Begin); Serializer.SerializeWithLengthPrefix(stream, metadata, PrefixStyle.Base128, 1); } } base.UnlockProject(); + + m_commitLog.Dispose(); + m_commitLog = null; + + m_commitLogMetadata.Dispose(); + m_commitLogMetadata = null; + +#if __MonoCS__ + if (delete) + { + File.Delete(Path.Combine(Path.GetTempPath(), CommitLogMetadataName)); + File.Delete(Path.Combine(Path.GetTempPath(), CommitLogName)); + } +#endif } finally { @@ -134,16 +160,6 @@ protected override void ShutdownInternal() base.ShutdownInternal(); - if (m_commitLog != null) - { - m_commitLog.Dispose(); - m_commitLog = null; - } - if (m_commitLogMetadata != null) - { - m_commitLogMetadata.Dispose(); - m_commitLogMetadata = null; - } if (m_mutex != null) { m_mutex.Dispose(); @@ -153,10 +169,13 @@ protected override void ShutdownInternal() protected override void CreateInternal() { - BasicInit(); - m_mutex.WaitOne(); + bool createdNew; + m_mutex = new Mutex(true, MutexName, out createdNew); + if (!createdNew) + throw new InvalidOperationException("Cannot create shared XML backend."); try { + CreateSharedMemory(createdNew); var metadata = new CommitLogMetadata { Slots = new int[8] }; m_slotIndex = 0; metadata.Master = 0; @@ -176,11 +195,45 @@ protected override void CreateInternal() } } - private void BasicInit() + private string MutexName { - m_mutex = new Mutex(false, ProjectId.Name + "_Mutex"); - m_commitLogMetadata = MemoryMappedFile.CreateOrOpen(ProjectId.Name + "_CommitLogMetadata", 1024); - m_commitLog = MemoryMappedFile.CreateOrOpen(ProjectId.Name + "_CommitLog", CommitLogSize); + get { return ProjectId.Name + "_Mutex"; } + } + + private string CommitLogName + { + get { return ProjectId.Name + "_CommitLog"; } + } + + private string CommitLogMetadataName + { + get { return ProjectId.Name + "_CommitLogMetadata"; } + } + + private void CreateSharedMemory(bool createdNew) + { + m_commitLogMetadata = CreateOrOpen(CommitLogMetadataName, CommitLogMetadataSize, createdNew); + m_commitLog = CreateOrOpen(CommitLogName, CommitLogSize, createdNew); + } + + [SuppressMessage("Gendarme.Rules.Portability", "MonoCompatibilityReviewRule", + Justification = "An actual file is passed into MemoryMappedFile.CreateOrOpen")] + private MemoryMappedFile CreateOrOpen(string name, long capacity, bool createdNew) + { +#if __MonoCS__ + name = Path.Combine(Path.GetTempPath(), name); + // delete old file that could be left after a crash + if (createdNew && File.Exists(name)) + File.Delete(name); + + // Mono only supports memory mapped files that are backed by an actual file + if (!File.Exists(name)) + { + using (var fs = new FileStream(name, FileMode.CreateNew)) + fs.SetLength(capacity); + } +#endif + return MemoryMappedFile.CreateOrOpen(name, capacity); } internal override void LockProject() @@ -208,6 +261,9 @@ internal override void LockProject() internal override void UnlockProject() { + if (m_commitLogMetadata == null) + return; + m_mutex.WaitOne(); try { @@ -301,7 +357,6 @@ public override bool Commit(HashSet newbies, HashSet CommitLogSize) return false; @@ -381,7 +436,7 @@ private bool GetUnseenForeignChanges(CommitLogMetadata metadata, { if (viewLength > 0) { - using (MemoryMappedViewStream stream = m_commitLog.CreateViewStream(viewOffset, viewLength, MemoryMappedFileAccess.Read)) + using (MemoryMappedViewStream stream = m_commitLog.CreateViewStream(viewOffset, viewLength)) { while (stream.Position < viewLength) { From 2926d8138486a5c0bc6fc557505e7af9be2db015 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 16 May 2014 16:03:27 +0700 Subject: [PATCH 113/143] updated SharedXMLBackendProvider to handle failures more gracefully Change-Id: I393cef69e57dc0ba9c0294a586d5e9a9dd3a4c35 --- .../Infrastructure/Impl/CommitLogMetadata.cs | 18 +- .../Infrastructure/Impl/CommitLogRecord.cs | 2 +- .../Impl/SharedXMLBackendProvider.cs | 197 +++++++++++++----- .../Infrastructure/Impl/XMLBackendProvider.cs | 28 +-- 4 files changed, 174 insertions(+), 71 deletions(-) diff --git a/Src/FDO/Infrastructure/Impl/CommitLogMetadata.cs b/Src/FDO/Infrastructure/Impl/CommitLogMetadata.cs index fa5c6f212a..f8f8b81a45 100644 --- a/Src/FDO/Infrastructure/Impl/CommitLogMetadata.cs +++ b/Src/FDO/Infrastructure/Impl/CommitLogMetadata.cs @@ -1,4 +1,6 @@ -using ProtoBuf; +using System; +using System.Collections.Generic; +using ProtoBuf; namespace SIL.FieldWorks.FDO.Infrastructure.Impl { @@ -21,9 +23,19 @@ internal class CommitLogMetadata public int Padding; [ProtoMember(6)] - public int[] Slots; + public Dictionary Peers; [ProtoMember(7)] - public int Master; + public Guid Master; + } + + [ProtoContract] + internal class CommitLogPeer + { + [ProtoMember(1)] + public int Generation; + + [ProtoMember(2)] + public int ProcessID; } } diff --git a/Src/FDO/Infrastructure/Impl/CommitLogRecord.cs b/Src/FDO/Infrastructure/Impl/CommitLogRecord.cs index fe8189e3e1..25f1e80a35 100644 --- a/Src/FDO/Infrastructure/Impl/CommitLogRecord.cs +++ b/Src/FDO/Infrastructure/Impl/CommitLogRecord.cs @@ -17,7 +17,7 @@ internal struct CommitLogRecord /// A guid unique to one particular writer; used by each client to eliminate its own commits from queries. /// [ProtoMember(2)] - public int Source; + public Guid Source; /// /// Our IDs of the objects that were added. /// diff --git a/Src/FDO/Infrastructure/Impl/SharedXMLBackendProvider.cs b/Src/FDO/Infrastructure/Impl/SharedXMLBackendProvider.cs index 657e67fe49..453e1048ad 100644 --- a/Src/FDO/Infrastructure/Impl/SharedXMLBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/SharedXMLBackendProvider.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.IO.MemoryMappedFiles; using System.Linq; @@ -23,12 +24,15 @@ internal class SharedXMLBackendProvider : XMLBackendProvider private Mutex m_mutex; private MemoryMappedFile m_commitLogMetadata; private MemoryMappedFile m_commitLog; - private int m_slotIndex = -1; + private readonly Guid m_peerID; + private readonly Dictionary m_peerProcesses; internal SharedXMLBackendProvider(FdoCache cache, IdentityMap identityMap, ICmObjectSurrogateFactory surrogateFactory, IFwMetaDataCacheManagedInternal mdc, IDataMigrationManager dataMigrationManager, IFdoUI ui, IFdoDirectories dirs) : base(cache, identityMap, surrogateFactory, mdc, dataMigrationManager, ui, dirs) { + m_peerProcesses = new Dictionary(); + m_peerID = Guid.NewGuid(); } internal int OtherApplicationsConnectedCount @@ -41,7 +45,12 @@ internal int OtherApplicationsConnectedCount using (MemoryMappedViewStream stream = m_commitLogMetadata.CreateViewStream()) { var metadata = Serializer.DeserializeWithLengthPrefix(stream, PrefixStyle.Base128, 1); - return metadata.Slots.Count(s => s != -1) - 1; + if (CheckExitedPeerProcesses(metadata)) + { + stream.Seek(0, SeekOrigin.Begin); + Serializer.SerializeWithLengthPrefix(stream, metadata, PrefixStyle.Base128, 1); + } + return metadata.Peers.Count - 1; } } finally @@ -68,28 +77,20 @@ protected override int StartupInternal(int currentModelVersion) { stream.Seek(0, SeekOrigin.Begin); metadata = Serializer.DeserializeWithLengthPrefix(stream, PrefixStyle.Base128, 1); + CheckExitedPeerProcesses(metadata); } else { - metadata = new CommitLogMetadata { Slots = new int[8], Master = -1 }; - for (int i = 0; i < metadata.Slots.Length; i++) - metadata.Slots[i] = -1; + metadata = CreateEmptyMetadata(); } - for (int i = 0; i < metadata.Slots.Length; i++) - { - if (metadata.Slots[i] == -1) - { - m_slotIndex = i; - metadata.Slots[i] = metadata.FileGeneration; - break; - } - } + using (Process curProcess = Process.GetCurrentProcess()) + metadata.Peers[m_peerID] = new CommitLogPeer { ProcessID = curProcess.Id, Generation = metadata.FileGeneration }; - if (metadata.Master == -1) + if (metadata.Master == Guid.Empty) { base.LockProject(); - metadata.Master = m_slotIndex; + metadata.Master = m_peerID; } stream.Seek(0, SeekOrigin.Begin); @@ -125,11 +126,29 @@ protected override void ShutdownInternal() { stream.Seek(0, SeekOrigin.Begin); var metadata = Serializer.DeserializeWithLengthPrefix(stream, PrefixStyle.Base128, 1); - metadata.Slots[m_slotIndex] = -1; - if (metadata.Master == m_slotIndex) - metadata.Master = -1; + + if (HasLockFile) + { + // commit any unseen foreign changes + List foreignNewbies; + List foreignDirtballs; + List foreignGoners; + if (GetUnseenForeignChanges(metadata, out foreignNewbies, out foreignDirtballs, out foreignGoners)) + { + var newObjects = new HashSet(foreignNewbies); + var editedObjects = new HashSet(foreignDirtballs); + var removedObjects = new HashSet(foreignGoners); + + IEnumerable fields; + if (HaveAnythingToCommit(newObjects, editedObjects, removedObjects, out fields) && (StartupVersionNumber == ModelVersion)) + base.WriteCommitWork(new CommitWork(newObjects, editedObjects, removedObjects, fields)); + } + // XML file is now totally up-to-date + metadata.FileGeneration = metadata.CurrentGeneration; + } + RemovePeer(metadata, m_peerID); #if __MonoCS__ - delete = metadata.Slots.All(s => s == -1); + delete = metadata.Peers.Count == 0; #endif stream.Seek(0, SeekOrigin.Begin); Serializer.SerializeWithLengthPrefix(stream, metadata, PrefixStyle.Base128, 1); @@ -158,13 +177,22 @@ protected override void ShutdownInternal() } } - base.ShutdownInternal(); - if (m_mutex != null) { m_mutex.Dispose(); m_mutex = null; } + + if (CommitThread != null) + { + CommitThread.Stop(); + CommitThread.Dispose(); + CommitThread = null; + } + + foreach (Process peerProcess in m_peerProcesses.Values) + peerProcess.Close(); + m_peerProcesses.Clear(); } protected override void CreateInternal() @@ -175,13 +203,11 @@ protected override void CreateInternal() throw new InvalidOperationException("Cannot create shared XML backend."); try { - CreateSharedMemory(createdNew); - var metadata = new CommitLogMetadata { Slots = new int[8] }; - m_slotIndex = 0; - metadata.Master = 0; - metadata.Slots[0] = metadata.FileGeneration; - for (int i = 1; i < metadata.Slots.Length; i++) - metadata.Slots[i] = -1; + CreateSharedMemory(true); + CommitLogMetadata metadata = CreateEmptyMetadata(); + metadata.Master = m_peerID; + using (Process curProcess = Process.GetCurrentProcess()) + metadata.Peers[m_peerID] = new CommitLogPeer { ProcessID = curProcess.Id, Generation = metadata.FileGeneration }; using (MemoryMappedViewStream stream = m_commitLogMetadata.CreateViewStream()) { Serializer.SerializeWithLengthPrefix(stream, metadata, PrefixStyle.Base128, 1); @@ -195,6 +221,11 @@ protected override void CreateInternal() } } + private static CommitLogMetadata CreateEmptyMetadata() + { + return new CommitLogMetadata { Peers = new Dictionary() }; + } + private string MutexName { get { return ProjectId.Name + "_Mutex"; } @@ -236,6 +267,63 @@ private MemoryMappedFile CreateOrOpen(string name, long capacity, bool createdNe return MemoryMappedFile.CreateOrOpen(name, capacity); } + /// + /// Checks for peer processes that have exited unexpectedly and update the metadata accordingly. + /// + [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", + Justification = "The process is disposed later.")] + private bool CheckExitedPeerProcesses(CommitLogMetadata metadata) + { + bool changed = false; + var processesToRemove = new HashSet(m_peerProcesses.Values); + foreach (KeyValuePair kvp in metadata.Peers.ToArray()) + { + if (kvp.Key == m_peerID) + continue; + + Process process; + if (m_peerProcesses.TryGetValue(kvp.Value.ProcessID, out process)) + { + if (process.HasExited) + { + RemovePeer(metadata, kvp.Key); + changed = true; + } + else + { + processesToRemove.Remove(process); + } + } + else + { + try + { + process = Process.GetProcessById(kvp.Value.ProcessID); + m_peerProcesses[kvp.Value.ProcessID] = process; + } + catch (ArgumentException) + { + RemovePeer(metadata, kvp.Key); + changed = true; + } + } + } + + foreach (Process process in processesToRemove) + { + m_peerProcesses.Remove(process.Id); + process.Close(); + } + return changed; + } + + private static void RemovePeer(CommitLogMetadata metadata, Guid peerID) + { + metadata.Peers.Remove(peerID); + if (metadata.Master == peerID) + metadata.Master = Guid.Empty; + } + internal override void LockProject() { m_mutex.WaitOne(); @@ -245,9 +333,9 @@ internal override void LockProject() using (MemoryMappedViewStream stream = m_commitLogMetadata.CreateViewStream()) { var metadata = Serializer.DeserializeWithLengthPrefix(stream, PrefixStyle.Base128, 1); - if (metadata.Master == -1) + if (metadata.Master == Guid.Empty) { - metadata.Master = m_slotIndex; + metadata.Master = m_peerID; stream.Seek(0, SeekOrigin.Begin); Serializer.SerializeWithLengthPrefix(stream, metadata, PrefixStyle.Base128, 1); } @@ -261,9 +349,6 @@ internal override void LockProject() internal override void UnlockProject() { - if (m_commitLogMetadata == null) - return; - m_mutex.WaitOne(); try { @@ -275,9 +360,9 @@ internal override void UnlockProject() { stream.Seek(0, SeekOrigin.Begin); var metadata = Serializer.DeserializeWithLengthPrefix(stream, PrefixStyle.Base128, 1); - if (metadata.Master == m_slotIndex) + if (metadata.Master == m_peerID) { - metadata.Master = -1; + metadata.Master = Guid.Empty; stream.Seek(0, SeekOrigin.Begin); Serializer.SerializeWithLengthPrefix(stream, metadata, PrefixStyle.Base128, 1); } @@ -301,12 +386,6 @@ public override bool Commit(HashSet newbies, HashSet(stream, PrefixStyle.Base128, 1); } - if (metadata.Master == -1) - { - base.LockProject(); - metadata.Master = m_slotIndex; - } - List foreignNewbies; List foreignDirtballs; List foreignGoners; @@ -322,6 +401,7 @@ public override bool Commit(HashSet newbies, HashSet(foreignNewbies); var editedObjects = new HashSet(foreignDirtballs); var removedObjects = new HashSet(foreignGoners); + IEnumerable fields; if (HaveAnythingToCommit(newObjects, editedObjects, removedObjects, out fields) && (StartupVersionNumber == ModelVersion)) PerformCommit(newObjects, editedObjects, removedObjects, fields); @@ -334,6 +414,16 @@ public override bool Commit(HashSet newbies, HashSet cfiList; if (!HaveAnythingToCommit(newbies, dirtballs, goners, out cfiList) && (StartupVersionNumber == ModelVersion)) return true; @@ -342,17 +432,15 @@ public override bool Commit(HashSet newbies, HashSet g.Guid).ToList(), ObjectsAdded = newbies.Select(n => n.XMLBytes).ToList(), ObjectsUpdated = dirtballs.Select(d => d.XMLBytes).ToList() }; - // we've seen our own change, and we use a semaphore to make sure there haven't been others since we checked. - metadata.Slots[m_slotIndex] = metadata.CurrentGeneration; - - // TODO handle custom fields + // we've seen our own change + metadata.Peers[m_peerID].Generation = metadata.CurrentGeneration; using (var buffer = new MemoryStream()) { @@ -362,6 +450,7 @@ public override bool Commit(HashSet newbies, HashSet CommitLogSize) { metadata.Padding = CommitLogSize - offset; @@ -403,7 +492,7 @@ protected override void WriteCommitWork(CommitWork workItem) using (MemoryMappedViewStream stream = m_commitLogMetadata.CreateViewStream()) { var metadata = Serializer.DeserializeWithLengthPrefix(stream, PrefixStyle.Base128, 1); - metadata.FileGeneration = metadata.Slots[m_slotIndex]; + metadata.FileGeneration = metadata.Peers[m_peerID].Generation; stream.Seek(0, SeekOrigin.Begin); Serializer.SerializeWithLengthPrefix(stream, metadata, PrefixStyle.Base128, 1); } @@ -423,9 +512,9 @@ private bool GetUnseenForeignChanges(CommitLogMetadata metadata, foreignDirtballs = new List(); foreignGoners = new List(); - int startGeneration = metadata.Slots[m_slotIndex]; - metadata.Slots[m_slotIndex] = metadata.CurrentGeneration; - int minGeneration = metadata.Slots.Where(g => g != -1).Min(); + int startGeneration = metadata.Peers[m_peerID].Generation; + metadata.Peers[m_peerID].Generation = metadata.CurrentGeneration; + int minPeerGeneration = metadata.Peers.Values.Min(s => s.Generation); var unseenCommits = new List(); int viewOffset = metadata.Offset; @@ -441,15 +530,17 @@ private bool GetUnseenForeignChanges(CommitLogMetadata metadata, while (stream.Position < viewLength) { var rec = Serializer.DeserializeWithLengthPrefix(stream, PrefixStyle.Base128, 1); - if (rec.WriteGeneration > startGeneration && rec.Source != m_slotIndex) + if (rec.WriteGeneration > startGeneration && rec.Source != m_peerID) unseenCommits.Add(rec); - if (rec.WriteGeneration <= minGeneration) + // remove the record from the commit log once all peers have seen it and it has been written to disk + if (rec.WriteGeneration <= minPeerGeneration && rec.WriteGeneration <= metadata.FileGeneration) metadata.Offset = viewOffset + (int) stream.Position; } } } curLength += viewLength; metadata.Length -= metadata.Offset - viewOffset; + // check if we've hit the end of the commit log. If so, wrap around to the beginning. if (metadata.Offset == CommitLogSize - metadata.Padding) { metadata.Length -= metadata.Padding; diff --git a/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs b/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs index bdd03cc7c4..6c8207fffc 100644 --- a/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/XMLBackendProvider.cs @@ -110,7 +110,6 @@ public void Combine(CommitWork work) #region Member variables private DateTime m_lastWriteTime; - private ConsumerThread m_thread; private FileStream m_lockFile; private bool m_needConversion; // communicates to MakeSurrogate that we're reading an old version. private int m_startupVersionNumber; @@ -142,6 +141,8 @@ protected int StartupVersionNumber get { return m_startupVersionNumber; } } + protected ConsumerThread CommitThread { get; set; } + /// ------------------------------------------------------------------------------------ /// /// Start the BEP. @@ -332,11 +333,11 @@ protected override void ShutdownInternal() { CompleteAllCommits(); // Make sure the commit thread is stopped. (FWR-3179) - if (m_thread != null) + if (CommitThread != null) { - m_thread.StopOnIdle(); // CompleteAllCommits should wait until idle, but just in case... - m_thread.Dispose(); - m_thread = null; + CommitThread.StopOnIdle(); // CompleteAllCommits should wait until idle, but just in case... + CommitThread.Dispose(); + CommitThread = null; } UnlockProject(); } @@ -465,17 +466,17 @@ public override bool Commit(HashSet newbies, HashSet newbies, HashSet dirtballs, HashSet goners, IEnumerable customFields) { - if (m_thread == null || !m_thread.WaitForNextRequest()) + if (CommitThread == null || !CommitThread.WaitForNextRequest()) { // If thread is already dead, then WaitForNextRequest will return false, but we still have to call Dispose() on it. - if (m_thread != null) - m_thread.Dispose(); + if (CommitThread != null) + CommitThread.Dispose(); - m_thread = new ConsumerThread(Work); - m_thread.Start(); + CommitThread = new ConsumerThread(Work); + CommitThread.Start(); } - m_thread.EnqueueWork(new CommitWork(newbies, dirtballs, goners, customFields)); + CommitThread.EnqueueWork(new CommitWork(newbies, dirtballs, goners, customFields)); } /// @@ -484,8 +485,8 @@ protected void PerformCommit(HashSet newbies, HashSet queueAccessor) else workItem.Combine(curWorkItem); } - if (workItem == null) return; From 9104d56ef030ec3250343478c998a723e8edb644 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 16 May 2014 16:14:31 +0700 Subject: [PATCH 114/143] added more information to XAmple exceptions Change-Id: I1edc6e09d4ef96eabc60d15d5b9105182e504737 --- .../XAmpleManagedWrapper/XAmpleDLLWrapper.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleDLLWrapper.cs b/Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleDLLWrapper.cs index 3023f9d22e..da65acf8ad 100644 --- a/Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleDLLWrapper.cs +++ b/Src/LexText/ParserCore/XAmpleManagedWrapper/XAmpleDLLWrapper.cs @@ -339,15 +339,15 @@ public void LoadFiles (string lspzFixedFilesDir, string lspzDynamicFilesDir, str // ortho string sResult = m_ampleLoadControlFiles (m_setup, lpszAdCtl, lpszCdTable, null, null); // INTX - ThrowIfError (sResult); + ThrowIfError (sResult, lpszAdCtl, lpszCdTable); //LOAD ROOT DICTIONARIES sResult = m_ampleLoadDictionary (m_setup, lpszDict, "u"); - ThrowIfError (sResult); + ThrowIfError (sResult, lpszDict); //LOAD GRAMMAR FILE sResult = m_ampleLoadGrammarFile (m_setup, lpszGram); - ThrowIfError (sResult); + ThrowIfError (sResult, lpszGram); } public void SetParameter (string lspzName, string lspzValue) @@ -400,7 +400,7 @@ protected void CheckLogForErrors () throw new NotImplementedException (); } - protected void ThrowIfError (string result) + protected void ThrowIfError (string result, params string[] filenames) { // REVIEW JohnH(RandyR): // Isn't the none in the XML supposed to have quote marks around it @@ -414,12 +414,13 @@ protected void ThrowIfError (string result) string t = Path.GetTempFileName (); using (var stream = new StreamWriter(t)) { - stream.Write (result); - stream.Close (); - throw new ApplicationException (result); + stream.Write (result); + stream.Close (); + string message = filenames.Length == 0 ? result : string.Format("{0}; Files: {1}", result, string.Join(",", filenames)); + throw new ApplicationException (message); + } } } - } protected void CheckPtr (IntPtr p) { From e325b11dfc08427158c9578cae8e47f934f93f0e Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 16 May 2014 17:17:13 +0700 Subject: [PATCH 115/143] added AssemblyInfoForTests to FwParatextLexiconPluginTests Change-Id: I602fc66cc8ece0d038d72f7d1844a16ea535fc14 --- .../FwParatextLexiconPluginTests.csproj | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FwParatextLexiconPluginTests.csproj b/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FwParatextLexiconPluginTests.csproj index 9fc7c6cb3a..a5262d78af 100644 --- a/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FwParatextLexiconPluginTests.csproj +++ b/Src/FwParatextLexiconPlugin/FwParatextLexiconPluginTests/FwParatextLexiconPluginTests.csproj @@ -38,6 +38,10 @@ ..\..\..\Output\Debug\BasicUtils.dll + + False + ..\..\..\Output\Debug\BasicUtilsTests.dll + ..\..\..\Output\Debug\COMInterfaces.dll @@ -64,6 +68,9 @@ + + Properties\AssemblyInfoForTests.cs + From e40439704012d00f0568c4ca76ce026daa29dae8 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 16 May 2014 17:42:20 +0700 Subject: [PATCH 116/143] fixed bug when removing senses from FdoLexEntryLexeme Change-Id: Iad177c221876a46e93411760cea72ee6dcad9505 --- Src/FwParatextLexiconPlugin/FdoLexEntryLexeme.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Src/FwParatextLexiconPlugin/FdoLexEntryLexeme.cs b/Src/FwParatextLexiconPlugin/FdoLexEntryLexeme.cs index 549a26532b..569b5ee1c3 100644 --- a/Src/FwParatextLexiconPlugin/FdoLexEntryLexeme.cs +++ b/Src/FwParatextLexiconPlugin/FdoLexEntryLexeme.cs @@ -252,7 +252,7 @@ public void RemoveSense(LexiconSense sense) if (entry.AllSenses.Count == 1) { foreach (int ws in leSense.Sense.Gloss.AvailableWritingSystemIds) - leSense.Sense.Gloss.set_String(ws, null); + leSense.Sense.Gloss.set_String(ws, (ITsString) null); } else { From 5b93ab4ac430745d102ac332eb6f9af6e66374c1 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Thu, 29 May 2014 16:34:27 +0700 Subject: [PATCH 117/143] updated registration-free COM to use assembly manifests Change-Id: Id75e1a238c42db9f4bb7fe28c9c98fbd2cea756b --- Build/FwBuildTasks.dll | Bin 157696 -> 158720 bytes Build/RegFree.targets | 11 +- Build/Src/FwBuildTasks/RegFree.cs | 43 +++++-- Build/Src/FwBuildTasks/RegFreeCreator.cs | 117 ++++++++++-------- Build/Windows.targets | 5 - Build/mkall.targets | 18 +-- .../BuildInclude.targets | 2 +- 7 files changed, 114 insertions(+), 82 deletions(-) diff --git a/Build/FwBuildTasks.dll b/Build/FwBuildTasks.dll index 22aadba24938b081c13d0cc8bd40cb1ae557255e..6e526b4d9556cceabd79e72e2cbcc0d7d30e9820 100755 GIT binary patch delta 38587 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 delta 37583 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 diff --git a/Build/RegFree.targets b/Build/RegFree.targets index da8a2c6f8a..c3566f9801 100644 --- a/Build/RegFree.targets +++ b/Build/RegFree.targets @@ -7,16 +7,15 @@ This allows our programs to run without registering our COM DLLs, which in turn allows different versions of FieldWorks to coexist on the same computer. This is only relevant for Windows.--> - - - + + + - - + + diff --git a/Build/Src/FwBuildTasks/RegFree.cs b/Build/Src/FwBuildTasks/RegFree.cs index 1834344e42..26cb4af371 100644 --- a/Build/Src/FwBuildTasks/RegFree.cs +++ b/Build/Src/FwBuildTasks/RegFree.cs @@ -16,6 +16,7 @@ // --------------------------------------------------------------------------------------------- using System; using System.Collections.Specialized; +using System.Diagnostics; using System.IO; using System.Linq; using System.Security.Principal; @@ -103,6 +104,12 @@ public RegFree() /// ------------------------------------------------------------------------------------ public ITaskItem[] AsIs { get; set; } + /// + /// Gets or sets the dependent assemblies. Currently, this only accepts paths to assembly + /// manifests. + /// + public ITaskItem[] DependentAssemblies { get; set; } + private bool? m_IsAdmin; private bool UserIsAdmin { @@ -130,12 +137,12 @@ public override bool Execute() StringCollection dllPaths = IdlImp.GetFilesFrom(Dlls); if (dllPaths.Count == 0) - dllPaths.Add(Executable); - bool isSxs = dllPaths.Count == 1 && dllPaths[0] == Executable; - string executable = Executable; - if (isSxs) - executable = Path.Combine(Path.GetDirectoryName(Executable), Path.GetFileNameWithoutExtension(Executable) + ".sxs"); - string manifestFile = string.IsNullOrEmpty(Output) ? executable + ".manifest" : Output; + { + string ext = Path.GetExtension(Executable); + if (ext != null && ext.Equals(".dll", StringComparison.InvariantCultureIgnoreCase)) + dllPaths.Add(Executable); + } + string manifestFile = string.IsNullOrEmpty(Output) ? Executable + ".manifest" : Output; try { @@ -170,7 +177,23 @@ public override bool Execute() } } - XmlElement root = creator.CreateExeInfo(Executable, isSxs); + string assemblyName = Path.GetFileNameWithoutExtension(manifestFile); + Debug.Assert(assemblyName != null); + // The C++ test programs won't run if an assemblyIdentity element exists. + //if (assemblyName.StartsWith("test")) + // assemblyName = null; + string assemblyVersion = null; + try + { + assemblyVersion = FileVersionInfo.GetVersionInfo(Executable).FileVersion; + } + catch + { + // just ignore + } + if (string.IsNullOrEmpty(assemblyVersion)) + assemblyVersion = "1.0.0.0"; + XmlElement root = creator.CreateExeInfo(assemblyName, assemblyVersion); foreach (string fileName in dllPaths) { if (NoTypeLib.Count(f => f.ItemSpec == fileName) != 0) @@ -193,6 +216,12 @@ public override bool Execute() creator.AddAsIs(root, fragmentName); } + foreach (string assemblyFileName in IdlImp.GetFilesFrom(DependentAssemblies)) + { + Log.LogMessage(MessageImportance.Low, "\tAdding dependent assembly {0}", Path.GetFileName(assemblyFileName)); + creator.AddDependentAssembly(root, assemblyFileName); + } + var settings = new XmlWriterSettings { OmitXmlDeclaration = false, diff --git a/Build/Src/FwBuildTasks/RegFreeCreator.cs b/Build/Src/FwBuildTasks/RegFreeCreator.cs index caffbb6d4c..d9c38133bc 100644 --- a/Build/Src/FwBuildTasks/RegFreeCreator.cs +++ b/Build/Src/FwBuildTasks/RegFreeCreator.cs @@ -17,6 +17,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using System.IO; using System.Linq; using System.Runtime.InteropServices; @@ -52,6 +53,7 @@ public class RegFreeCreator private readonly Dictionary _interfaceProxies = new Dictionary(); private readonly Dictionary _tlbGuids = new Dictionary(); private readonly List _nonExistingServers = new List(); + private readonly XmlNamespaceManager _nsManager; private const string UrnSchema = "http://www.w3.org/2001/XMLSchema-instance"; private const string UrnAsmv1 = "urn:schemas-microsoft-com:asm.v1"; @@ -69,6 +71,7 @@ public class RegFreeCreator public RegFreeCreator(XmlDocument doc) { _doc = doc; + _nsManager = CreateNamespaceManager(_doc); } /// ------------------------------------------------------------------------------------ @@ -76,16 +79,25 @@ public RegFreeCreator(XmlDocument doc) /// Initializes a new instance of the class. /// /// The XML document. - /// set to true to display warnings, otherwise - /// false. + /// /// ------------------------------------------------------------------------------------ - public RegFreeCreator(XmlDocument doc, TaskLoggingHelper Log): this(doc) + public RegFreeCreator(XmlDocument doc, TaskLoggingHelper log): this(doc) { - this._log = Log; + _log = log; } #endregion + private static XmlNamespaceManager CreateNamespaceManager(XmlDocument doc) + { + var namespaceManager = new XmlNamespaceManager(doc.NameTable); + namespaceManager.AddNamespace("asmv1", UrnAsmv1); + namespaceManager.AddNamespace("asmv2", UrnAsmv2); + namespaceManager.AddNamespace("dsig", UrnDsig); + namespaceManager.AddNamespace("xsi", UrnSchema); + return namespaceManager; + } + /// ------------------------------------------------------------------------------------ /// /// Creates the info for the executable. The info consist of: @@ -96,10 +108,8 @@ public RegFreeCreator(XmlDocument doc, TaskLoggingHelper Log): this(doc) /// /// This method also adds the root element with all necessary namespaces. /// - /// pathname of the file. - /// /// ------------------------------------------------------------------------------------ - public XmlElement CreateExeInfo(string pathName, bool isSxs) + public XmlElement CreateExeInfo(string assemblyName, string assemblyVersion) { XmlElement elem = _doc.CreateElement("assembly", UrnAsmv1); elem.SetAttribute("manifestVersion", "1.0"); @@ -109,35 +119,21 @@ public XmlElement CreateExeInfo(string pathName, bool isSxs) elem.SetAttribute("xmlns:xsi", UrnSchema); elem.SetAttribute("schemaLocation", UrnSchema, UrnAsmv1 + " assembly.adaptive.xsd"); - XmlNode oldChild = _doc.SelectSingleNode("assembly"); + XmlNode oldChild = _doc.SelectSingleNode("asmv1:assembly", _nsManager); if (oldChild != null) _doc.ReplaceChild(elem, oldChild); else _doc.AppendChild(elem); - // The C++ test programs won't run if an assemblyIdentity element exists. - string fileName = Path.GetFileName(pathName); - if (!fileName.StartsWith("test")) + if (!string.IsNullOrEmpty(assemblyName)) { // XmlElement assemblyIdentity = _doc.CreateElement("assemblyIdentity", UrnAsmv1); - if (isSxs) - fileName = Path.GetFileNameWithoutExtension(fileName) + ".sxs"; - assemblyIdentity.SetAttribute("name", fileName); - // ReSharper disable EmptyGeneralCatchClause - try - { - FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(pathName); - assemblyIdentity.SetAttribute("version", versionInfo.FileVersion); - } - catch - { - // just ignore - } - // ReSharper restore EmptyGeneralCatchClause + assemblyIdentity.SetAttribute("name", assemblyName); + assemblyIdentity.SetAttribute("version", assemblyVersion); assemblyIdentity.SetAttribute("type", "win32"); - oldChild = elem.SelectSingleNode("assemblyIdentity"); + oldChild = elem.SelectSingleNode("asmv1:assemblyIdentity", _nsManager); if (oldChild != null) elem.ReplaceChild(assemblyIdentity, oldChild); else @@ -197,16 +193,16 @@ public void ProcessTypeLibrary(XmlElement parent, string fileName) elem.SetAttribute("helpdir", string.Empty); elem.SetAttribute("resourceid", "0"); elem.SetAttribute("flags", flags); - oldChild = file.SelectSingleNode(string.Format("typelib[tlbid='{0}']", - libAttr.guid.ToString("B"))); + oldChild = file.SelectSingleNode(string.Format("asmv1:typelib[asmv1:tlbid='{0}']", + libAttr.guid.ToString("B")), _nsManager); if (oldChild != null) file.ReplaceChild(elem, oldChild); else file.AppendChild(elem); } - Debug.WriteLine(string.Format(@"typelib tlbid=""{0}"" version=""{1}.{2}"" helpdir="""" resourceid=""0"" flags=""{3}""", - libAttr.guid, libAttr.wMajorVerNum, libAttr.wMinorVerNum, flags)); + Debug.WriteLine(@"typelib tlbid=""{0}"" version=""{1}.{2}"" helpdir="""" resourceid=""0"" flags=""{3}""", + libAttr.guid, libAttr.wMajorVerNum, libAttr.wMinorVerNum, flags); int count = typeLib.GetTypeInfoCount(); _log.LogMessage(MessageImportance.Low, "\t\tTypelib has {0} types", count); @@ -218,8 +214,8 @@ public void ProcessTypeLibrary(XmlElement parent, string fileName) ProcessTypeInfo(parent, libAttr.guid, typeInfo); } - oldChild = parent.SelectSingleNode(string.Format("file[name='{0}']", - Path.GetFileName(fileName))); + oldChild = parent.SelectSingleNode(string.Format("asmv1:file[asmv1:name='{0}']", + Path.GetFileName(fileName)), _nsManager); if (oldChild != null) parent.ReplaceChild(file, oldChild); else @@ -261,7 +257,7 @@ private static string GetDefaultValueForKey(RegistryKey parentKey, string keyNam /// ------------------------------------------------------------------------------------ public void ProcessClasses(XmlElement parent) { - using (var regKeyClsid = Registry.CurrentUser.OpenSubKey(Tasks.RegHelper.TmpRegistryKeyHKCR + @"\CLSID")) + using (var regKeyClsid = Registry.CurrentUser.OpenSubKey(RegHelper.TmpRegistryKeyHKCR + @"\CLSID")) { if (regKeyClsid == null) { @@ -277,7 +273,7 @@ public void ProcessClasses(XmlElement parent) if (_coClasses.ContainsKey(clsId.ToLower())) continue; - using (var regKeyClass = regKeyClsid.OpenSubKey(clsId)) + using (RegistryKey regKeyClass = regKeyClsid.OpenSubKey(clsId)) { var className = (string)regKeyClass.GetValue(string.Empty, string.Empty); using (var regKeyInProcServer = regKeyClass.OpenSubKey("InProcServer32")) @@ -304,7 +300,7 @@ public void ProcessClasses(XmlElement parent) /// ------------------------------------------------------------------------------------ public void ProcessInterfaces(XmlElement root) { - using (var regKeyBase = Registry.CurrentUser.OpenSubKey(Tasks.RegHelper.TmpRegistryKeyHKCR)) + using (var regKeyBase = Registry.CurrentUser.OpenSubKey(RegHelper.TmpRegistryKeyHKCR)) using (var regKeyInterfaces = regKeyBase.OpenSubKey("Interface")) { if (regKeyInterfaces == null) @@ -323,8 +319,7 @@ public void ProcessInterfaces(XmlElement root) _log.LogError("no proxyStubClsid32 set for interface with iid {0}", interfaceIid); continue; } - Debug.WriteLine(string.Format("Interface {0} is {1}: {2} methods, proxy: {3}", interfaceIid, - interfaceName, numMethods, proxyStubClsId)); + Debug.WriteLine("Interface {0} is {1}: {2} methods, proxy: {3}", interfaceIid, interfaceName, numMethods, proxyStubClsId); if (!_coClasses.ContainsKey(proxyStubClsId)) { @@ -360,21 +355,6 @@ public void ProcessInterfaces(XmlElement root) } } - /// ------------------------------------------------------------------------------------ - /// - /// Gets the child node. This is similar to XmlNode.SelectSingleNode which has the draw- - /// back that it doesn't work "live". - /// - /// The parent node. - /// Name of the child. - /// The child node, or null if no child with name - /// exists. - /// ------------------------------------------------------------------------------------ - private static XmlNode GetChildNode(XmlNode parentNode, string childName) - { - return parentNode.ChildNodes.Cast().FirstOrDefault(child => child.Name == childName); - } - /// ------------------------------------------------------------------------------------ /// /// Gets the child node with name which has an @@ -481,6 +461,34 @@ public void AddAsIs(XmlElement parent, string fileName) AddFragmentInternal(parent, fileName, null); } + public void AddDependentAssembly(XmlElement parent, string fileName) + { + var depAsmElem = (XmlElement) parent.SelectSingleNode(string.Format("asmv1:dependency/asmv1:dependentAssembly[@asmv2:codebase = '{0}']", Path.GetFileName(fileName)), _nsManager); + if (depAsmElem == null) + { + var depElem = _doc.CreateElement("dependency", UrnAsmv1); + parent.AppendChild(depElem); + depAsmElem = _doc.CreateElement("dependentAssembly", UrnAsmv1); + depElem.AppendChild(depAsmElem); + depAsmElem.SetAttribute("codebase", UrnAsmv2, Path.GetFileName(fileName)); + } + var asmIdElem = (XmlElement) depAsmElem.SelectSingleNode("asmv1:assemblyIdentity", _nsManager); + if (asmIdElem == null) + { + asmIdElem = _doc.CreateElement("assemblyIdentity", UrnAsmv1); + depAsmElem.AppendChild(asmIdElem); + } + + var depAsmManifestDoc = new XmlDocument(); + depAsmManifestDoc.Load(fileName); + var depAsmNsManager = CreateNamespaceManager(depAsmManifestDoc); + var manifestAsmIdElem = (XmlElement) depAsmManifestDoc.SelectSingleNode("/asmv1:assembly/asmv1:assemblyIdentity", depAsmNsManager); + Debug.Assert(manifestAsmIdElem != null); + asmIdElem.SetAttribute("name", manifestAsmIdElem.GetAttribute("name")); + asmIdElem.SetAttribute("version", manifestAsmIdElem.GetAttribute("version")); + asmIdElem.SetAttribute("type", manifestAsmIdElem.GetAttribute("type")); + } + /// ------------------------------------------------------------------------------------ /// /// Processes one type info. We get the necessary information from the type library @@ -512,7 +520,7 @@ private void ProcessTypeInfo(XmlNode parent, Guid tlbGuid, ITypeInfo typeInfo) // Try to get the file element for the server var bldr = new StringBuilder(255); - Tasks.RegHelper.GetLongPathName((string)inprocServer.GetValue(null), bldr, 255); + RegHelper.GetLongPathName((string)inprocServer.GetValue(null), bldr, 255); string serverFullPath = bldr.ToString(); string server = Path.GetFileName(serverFullPath); if (!File.Exists(serverFullPath) && @@ -598,6 +606,7 @@ private void AddOrReplaceCoClass(XmlElement parent, string clsId, string threadi private XmlElement GetOrCreateFileNode(XmlNode parent, string filePath) { string fileName = Path.GetFileName(filePath); + Debug.Assert(fileName != null); if (_files.ContainsKey(fileName)) return _files[fileName]; @@ -609,7 +618,7 @@ private XmlElement GetOrCreateFileNode(XmlNode parent, string filePath) if (fileInfo.Exists) { parent.AppendChild(file); - file.SetAttribute("size", "urn:schemas-microsoft-com:asm.v2", fileInfo.Length.ToString()); + file.SetAttribute("size", "urn:schemas-microsoft-com:asm.v2", fileInfo.Length.ToString(CultureInfo.InvariantCulture)); } _files.Add(fileName, file); return file; diff --git a/Build/Windows.targets b/Build/Windows.targets index 9bb3d4ae70..edbdf51d42 100644 --- a/Build/Windows.targets +++ b/Build/Windows.targets @@ -100,11 +100,6 @@ --> - - - - - ..\Src\Transforms\Application ..\Src\Transforms\Presentation diff --git a/Build/mkall.targets b/Build/mkall.targets index 9e0b076cce..dd7a2cdab5 100644 --- a/Build/mkall.targets +++ b/Build/mkall.targets @@ -65,7 +65,7 @@ - + @@ -103,6 +102,7 @@ Configuration="$(config-capital)" Target="$(make-target)" BuildRoot="$(fwrt)" WorkingDirectory="$(fwrt)/Src/Graphite/GrEngine"/> + @@ -118,10 +118,11 @@ Configuration="$(config-capital)" Target="$(make-target)" BuildRoot="$(fwrt)" WorkingDirectory="$(fwrt)/Src/Kernel"/> + - + @@ -173,10 +173,11 @@ Configuration="$(config-capital)" Target="$(make-target)" BuildRoot="$(fwrt)" WorkingDirectory="$(fwrt)/Src/views"/> + - + diff --git a/Src/FwParatextLexiconPlugin/BuildInclude.targets b/Src/FwParatextLexiconPlugin/BuildInclude.targets index 9a053ab3f8..f922c466f0 100644 --- a/Src/FwParatextLexiconPlugin/BuildInclude.targets +++ b/Src/FwParatextLexiconPlugin/BuildInclude.targets @@ -2,6 +2,6 @@ - + From 40181c2bfd59417f29afd159f9ad4c59112c5b3f Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Thu, 29 May 2014 17:51:51 +0700 Subject: [PATCH 118/143] added comments to clarify targets that build XSL assemblies Change-Id: I92ac1720274b9b24580c2218239dde8bb05199ea --- Build/Linux.targets | 2 ++ Build/Windows.targets | 1 + 2 files changed, 3 insertions(+) diff --git a/Build/Linux.targets b/Build/Linux.targets index 946d1ddf40..fe60c48b1c 100644 --- a/Build/Linux.targets +++ b/Build/Linux.targets @@ -230,6 +230,8 @@ FirstLine="3fb0fcd2-ac55-42a8-b580-73b89a2b6215 libManagedComBridge.so ManagedVwWindow.dll SIL.FieldWorks.Views.ManagedVwWindow" SecondLine="8856396c-63a9-4bc7-ad47-87ec8b6ef5a4 libManagedComBridge.so"/> + + diff --git a/Build/Windows.targets b/Build/Windows.targets index edbdf51d42..4eca312d03 100644 --- a/Build/Windows.targets +++ b/Build/Windows.targets @@ -100,6 +100,7 @@ --> + ..\Src\Transforms\Application ..\Src\Transforms\Presentation From 5f66a6380f8460f2e0eaed8ff39c5f372cb9333b Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 30 May 2014 09:38:45 +0700 Subject: [PATCH 119/143] refactored DirectoryFinderTests Change-Id: I9a5efaed5b3368073cada42d5a7e188e57d36174 --- .../CoreImplTests/DirectoryFinderTests.cs | 112 ++++++------------ 1 file changed, 39 insertions(+), 73 deletions(-) diff --git a/Src/Common/CoreImpl/CoreImplTests/DirectoryFinderTests.cs b/Src/Common/CoreImpl/CoreImplTests/DirectoryFinderTests.cs index 920dfa3c4a..4b8974a8fa 100644 --- a/Src/Common/CoreImpl/CoreImplTests/DirectoryFinderTests.cs +++ b/Src/Common/CoreImpl/CoreImplTests/DirectoryFinderTests.cs @@ -3,94 +3,60 @@ namespace SIL.CoreImpl { - /// - /// Base class for testing CommonApplicationData. This base class deals with setting - /// and resetting the environment variable. - /// - public class GetCommonAppDataBaseTest - { - private string PreviousEnvironment; + [TestFixture] + public class DirectoryFinderTests + { + private string m_previousEnvironment; - /// - /// Setup the tests. - /// - [TestFixtureSetUp] - public void FixtureSetup() - { - DirectoryFinder.ResetStaticVars(); - PreviousEnvironment = Environment.GetEnvironmentVariable("FW_CommonAppData"); - var properties = (PropertyAttribute[])GetType().GetCustomAttributes(typeof(PropertyAttribute), true); - Assert.That(properties.Length, Is.GreaterThan(0)); - Environment.SetEnvironmentVariable("FW_CommonAppData", (string)properties[0].Properties["Value"]); - } + private void SetupEnvironment(string path) + { + m_previousEnvironment = Environment.GetEnvironmentVariable("FW_CommonAppData"); + DirectoryFinder.ResetStaticVars(); + Environment.SetEnvironmentVariable("FW_CommonAppData", path); + } - /// - /// Reset environment variable to previous value - /// - [TestFixtureTearDown] - public void FixtureTeardown() - { - Environment.SetEnvironmentVariable("FW_CommonAppData", PreviousEnvironment); - } + private void ResetEnvironment() + { + Environment.SetEnvironmentVariable("FW_CommonAppData", m_previousEnvironment); } - /// - /// Tests the GetFolderPath method for CommonApplicationData when no environment variable - /// is set. - /// - [TestFixture] - [Property("Value", null)] - public class GetCommonAppDataNormalTests: GetCommonAppDataBaseTest + [Test] + public void GetFolderPath_NoEnvVariableSet() { - /// Tests the GetFolderPath method for CommonApplicationData when no environment - /// variable is set - [Test] - [Platform(Include="Linux", Reason="Test is Linux specific")] - public void Linux() + try { - Assert.AreEqual("/var/lib/fieldworks", - DirectoryFinder.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)); + SetupEnvironment(null); + string path = DirectoryFinder.GetFolderPath(Environment.SpecialFolder.CommonApplicationData); +#if __MonoCS__ + Assert.That(path, Is.EqualTo("/var/lib/fieldworks")); +#else + Assert.That(path, Is.EqualTo(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData))); +#endif } - - /// Tests the GetFolderPath method for CommonApplicationData when no environment - /// variable is set - [Test] - [Platform(Exclude="Linux", Reason="Test is Windows specific")] - public void Windows() + finally { - Assert.AreEqual( - Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), - DirectoryFinder.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)); + ResetEnvironment(); } } - /// - /// Tests the GetFolderPath method for CommonApplicationData when the environment variable - /// is set. - /// - [TestFixture] - [Property("Value", "/bla")] - public class GetCommonAppDataOverrideTests: GetCommonAppDataBaseTest + [Test] + public void GetFolderPath_EnvVariableSet() { - /// Tests the GetFolderPath method for CommonApplicationData when the environment - /// variable is set - [Test] - [Platform(Include="Linux", Reason="Test is Linux specific")] - public void Linux() + try { - Assert.AreEqual("/bla", - DirectoryFinder.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)); + SetupEnvironment("/bla"); + string path = DirectoryFinder.GetFolderPath(Environment.SpecialFolder.CommonApplicationData); +#if __MonoCS__ + Assert.That(path, Is.EqualTo("/bla")); +#else + Assert.That(path, Is.EqualTo(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData))); +#endif } - - /// Tests the GetFolderPath method for CommonApplicationData when the environment - /// variable is set - [Test] - [Platform(Exclude="Linux", Reason="Test is Windows specific")] - public void Windows() + finally { - Assert.AreEqual( - Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), - DirectoryFinder.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)); + ResetEnvironment(); } } + + } } From a047614f61d26aa702c9aed3a546fe879b795cbd Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 30 May 2014 09:48:33 +0700 Subject: [PATCH 120/143] refactored dipose of ThreadHelper in ProgressDlgTests Change-Id: I4030f3e479303758c43a99723d03b68c9f231614 --- .../FwControlsTests/ProgressDlgTests.cs | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/Src/Common/Controls/FwControls/FwControlsTests/ProgressDlgTests.cs b/Src/Common/Controls/FwControls/FwControlsTests/ProgressDlgTests.cs index 92d2349111..80cbdb1270 100644 --- a/Src/Common/Controls/FwControls/FwControlsTests/ProgressDlgTests.cs +++ b/Src/Common/Controls/FwControls/FwControlsTests/ProgressDlgTests.cs @@ -5,10 +5,10 @@ // File: ProgressDlgTests.cs using System; +using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Threading; using NUnit.Framework; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.Test.TestUtils; using SIL.Utils; @@ -27,20 +27,11 @@ public class DummyProgressDlg : ProgressDialogWithTask /// Initializes a new instance of the class. /// /// ------------------------------------------------------------------------------------ - public DummyProgressDlg() : base(new ThreadHelper()) + public DummyProgressDlg(ISynchronizeInvoke synchronizeInvoke) + : base(synchronizeInvoke) { } - /// - protected override void Dispose(bool disposing) - { - if (disposing && !IsDisposed) - { - ((ThreadHelper) SynchronizeInvoke).Dispose(); - } - base.Dispose(disposing); - } - /// ------------------------------------------------------------------------------------ /// /// Gets a value indicating wether or not the cancel button is visible. @@ -78,6 +69,7 @@ public void SimulatePressCancel() Justification="Unit test, object is disposed in TearDown method")] public class ProgressDlgTests : BaseTest { + private ThreadHelper m_threadHelper; private DummyProgressDlg m_dlg; private Timer m_timer; @@ -91,7 +83,8 @@ public class ProgressDlgTests : BaseTest Justification="Unit test, object is disposed in TearDown method")] public void Setup() { - m_dlg = new DummyProgressDlg {Maximum = 10}; + m_threadHelper = new ThreadHelper(); + m_dlg = new DummyProgressDlg(m_threadHelper) {Maximum = 10}; } /// ------------------------------------------------------------------------------------ @@ -114,6 +107,12 @@ public void Teardown() m_dlg = null; } + if (m_threadHelper != null) + { + m_threadHelper.Dispose(); + m_threadHelper = null; + } + } /// ------------------------------------------------------------------------------------ @@ -174,7 +173,7 @@ private static object BackgroundTask(IThreadedProgress progressDlg, object[] par /// /// ------------------------------------------------------------------------------------ [Test] - [Category("DesktopRequired")] + [NUnit.Framework.Category("DesktopRequired")] public void TestWithCancel() { StartTimer(2500); @@ -192,7 +191,7 @@ public void TestWithCancel() /// /// ------------------------------------------------------------------------------------ [Test] - [Category("DesktopRequired")] + [NUnit.Framework.Category("DesktopRequired")] public void TestWithoutCancel() { var nProgress = (int) m_dlg.RunTask(false, BackgroundTask); From 1892dbe2701064b0459f876ead3f7c4b2fb21a50 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 30 May 2014 10:51:40 +0700 Subject: [PATCH 121/143] refactored error handling in IcuWrappers Change-Id: I916750802655b81c7c28f7db8ccdf010ac8b2667 --- Src/Common/COMInterfaces/IcuWrappers.cs | 270 ++++++++++-------- .../Controls/XMLViews/ConfiguredExport.cs | 2 +- 2 files changed, 152 insertions(+), 120 deletions(-) diff --git a/Src/Common/COMInterfaces/IcuWrappers.cs b/Src/Common/COMInterfaces/IcuWrappers.cs index ad645ae001..3e6633558e 100644 --- a/Src/Common/COMInterfaces/IcuWrappers.cs +++ b/Src/Common/COMInterfaces/IcuWrappers.cs @@ -130,8 +130,10 @@ private static bool IsInRange(string codepoint, CharacterRange[] rangesToCheck) return false; } - private static readonly CharacterRange[] s_validCodepointRanges = new[] { - new CharacterRange {Start = "0000", End = "10FFFD"} }; + private static readonly CharacterRange[] s_validCodepointRanges = + { + new CharacterRange {Start = "0000", End = "10FFFD"} + }; /// ------------------------------------------------------------------------------------ /// @@ -145,11 +147,12 @@ public static bool IsValidCodepoint(string codepoint) } // List of the ranges that are acceptable - private static readonly CharacterRange[] s_puaRanges = new[] { - new CharacterRange { Start = "E000", End = "F8FF" }, - new CharacterRange { Start = "F0000", End = "FFFFD" }, - new CharacterRange { Start = "100000", End = "10FFFD" } - }; + private static readonly CharacterRange[] s_puaRanges = + { + new CharacterRange { Start = "E000", End = "F8FF" }, + new CharacterRange { Start = "F0000", End = "FFFFD" }, + new CharacterRange { Start = "100000", End = "10FFFD" } + }; /// ------------------------------------------------------------------------------------ /// @@ -172,11 +175,12 @@ public static bool IsPrivateUse(string codepoint) // but that's not clear, so we're adding plane 16 as of September 15, 2005. If // there's really a reason why plane 16 was not included here, remove it and // document the reason! - private static readonly CharacterRange[] s_customPuaRanges = new[] { - new CharacterRange { Start = "E000", End = "EFFF" }, - new CharacterRange { Start = "F0000", End = "FFFFD" }, - new CharacterRange { Start = "100000", End = "10FFFD"} - }; + private static readonly CharacterRange[] s_customPuaRanges = + { + new CharacterRange { Start = "E000", End = "EFFF" }, + new CharacterRange { Start = "F0000", End = "FFFFD" }, + new CharacterRange { Start = "100000", End = "10FFFD"} + }; /// ------------------------------------------------------------------------------------ /// @@ -190,8 +194,10 @@ public static bool IsCustomUse(string codepoint) } // List of the ranges that are set aside for surrogates - private static readonly CharacterRange[] s_surrogateRanges = new[] { - new CharacterRange {Start = "D800", End = "DFFF"} }; + private static readonly CharacterRange[] s_surrogateRanges = + { + new CharacterRange {Start = "D800", End = "DFFF"} + }; /// ------------------------------------------------------------------------------------ /// @@ -213,7 +219,7 @@ public static bool IsSurrogate(string codepoint) /// ------------------------------------------------------------------------------------ public static void InitIcuDataDir() { - System.Diagnostics.Debug.Assert(kIcuVersion == "_50", "Yo developers! We are using a different version of ICU. " + + Debug.Assert(kIcuVersion == "_50", "Yo developers! We are using a different version of ICU. " + "Change UnicodeVersion to return the correct version, and then change this assertion so that it checks for the new version of kIcuVersion." + "We had to do it this way because ICU can't tell us which version of Unicode it supports. " + "If they add a method to do this in the future, then we can just make UnicodeVersion work by calling that method." + @@ -644,7 +650,7 @@ public static bool IsControl(int characterCode) /// ------------------------------------------------------------------------------------ public static bool IsControl(string chr) { - return (string.IsNullOrEmpty(chr) || chr.Length != 1 ? false : IsControl(chr[0])); + return (!string.IsNullOrEmpty(chr) && chr.Length == 1 && IsControl(chr[0])); } /// ------------------------------------------------------------------------------------ @@ -685,7 +691,7 @@ public static bool IsSpace(int characterCode) /// ------------------------------------------------------------------------------------ public static bool IsSpace(string chr) { - return (string.IsNullOrEmpty(chr) || chr.Length != 1 ? false : IsSpace(chr[0])); + return (!string.IsNullOrEmpty(chr) && chr.Length == 1 && IsSpace(chr[0])); } /// ------------------------------------------------------------------------------------ @@ -744,7 +750,7 @@ public static string GetCharName(int code) string name; UErrorCode error; if (u_CharName(code, UCharNameChoice.U_UNICODE_CHAR_NAME, out name, out error) > 0 && - error == UErrorCode.U_ZERO_ERROR) + IsSuccess(error)) { return name; } @@ -887,20 +893,14 @@ public static int GetLanguageCode(string localeID, out string language, out UErr /// /// the locale to get the language code with /// the language code for the locale. - /// Thrown if ICU method fails with an error. - /// /// ------------------------------------------------------------------------------------ public static string GetLanguageCode(string locale) { string languageCode; UErrorCode err; GetLanguageCode(locale, out languageCode, out err); - if (err != UErrorCode.U_ZERO_ERROR) - { - throw new ArgumentException( - string.Format("ICU uloc_getLanguage with argument '{0}' failed with error {1}", locale, err), - "locale"); - } + if (IsFailure(err)) + throw new IcuException(string.Format("uloc_getLanguage() with argument '{0}' failed with error {1}", locale, err), err); return languageCode; } @@ -996,20 +996,14 @@ public static int GetCountryCode(string localeID, out string country, out UError /// /// the locale to get the country code with /// The country code for the locale. - /// Thrown if ICU method fails with an error. - /// /// ------------------------------------------------------------------------------------ public static string GetCountryCode(string locale) { string countryCode; UErrorCode err; GetCountryCode(locale, out countryCode, out err); - if (err != UErrorCode.U_ZERO_ERROR) - { - throw new ArgumentException( - string.Format("ICU uloc_getCountry with argument '{0}' failed with error {1}", locale, err), - "locale"); - } + if (IsFailure(err)) + throw new IcuException(string.Format("uloc_getCountry() with argument '{0}' failed with error {1}", locale, err), err); return countryCode; } @@ -1136,7 +1130,7 @@ public static string GetDisplayName(string localeID) string displayName; UErrorCode uerr; GetDisplayName(localeID, uilocale, out displayName, out uerr); - if (uerr == UErrorCode.U_ZERO_ERROR) + if (IsSuccess(uerr)) return displayName; return string.Empty; } @@ -1274,9 +1268,9 @@ public static string GetName(string localeID) try { UErrorCode err; - int nResult = uloc_getName(localeID, resPtr, nSize, out err); - if (err > UErrorCode.U_ZERO_ERROR) - throw new Exception("uloc_getName failed with code " + err); + uloc_getName(localeID, resPtr, nSize, out err); + if (IsFailure(err)) + throw new IcuException("uloc_getName() failed with code " + err, err); return Marshal.PtrToStringAnsi(resPtr); } finally @@ -1327,18 +1321,17 @@ public static string ToLower(string src, string locale) { UErrorCode err; int outLength = u_strToLower(resPtr, length, src, src.Length, locale, out err); - if (err > 0 && err != UErrorCode.U_BUFFER_OVERFLOW_ERROR) - throw new Exception("Icu.ToLower() failed with code " + err); + if (IsFailure(err) && err != UErrorCode.U_BUFFER_OVERFLOW_ERROR) + throw new IcuException("u_strToLower() failed with code " + err, err); if (outLength > length) { - err = UErrorCode.U_ZERO_ERROR; // ignore possible U_BUFFER_OVERFLOW_ERROR Marshal.FreeCoTaskMem(resPtr); length = outLength + 1; resPtr = Marshal.AllocCoTaskMem(length * 2); u_strToLower(resPtr, length, src, src.Length, locale, out err); } - if (err > 0) - throw new Exception("Icu.ToLower() failed with code " + err); + if (IsFailure(err)) + throw new IcuException("u_strToLower() failed with code " + err, err); string result = Marshal.PtrToStringUni(resPtr); // Strip any garbage left over at the end of the string. @@ -1367,8 +1360,8 @@ public static IntPtr OpenCollator(string locale) { UErrorCode err; IntPtr collator = ucol_open(string.IsNullOrEmpty(locale) ? null : Encoding.UTF8.GetBytes(locale), out err); - if (err > UErrorCode.U_ZERO_ERROR) - throw new Exception("ucol_open failed with code " + err); + if (IsFailure(err)) + throw new IcuException("ucol_open() failed with code " + err, err); return collator; } @@ -1447,56 +1440,6 @@ private static extern IntPtr ucol_openRules(string rules, int rulesLength, UColA CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] private static extern void ucol_close(IntPtr coll); - /// ------------------------------------------------------------------------------------ - /// - /// Simple class to allow passing collation error info back to the caller of CheckRules. - /// - /// ------------------------------------------------------------------------------------ - public class CollationRuleErrorInfo - { - internal CollationRuleErrorInfo(UParseError parseError) - { - Line = parseError.line + 1; - Offset = parseError.offset + 1; - PreContext = parseError.preContext; - PostContext = parseError.postContext; - } - - /// Line number (1-based) containing the error - public int Line { get; private set; } - /// Character offset (1-based) on Line where the error was detected - public int Offset { get; private set; } - /// Characters preceding the the error - public String PreContext { get; private set; } - /// Characters following the the error - public String PostContext { get; private set; } - } - - /// - /// Collation rule exception - /// - public class CollationRuleException : Exception - { - private readonly CollationRuleErrorInfo m_errorInfo; - - /// - /// Initializes a new instance of the class. - /// - /// The error information. - public CollationRuleException(CollationRuleErrorInfo errorInfo) - { - m_errorInfo = errorInfo; - } - - /// - /// Gets the parse error information. - /// - public CollationRuleErrorInfo ErrorInfo - { - get { return m_errorInfo; } - } - } - /// /// Opens the specified collation rules as a collator. /// @@ -1508,9 +1451,9 @@ public static IntPtr OpenRuleBasedCollator(string rules) UParseError parseError; IntPtr collator = ucol_openRules(rules, rules.Length, UColAttributeValue.UCOL_DEFAULT, UColAttributeValue.UCOL_DEFAULT_STRENGTH, out parseError, out err); - if (err <= UErrorCode.U_ZERO_ERROR) + if (IsSuccess(err)) return collator; - throw new CollationRuleException(new CollationRuleErrorInfo(parseError)); + throw new CollationRuleException(err, new CollationRuleErrorInfo(parseError)); } /// ------------------------------------------------------------------------------------ @@ -1531,7 +1474,7 @@ public static CollationRuleErrorInfo CheckRules(string rules) UColAttributeValue.UCOL_DEFAULT_STRENGTH, out parseError, out err); try { - if (err == UErrorCode.U_ZERO_ERROR) + if (IsSuccess(err)) return null; return new CollationRuleErrorInfo(parseError); @@ -1611,14 +1554,14 @@ public static void GetSortKeyBound(byte[] sortKey, UColBoundMode boundType, ref { UErrorCode err; int size = ucol_getBound(sortKey, sortKey.Length, boundType, 1, result, result.Length, out err); - if (err > 0 && err != UErrorCode.U_BUFFER_OVERFLOW_ERROR) - throw new Exception("ucol_getBound failed with code " + err); + if (IsFailure(err) && err != UErrorCode.U_BUFFER_OVERFLOW_ERROR) + throw new IcuException("ucol_getBound() failed with code " + err, err); if (size > result.Length) { result = new byte[size + 1]; ucol_getBound(sortKey, sortKey.Length, boundType, 1, result, result.Length, out err); - if (err > 0) - throw new Exception("ucol_getBound failed with code " + err); + if (IsFailure(err)) + throw new IcuException("ucol_getBound() failed with code " + err, err); } } @@ -1662,18 +1605,17 @@ public static string ToTitle(string src, string locale) { UErrorCode err; int outLength = u_strToTitle(resPtr, length, src, src.Length, IntPtr.Zero, locale, out err); - if (err > 0 && err != UErrorCode.U_BUFFER_OVERFLOW_ERROR) - throw new Exception("Icu.ToTitle() failed with code " + err); + if (IsFailure(err) && err != UErrorCode.U_BUFFER_OVERFLOW_ERROR) + throw new IcuException("u_strToTitle() failed with code " + err, err); if (outLength > length) { - err = UErrorCode.U_ZERO_ERROR; // ignore possible U_BUFFER_OVERFLOW_ERROR Marshal.FreeCoTaskMem(resPtr); length = outLength + 1; resPtr = Marshal.AllocCoTaskMem(length * 2); u_strToTitle(resPtr, length, src, src.Length, IntPtr.Zero, locale, out err); } - if (err > 0) - throw new Exception("Icu.ToTitle() failed with code " + err); + if (IsFailure(err)) + throw new IcuException("u_strToTitle() failed with code " + err, err); string result = Marshal.PtrToStringUni(resPtr); if (result != null) @@ -1710,8 +1652,8 @@ public static string ToUpper(string src, string locale) { UErrorCode err; int outLength = u_strToUpper(resPtr, length, src, src.Length, locale, out err); - if (err > 0 && err != UErrorCode.U_BUFFER_OVERFLOW_ERROR) - throw new Exception("Icu.ToUpper() failed with code " + err); + if (IsFailure(err) && err != UErrorCode.U_BUFFER_OVERFLOW_ERROR) + throw new IcuException("u_strToUpper() failed with code " + err, err); if (outLength > length) { err = UErrorCode.U_ZERO_ERROR; // ignore possible U_BUFFER_OVERFLOW_ERROR @@ -1720,8 +1662,8 @@ public static string ToUpper(string src, string locale) resPtr = Marshal.AllocCoTaskMem(length * 2); u_strToUpper(resPtr, length, src, src.Length, locale, out err); } - if (err > 0) - throw new Exception("Icu.ToUpper() failed with code " + err); + if (IsFailure(err)) + throw new IcuException("u_strToUpper() failed with code " + err, err); string result = Marshal.PtrToStringUni(resPtr); // Strip any garbage left over at the end of the string. @@ -1794,8 +1736,8 @@ public static string Normalize(string src, UNormalizationMode mode) { UErrorCode err; int outLength = unorm_normalize(src, src.Length, mode, 0, resPtr, length, out err); - if (err > 0 && err != UErrorCode.U_BUFFER_OVERFLOW_ERROR) - throw new Exception("Icu.Normalize() failed with code " + err); + if (IsFailure(err) && err != UErrorCode.U_BUFFER_OVERFLOW_ERROR) + throw new IcuException("unorm_normalize() failed with code " + err, err); if (outLength >= length) { err = UErrorCode.U_ZERO_ERROR; // ignore possible U_BUFFER_OVERFLOW_ERROR @@ -1804,8 +1746,8 @@ public static string Normalize(string src, UNormalizationMode mode) resPtr = Marshal.AllocCoTaskMem(length * 2); unorm_normalize(src, src.Length, mode, 0, resPtr, length, out err); } - if (err > 0) - throw new Exception("Icu.Normalize() failed with code " + err); + if (IsFailure(err)) + throw new IcuException("unorm_normalize() failed with code " + err, err); string result = Marshal.PtrToStringUni(resPtr); // Strip any garbage left over at the end of the string. @@ -1834,8 +1776,8 @@ public static bool IsNormalized(string src, UNormalizationMode mode) UErrorCode err; byte fIsNorm = unorm_isNormalize(src, src.Length, mode, out err); - if (err > 0) - throw new Exception("Icu.IsNormalized() failed with code " + err); + if (IsFailure(err)) + throw new IcuException("unorm_isNormalize() failed with code " + err, err); return fIsNorm != 0; } @@ -1949,8 +1891,8 @@ public static IEnumerable Split(UBreakIteratorType type, string locale, UErrorCode err; IntPtr bi = ubrk_open(type, locale, text, text.Length, out err); - if (err > 0) - throw new Exception("ubrk_open failed with code " + err); + if (IsFailure(err)) + throw new IcuException("ubrk_open() failed with code " + err, err); var tokens = new List(); int cur = ubrk_first(bi); while (cur != UBRK_DONE) @@ -1967,6 +1909,16 @@ public static IEnumerable Split(UBreakIteratorType type, string locale, #endregion Break iterator + private static bool IsSuccess(UErrorCode errorCode) + { + return errorCode <= 0; + } + + private static bool IsFailure(UErrorCode errorCode) + { + return errorCode > 0; + } + /** * Selector constants for u_charName(). * u_charName() returns the "modern" name of a @@ -2646,4 +2598,84 @@ public enum UCharCategory } // JT notes on how to pass arguments // const char *: pass string. + + + /// + /// General ICU exception + /// + public class IcuException : Exception + { + private readonly Icu.UErrorCode m_errorCode; + + /// + /// Initializes a new instance of the class. + /// + /// The message. + /// The error code. + public IcuException(string message, Icu.UErrorCode errorCode) + : base(message) + { + m_errorCode = errorCode; + } + + /// + /// Gets the ICU error code. + /// + public Icu.UErrorCode ErrorCode + { + get { return m_errorCode; } + } + } + + /// ------------------------------------------------------------------------------------ + /// + /// Simple class to allow passing collation error info back to the caller of CheckRules. + /// + /// ------------------------------------------------------------------------------------ + public class CollationRuleErrorInfo + { + internal CollationRuleErrorInfo(Icu.UParseError parseError) + { + Line = parseError.line + 1; + Offset = parseError.offset + 1; + PreContext = parseError.preContext; + PostContext = parseError.postContext; + } + + /// Line number (1-based) containing the error + public int Line { get; private set; } + /// Character offset (1-based) on Line where the error was detected + public int Offset { get; private set; } + /// Characters preceding the the error + public String PreContext { get; private set; } + /// Characters following the the error + public String PostContext { get; private set; } + } + + /// + /// Collation rule exception + /// + public class CollationRuleException : IcuException + { + private readonly CollationRuleErrorInfo m_errorInfo; + + /// + /// Initializes a new instance of the class. + /// + /// The ICU error code. + /// The error information. + public CollationRuleException(Icu.UErrorCode errorCode, CollationRuleErrorInfo errorInfo) + : base("Failed to parse collation rules.", errorCode) + { + m_errorInfo = errorInfo; + } + + /// + /// Gets the parse error information. + /// + public CollationRuleErrorInfo ErrorInfo + { + get { return m_errorInfo; } + } + } } diff --git a/Src/Common/Controls/XMLViews/ConfiguredExport.cs b/Src/Common/Controls/XMLViews/ConfiguredExport.cs index 120202471f..ef875402db 100644 --- a/Src/Common/Controls/XMLViews/ConfiguredExport.cs +++ b/Src/Common/Controls/XMLViews/ConfiguredExport.cs @@ -647,7 +647,7 @@ private string GetLeadChar(string sEntryNFD, string sWs) string icuLocale = Icu.GetName(sWs); col = Icu.OpenCollator(icuLocale); } - catch (Exception) + catch (IcuException) { return sFirst; } From a016783fd37b037a02375f477cfc6eca11e78a38 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 30 May 2014 11:37:42 +0700 Subject: [PATCH 122/143] added a method to check if a shared XML backend is needed Change-Id: Id639f1eacb7b52f2c3e43051aa90cac6458f13f8 --- Src/Common/FieldWorks/FieldWorks.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Src/Common/FieldWorks/FieldWorks.cs b/Src/Common/FieldWorks/FieldWorks.cs index 32f48d03b7..0de6f11a64 100644 --- a/Src/Common/FieldWorks/FieldWorks.cs +++ b/Src/Common/FieldWorks/FieldWorks.cs @@ -419,7 +419,7 @@ private static bool LaunchApplicationFromCommandLine(FwAppArgs appArgs) // Get the project the user wants to open and attempt to launch it. ProjectId projectId = DetermineProject(appArgs); - if (projectId != null && ParatextHelper.GetAssociatedProject(projectId) != null) + if (projectId != null && IsSharedXmlBackendNeeded(projectId)) projectId.Type = FDOBackendProviderType.kSharedXML; // s_projectId can be non-null if the user decided to restore a project from @@ -441,6 +441,11 @@ private static bool LaunchApplicationFromCommandLine(FwAppArgs appArgs) return true; } + private static bool IsSharedXmlBackendNeeded(ProjectId projectId) + { + return projectId.Type == FDOBackendProviderType.kXML && ParatextHelper.GetAssociatedProject(projectId) != null; + } + /// ------------------------------------------------------------------------------------ /// /// Creates the application requested on the command line. @@ -1789,7 +1794,7 @@ internal static ProjectId ChooseLangProject(Form dialogOwner, IHelpTopicProvider if (dlg.DialogResult == DialogResult.OK) { var projId = new ProjectId(dlg.Project, dlg.Server); - if (ParatextHelper.GetAssociatedProject(projId) != null) + if (IsSharedXmlBackendNeeded(projId)) projId.Type = FDOBackendProviderType.kSharedXML; return projId; } From f16baa18c0260c58df5d8d65bd9bca24c840cd20 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 30 May 2014 11:56:42 +0700 Subject: [PATCH 123/143] refactored EnsureValidLinkedFileFolderCore test Change-Id: Iee103b0a29916a26429cc757c51645dad585be69 --- Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.cs b/Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.cs index 7152495bca..8174f28ba8 100644 --- a/Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.cs +++ b/Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.cs @@ -144,14 +144,11 @@ public void EnsureValidLinkedFilesFolderCore_IfUsingDefaultDir_CreatesDirIfNotEx public void EnsureValidLinkedFilesFolderCore_IfUsingDefaultDirAndItExists_DoesntCrashOrAnything() { EnsureValidLinkedFilesFolderCore_TestHelper(defaultFolder => { - var configuredFolder = defaultFolder; - // Make default linked files directory already exist FileUtils.EnsureDirectoryExists(defaultFolder); - Assert.That(FileUtils.DirectoryExists(configuredFolder), Is.True, "Unit test not testing what it's supposed to"); // Not crash or anything - FieldWorks.EnsureValidLinkedFilesFolderCore(configuredFolder, defaultFolder); + Assert.DoesNotThrow(() => FieldWorks.EnsureValidLinkedFilesFolderCore(defaultFolder, defaultFolder)); }); } From deabe19b3397e043d516f2423963056b2617cf67 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 30 May 2014 14:42:30 +0700 Subject: [PATCH 124/143] removed obsolete comments Change-Id: I919792c4ec8be26c1ffd1092be6e902c7a2b533c --- Src/FDO/Application/ApplicationServices/XmlImportData.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Src/FDO/Application/ApplicationServices/XmlImportData.cs b/Src/FDO/Application/ApplicationServices/XmlImportData.cs index 0a012f7d1f..f0c50467ab 100644 --- a/Src/FDO/Application/ApplicationServices/XmlImportData.cs +++ b/Src/FDO/Application/ApplicationServices/XmlImportData.cs @@ -178,7 +178,6 @@ public XmlImportData(FdoCache cache) /// Import the file contents into the database represented by the FdoCache established /// by the constructor. /// - /// true if successful, false if an error occurs /// ------------------------------------------------------------------------------------ public void ImportData(string sFilename, IProgress progress) { @@ -258,7 +257,6 @@ private void LogMessage(string sMsg) /// Import the text reader contents into the database represented by the FdoCache set /// in the constructor. /// - /// true if successful, false if an error occurs /// ------------------------------------------------------------------------------------ [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", Justification = "xrdr is disposed when closed.")] From c27b6e0b81442c4d30ab4fff3ed5a14df4f9dd8a Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 30 May 2014 15:06:13 +0700 Subject: [PATCH 125/143] renamed some properties on ICmPossibility to be more clear Change-Id: Ib6ca3317206535c0a4e0dd97279bdd811e3a35a0 --- Src/FDO/DomainImpl/OverridesCellar.cs | 16 ++++++++-------- Src/FDO/FdoInterfaceAdditions.cs | 6 +++--- Src/FdoUi/FdoUiCore.cs | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Src/FDO/DomainImpl/OverridesCellar.cs b/Src/FDO/DomainImpl/OverridesCellar.cs index 8b97efa714..bd68a0526b 100644 --- a/Src/FDO/DomainImpl/OverridesCellar.cs +++ b/Src/FDO/DomainImpl/OverridesCellar.cs @@ -1771,7 +1771,7 @@ public bool IsDefaultDiscourseTemplate } } - public bool IsInUseAsChartColumn + public bool IsThisOrDescendantInUseAsChartColumn { get { @@ -1782,19 +1782,19 @@ public bool IsInUseAsChartColumn while (rootPossibility.Owner is CmPossibility) rootPossibility = (CmPossibility) rootPossibility.Owner; IDsChart chart = Services.GetInstance().InstancesWithTemplate(rootPossibility).FirstOrDefault(); - return chart != null && GetIsInUseAsChartColumn(); + return chart != null && GetIsThisOrDescendantInUseAsChartColumn(); } } - private bool GetIsInUseAsChartColumn() + private bool GetIsThisOrDescendantInUseAsChartColumn() { var repo = Services.GetInstance(); if (repo.InstancesWithChartCellColumn(this).FirstOrDefault() != null) return true; - return SubPossibilitiesOS.Cast().Any(poss => poss.GetIsInUseAsChartColumn()); + return SubPossibilitiesOS.Cast().Any(poss => poss.GetIsThisOrDescendantInUseAsChartColumn()); } - public bool IsLastTextMarkupTag + public bool IsOnlyTextMarkupTag { get { @@ -1803,7 +1803,7 @@ public bool IsLastTextMarkupTag return false; IFdoOwningSequence tagTypes = tags.PossibilitiesOS; - return tagTypes.Count == 1 && Hvo == tagTypes[0].Hvo; + return tagTypes.Count == 1 && this == tagTypes[0]; } } @@ -1818,8 +1818,8 @@ public override bool CanDelete get { return base.CanDelete - && !IsDefaultDiscourseTemplate && !IsInUseAsChartColumn - && !IsLastTextMarkupTag + && !IsDefaultDiscourseTemplate && !IsThisOrDescendantInUseAsChartColumn + && !IsOnlyTextMarkupTag && (OwningList != Cache.LangProject.TextMarkupTagsOA || !Services.GetInstance().GetByTextMarkupTag(this).Any()) && !IsProtected; } diff --git a/Src/FDO/FdoInterfaceAdditions.cs b/Src/FDO/FdoInterfaceAdditions.cs index 1354e4ae34..0acce21c96 100644 --- a/Src/FDO/FdoInterfaceAdditions.cs +++ b/Src/FDO/FdoInterfaceAdditions.cs @@ -1664,12 +1664,12 @@ ICmPossibility MainPossibility /// Return true if this or one of its children is in use as a Constituent chart column. /// Most efficient to call this after checking that the root is a chart template. /// - bool IsInUseAsChartColumn { get; } + bool IsThisOrDescendantInUseAsChartColumn { get; } /// - /// Gets a value indicating whether this is the last text markup tag. + /// Gets a value indicating whether this is the only text markup tag. /// - bool IsLastTextMarkupTag { get; } + bool IsOnlyTextMarkupTag { get; } /// ------------------------------------------------------------------------------------ /// diff --git a/Src/FdoUi/FdoUiCore.cs b/Src/FdoUi/FdoUiCore.cs index 00733ee6e3..e04f2d2878 100644 --- a/Src/FdoUi/FdoUiCore.cs +++ b/Src/FdoUi/FdoUiCore.cs @@ -1675,7 +1675,7 @@ private bool CanModifyChartColumn(out string msg) return false; } - if (poss.IsInUseAsChartColumn) + if (poss.IsThisOrDescendantInUseAsChartColumn) { var rootPossibility = (ICmPossibility) Object; while (rootPossibility.Owner is ICmPossibility) @@ -1694,7 +1694,7 @@ private bool CanModifyChartColumn(out string msg) private bool CanDeleteTextMarkupTag(out string msg) { var poss = (ICmPossibility) Object; - if (poss.IsLastTextMarkupTag) + if (poss.IsOnlyTextMarkupTag) { msg = FdoUiStrings.ksCantDeleteLastTagList; return false; From 3b667bd3e7b44ac003315e82b68645f76e94bd49 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 30 May 2014 15:21:58 +0700 Subject: [PATCH 126/143] removed empty region from ScrImportSet Change-Id: I2267e4b2b3ab31f19b1c4097ebc304b9c0864f4b --- Src/FDO/DomainImpl/ScrImportSet.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Src/FDO/DomainImpl/ScrImportSet.cs b/Src/FDO/DomainImpl/ScrImportSet.cs index b7286aa209..254943f86a 100644 --- a/Src/FDO/DomainImpl/ScrImportSet.cs +++ b/Src/FDO/DomainImpl/ScrImportSet.cs @@ -256,10 +256,6 @@ public TypeOfImport ImportTypeEnum } #endregion - #region Import Project Accessibility Methods - - #endregion - #region Public Properties /// ------------------------------------------------------------------------------------ /// From 33a00fbc302fab3dcebdadcc42665024e4936115 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 30 May 2014 15:35:45 +0700 Subject: [PATCH 127/143] redundant comment removed from ClientServerServices Change-Id: I77e73f122088f552e31a75a23a6efaa0e8c38c78 --- Src/FDO/DomainServices/ClientServerServices.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Src/FDO/DomainServices/ClientServerServices.cs b/Src/FDO/DomainServices/ClientServerServices.cs index 4b72072366..e8ff5a5297 100644 --- a/Src/FDO/DomainServices/ClientServerServices.cs +++ b/Src/FDO/DomainServices/ClientServerServices.cs @@ -153,7 +153,6 @@ void BeginFindProjects(string host, Action foundProject, /// Returns the number of other users currently connected /// /// The FDO cache. - /// The number of other users currently connected int CountOfOtherUsersConnected(FdoCache cache); } #endregion From e3dff89c42345e38530a2693745659bcb7be1712 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 30 May 2014 16:11:43 +0700 Subject: [PATCH 128/143] encapsulated some frequently used code into methods in FDOTests Change-Id: Ie2bed37bedcf2fd54d2711ed528e7aa71ea8997a --- .../FieldWorksTests/FieldWorksTests.cs | 5 +- Src/FDO/FDOTests/ClientServerServicesTests.cs | 3 +- Src/FDO/FDOTests/Db4oServerInfoTests.cs | 3 +- Src/FDO/FDOTests/DummyFdoUI.cs | 2 +- Src/FDO/FDOTests/FdoScriptureTests.cs | 72 ++++++++----------- Src/FDO/FDOTests/FdoTestBase.cs | 3 +- Src/FDO/FDOTests/FdoTestHelper.cs | 10 +++ Src/FDO/FDOTests/FwSetupFixtureClass.cs | 5 +- 8 files changed, 44 insertions(+), 59 deletions(-) diff --git a/Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.cs b/Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.cs index 8174f28ba8..25a7115cec 100644 --- a/Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.cs +++ b/Src/Common/FieldWorks/FieldWorksTests/FieldWorksTests.cs @@ -7,9 +7,7 @@ // --------------------------------------------------------------------------------------------- using System; using NUnit.Framework; -using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO; -using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.FDOTests; using SIL.FieldWorks.Test.TestUtils; using SIL.Utils; @@ -29,8 +27,7 @@ public override void FixtureSetup() { base.FixtureSetup(); - ClientServerServices.SetCurrentToDb4OBackend(new DummyFdoUI(), FwDirectoryFinder.FdoDirectories, - () => FwDirectoryFinder.ProjectsDirectory == FwDirectoryFinder.ProjectsDirectoryLocalMachine); + FdoTestHelper.SetupClientServerServices(); } #region GetProjectMatchStatus tests diff --git a/Src/FDO/FDOTests/ClientServerServicesTests.cs b/Src/FDO/FDOTests/ClientServerServicesTests.cs index b829da1a0d..b3338463a5 100644 --- a/Src/FDO/FDOTests/ClientServerServicesTests.cs +++ b/Src/FDO/FDOTests/ClientServerServicesTests.cs @@ -34,8 +34,7 @@ public void StartFwRemoteDatabaseConnector() FwDirectoryFinder.ProjectsDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); Directory.CreateDirectory(FwDirectoryFinder.ProjectsDirectory); - ClientServerServices.SetCurrentToDb4OBackend(new DummyFdoUI(), FwDirectoryFinder.FdoDirectories, - () => FwDirectoryFinder.ProjectsDirectory == FwDirectoryFinder.ProjectsDirectoryLocalMachine); + FdoTestHelper.SetupClientServerServices(); m_projectShared = false; RemotingServer.Start(FwDirectoryFinder.RemotingTcpServerConfigFile, FwDirectoryFinder.FdoDirectories, () => m_projectShared, v => m_projectShared = v); diff --git a/Src/FDO/FDOTests/Db4oServerInfoTests.cs b/Src/FDO/FDOTests/Db4oServerInfoTests.cs index d4a852146a..e2694cac7a 100644 --- a/Src/FDO/FDOTests/Db4oServerInfoTests.cs +++ b/Src/FDO/FDOTests/Db4oServerInfoTests.cs @@ -184,8 +184,7 @@ public class Db4oServerInfoTests : BaseTest [SetUp] public void StartFwRemoteDatabaseConnector() { - ClientServerServices.SetCurrentToDb4OBackend(new DummyFdoUI(), FwDirectoryFinder.FdoDirectories, - () => FwDirectoryFinder.ProjectsDirectory == FwDirectoryFinder.ProjectsDirectoryLocalMachine); + FdoTestHelper.SetupClientServerServices(); m_sharedProject = true; RemotingServer.Start(FwDirectoryFinder.RemotingTcpServerConfigFile, FwDirectoryFinder.FdoDirectories, () => m_sharedProject, v => m_sharedProject = v); diff --git a/Src/FDO/FDOTests/DummyFdoUI.cs b/Src/FDO/FDOTests/DummyFdoUI.cs index f3c0010073..e1a31224cb 100644 --- a/Src/FDO/FDOTests/DummyFdoUI.cs +++ b/Src/FDO/FDOTests/DummyFdoUI.cs @@ -10,7 +10,7 @@ namespace SIL.FieldWorks.FDO.FDOTests { /// - /// Dummy implementation of FdoUserAction for unit tests + /// Dummy implementation of IFdoUI for unit tests /// [SuppressMessage("Gendarme.Rules.Design", "TypesWithDisposableFieldsShouldBeDisposableRule", Justification="m_threadHelper is a singleton and disposed by the SingletonsContainer")] diff --git a/Src/FDO/FDOTests/FdoScriptureTests.cs b/Src/FDO/FDOTests/FdoScriptureTests.cs index 340248af18..7f584c2ae9 100644 --- a/Src/FDO/FDOTests/FdoScriptureTests.cs +++ b/Src/FDO/FDOTests/FdoScriptureTests.cs @@ -754,8 +754,7 @@ public void AdjustAnnotationReferences_WithQuote() [Test] public void RecordError_ParaContentsToken() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0); Dictionary> bkChkFailedLst = @@ -801,8 +800,7 @@ public void RecordError_ParaContentsToken() [Test] public void RecordError_ParaContentsToken_SecondRun() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 10); Dictionary> bkChkFailedLst = @@ -846,8 +844,7 @@ public void RecordError_ParaContentsToken_SecondRun() [Test] public void RecordError_PictureCaptionToken() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); ScrCheckingToken tok = new DummyPictureCheckingToken(m_scr, Cache.DefaultUserWs, "en"); Dictionary> bkChkFailedLst = @@ -890,8 +887,7 @@ public void RecordError_PictureCaptionToken() [Test] public void RecordError_Duplicate() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0); check.m_ErrorsToReport.Add(new DummyEditorialCheck.DummyError(tok, 5, 8, "Lousy message")); @@ -920,8 +916,7 @@ public void RecordError_Duplicate() [Test] public void RecordError_DuplicateAfterAdjustingReference() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0); tok.MissingStartRef = new BCVRef(tok.StartRef); @@ -1243,8 +1238,7 @@ public void RecordError_ErrorMaxIncreased() [Test] public void RecordError_Duplicate_SameErrorTwiceInVerse() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0); check.m_ErrorsToReport.Add(new DummyEditorialCheck.DummyError(tok, 5, 2, "Lousy message")); @@ -1285,8 +1279,7 @@ public void RecordError_Duplicate_SameErrorTwiceInVerse() [Test] public void RunCheck_ScrCheckRunRecordsWithFixedInconsistency() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0); check.m_ErrorsToReport.Add(new DummyEditorialCheck.DummyError(tok, 5, 2, "Verbification")); @@ -1324,8 +1317,7 @@ public void RunCheck_ScrCheckRunRecordsWithFixedInconsistency() [Test] public void RunCheck_ScrCheckRunRecordsWithOneBookOneCheck() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0); check.m_ErrorsToReport.Add(new DummyEditorialCheck.DummyError(tok, 5, 2, "Verbification")); @@ -1368,8 +1360,7 @@ public void RunCheck_ScrCheckRunRecordsWithOneBookOneCheck() [Test] public void RunCheck_ScrCheckRunRecordsWithOneBookTwoChecks() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); DummyEditorialCheck check1 = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0); check1.m_ErrorsToReport.Add(new DummyEditorialCheck.DummyError(tok, 5, 2, "Verbification")); @@ -1420,8 +1411,7 @@ public void RunCheck_ScrCheckRunRecordsWithOneBookTwoChecks() [Test] public void RunCheck_CorrectedErrorGetsDeleted() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0); check.m_ErrorsToReport.Add(new DummyEditorialCheck.DummyError(tok, 5, 8, "Lousy message")); @@ -1457,8 +1447,7 @@ public void RunCheck_CorrectedErrorGetsDeleted() [Test] public void RecordError_NearDuplicate_DifferByMessage() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0); check.m_ErrorsToReport.Add(new DummyEditorialCheck.DummyError(tok, 5, 8, "Lousy message")); @@ -1493,8 +1482,7 @@ public void RecordError_NearDuplicate_DifferOnlyByParaHvo() BCVRef reference = new BCVRef(1, 2, 3); - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(book, Cache.DefaultVernWs, 0, reference, reference); @@ -1540,8 +1528,7 @@ public void RecordError_NearDuplicate_DifferOnlyByParaHvo() public void RecordError_NearDuplicate_DifferByCheck() { IFdoServiceLocator servloc = Cache.ServiceLocator; - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); ICmAnnotationDefn annDefnChkError = servloc.GetInstance().CheckingError; ICmAnnotationDefn errorCheck1 = servloc.GetInstance().Create( Guid.NewGuid(), annDefnChkError); @@ -1584,8 +1571,7 @@ public void RecordError_NearDuplicate_DifferByStartRef() { BCVRef endRef = new BCVRef(1, 2, 3); - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0, new BCVRef(1, 2, 3), endRef); @@ -1620,8 +1606,7 @@ public void RecordError_NearDuplicate_DifferByEndRef() { BCVRef startRef = new BCVRef(1, 2, 3); - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0, startRef, new BCVRef(1, 2, 3)); @@ -1654,8 +1639,7 @@ public void RecordError_NearDuplicate_DifferByEndRef() [Test] public void RecordError_NearDuplicate_DifferByCitedText() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); DummyEditorialCheck check = new DummyEditorialCheck(kCheckId1); ScrCheckingToken tok = new DummyParaCheckingToken(m_scr, Cache.DefaultVernWs, 0); check.m_ErrorsToReport.Add(new DummyEditorialCheck.DummyError(tok, 0, 4, "Message")); @@ -1684,8 +1668,7 @@ public void RecordError_NearDuplicate_DifferByCitedText() [Test] public void GetTextTokens_Chapter0() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); int iExodus = 2; IScrBook exodus = AddBookToMockedScripture(iExodus, "Exodus"); AddTitleToMockedBook(exodus, "Exodus"); @@ -1719,8 +1702,7 @@ public void GetTextTokens_Chapter0() [Test] public void GetTextTokens_WholeBook() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); AddBookToMockedScripture(1, "Genesis"); int iExodus = 2; IScrBook exodus = AddBookToMockedScripture(iExodus, "Exodus"); @@ -1809,8 +1791,7 @@ public void GetTextTokens_FirstChapter() IScrBook exodus = AddBookToMockedScripture(iExodus, "Exodus"); AddTitleToMockedBook(exodus, "Exodus"); - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); IScrSection section = AddSectionToMockedBook(exodus, true); IStTxtPara para = AddParaToMockedText(section.HeadingOA, ScrStyleNames.IntroSectionHead); AddRunToMockedPara(para, "Everything you wanted to know about Exodus but were afraid to ask", null); @@ -1878,8 +1859,7 @@ public void GetTextTokens_DifferentWritingSystem() AddTitleToMockedBook(exodus, "Exodus"); // Get the text (and set the valid characters for each writing system). - var dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); dataSource.GetText(iExodus, 1); iWs = 0; @@ -1901,8 +1881,7 @@ public void GetTextTokens_DifferentWritingSystem() [Test] public void GetTextTokens_LastChapter() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); AddBookToMockedScripture(1, "Genesis"); int iExodus = 2; IScrBook exodus = AddBookToMockedScripture(iExodus, "Exodus"); @@ -1950,8 +1929,7 @@ public void GetTextTokens_LastChapter() public void GetTextTokens_ChapterStartsAndEndsMidSection() { - ScrChecksDataSource dataSource = new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), - FwDirectoryFinder.LegacyWordformingCharOverridesFile); + ScrChecksDataSource dataSource = CreateScrChecksDataSource(); AddBookToMockedScripture(1, "Genesis"); int iExodus = 2; IScrBook exodus = AddBookToMockedScripture(iExodus, "Exodus"); @@ -2005,6 +1983,12 @@ public void GetTextTokens_ChapterStartsAndEndsMidSection() } #region Helper methods + private ScrChecksDataSource CreateScrChecksDataSource() + { + return new ScrChecksDataSource(Cache, ResourceHelper.GetResourceString("kstidPunctCheckWhitespaceChar"), + FwDirectoryFinder.LegacyWordformingCharOverridesFile); + } + /// ------------------------------------------------------------------------------------ /// /// Verifies that an "empty" journal text has a single empty paragraph with the correct diff --git a/Src/FDO/FDOTests/FdoTestBase.cs b/Src/FDO/FDOTests/FdoTestBase.cs index d88b16cbbd..f2efcf26eb 100644 --- a/Src/FDO/FDOTests/FdoTestBase.cs +++ b/Src/FDO/FDOTests/FdoTestBase.cs @@ -99,8 +99,7 @@ protected void SetupEverythingButBase() // We need FieldWorks here to get the correct registry key HKLM\Software\SIL\FieldWorks. // The default without this would be HKLM\Software\SIL\SIL FieldWorks, which breaks some tests. RegistryHelper.ProductName = "FieldWorks"; - ClientServerServices.SetCurrentToDb4OBackend(new DummyFdoUI(), FwDirectoryFinder.FdoDirectories, - () => FwDirectoryFinder.ProjectsDirectory == FwDirectoryFinder.ProjectsDirectoryLocalMachine); + FdoTestHelper.SetupClientServerServices(); m_cache = CreateCache(); m_actionHandler = m_cache.ServiceLocator.GetInstance(); } diff --git a/Src/FDO/FDOTests/FdoTestHelper.cs b/Src/FDO/FDOTests/FdoTestHelper.cs index 5d8021889a..17a17642f5 100644 --- a/Src/FDO/FDOTests/FdoTestHelper.cs +++ b/Src/FDO/FDOTests/FdoTestHelper.cs @@ -10,6 +10,7 @@ using System.Linq; using SIL.FieldWorks.Common.COMInterfaces; using NUnit.Framework; +using SIL.FieldWorks.Common.FwUtils; using SIL.FieldWorks.FDO.DomainServices; using SIL.CoreImpl; using SIL.Utils; @@ -410,5 +411,14 @@ public static void VerifyHyperlinkPropsAreCorrect(ITsTextProps props, int expect Assert.AreEqual(Convert.ToChar((int)FwObjDataTypes.kodtExternalPathName), sObjData[0]); Assert.AreEqual(sUrl, sObjData.Substring(1)); } + + /// + /// Sets up the client server services. + /// + public static void SetupClientServerServices() + { + ClientServerServices.SetCurrentToDb4OBackend(new DummyFdoUI(), FwDirectoryFinder.FdoDirectories, + () => FwDirectoryFinder.ProjectsDirectory == FwDirectoryFinder.ProjectsDirectoryLocalMachine); + } } } diff --git a/Src/FDO/FDOTests/FwSetupFixtureClass.cs b/Src/FDO/FDOTests/FwSetupFixtureClass.cs index bda42ff3cd..ac47a4a6df 100644 --- a/Src/FDO/FDOTests/FwSetupFixtureClass.cs +++ b/Src/FDO/FDOTests/FwSetupFixtureClass.cs @@ -3,8 +3,6 @@ // (http://www.gnu.org/licenses/lgpl-2.1.html) using NUnit.Framework; -using SIL.FieldWorks.Common.FwUtils; -using SIL.FieldWorks.FDO.DomainServices; using SIL.FieldWorks.FDO.FDOTests; using SIL.Utils; @@ -27,8 +25,7 @@ public class FwSetupFixtureClass [SetUp] public void SetUp() { - ClientServerServices.SetCurrentToDb4OBackend(new DummyFdoUI(), FwDirectoryFinder.FdoDirectories, - () => FwDirectoryFinder.ProjectsDirectory == FwDirectoryFinder.ProjectsDirectoryLocalMachine); + FdoTestHelper.SetupClientServerServices(); } ///-------------------------------------------------------------------------------------- From 99ec1abe962834f12e9494723bf8300fb4c22eb7 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Mon, 2 Jun 2014 14:37:18 +0700 Subject: [PATCH 129/143] fixed platform-dependent slashes in FDOTests Change-Id: Ib0fc97b2813bd6b74da91d198d0aed1819e21176 --- .../LinkedFilesRelativePathHelperTests.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Src/FDO/FDOTests/LinkedFilesRelativePathHelperTests.cs b/Src/FDO/FDOTests/LinkedFilesRelativePathHelperTests.cs index 5184e7d21c..57dead5112 100644 --- a/Src/FDO/FDOTests/LinkedFilesRelativePathHelperTests.cs +++ b/Src/FDO/FDOTests/LinkedFilesRelativePathHelperTests.cs @@ -21,7 +21,7 @@ public void GetLinkedFilesRelativePathFromFullPath() { Assert.AreEqual(String.Format("%proj%{0}LinkedFiles", Path.DirectorySeparatorChar), LinkedFilesRelativePathHelper.GetLinkedFilesRelativePathFromFullPath(FwDirectoryFinder.ProjectsDirectory, String.Format("%proj%{0}LinkedFiles", Path.DirectorySeparatorChar), - Path.Combine(FwDirectoryFinder.SourceDirectory, "FDO/FDOTests/BackupRestore/Project"), + Path.Combine(FwDirectoryFinder.SourceDirectory, "FDO", "FDOTests", "BackupRestore", "Project"), "Project")); } @@ -49,9 +49,9 @@ public void GetLinkedFilesFullPathFromRelativePath() [Test] public void GetFullFilePathFromRelativeLFPath() { - var linkedFilesRootDir = Path.Combine(Path.Combine(FwDirectoryFinder.ProjectsDirectory, "TestProject"), "LinkedFiles"); + var linkedFilesRootDir = Path.Combine(FwDirectoryFinder.ProjectsDirectory, "TestProject", "LinkedFiles"); var fullLFPath = LinkedFilesRelativePathHelper.GetFullFilePathFromRelativeLFPath(String.Format("%lf%{0}AudioVisual{0}StarWars.mvi", Path.DirectorySeparatorChar), linkedFilesRootDir); - var audioVisualFile = Path.Combine(Path.Combine(linkedFilesRootDir, "AudioVisual"), "StarWars.mvi"); + var audioVisualFile = Path.Combine(linkedFilesRootDir, "AudioVisual", "StarWars.mvi"); Assert.AreEqual(audioVisualFile, fullLFPath); //if a fully rooted path is passed in the return value should be null. @@ -69,8 +69,8 @@ public void GetFullFilePathFromRelativeLFPath() [Test] public void GetRelativeLFPathFromFullFilePath() { - var linkedFilesRootDir = Path.Combine(Path.Combine(FwDirectoryFinder.ProjectsDirectory, "TestProject"), "LinkedFiles"); - var audioVisualFile = Path.Combine(Path.Combine(linkedFilesRootDir, "AudioVisual"), "StarWars.mvi"); + var linkedFilesRootDir = Path.Combine(FwDirectoryFinder.ProjectsDirectory, "TestProject", "LinkedFiles"); + var audioVisualFile = Path.Combine(linkedFilesRootDir, "AudioVisual", "StarWars.mvi"); var relativeLFPath = LinkedFilesRelativePathHelper.GetRelativeLFPathFromFullFilePath(audioVisualFile, linkedFilesRootDir); Assert.AreEqual(String.Format("%lf%{0}AudioVisual{0}StarWars.mvi", Path.DirectorySeparatorChar), relativeLFPath); @@ -88,8 +88,8 @@ public void GetRelativeLFPathFromFullFilePath() [Test] public void GetRelativeLinkedFilesPath() { - var linkedFilesRootDir = Path.Combine(Path.Combine(FwDirectoryFinder.ProjectsDirectory, "TestProject"), "LinkedFiles"); - var audioVisualFile = Path.Combine(Path.Combine(linkedFilesRootDir, "AudioVisual"), "StarWars.mvi"); + var linkedFilesRootDir = Path.Combine(FwDirectoryFinder.ProjectsDirectory, "TestProject", "LinkedFiles"); + var audioVisualFile = Path.Combine(linkedFilesRootDir, "AudioVisual", "StarWars.mvi"); var relativeLFPath = LinkedFilesRelativePathHelper.GetRelativeLinkedFilesPath(audioVisualFile, linkedFilesRootDir); Assert.True(String.Equals(String.Format("AudioVisual{0}StarWars.mvi", Path.DirectorySeparatorChar), relativeLFPath)); @@ -98,7 +98,7 @@ public void GetRelativeLinkedFilesPath() relativeLFPath = LinkedFilesRelativePathHelper.GetRelativeLinkedFilesPath(pathNotUnderLinkedFiles, linkedFilesRootDir); Assert.True(String.Equals(pathNotUnderLinkedFiles,relativeLFPath)); Assert.That(LinkedFilesRelativePathHelper.GetRelativeLinkedFilesPath( - "silfw:\\localhost\\link?app%3dflex%26database%3dc%3a%5cTestLangProj%5cTestLangProj.fwdata%26server%3d%26tool%3dnaturalClassedit%26guid%3d43c9ba97-2883-4f95-aa5d-ef9309e85025%26tag%3d", + "silfw://localhost/link?app%3dflex%26database%3dc%3a%5cTestLangProj%5cTestLangProj.fwdata%26server%3d%26tool%3dnaturalClassedit%26guid%3d43c9ba97-2883-4f95-aa5d-ef9309e85025%26tag%3d", relativeLFPath), Is.Null, "hyperlinks should be left well alone!!"); } @@ -110,9 +110,9 @@ public void GetRelativeLinkedFilesPath() [Test] public void GetFullPathFromRelativeLFPath() { - var linkedFilesRootDir = Path.Combine(Path.Combine(FwDirectoryFinder.ProjectsDirectory, "TestProject"), "LinkedFiles"); + var linkedFilesRootDir = Path.Combine(FwDirectoryFinder.ProjectsDirectory, "TestProject", "LinkedFiles"); var fullLFPath = LinkedFilesRelativePathHelper.GetFullPathFromRelativeLFPath(String.Format("AudioVisual{0}StarWars.mvi", Path.DirectorySeparatorChar), linkedFilesRootDir); - var audioVisualFile = Path.Combine(Path.Combine(linkedFilesRootDir, "AudioVisual"), "StarWars.mvi"); + var audioVisualFile = Path.Combine(linkedFilesRootDir, "AudioVisual", "StarWars.mvi"); Assert.AreEqual(audioVisualFile, fullLFPath); //if a fully rooted path is passed in the return value should be the path that was passed in. @@ -129,7 +129,7 @@ public void GetFullPathFromRelativeLFPath() [Test] public void GetFullPathFromRelativeLFPath_WithIllegalCharacters_ReturnsSpecialPath() { - var linkedFilesRootDir = Path.Combine(Path.Combine(FwDirectoryFinder.ProjectsDirectory, "TestProject"), "LinkedFiles"); + var linkedFilesRootDir = Path.Combine(FwDirectoryFinder.ProjectsDirectory, "TestProject", "LinkedFiles"); var fullLFPath = LinkedFilesRelativePathHelper.GetFullPathFromRelativeLFPath("1\";1\"", linkedFilesRootDir); Assert.That(fullLFPath, Is.EqualTo(Path.Combine(linkedFilesRootDir,"__ILLEGALCHARS__"))); } From 9edbf6441edf5729f3a21526c66d7840992ae37b Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Mon, 2 Jun 2014 15:11:39 +0700 Subject: [PATCH 130/143] check for user prompt for conflicting changes in shared XML tests Change-Id: I2eb7e75355fdfe8d60b5cc36dfb3677d7b7a344c --- Src/FDO/FDOTests/DummyFdoUI.cs | 15 +++++++++++++++ Src/FDO/FDOTests/FdoScriptureTests.cs | 8 ++++---- .../FDOTests/PersistingBackendProviderTests.cs | 8 ++++++-- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/Src/FDO/FDOTests/DummyFdoUI.cs b/Src/FDO/FDOTests/DummyFdoUI.cs index e1a31224cb..0d9d99188a 100644 --- a/Src/FDO/FDOTests/DummyFdoUI.cs +++ b/Src/FDO/FDOTests/DummyFdoUI.cs @@ -34,15 +34,30 @@ public ISynchronizeInvoke SynchronizeInvoke /// public string ErrorMessage { get; private set; } + /// + /// Indicates whether a conflicting save occurred. + /// + public bool ConflictingSaveOccurred { get; private set; } + /// /// Check with user regarding conflicting changes /// /// True if user wishes to revert to saved state. False otherwise. public bool ConflictingSave() { + ConflictingSaveOccurred = true; return true; } + /// + /// Resets all testing metadata. + /// + public void Reset() + { + ConflictingSaveOccurred = false; + ErrorMessage = null; + } + /// /// Inform the user of a lost connection /// diff --git a/Src/FDO/FDOTests/FdoScriptureTests.cs b/Src/FDO/FDOTests/FdoScriptureTests.cs index 7f584c2ae9..d3b7c91cfa 100644 --- a/Src/FDO/FDOTests/FdoScriptureTests.cs +++ b/Src/FDO/FDOTests/FdoScriptureTests.cs @@ -2524,6 +2524,9 @@ public void SavedVersion_TestFootnoteOrder() [Test] public void SavedVersion_BogusUnownedFootnoteORC() { + var ui = (DummyFdoUI) Cache.ServiceLocator.GetInstance(); + ui.Reset(); + IStText titleText; IScrBook hebrews = m_servloc.GetInstance().Create(58, out titleText); IStTxtPara title = AddParaToMockedText(titleText, ScrStyleNames.MainBookTitle); @@ -2589,10 +2592,7 @@ public void SavedVersion_BogusUnownedFootnoteORC() Assert.AreEqual(StringUtils.kChObject, sOrc[0]); // Expecting error to have been thrown in ScriptureServices.AdjustObjectsInArchivedBook, so now we make sure the error is the one expected. - var userAction = Cache.ServiceLocator.GetInstance(); - Assert.IsTrue(userAction is DummyFdoUI); - string sWarningMessage = ((DummyFdoUI)userAction).ErrorMessage; - Assert.AreEqual("1 footnote(s) in HEB did not correspond to any owned footnotes in the vernacular text of that book. They have been moved to the end of the footnote sequence.", sWarningMessage); + Assert.AreEqual("1 footnote(s) in HEB did not correspond to any owned footnotes in the vernacular text of that book. They have been moved to the end of the footnote sequence.", ui.ErrorMessage); } /// ------------------------------------------------------------------------------------ diff --git a/Src/FDO/FDOTests/PersistingBackendProviderTests.cs b/Src/FDO/FDOTests/PersistingBackendProviderTests.cs index 485de9a3e5..d0e9227fbf 100644 --- a/Src/FDO/FDOTests/PersistingBackendProviderTests.cs +++ b/Src/FDO/FDOTests/PersistingBackendProviderTests.cs @@ -858,7 +858,6 @@ protected override FdoCache CreateCache() if (File.Exists(projectID.Path)) File.Delete(projectID.Path); } - return BootstrapSystem(projectID, m_loadType); } @@ -1022,8 +1021,13 @@ public void ConflictingChanges() { entry1.CitationForm.set_String(Cache.DefaultVernWs, "citation"); }); + var ui = (DummyFdoUI) Cache.ServiceLocator.GetInstance(); + ui.Reset(); Cache.ServiceLocator.GetInstance().Save(); - Assert.That(entry1.CitationForm.VernacularDefaultWritingSystem.Text, Is.EqualTo(otherEntry1.CitationForm.VernacularDefaultWritingSystem.Text)); + // the first in should win + Assert.That(entry1.CitationForm.VernacularDefaultWritingSystem.Text, Is.EqualTo("othercitation")); + // check that the user was prompted about conflicting changes + Assert.That(ui.ConflictingSaveOccurred, Is.True); } } From 177daba7fa7e9d162d50469013b1ed8df2db55b0 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Mon, 2 Jun 2014 16:35:55 +0700 Subject: [PATCH 131/143] check for WinForms reference in FDO Change-Id: I2809fd563a78d48f74bdbceb5ef3a52e2738737c --- Src/FDO/BuildInclude.targets | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Src/FDO/BuildInclude.targets b/Src/FDO/BuildInclude.targets index 2e5cf477f4..d13f12120c 100644 --- a/Src/FDO/BuildInclude.targets +++ b/Src/FDO/BuildInclude.targets @@ -77,7 +77,12 @@ TemplateFile="FDOGenerate/main.vm.cs"/> - + + + + + From 8397cb93f3822bdd18ed4ac06274ee63d78da81f Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Tue, 3 Jun 2014 11:33:15 +0700 Subject: [PATCH 132/143] removed protobuf-net.dll Change-Id: I15d3cf4fa17a45de84d87e13612b6c0d5b547a35 --- Build/mkall.targets | 9 +++++++++ DistFiles/protobuf-net.dll | Bin 197632 -> 0 bytes Src/FDO/FDO.csproj | 5 +++-- 3 files changed, 12 insertions(+), 2 deletions(-) delete mode 100644 DistFiles/protobuf-net.dll diff --git a/Build/mkall.targets b/Build/mkall.targets index dd7a2cdab5..65d228a951 100644 --- a/Build/mkall.targets +++ b/Build/mkall.targets @@ -4,6 +4,7 @@ + @@ -308,6 +309,7 @@ http://build.palaso.org/guestAuth/repository/download/bt278/.lastSuccessful http://build.palaso.org/guestAuth/repository/download/bt279/.lastSuccessful + https://protobuf-net.googlecode.com/files/protobuf-net%20r668.zip dll.mdb pdb @@ -351,6 +353,11 @@ + + + + + @@ -390,6 +397,8 @@ + + diff --git a/DistFiles/protobuf-net.dll b/DistFiles/protobuf-net.dll deleted file mode 100644 index de4701c6a6cb56645a37240b0b07d7f36fda5c02..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 197632 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

0pH_ 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


#gzXxB1dfwf0vpYABMd=(P?|ZwqvenpE)>KttP@ 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 diff --git a/Src/FDO/FDO.csproj b/Src/FDO/FDO.csproj index 444473c31b..904b7ff3b8 100644 --- a/Src/FDO/FDO.csproj +++ b/Src/FDO/FDO.csproj @@ -90,8 +90,9 @@ ..\..\Output\Debug\BasicUtils.dll - - ..\..\DistFiles\protobuf-net.dll + + False + ..\..\Output\Debug\protobuf-net.dll From 13e235c1ab2ac5cd5bbc8e03ae6375e70e5f9bea Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Tue, 3 Jun 2014 17:34:48 +0700 Subject: [PATCH 133/143] cleaned up and commented shared XML backend provider code Change-Id: Ie0bdd2b3345bd5b6c4b6de415fcc70e612260639 --- .../Infrastructure/Impl/CommitLogMetadata.cs | 44 ++- .../Infrastructure/Impl/CommitLogRecord.cs | 11 +- .../Impl/Db4oClientServerBackendProvider.cs | 2 +- .../Impl/SharedXMLBackendProvider.cs | 285 ++++++++++-------- 4 files changed, 212 insertions(+), 130 deletions(-) diff --git a/Src/FDO/Infrastructure/Impl/CommitLogMetadata.cs b/Src/FDO/Infrastructure/Impl/CommitLogMetadata.cs index f8f8b81a45..211e714aac 100644 --- a/Src/FDO/Infrastructure/Impl/CommitLogMetadata.cs +++ b/Src/FDO/Infrastructure/Impl/CommitLogMetadata.cs @@ -4,37 +4,77 @@ namespace SIL.FieldWorks.FDO.Infrastructure.Impl { + /// + /// Contains all of the commit log metadata for the shared XML backend. This + /// class is serialized to a memory mapped file using protobuf-net. + /// [ProtoContract] internal class CommitLogMetadata { + public CommitLogMetadata() + { + Peers = new Dictionary(); + } + + /// + /// The current commit generation of the commit log. + /// [ProtoMember(1)] public int CurrentGeneration; + /// + /// The current commit generation of the XML file. + /// [ProtoMember(2)] public int FileGeneration; + /// + /// The offset into the memory mapped file where the commit log starts. + /// [ProtoMember(3)] - public int Offset; + public int LogOffset; + /// + /// The length of the commit log. The length includes padding. + /// [ProtoMember(4)] - public int Length; + public int LogLength; + /// + /// The amount of padding at the end of the memory mapped file if the commit log wraps + /// around the file. + /// [ProtoMember(5)] public int Padding; + /// + /// All of the peers that are currently accessing the XML file. + /// [ProtoMember(6)] public Dictionary Peers; + /// + /// The GUID of the master peer that is reponsible for reading and writing to the XML file. + /// [ProtoMember(7)] public Guid Master; } + /// + /// A shared XML backend peer. + /// [ProtoContract] internal class CommitLogPeer { + /// + /// The commit generation that the peer has seen. + /// [ProtoMember(1)] public int Generation; + /// + /// The peer's process ID. + /// [ProtoMember(2)] public int ProcessID; } diff --git a/Src/FDO/Infrastructure/Impl/CommitLogRecord.cs b/Src/FDO/Infrastructure/Impl/CommitLogRecord.cs index 25f1e80a35..9095883e7c 100644 --- a/Src/FDO/Infrastructure/Impl/CommitLogRecord.cs +++ b/Src/FDO/Infrastructure/Impl/CommitLogRecord.cs @@ -4,6 +4,11 @@ namespace SIL.FieldWorks.FDO.Infrastructure.Impl { + /// + /// A record that is used by the shared XML backend to record all information for a commit so that peers + /// can update their FDO instance appropriately. These records are serialized to the commit log memory + /// mapped file using protobuf-net. + /// [ProtoContract] internal struct CommitLogRecord { @@ -13,21 +18,25 @@ internal struct CommitLogRecord ///
[ProtoMember(1)] public int WriteGeneration; + /// - /// A guid unique to one particular writer; used by each client to eliminate its own commits from queries. + /// A guid unique to one particular peer; used by each peer to eliminate its own commits from queries. /// [ProtoMember(2)] public Guid Source; + /// /// Our IDs of the objects that were added. /// [ProtoMember(3)] public List ObjectsAdded; + /// /// Our IDs of the objects that were modified. /// [ProtoMember(4)] public List ObjectsUpdated; + /// /// Our IDs of the objects that were deleted. /// diff --git a/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs b/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs index 989c5c8a5c..f3d81fcdb3 100644 --- a/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/Db4oClientServerBackendProvider.cs @@ -255,7 +255,7 @@ protected override int StartupInternal(int currentModelVersion) /// /// Get changes we haven't seen. (This has a side effect of updating the record of which ones HAVE been seen.) - /// Returns true if there are any unseen foreign changes. + /// This method assumes that the commit lock has already been obtained. Returns true if there are any unseen foreign changes. /// [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", Justification="Ext() returns a reference")] diff --git a/Src/FDO/Infrastructure/Impl/SharedXMLBackendProvider.cs b/Src/FDO/Infrastructure/Impl/SharedXMLBackendProvider.cs index 453e1048ad..2bb5d3e609 100644 --- a/Src/FDO/Infrastructure/Impl/SharedXMLBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/SharedXMLBackendProvider.cs @@ -15,13 +15,23 @@ namespace SIL.FieldWorks.FDO.Infrastructure.Impl { + /// + /// An XML file-based backend provider that allows multiple applications to access the same project + /// simultaneously. It uses memory mapped files to maintain a shared commit log that all applications + /// use to update their state to reflect changes made by other applications. The commit log is + /// implemented as a circular buffer of commit records. A single peer is responsible for updating + /// the XML file. + /// internal class SharedXMLBackendProvider : XMLBackendProvider { private const int PageSize = 4096; - private const int CommitLogSize = 2500 * PageSize; - private const int CommitLogMetadataSize = 1 * PageSize; + private const int CommitLogFileSize = 2500 * PageSize; + private const int CommitLogMetadataFileSize = 1 * PageSize; - private Mutex m_mutex; + /// + /// This mutex synchronizes access to the commit log, its metadata, and the XML file. + /// + private Mutex m_commitLogMutex; private MemoryMappedFile m_commitLogMetadata; private MemoryMappedFile m_commitLog; private readonly Guid m_peerID; @@ -39,23 +49,20 @@ internal int OtherApplicationsConnectedCount { get { - m_mutex.WaitOne(); + m_commitLogMutex.WaitOne(); try { using (MemoryMappedViewStream stream = m_commitLogMetadata.CreateViewStream()) { - var metadata = Serializer.DeserializeWithLengthPrefix(stream, PrefixStyle.Base128, 1); + CommitLogMetadata metadata = GetMetadata(stream); if (CheckExitedPeerProcesses(metadata)) - { - stream.Seek(0, SeekOrigin.Begin); - Serializer.SerializeWithLengthPrefix(stream, metadata, PrefixStyle.Base128, 1); - } + SaveMetadata(stream, metadata); return metadata.Peers.Count - 1; } } finally { - m_mutex.ReleaseMutex(); + m_commitLogMutex.ReleaseMutex(); } } } @@ -63,26 +70,19 @@ internal int OtherApplicationsConnectedCount protected override int StartupInternal(int currentModelVersion) { bool createdNew; - m_mutex = new Mutex(true, MutexName, out createdNew); + m_commitLogMutex = new Mutex(true, MutexName, out createdNew); if (!createdNew) - m_mutex.WaitOne(); + m_commitLogMutex.WaitOne(); try { CreateSharedMemory(createdNew); using (MemoryMappedViewStream stream = m_commitLogMetadata.CreateViewStream()) { CommitLogMetadata metadata; - int length; - if (!createdNew && Serializer.TryReadLengthPrefix(stream, PrefixStyle.Base128, out length) && length > 0) - { - stream.Seek(0, SeekOrigin.Begin); - metadata = Serializer.DeserializeWithLengthPrefix(stream, PrefixStyle.Base128, 1); + if (!createdNew && TryGetMetadata(stream, out metadata)) CheckExitedPeerProcesses(metadata); - } else - { - metadata = CreateEmptyMetadata(); - } + metadata = new CommitLogMetadata(); using (Process curProcess = Process.GetCurrentProcess()) metadata.Peers[m_peerID] = new CommitLogPeer { ProcessID = curProcess.Id, Generation = metadata.FileGeneration }; @@ -93,27 +93,28 @@ protected override int StartupInternal(int currentModelVersion) metadata.Master = m_peerID; } - stream.Seek(0, SeekOrigin.Begin); - Serializer.SerializeWithLengthPrefix(stream, metadata, PrefixStyle.Base128, 1); - } + int startupModelVersion = ReadInSurrogates(currentModelVersion); + // non-master peers cannot migrate the XML file + if (startupModelVersion < currentModelVersion && metadata.Master != m_peerID) + throw new FdoDataMigrationForbiddenException(); + + SaveMetadata(stream, metadata); - int startupModelVersion = ReadInSurrogates(currentModelVersion); - if (startupModelVersion < currentModelVersion && !HasLockFile) - throw new FdoDataMigrationForbiddenException(); - return startupModelVersion; + return startupModelVersion; + } } finally { - m_mutex.ReleaseMutex(); + m_commitLogMutex.ReleaseMutex(); } } protected override void ShutdownInternal() { - if (m_mutex != null && m_commitLogMetadata != null) + if (m_commitLogMutex != null && m_commitLogMetadata != null) { CompleteAllCommits(); - m_mutex.WaitOne(); + m_commitLogMutex.WaitOne(); try { #if __MonoCS__ @@ -121,13 +122,10 @@ protected override void ShutdownInternal() #endif using (MemoryMappedViewStream stream = m_commitLogMetadata.CreateViewStream()) { - int length; - if (Serializer.TryReadLengthPrefix(stream, PrefixStyle.Base128, out length) && length > 0) + CommitLogMetadata metadata; + if (TryGetMetadata(stream, out metadata)) { - stream.Seek(0, SeekOrigin.Begin); - var metadata = Serializer.DeserializeWithLengthPrefix(stream, PrefixStyle.Base128, 1); - - if (HasLockFile) + if (metadata.Master == m_peerID) { // commit any unseen foreign changes List foreignNewbies; @@ -150,8 +148,7 @@ protected override void ShutdownInternal() #if __MonoCS__ delete = metadata.Peers.Count == 0; #endif - stream.Seek(0, SeekOrigin.Begin); - Serializer.SerializeWithLengthPrefix(stream, metadata, PrefixStyle.Base128, 1); + SaveMetadata(stream, metadata); } } @@ -173,14 +170,14 @@ protected override void ShutdownInternal() } finally { - m_mutex.ReleaseMutex(); + m_commitLogMutex.ReleaseMutex(); } } - if (m_mutex != null) + if (m_commitLogMutex != null) { - m_mutex.Dispose(); - m_mutex = null; + m_commitLogMutex.Dispose(); + m_commitLogMutex = null; } if (CommitThread != null) @@ -198,32 +195,53 @@ protected override void ShutdownInternal() protected override void CreateInternal() { bool createdNew; - m_mutex = new Mutex(true, MutexName, out createdNew); + m_commitLogMutex = new Mutex(true, MutexName, out createdNew); if (!createdNew) throw new InvalidOperationException("Cannot create shared XML backend."); try { CreateSharedMemory(true); - CommitLogMetadata metadata = CreateEmptyMetadata(); - metadata.Master = m_peerID; + var metadata = new CommitLogMetadata { Master = m_peerID }; using (Process curProcess = Process.GetCurrentProcess()) metadata.Peers[m_peerID] = new CommitLogPeer { ProcessID = curProcess.Id, Generation = metadata.FileGeneration }; using (MemoryMappedViewStream stream = m_commitLogMetadata.CreateViewStream()) { - Serializer.SerializeWithLengthPrefix(stream, metadata, PrefixStyle.Base128, 1); + SaveMetadata(stream, metadata); } base.CreateInternal(); } finally { - m_mutex.ReleaseMutex(); + m_commitLogMutex.ReleaseMutex(); } } - private static CommitLogMetadata CreateEmptyMetadata() + private static bool TryGetMetadata(MemoryMappedViewStream stream, out CommitLogMetadata metadata) { - return new CommitLogMetadata { Peers = new Dictionary() }; + stream.Seek(0, SeekOrigin.Begin); + int length; + if (Serializer.TryReadLengthPrefix(stream, PrefixStyle.Base128, out length) && length > 0) + { + stream.Seek(0, SeekOrigin.Begin); + metadata = Serializer.DeserializeWithLengthPrefix(stream, PrefixStyle.Base128, 1); + return true; + } + + metadata = null; + return false; + } + + private static CommitLogMetadata GetMetadata(MemoryMappedViewStream stream) + { + stream.Seek(0, SeekOrigin.Begin); + return Serializer.DeserializeWithLengthPrefix(stream, PrefixStyle.Base128, 1); + } + + private static void SaveMetadata(MemoryMappedViewStream stream, CommitLogMetadata metadata) + { + stream.Seek(0, SeekOrigin.Begin); + Serializer.SerializeWithLengthPrefix(stream, metadata, PrefixStyle.Base128, 1); } private string MutexName @@ -243,8 +261,8 @@ private string CommitLogMetadataName private void CreateSharedMemory(bool createdNew) { - m_commitLogMetadata = CreateOrOpen(CommitLogMetadataName, CommitLogMetadataSize, createdNew); - m_commitLog = CreateOrOpen(CommitLogName, CommitLogSize, createdNew); + m_commitLogMetadata = CreateOrOpen(CommitLogMetadataName, CommitLogMetadataFileSize, createdNew); + m_commitLog = CreateOrOpen(CommitLogName, CommitLogFileSize, createdNew); } [SuppressMessage("Gendarme.Rules.Portability", "MonoCompatibilityReviewRule", @@ -326,64 +344,60 @@ private static void RemovePeer(CommitLogMetadata metadata, Guid peerID) internal override void LockProject() { - m_mutex.WaitOne(); + m_commitLogMutex.WaitOne(); try { base.LockProject(); using (MemoryMappedViewStream stream = m_commitLogMetadata.CreateViewStream()) { - var metadata = Serializer.DeserializeWithLengthPrefix(stream, PrefixStyle.Base128, 1); + CommitLogMetadata metadata = GetMetadata(stream); if (metadata.Master == Guid.Empty) { metadata.Master = m_peerID; - stream.Seek(0, SeekOrigin.Begin); - Serializer.SerializeWithLengthPrefix(stream, metadata, PrefixStyle.Base128, 1); + SaveMetadata(stream, metadata); } } } finally { - m_mutex.ReleaseMutex(); + m_commitLogMutex.ReleaseMutex(); } } internal override void UnlockProject() { - m_mutex.WaitOne(); + m_commitLogMutex.WaitOne(); try { base.UnlockProject(); using (MemoryMappedViewStream stream = m_commitLogMetadata.CreateViewStream()) { - int length; - if (Serializer.TryReadLengthPrefix(stream, PrefixStyle.Base128, out length) && length > 0) + CommitLogMetadata metadata; + if (TryGetMetadata(stream, out metadata)) { - stream.Seek(0, SeekOrigin.Begin); - var metadata = Serializer.DeserializeWithLengthPrefix(stream, PrefixStyle.Base128, 1); if (metadata.Master == m_peerID) { metadata.Master = Guid.Empty; - stream.Seek(0, SeekOrigin.Begin); - Serializer.SerializeWithLengthPrefix(stream, metadata, PrefixStyle.Base128, 1); + SaveMetadata(stream, metadata); } } } } finally { - m_mutex.ReleaseMutex(); + m_commitLogMutex.ReleaseMutex(); } } public override bool Commit(HashSet newbies, HashSet dirtballs, HashSet goners) { CommitLogMetadata metadata = null; - m_mutex.WaitOne(); + m_commitLogMutex.WaitOne(); try { using (MemoryMappedViewStream stream = m_commitLogMetadata.CreateViewStream()) { - metadata = Serializer.DeserializeWithLengthPrefix(stream, PrefixStyle.Base128, 1); + metadata = GetMetadata(stream); } List foreignNewbies; @@ -391,12 +405,15 @@ public override bool Commit(HashSet newbies, HashSet foreignGoners; if (GetUnseenForeignChanges(metadata, out foreignNewbies, out foreignDirtballs, out foreignGoners)) { + // we have now seen every commit generation + metadata.Peers[m_peerID].Generation = metadata.CurrentGeneration; + IUnitOfWorkService uowService = ((IServiceLocatorInternal) m_cache.ServiceLocator).UnitOfWorkService; IReconcileChanges reconciler = uowService.CreateReconciler(foreignNewbies, foreignDirtballs, foreignGoners); if (reconciler.OkToReconcileChanges()) { reconciler.ReconcileForeignChanges(); - if (HasLockFile) + if (metadata.Master == m_peerID) { var newObjects = new HashSet(foreignNewbies); var editedObjects = new HashSet(foreignDirtballs); @@ -445,64 +462,73 @@ public override bool Commit(HashSet newbies, HashSet CommitLogSize) + if (metadata.LogLength + buffer.Length > CommitLogFileSize) return false; byte[] bytes = buffer.GetBuffer(); - int offset = (metadata.Offset + metadata.Length) % CommitLogSize; + int commitRecOffset = (metadata.LogOffset + metadata.LogLength) % CommitLogFileSize; // check if the record can fit at the end of the commit log. If not, we wrap around to the beginning. - if (offset + buffer.Length > CommitLogSize) + if (commitRecOffset + buffer.Length > CommitLogFileSize) { - metadata.Padding = CommitLogSize - offset; - metadata.Length += metadata.Padding; - offset = 0; + metadata.Padding = CommitLogFileSize - commitRecOffset; + metadata.LogLength += metadata.Padding; + commitRecOffset = 0; } - using (MemoryMappedViewStream stream = m_commitLog.CreateViewStream(offset, buffer.Length)) + using (MemoryMappedViewStream stream = m_commitLog.CreateViewStream(commitRecOffset, buffer.Length)) { stream.Write(bytes, 0, (int) buffer.Length); - metadata.Length += (int) buffer.Length; + metadata.LogLength += (int) buffer.Length; } } - if (HasLockFile) + if (metadata.Master == m_peerID) PerformCommit(newbies, dirtballs, goners, cfiList); return true; } finally { - if (metadata != null) + try { - using (MemoryMappedViewStream stream = m_commitLogMetadata.CreateViewStream()) + if (metadata != null) { - Serializer.SerializeWithLengthPrefix(stream, metadata, PrefixStyle.Base128, 1); + using (MemoryMappedViewStream stream = m_commitLogMetadata.CreateViewStream()) + { + SaveMetadata(stream, metadata); + } } } - m_mutex.ReleaseMutex(); + finally + { + m_commitLogMutex.ReleaseMutex(); + } } } protected override void WriteCommitWork(CommitWork workItem) { - m_mutex.WaitOne(); + m_commitLogMutex.WaitOne(); try { base.WriteCommitWork(workItem); using (MemoryMappedViewStream stream = m_commitLogMetadata.CreateViewStream()) { - var metadata = Serializer.DeserializeWithLengthPrefix(stream, PrefixStyle.Base128, 1); + CommitLogMetadata metadata = GetMetadata(stream); metadata.FileGeneration = metadata.Peers[m_peerID].Generation; - stream.Seek(0, SeekOrigin.Begin); - Serializer.SerializeWithLengthPrefix(stream, metadata, PrefixStyle.Base128, 1); + SaveMetadata(stream, metadata); } } finally { - m_mutex.ReleaseMutex(); + m_commitLogMutex.ReleaseMutex(); } } + /// + /// Gets all unseen foreign changes from the commit log. The metadata should be saved after calling this method, + /// because inactive records might have been purged. + /// private bool GetUnseenForeignChanges(CommitLogMetadata metadata, out List foreignNewbies, out List foreignDirtballs, @@ -512,46 +538,19 @@ private bool GetUnseenForeignChanges(CommitLogMetadata metadata, foreignDirtballs = new List(); foreignGoners = new List(); - int startGeneration = metadata.Peers[m_peerID].Generation; - metadata.Peers[m_peerID].Generation = metadata.CurrentGeneration; - int minPeerGeneration = metadata.Peers.Values.Min(s => s.Generation); - var unseenCommits = new List(); + int minPeerGeneration = metadata.Peers.Select(p => p.Key == m_peerID ? metadata.CurrentGeneration : p.Value.Generation).Min(); + var unseenCommitRecs = new List(); - int viewOffset = metadata.Offset; - int origLength = metadata.Length; - int curLength = 0; - int viewLength = Math.Min(origLength, CommitLogSize - metadata.Offset - metadata.Padding); - while (curLength < origLength) - { - if (viewLength > 0) - { - using (MemoryMappedViewStream stream = m_commitLog.CreateViewStream(viewOffset, viewLength)) - { - while (stream.Position < viewLength) - { - var rec = Serializer.DeserializeWithLengthPrefix(stream, PrefixStyle.Base128, 1); - if (rec.WriteGeneration > startGeneration && rec.Source != m_peerID) - unseenCommits.Add(rec); - // remove the record from the commit log once all peers have seen it and it has been written to disk - if (rec.WriteGeneration <= minPeerGeneration && rec.WriteGeneration <= metadata.FileGeneration) - metadata.Offset = viewOffset + (int) stream.Position; - } - } - } - curLength += viewLength; - metadata.Length -= metadata.Offset - viewOffset; - // check if we've hit the end of the commit log. If so, wrap around to the beginning. - if (metadata.Offset == CommitLogSize - metadata.Padding) - { - metadata.Length -= metadata.Padding; - curLength += metadata.Padding; - metadata.Padding = 0; - } - viewOffset = 0; - viewLength = origLength - curLength; - } + int bytesRemaining = metadata.LogLength; + // read all records up to the end of the file or the end of the log, whichever comes first + int length = Math.Min(metadata.LogLength, CommitLogFileSize - metadata.LogOffset - metadata.Padding); + bytesRemaining -= ReadUnseenCommitRecords(metadata, minPeerGeneration, metadata.LogOffset, length, unseenCommitRecs); + // if there are bytes remaining, it means that we hit the end of the file, so we need to wrap around to the beginning + if (bytesRemaining > 0) + bytesRemaining -= ReadUnseenCommitRecords(metadata, minPeerGeneration, 0, bytesRemaining, unseenCommitRecs); + Debug.Assert(bytesRemaining == 0); - if (unseenCommits.Count == 0) + if (unseenCommitRecs.Count == 0) return false; var idFactory = m_cache.ServiceLocator.GetInstance(); @@ -562,7 +561,7 @@ private bool GetUnseenForeignChanges(CommitLogMetadata metadata, var surrogateFactory = m_cache.ServiceLocator.GetInstance(); - foreach (CommitLogRecord commitRec in unseenCommits) + foreach (CommitLogRecord commitRec in unseenCommitRecs) { if (commitRec.ObjectsDeleted != null) { @@ -586,7 +585,6 @@ private bool GetUnseenForeignChanges(CommitLogMetadata metadata, // should not show up as a dirtball in a later transaction until it has shown up as a newby. // goners.Remove(dirtball); // If this was previously known as a newby or modified, then to us it still is. - // We already have its CURRENT data from the object itself. if (newbies.ContainsKey(dirtballSurrogate.Guid) || dirtballs.ContainsKey(dirtballSurrogate.Guid)) continue; dirtballs[dirtballSurrogate.Guid] = dirtballSurrogate; @@ -616,6 +614,41 @@ private bool GetUnseenForeignChanges(CommitLogMetadata metadata, return true; } + private int ReadUnseenCommitRecords(CommitLogMetadata metadata, int minPeerGeneration, int startOffset, int length, List unseenCommits) + { + if (length == 0) + return 0; + + int generation = metadata.Peers[m_peerID].Generation; + using (MemoryMappedViewStream stream = m_commitLog.CreateViewStream(startOffset, length)) + { + while (stream.Position < length) + { + long startPos = stream.Position; + var rec = Serializer.DeserializeWithLengthPrefix(stream, PrefixStyle.Base128, 1); + if (rec.WriteGeneration > generation && rec.Source != m_peerID) + unseenCommits.Add(rec); + // remove the record from the commit log once all peers have seen it and it has been written to disk + if (rec.WriteGeneration <= minPeerGeneration && rec.WriteGeneration <= metadata.FileGeneration) + { + metadata.LogOffset = startOffset + (int) stream.Position; + metadata.LogLength -= (int) (stream.Position - startPos); + } + } + } + + // check if we've purged all records up to the end of the file. If so, wrap around to the beginning. + if (metadata.LogOffset == CommitLogFileSize - metadata.Padding) + { + metadata.LogOffset = 0; + metadata.LogLength -= metadata.Padding; + length += metadata.Padding; + metadata.Padding = 0; + } + + return length; + } + public override bool RenameDatabase(string sNewProjectName) { if (OtherApplicationsConnectedCount > 0) From 12a7947dee2a0907a75e657d89225dc00bb12fcd Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Wed, 4 Jun 2014 16:01:13 +0700 Subject: [PATCH 134/143] display error message when project cannot be migrated Change-Id: Ia438ac157e21a723c709762890d0d5f8becd769c --- Src/Common/FieldWorks/FieldWorks.cs | 6 +++ Src/FwResources/FwStrings.Designer.cs | 20 ++++++++- Src/FwResources/FwStrings.resx | 60 +++++++++++++++------------ 3 files changed, 58 insertions(+), 28 deletions(-) diff --git a/Src/Common/FieldWorks/FieldWorks.cs b/Src/Common/FieldWorks/FieldWorks.cs index 0de6f11a64..8b54fe2054 100644 --- a/Src/Common/FieldWorks/FieldWorks.cs +++ b/Src/Common/FieldWorks/FieldWorks.cs @@ -3134,6 +3134,12 @@ private static bool InitializeFirstApp(FwApp app, ProjectId projectId) } throw; } + catch (FdoDataMigrationForbiddenException) + { + // tell the user to close all other applications using this project + MessageBox.Show(ResourceHelper.GetResourceString("kstidDataMigrationProhibitedText"), + ResourceHelper.GetResourceString("kstidDataMigrationProhibitedCaption"), MessageBoxButtons.OK, MessageBoxIcon.Error); + } finally { CloseSplashScreen(); diff --git a/Src/FwResources/FwStrings.Designer.cs b/Src/FwResources/FwStrings.Designer.cs index 21202c9265..926a270efb 100644 --- a/Src/FwResources/FwStrings.Designer.cs +++ b/Src/FwResources/FwStrings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.18052 +// Runtime Version:4.0.30319.18444 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -438,6 +438,24 @@ internal static string kstidCurrentScriptureProject { } } + /// + /// Looks up a localized string similar to Error migrating project. + /// + internal static string kstidDataMigrationProhibitedCaption { + get { + return ResourceManager.GetString("kstidDataMigrationProhibitedCaption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This project cannot be migrated to a newer version. Please shutdown all other applications that are currently using this project and try opening the project again.. + /// + internal static string kstidDataMigrationProhibitedText { + get { + return ResourceManager.GetString("kstidDataMigrationProhibitedText", resourceCulture); + } + } + /// /// Looks up a localized string similar to Date Created. /// diff --git a/Src/FwResources/FwStrings.resx b/Src/FwResources/FwStrings.resx index c06d97388e..0eb5a042f6 100644 --- a/Src/FwResources/FwStrings.resx +++ b/Src/FwResources/FwStrings.resx @@ -1,17 +1,17 @@ - @@ -1419,4 +1419,10 @@ FieldWorks ReadMe for help in this area. Title + + Error migrating project + + + This project cannot be migrated to a newer version. Please shutdown all other applications that are currently using this project and try opening the project again. + \ No newline at end of file From a213f5f9580f680633b500824b6a3c7459548d1d Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 6 Jun 2014 20:26:42 +0700 Subject: [PATCH 135/143] added test circular buffer test for shared XML backend Change-Id: Iae76e15f7c0d78f717e577d8796de9b4d2c2ee2e --- .../PersistingBackendProviderTests.cs | 54 +++++++++++++++++++ .../Impl/SharedXMLBackendProvider.cs | 7 ++- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/Src/FDO/FDOTests/PersistingBackendProviderTests.cs b/Src/FDO/FDOTests/PersistingBackendProviderTests.cs index d0e9227fbf..4080fabf41 100644 --- a/Src/FDO/FDOTests/PersistingBackendProviderTests.cs +++ b/Src/FDO/FDOTests/PersistingBackendProviderTests.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; +using System.Linq; using FwRemoteDatabaseConnector; using NUnit.Framework; using SIL.FieldWorks.Common.COMInterfaces; @@ -852,6 +853,7 @@ public sealed class SharedXMLTests : PersistingBackendProviderTestBase /// ------------------------------------------------------------------------------------ protected override FdoCache CreateCache() { + SharedXMLBackendProvider.CommitLogFileSize = 102400; IProjectIdentifier projectID = ProjectID; if (!m_internalRestart) { @@ -1060,5 +1062,57 @@ public void SwitchMasters() Assert.That(entry1.LexemeFormOA.Form.VernacularDefaultWritingSystem.Text, Is.EqualTo("form1")); Assert.That(entry1.SensesOS[0].Gloss.AnalysisDefaultWritingSystem.Text, Is.EqualTo("gloss1")); } + + /// + /// Tests wrapping around the internal commit log circular buffer. + /// + [Test] + public void WrapAroundCommitLogBuffer() + { + // totally reset project + SetupEverythingButBase(); + + // add some commit records to log, so that the log will wrap around + int i; + for (i = 0; i < 5; i++) + { + NonUndoableUnitOfWorkHelper.Do(Cache.ServiceLocator.ActionHandler, () => + { + IMoMorphType stemType = Cache.ServiceLocator.GetInstance().GetObject(MoMorphTypeTags.kguidMorphStem); + ILexEntry entry1 = Cache.ServiceLocator.GetInstance().Create(stemType, Cache.TsStrFactory.MakeString("form1", Cache.DefaultVernWs), + Cache.TsStrFactory.MakeString("gloss1", Cache.DefaultAnalWs), new SandboxGenericMSA()); + }); + Cache.ServiceLocator.GetInstance().Save(); + } + Cache.ServiceLocator.GetInstance().CompleteAllCommits(); + Cache.ServiceLocator.GetInstance().Save(); + using (FdoCache otherCache = CreateOtherCache()) + { + // add commit records until the log fills up + // once the log is full, we know that the internal buffer has wrapped around + while (true) + { + NonUndoableUnitOfWorkHelper.Do(Cache.ServiceLocator.ActionHandler, () => + { + IMoMorphType stemType = Cache.ServiceLocator.GetInstance().GetObject(MoMorphTypeTags.kguidMorphStem); + ILexEntry entry1 = Cache.ServiceLocator.GetInstance().Create(stemType, Cache.TsStrFactory.MakeString("form1", Cache.DefaultVernWs), + Cache.TsStrFactory.MakeString("gloss1", Cache.DefaultAnalWs), new SandboxGenericMSA()); + }); + try + { + Cache.ServiceLocator.GetInstance().Save(); + } + catch (InvalidOperationException) + { + break; + } + i++; + } + // the other cache will now read the wrapped around commit log buffer + otherCache.ServiceLocator.GetInstance().Save(); + + Assert.That(otherCache.ServiceLocator.GetInstance().GetHomographs("form1").Count, Is.EqualTo(i)); + } + } } } diff --git a/Src/FDO/Infrastructure/Impl/SharedXMLBackendProvider.cs b/Src/FDO/Infrastructure/Impl/SharedXMLBackendProvider.cs index 2bb5d3e609..0bc87a3fac 100644 --- a/Src/FDO/Infrastructure/Impl/SharedXMLBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/SharedXMLBackendProvider.cs @@ -25,7 +25,7 @@ namespace SIL.FieldWorks.FDO.Infrastructure.Impl internal class SharedXMLBackendProvider : XMLBackendProvider { private const int PageSize = 4096; - private const int CommitLogFileSize = 2500 * PageSize; + internal static int CommitLogFileSize = 2500 * PageSize; private const int CommitLogMetadataFileSize = 1 * PageSize; /// @@ -637,12 +637,15 @@ private int ReadUnseenCommitRecords(CommitLogMetadata metadata, int minPeerGener } } + // if we have read everything to the end of the file, add padding to read length + if (startOffset + length == CommitLogFileSize - metadata.Padding) + length += metadata.Padding; + // check if we've purged all records up to the end of the file. If so, wrap around to the beginning. if (metadata.LogOffset == CommitLogFileSize - metadata.Padding) { metadata.LogOffset = 0; metadata.LogLength -= metadata.Padding; - length += metadata.Padding; metadata.Padding = 0; } From d0b7e5a0933de59a5f75ad2a87e0c97d73d0dac9 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Thu, 19 Jun 2014 13:10:25 +0700 Subject: [PATCH 136/143] removed Paratext DLLs from repo Change-Id: I68fffa98a8ee92a6edba5a48f4b087416d262074 --- Build/mkall.targets | 29 ++++++++++-------- DistFiles/FormattedEditor.dll | Bin 102400 -> 0 bytes DistFiles/HelpSystem.dll | Bin 155648 -> 0 bytes DistFiles/HtmlEditor.dll | Bin 184320 -> 0 bytes DistFiles/NetLoc.dll | Bin 114176 -> 0 bytes DistFiles/Paratext.LexicalContracts.dll | Bin 10752 -> 0 bytes DistFiles/ParatextShared.dll | Bin 2060288 -> 0 bytes DistFiles/Utilities.dll | Bin 442880 -> 0 bytes .../Controls/FwControls/FwControls.csproj | 7 +++-- Src/Common/FieldWorks/FieldWorks.csproj | 2 +- .../FwUtils/FwUtilsTests/FwUtilsTests.csproj | 4 --- .../ScriptureUtils/ScriptureUtils.csproj | 7 ++--- .../ScriptureUtilsTests.csproj | 4 +-- Src/FDO/FDOTests/FDOTests.csproj | 4 --- .../FwParatextLexiconPlugin.csproj | 5 +-- Src/LexText/Interlinear/ITextDll.csproj | 4 +-- .../TeImportExportTests.csproj | 4 +-- Src/TeDll/TeDll.csproj | 4 +-- 18 files changed, 35 insertions(+), 39 deletions(-) delete mode 100644 DistFiles/FormattedEditor.dll delete mode 100644 DistFiles/HelpSystem.dll delete mode 100644 DistFiles/HtmlEditor.dll delete mode 100644 DistFiles/NetLoc.dll delete mode 100644 DistFiles/Paratext.LexicalContracts.dll delete mode 100644 DistFiles/ParatextShared.dll delete mode 100644 DistFiles/Utilities.dll diff --git a/Build/mkall.targets b/Build/mkall.targets index 65d228a951..02988b736f 100644 --- a/Build/mkall.targets +++ b/Build/mkall.targets @@ -310,6 +310,7 @@ http://build.palaso.org/guestAuth/repository/download/bt279/.lastSuccessful https://protobuf-net.googlecode.com/files/protobuf-net%20r668.zip + https://drive.google.com/uc?export=download&id= dll.mdb pdb @@ -358,6 +359,15 @@ + + + + + + + + + @@ -399,6 +409,13 @@ + + + + + + + @@ -421,9 +438,6 @@ SkipUnchangedFiles="true" OverwriteReadOnlyFiles="true" Condition="'$(OS)'=='Windows_NT'"/> - - @@ -433,15 +447,6 @@ SkipUnchangedFiles="true" OverwriteReadOnlyFiles="true" Condition="'$(OS)'=='Windows_NT'"/> - - - - - diff --git a/DistFiles/FormattedEditor.dll b/DistFiles/FormattedEditor.dll deleted file mode 100644 index d52e4f82ae10a90d7fc1d5b81f36c32598b3c447..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102400 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 XLIWo>a6$toG;l%#Cp7T?rw0Bv>vM37 diff --git a/DistFiles/HelpSystem.dll b/DistFiles/HelpSystem.dll deleted file mode 100644 index 3c40d5e136c935925bf9db609779bfe0cd4467dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 155648 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 diff --git a/DistFiles/HtmlEditor.dll b/DistFiles/HtmlEditor.dll deleted file mode 100644 index 8711ce933833aeff989997d47d09de5b84d7290c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 184320 zcmeFacVHA%+s1u%H@itT36QoMYC;Q3vI!VaKtdG(QIQT-nus8GptS-d^uC{bda8zR9LJ zIf9R!CK*`F$xw{5 zZ?f!CW@T(g+Z)rquw>Y%5DH3P4f@P-QaU)l&0Z#((_ zx-u60G+IK}%D$0dFHDdTXPHb6Ex~%o&BIDeZ|XDwta|h<)hb%xDd~wB=amL9XRotN zx*2MW@n98C$v{LxsOQbiPxh1yQ?rZZ|KExQ|8K<#Pz>wKbht1zdd@9h!8Ch@c99$w zxkbCva>lO^naWd$sZNl#G{Pg8i`*K8{f)!c_bc;jaTa^?cW`VWBuH(=5bDu zZ5$}XB88d&xt@|o{w3P|ruFW)DMAS#BvR!>FR%<)e2-6qQ{qZ=yAH6-t9VMxskaj_Yrw zaGEQlXP$@ujd7OAB$qV^wLqUn#D!X7kc)U*I~o^i#VHrr9=aHsSI_l#W(E#|sDi$@ zP-_YOUr!eQQ#l@E4pT*TNE~A&v$5p@ZP2pM8#xo<86l3tUMM3kJ#{%fSe?!?8H|s| z^m13!1U%Jqmd8a+NR$cgs0m(~;K2l0da3I2XM}DxI0NEzC?0w^TCl1-c~~#frYp25 z#x{$E7qMf>+VDc;JX+PX&-427a@`p{a~$o>)Vy45k{qXuVY2mqWTVAPZ?L89VW6$G zipvsYdOd7#j-b2*pow;Q4%>z&_bB(;(>aVZpCpr4IB#!<+U3a*do)Ex1MRIgIo(w* z)1)h+I+QMOLZr>Ac04?+A}-}Pf(ELECvYUZlCT|JORjH&3nsndqYn`=_h4IvVmiJ)vG0dO|fp9Q(LV#2H+Q?PvowHqlM`G49N$(lfpMu@F4+XeW!;raI)QOnr{#w* zp5_Xqqh6plCL}CDN8a*xL;`6jRDJ}b)*KT;uS+NL$2$Z4P{^7XyvZ5p z4=cDKP!Gk^<)oskx176HXaM5Aza6RAp=9d@t_B9e$|P)AFx!gNPK^s(BgF$bXe~EC z!5LVLnfkq+f_SGZz>SYHj_h#-*e9DImWSi1C58xJi<)_}oPp~wEO6vmJt;_bmIYDX zAG#isQR)UM^_Vk&gu@%maF*3TFo;6=(S-&{p}E$w1%0m2V0d5%;0z1}LpRE(D=-WL zYaekMv}Zin5B&B%!rh_SCDsN>PIFq@GCn({85$Xc9tWL1Z+vzlv<$~WoTZHltHx(H zEJPr;&>f#0Xof^ybiQ?SOkzH^<< z($^3um+fM2oi(z;tTm8gPg;vf`RO=|$ohy`8+L(JC@>y7wzIsUlyH{Gp!ApnZs{vWW|^V(dmLWX5H3TH*;RfNKV_KQtzj0&}GgNzRgQAp^KZ|Em~-i9L_=d(#M-&6;xZmC&L;o%TohZ}7YLzN-d)yg!ewRC z$Qg`>j%*1zDMdBLEvtLHbuGOYbM!`d4&xDO)7u+9b6nPCVvF;+iv z!wKlccyz^CE}j<&O#IhCi%5-IrG_|bSOM0E4dC<>p2uXVAN<4J*JJv4J*`8h1+# zan`T`tPvY%8>vwnX>qwYYghr+hy>(3S0DQg5>VVj%IXZ(DE%I%9IwX}`Vm8GB65m9 zAhMsi3~C!M%gY7}X1Gd!l?u)>QItH#lGZs?$|kX_tavGlj9AKwqU`yovbaH!_ny%Y zS>-{TeB=bk6CJbNP-~furxban2S<(+a>j>{HS=JW{Z0-M89H61-=S;>_sgEVk+tykFJgKwk_8EurArIAA}z5dUM&-&`rz~guEeCg1J+uQ z9y&{rNqNd~y2Y7UdOJP~b8wb%!W1N>aiRLosAmlgu#CJOMz%}L1;{?R43OERH%&3v zFXi3|>z&&XiI3Bp<}A4Y>!K7#tM^U>9ciwd-+t-QG-u6Ic)D^h71)4kId=iRoTcO@ znQ#EePAbJQYt{1v^E_#;G-p~|Xrg2?$ZN_F8;@MenH28|jkPDr*%VJpBu^fICaP+G zf>+u5S(m8&3_B+KDytg17{{@zJCi-m5KeI(3~*uc#5+UVFi3EQj#z_tFpwLOT&y&? zvdB3ed6BcU0Nt?9_%cn(WXe!(LO6m6*ypSX9KnQI;RzhUgqq^LY_KU|I@m>{=ItjG~e zXd0ft5loPyB5yO+sf^eM4l>?kJ(i-eAYU!&Ruf;$AOnxiuKLg$37T(LfFib zLFYNMYiM~??&9*>l_B}jk=oHxEn1pKOG}lu&YTJ)SnB9UP3*rdF-()=G;kZbfYnnj zYr{H4mE0}6*l;WfmJ}BZZvaDNs zj2F{9xe_s{JU?06#+b8bjYqak67D4qU_@Tl_Rjd*;ljT`LHDtB2-r(6bHZI>5t`&< zuv}ND0OR#gt;2=2?LxA!KL3o%(5_Xe3>P-CngJc#9$y+ndO z>j@$<2D#Xm#O_e8P=0iI3I3ye>|W*y1*6MLFkJq)EBCm;#i&CqtSS4o2b)s$%jPfx*)A!C1JJ z3(!iqgW+k?@;|3ZH+0%v|I*9LVmgy|*eVdrw-+KdEYHEMg_G(3q1DmSE)t!L8C)_mnjx+ipV9ImSuIkQv4Vdg__^R2atQeBbTe=9k~#duJ#8m{z`sp6t4 z&ja!^!``qg1MVMCE(7acv!Irf6SJBmAmfl)c_mMxbEV6%quplr1*dgS)OAT7O#Dk^ z3o7xE#lYadY4W{Dle_@?%8~lYV+Ki_0xw}+Ugs3K6k3lktTf5z2{gi~AHA3UN{%GY zcCW)wUYIPYHx`mla;?VzF|(F%?9#j-S0#s?5!ij;Y+b%UgQ!_aE+#p%kNYTVNg~0k z8lJadJPirGWPyP^RFh3~NrruK&BaqUYrFUZ^Dw`>Jf|zp9+mrzc4*g+cI`(uldv*_ zaT(tHDscg%&fWqUcgA^L*o-+xaK87r!&g0LcFl<33VaQ(z}C$Kp6&5TtvuO6w(QO0 zGe`TWEz)^!V46%VvGO0e+tNG;r)){(aA@M#^cY;eOqMJ+bLavb=2dX_=M0o%S**N7 zwm;JgE6YYbBrgR?C4cEgPIHvBaz)=OWF-3^l9NZeC)MMNdm+`6;tsm~>F#`2R=V4h z=5VFD6B9y5anF(-ml`MCL0{aw52>zw8UKHoQ=0Sd%ueW08g`72`9$~c%uC^zi60Mf zLm%1m2s&%zVJ&=uA~gopXy&XQwyZ%}&74_b^AGYj!wHS&EthOJxzwiO;mrcsXFXYe zJ3Q6pm}8kDd#$dO%|6n8bdD7%kI+Nh2o2=k##*+a_I_a90myoeI;NslbRv#RxkE(U z#}VruC4@r(2Te{gZg~9Bx0S)F&YUWk=&^4zt-d?V6_{U5^j%K1l0M-4%d`Qva!e_5 zFvJdJ@*4!Ea|gPIyqCO>ygzC>qv=iKja=$+xzOkTIdYXKO0gcQ=OjQbxYib#Pf=f6 zypX0{ZE-*fTiX&RQfP}yq^>QAA{n-LMB@G4mLH?n*0kh=9BJw5OR@ZXqv0hCpTj@A zS75^9G7OKmTmW&FwZr<&k!;Fuy)Tf0r~Rnn&5}o>; z52KK;^bs(GvzI4-fVPzrZY$lL=Kj~l!f#;wr^av_D;*2r*3@G!v#i@@7uj!u#HYpE z56KCElaV*|E+|LW11d7=!lKp@2M! z!DEX!-U0?)*<FA4?^_HtEnBbE1!CT-dorS?|IC7RYB15U4R}%-pE0`yqRbl^g%EvZ5;{)hpxfHVs2kOW%XN@~Uo8+;GC4OHZ zI}$3n8z(FxgiBetjMF)#Ct3>amq|FQ&51dyS?!F!1t+%Tgfxe93U0sRLQkQm&N3NA z?Orlv4yO3M$CKopnhbXBXr7UL+KK<>zsO7;=R23VMAjdcCC!w4_K!Kq8VSi=6=#lOFq6Og6$Az_G8z~;k-Btob&K#OGaZh<6N#B**XR8W6z?Bv+OEJ zu(>tN3@x-)zD&#vEs97+XkJ8op(P?rSM7}%+WLW!1Ft6d*B1Zq6pi-+IoRtlYR2MURs6dH|6KT&V^7DZ z*^LtNFFalHDru)K_Y>*Gf7}bDfG6~VtU-A+$F+ccS%$9AI!yK#^1ADd{v?FY$ z2m}H(avbuh2z!7D(uYClgB%yG0#8nV6F>ETJ`!Bky5bgbM(=|D=$+H2tib z7yI&FbMX+mvn$q#wW5RR_^6ER3_P3|@a5&WW4nl6;(zo}KA$oKLwUtz^u&_6Wk1yV zZtHkOf|edN6`3Rt<0@`n`A5ias<@+q;o>XnB3ViJ|&dA&>vpgvFjeokc8#I+ZcSg3NE%=u}&4-x;U-Kko$PJ z6VVq8D`(Fy!X-k=Ij6{F;O|UXzb;Ec6+Gbl)(wW$O}yXc;r=WuHT)c7+&JUPfyQ<+ z*1Uc>kGjkQ=yAQsx$S1O7c8@TKM(7m0BQObrg3QGqeToH09zU7^WSc zkcN+>bw(jyIzI7%55h<+6_+Xr4#4e$KeS#Z+2{Irl#~Z^X)bPV3}kzU@R-RXH#%0e zy4J=^^_0t73}Fdff%RnXld17?tXunKu9>&9F2R(Z{-pdePpB$qAmyx2NF=+hX%fEfpAA@x!W>wEXb;V6GpXWaqkQ=Mvo|L#=+rTc^FqI{cT@ z2+kzt~ z=g(h#sTNA7VzbR-&`iEy3a@#kxX`YA2gEiCUh+d3;k_^c|oFp()DOZ@A-_gn<3JX2_gd1A1 z?xgcds=D!+?vmY7E6Y&AdMpw zZR2(J;N4DAyvI&deymbHc#~^ioWWZu@)^W`_5rh&(_e1PhabK614%jY1mpSMV>O4{ z?roCY+vJ3JtG5{`o;Wz$q1beELAPL zkpl{=CR*YjFp@#k_pxanuGnH8I%Am+nnX42{7eW5iofJvA{gbc=04UsNBW zMl;eA^P{_m%~#J^(|QIe&+Zx0`lvOlMLICyA0)?#|RFFhe4HQtvRk4@4N&GE@z zTS*E$7azv~;7d=$68h4UeCf$3H#6rvCgPKh@&1`Pe{*zT(Bn@}^xI);8pBpehP~nN zcahriDFd9#Q{%H{=4^?ylq5wHah6Y&PgD*}P2vf^fwU+SPbzwntP=6QT>)D zkqRY*&_k54KDN(uA9g%>TO-w#lE`OoIJ`{}{?)_38u%w?7CCF=cd!qur1%i_6nuU) zun}!}^P83;&%rQIx|zeAQY<+dX1H0U)0tmFJH%pd(qb#ia6(FBP+m)+^B5!!~rp*Lhs*81R@2ozuj^5B!J?w`eE zb^fE6tkr)OlWDQVtQ^C|=kHi2sm_N-xE>xM-NA*WiqkXG<(XLs^Y{nglTHthC_3%W z!+~iI?D=jp7S7;dmKoK1a_RVCqYHZtD-BI389J;~$9fGLeB-c^V9w~$p`nsdBZdTX z`VA{79T6JSrl_!~{1?o*WWuQN6H11)88d9c_>#e+f;l}V3>h_I=;gyE_X*uHY)qRW zEm{n|aOi~>UC^po^I=U}wyOWHGn+7G{D{%R!gKFEY`kpT@T*6MPV&F>xnu8c9UZbs z@JhzNiPDJ+o3jJnx*)$hn#mg+GIyM>&4c)di@d>B zHJxy{`{8fk-xbU#J_C(`xgJEV*-lsZE1NsTH;bxhVl;^*&ce# z)P%|S7}(r|d%;BG)Qr)F7LY-N_N;UF5T51$mJClFT~eK6Atb&&c|{_Dt(D9#clnIU{p?ncPYqAip4g zCX>FCGPTGc*@5gu4*!m=kq>doXXI~W+*w)PYGmHoIUjhbf3Zb1~O+KLBy+F&lk~79IRLC;#{48(unbX; zdFm(bV;HYu3eL$Ezl=P{PCYm=oF6e6%vyjs<8T+Zxkuw{4br z9wi^LZHsvxZ9Ze$e$HW;Z6DLN*yeG_-1pg5gLcZc+BD<9^$ESqp{3c@z#%=$wylh@ z0^7b|tdni08N1pxhg0S^+_r4mMB8#`57<_h_H>Lbw=LjwVAXDfrJ!eRSn?2K31aBk z$F}uk?0eg8X3XJ~B}y>kY1M4IjV0^YR!%Fj?QYs7wmm}YYuj^dm9kuP4Q}&*-FgKRr1lPnLuoQEL<6~N!OKdev-ndGG zxy^dpYS9imK4F^;V8*;3_bE#@XYBpBRF|yXi(y#1?nbUeM>W$KmWp?r8@Uo--DxQ> zDLIHGtJyY&*4Vak+S9hppv|}K8QNmoUZSnAZ5?erOy;*0mTETJww?9{ED_7M59T&| zZ2ORQ&>djxIPG0`W7=o558ZjRZ)hj*MzbuRBTnY5EJt7cm{t&VN8 zIQIhEX46{Qc3GVCv#V`4(1zMJn0Bje!)UW?8%|qh+by)$ZA)>>`rKt(Z`#|o^`(7g z+i=<$+ir17U)&yRiAK}>wymVqvuz`-D8??aZ98LqZ9D9i{pDtu8*AwZZ7l6K_uDKv znI->lzr)zQjQ!#Mfc7NqFZYMYnW~w2G^ghyx9nL9Z97I=PK)<^=62v1+YGC2;yvFm z_MRR4j`l6Awn^}O&yucqDVgZ`iLqL++OS_4Yr&Y;^E<7JZGW@mwJhoNI6X4Iaf~H- z;ylu`yI^jU1l2tsJEP0%*RPj`2 z>}STRd1^D3m>_eg=BZ1o4r^#qJ@`;D=H39-*tGL3WxXO;ifQk8nbwZhMGPgcgcX=8 zZ5s@8!(L%*ByE7FZoI=x#`WFf+1#ki*>7rPquasv$*)OgK&DhD-)kaeJ|ll5t2C7< zwa9$3HQALMOqP<<$S27~!kkV(yDF4<%=vI}`F86xi{=aMgzo5@4uN90NJ2l5ZnbD^|c zm8?rPCEJqS$$?}Ec^^5Ke3{%rzD0gc{zArIBrW^N`eYH=j=Yi_Kn^FzlXsJklFyOL z$=AtB@?G*Id5(0oka=a2jmTEy<>d9`SaKRUi+qXPK)y-7Po5%wAe}9x^T<}@mE^VLE#w{KOmYFap4?4-M1D)2CsT{1<$7c@vNPGA97&dw_mEGL3&}O) z4)O^38TkY0Xd^ABkwLN@c@=pBIf|S_-b2nMSCE^?{p5$_cVt{!X}KoZh-^t-MGhfL z$m!%v?1Q_|U9+Nn>rA^VUwlT*ki z$ra>g@@?`H@(0p%kajZ3AlZWKNcJL!kfr1_@=0<5xt2UkeoOvECU=yU>yS;!PGm1~ z2sx2_keo-ZCU=nUkl&DhklstA&FW+mvMt$*96?SZXOMHrRpepv6!|lm)Ja-vM7AQY zAP14Rku%7JWCgj8{DeG5CR{4*)FA7V`DAml9od~6NRB4&Anzw^f$erZd{-ctWMS=^T_687jghOk}M}5AZL;D$O>{ld6N8{OzI+YX+X9kdy@mnk>nKe zNpdNiQ>m8+kAJB)O1WPrgYWC%-4nWl}4H ztV=c_+me0AA>>%{Zt`jJC2|Y-9{DBtGnw2?T5doVlYPnI-PR=41ldH%b6 zb|U+bBgs3+$H@icdh!7I8Tl)je6_S$gKS22A+IMVkav?$ldq7w$@j=JWc)R3hs-D2 zlfB8|WEuGoIiK7_zC)fQeC{ja-G!8C5y>k>sarsHCqv{t&CS8N2h1z5b zvO779ypw#ETu;73{y?S3dwHdP2^qVv*bE*Klv%?yjg11BioW!ljF&md75;L zkXk_wK4Gss2cX7XL~2eQg7QY%1qB(EnYk&lxr z$X(>e+NPpJa{EQY%PaO!gp$k@t{`$-U%Pq!}Z%YLRWp z0c0up2)TmXM}A4hhon|6*_phFyoX#sZX-V;e-m0E4cYslNkr^(gi5%PO7b)1wh zB72kL$VbTKFD9=gCy+DASIGn9_hfphl)sSdO_q?e$qnQuWZZZuS(j`@ z4j?Cy&yZWlQ>1%>l&?>=BX1z@Am@==$)n_7WY$EfburnGoJ`Il*OA9b=dDt*fb2n* zl5@z_erEV_SjO;^BCTEcw z$WKUfrB~n`)(=On!JvjPA(_kA%7-gAWiBR%koS_y$s^<+WTS_qWM8s`oJp=C50l@MX%9=uBC;z-yu(tKauf|N?jk>jvPtOBv+FkkUx>WnNt1& zvIjYie2`pBzCj)(enl5{*Swd#-;lYPmt z^Q3$uvMV`)e282}enKWZFC~k}0puOz^W<*w7 zN%ta|V+L85EF#;JSCQ9|qsb}c{p4KoC9;CtPQFE+AipNhk!G>XE0N3~v&nog{7moq zB||d%O`XzRSi_>`#s+?*qfVdSU5vsJoopKyD}BB2SQ~ z$zRCxq<5Lrs!rA?FCbf!UC06CP;wMGnY@>Lf}BS#C0CQ%$+yVQ$kXJ{qm@VD z+GH--gltWABm0tr$Wde&c|Z9W`82tJTuxSyTgW}+5%M^BlKheUi%eWDy-Fu*la0xX z$aZ8masWAm97~pw_mGd1&yg>a8^}H6d*sLDx8ym}u|npaO4cOnlR@%AvOU?A>`e|L zN0XDuY2-}uIdUnvn%qq8A>SoWkYAF&kgivxC&^?M*?=q{FCyELUC5r~wd62zEO`g{ zAUPil@2jg{IfM4!B#)8blL;%&XqlQTe?*y9WOs5nc?TG7=kb-lqRe7)19_M{Mg9(k zOD4Vg7fNQ6MPz64I&vI&ANf4_I{6M5ZsE&UoxXlke3&bOw>f^4JVl-+e-oPXYou3671FEZ zeNw9`89ko1Z)=vPT5U34qNe#iDc_PMJCM?v!*t!ZJBmg^}d7Pz4&&bc7sk8om+^l4+u&<~cYqEvol_nnH}97v+PnV&Ot;2=CpXaw%Cs?mV!zy2~6muo1Q1Js^Gf5OkT(5p|fer01Ya$vi0S zcd)^b5z#VqN92E(HnVHx=ZjG zZ-?oTBX&>L^u%=7K-x)%#N-KYwmF}tD?0=Yii$z|Q?gzZ}@i{~5Rq3AT z4e;A8R%{LoABp6v(!CTV@dX;&R>Kn2w!pkhov! zEb9c5FV|XjRZ=m(4`kW(sF!7hQ12GRs;f;zOuo@3uS)lwh}nl9YzAVrtPpHAVzt#4 zAXZ21Rm9}GMe?e2Z$T`F<6`@<40Y8$K&+nH7l_GMgXLA}K9^L$Z;@H{Ct?j5k(evF zz~Gy;d{w$rl8g9vHbg7ke#G!CO1>)HbrF+K7R#&BouAx+-+;30qU6pdpAm_5K)s;a z6{uIB)*rD#wGoKP@1V%5(p?5?Y64Jbbp`Rjla|?;Y#MYBMu^K7;qhd{A z9ki8BuuIhX!7f$1CFMHPMQuvTU~`$;!znlEZyQv)=c3+K8e5Svnm^+u6Dr*sQ;JP* zja8;(xc_Y?#_>h~1>N z6|v!J2NAnj?Kom1)P6#2q?)&CvAIR9X4Pzd_fRHOx`T*~)>tdV#;A2hETq;4v9W4H zs+O8@YU2U$tU$pV}Ps?0&VSh(&A@Vh?ES z5MmMg1Tp!}ro1Xsen2c@@u}Hnh804rR%&sSHAU zh(+uL#2(eyQp6&*5wV#XJAhckK0xfTaLoOA>cS}dBid5DX&oZ5l-g;X&Ew&EDNWM~ zqO3Tr$UG5_xx1!iM=Yf`TG3d_NVM`~xMa$mX~j`C8}(*|WA5c?OQUQ{+GsOdV+Rm> zN^N2KM*RybmF{KfTO*dTI=$G;4VO&Wlb&s!R{J>G+~1{FM#bD21?E{TSv8}GKWQiv zD&5sH_D5NM#*rwyFykXLU+ZBNw zgjJ|Lj*@HDouuW?3!8WUXjXB^40q~MmenV`V zTD<=hzsGIGQvGMl4vp19Y^PcPwoC0I*lx8x>8H$IwIQ(mYM-T@F$dMo!VamOhrOlN zF8z!-tdYY|Q1p8L)DC|twQoi&TneWuj`HQ2>m6dJI zYAiMDT$JU+SYeEHjIlLY8zc4H`?3lg+NS%%tRlzvItMBFBh6K2<`U*S~1&WLD>hx&O{8cKjNSxs$42;`l=?tNLY*zrvOhs9q5M0ynnpMb(Rp ze4|ZX*wTna>~h5LxWSI~im@B22clwQt6$~7mq_iBw^c7Taca}6XB&JG&yGEcSj3(| z3}0fiV@nW=*jmK!l{Pz8iCDzmMofNZS6-DVpCT5qGl(T>?03W>mRKX(cr}()qd3YM zA%;gmcAFO=7O~EVC2Oo7ViCIuu@sF>L@Z+WAXY_Vvk;5e0>tF6w#ln9<+T{wQUmw5 z8rxk1_qS?C5R2Hyh^1-lTg)M1=h0?*IOa~RSsZ0KHTya;!m*UbH8&bOPP6;cs%CbS zb*otrWxZ<_89c7DOJ0Y15xXVECdb(QF*dhmAgbOn%mEK0?KanA4tN-6+b+cLK+Lvx z5X0jx+df0AmfH7-)mA%?SRJ*LT1EIyzg^E=v(~kah!w)>hGQumY6VPvwLY~vn+9QX z53S`j4a1f)qE>d4O{i6Day2#`u|{EI?yZ*cBue53PV8k^f|B@|6WcZ*7P0+^j7qK3gAO47v9UB^BV_`+%n0rzk-07=LuhYRaS9`RM*IcMJuTF84t*n!6F4EYx zI-?vd)ZRwPi`9<7TC079dc|tz5No4$98q;@@Gm#U3Itg~7fVqMgxBi2>z5yUQ2dk(Q~YReJ3T&)7JE7Z0icBR@u#Ja1U zK?i7P0k&T!D`!bra6YF?a%R=p=w8R3Zm@eoFa3h#=b>A zhpGL7zTBkdsEg+eYRPr+oI%Zx*a)@yh>cWhQrBy4QEQHp5o-$@rLoKFZZxCSu7!pkaqT+P()Y-XvY*I(e6t(IMXnPaY6Vg0KdMnpKYF1>t4UWJf}9Gevz4{ zHl%*Bd0y>S)SIt1qy9$og4(?LOU;XFt1-WYYTN3UI2NhBgV!S~wTBOmg9_4JsV3g-aqcu5jRQ z`&icw_mvG=IM%84YH*d~b+v07bTAv#ZfejOzo8SZHx98)YSR(htTqR+Eow^<+p4w! zz22s_zrjZHhS~|NiS26NBep}$)v$xvsg~BTv#C_8+pxgwQfuC@$h@i61@(5T^+UZq zYQq|CbnI0d*YFL;KDBbx+pl&n>KzDM%1q4RpxSeo`ysW(h`kjy_d~S%MmeokMC`*x4q#3N5tNQy{ECmun*NfZ0I$|)ILG4Blbxst+6X}&pN(S>!16x<9oH?xen*g zYUR0!&fnCY%&p@5gC){L_Kxpkcmz6~sWc`rBMls`XWJvlj%Tj+GF zeVx12#H*dnZRV7}O=3TP$=zs@)Z!X#HOXqJjaoXZsMTrI&RI>Zd85wGbhVC+u5jYd zT-j~*YSi1ArPd!-NA3DXL!1q0vV0>Ojd0?p|M;qOm%;*S(_wjPkHCUzFTe_Evg|K6 zDsP?*xndB9%J9dm}wk6KYxrh ziLov*HZ;cWh_R>DWZBm?Uf{HrNNjK8mCiQ0d?!${gW7K~Rv6gmjKos&wmUm&$rUNP zotLOJ$~)rhtkyj5BWG8&j(PVvE?4W3_l5Hcwf=eEI=ib~2kWUeIPVu{AGJ|==bio4 zCgml$u2Y+q=XVWOdm^unYpB|Syhg5JYOC{_xQ45(ZQQ~<zv34z5vZJMs$nE0MCt zRJsr6dCgdj9nZVm6|vKK*SIEX?617ht|>HG*O~dHuG`hJ^P4%Rsx{9?PNdcacDLHq zuxV;HiP&$y$0z zP1e#fwNAk&UCY(F!(LGv40}~=Y;dD%m727PznoytUE0Lo*RW06d|gf2+^8mPZdQ{v zx2jDI?r?2an-SdSs#JR-c*M0w?fKyQu6=4Nu(bI5D)!tr1&_H7sYySNs7XKHQIkCc ze`wCGCws{IYO;rXpeB3BhibBie5@vWi2PEXbuO1Z;aC>>;Pr4hO$* zeWi91OLSW8Pi*%yYE=qOyS`JaUht#qd$j=UN3|9OrRJR4B?V8qeo?y|_M2Mog5O+! zs0}H=dEFIWqTw)nV9H*;#FUNr`T4MwAm&z^Qji!Iul4|pzZ=W<80HjIjZ4zlyn^a+ zRn%TCs27)}wyt2K$yD2kk`a@wi4UdOeUYt+k9hHg&v_Jh4SvAfj-5a&5j$Ow7l%LV zWXJwMtgf20Sx-&c#2;O=OKu7_kIPj{DQxBpsMUw%skJC<9T!xSJrX~uZ@1E^uv1)- zTCc)xan02R750p~NUcgrqO+CS=)(SSt<~hL(N=9z;q`GHX>$IYUU*|%XN}D&yd|!y z+Ovg|;;vF#T)5HnRC^WHOKn@>?Qy-;4i!$1>#KGYeHoy35_YZH*}@rdH>mwmSm+$A zW|~Zj8>*JnA@;1s zen2c@e=ZQjh0-JS)tZ!$>o`^tF>FwJ9D#IW`6%D>$=37xm9C5mt3E@%{47Yj$7*p zf5SB+#-50=O)<7J#`ee9Coxv1uEERtWbqrW0hT2!S=HHWcMY;_^{NiANw#fWRb+O! zUarr235QoT_w8`4w(a9ptzhrjb_TJXt`oNXiP%n;vw>C5ySkmP(&e?S#_CS6fMxi6 z>j2*_R}0!Fj!CO;@V)6Ork!-GSl!L+cD1!_&FW#kJ+Ah)ZCpLZcfi%rwq2_y_}+5e zVB0?Y=JwmJL9|aCM^=~n-gb?(V<~H<`QCHgZd>g&_xs*=-D_LDHDi1qy6(5F$(jki zW3D+gYpZF1iYf-q`cTR0naEtFZwVT)M@%^PXdCgls6Bq91y=x}LxzrwCbJXWndw$L5zC^WG z*L>$oR;yT3=&Yu;0liLBn^W)`{`ypS4zI3p_~lRASnEaVRj1*a^DM<3y zjGNy;%3ABQR@_T5_G*ktIccRvh0kA$t;m{hSb;oCt)QZ|zm8f_MI(QGwH6gk{f%hS z%B2-8{CR4tZ=<08xHnGBM@JD9sSb2;|&#YLuXBV)fSV2W% zT#;H)MR$L5ZDo4JG+zsiJ&Gl2srFPwUw-+No`tGO~HHp{nUyOyIQU5+DH7?sr6Yq*MB1o z>pJE7wE=UB+NiaiqwLlgyF11nU5j^HwBGY;@flCGm1{dh**4T0t+B(HU&KC*v9oKt zMaBMHi+5?XUc$O)OJ7$M6{{O#O=3!39AoWctaFU@im@AFY-Eg0jIq07?BR9zM633? z-}-E{@R<)l|Z<5;Is5e>7^Ey5Wt5)@Od=geI>-7RNMJ@OBB2%u`9QAHj>wMJTY}g$wXKLvS9>3^d(_S#cCT9827E47t>y-NE>^7wu?N&H zL+nAdL5R&z3nBK9+Ub}M3Y)Sf_WuG%uho>qHfBXUKxBO8$`s(ro@?~kdS z+lcqa)I6IC%=2pLn~KbQwVX}G<^{FFP1)u}wPM5;sC7eZq1ph%7O4$GY_VDiVoTKS zMC>KCM-f}9_B>+C)K(()vf5_EmaFZ%m%e7h;3B6AN4k= z%|dLm+Cs#(sI5k9tJ)64wyC|1*c)n}BDP)aEMhy<&Lg%{t;&{SQ>m7-CEM&$D?;o| zwa$p`R=WnVJ!&Du_Nq-oY@ga}#P+K#-BMr^-#`w-(^9V1#px(yc}21GT#l`%vu(#6D76gxFEF z*AY9Wb^x*CYM&u?LhVzL9NyQyYNT?`ne(`$O$! zwDPCgc$EB0?RJ#>TkSr~{k+-}s2BdqU#0tb#2oJM-m?lZr&=XqF17a&i&Og=F}K<| z#5`(ddp8rWmb`tVNl?o|EK#i?VqUc(#FEt7BbKbz9kCR(>k+G>HfsAKKmH`8oo!Ft zzRX`uZ7O1^Y7ZiorZx+)bhQ@{%TQZ^Sf<(r#C&RRZZ9x?wZq$sOqSYF#PEkP?Y?}D zSPiw)h}Bg48L?Vw^4Z?nYVz6M95wlDZ+$iS24$|Ae1o!)n%VJ+KcJSeBVh37IqkkQ z+=1`-sa>!G-|}Q0ub;-|q=-Lqqj z|3bBgci`K3YEQ#1R$GMmwN`rtZ5FG^Ue`uV_PVxe>vnAPw+mZ}d;+CCE&K@-%jB-E zYlAoZ9l|Bu+c3XN)ZW7UI;r()@TQ-CofYe_(k*MLv&KHzvC(u<>)POezpL6eJMfu3 zwO@94&E;zHeM7aBzc4>F=H*vtNy*EvRFk~CyPD+XSE)%}-a}3D@}6pvm-kYWyu7!X z3HOb5I=Uwf6N%HamYLb^hLUm*1`?dHEe`l9x|alf3*+ zHOb5GQj@&=ZZ*lvr>RL^K3z@n@_W=IFTYn!^78xCBrm^TP4e;w)Fdx|P)+jk8ETT3 zKcpsk`NL|Gmp`H=dHJJil9$g^lf3*fHOb2#SChQ_2{p;fpH!2)e3qKz<+If!FMmo+ z^71)ql9$g_lf3+CHOb4LQIov?`Ace&moHV5ynLCOgQo zzEMr`@=a=zmv2^+ynKtADo^RshmwRgVbk62(Q?v^xm@lM<=sa=6s#QG!lYdGc}vhyQ< z#76JzX8zFFZK(IB+SHx>&0lKw?Of^jJ8UVB?8I+$cW{?!M$Drn<13@BYP7j)R2D>) ztY3-m)oHyZmH1wrT5H52))_JUSy{U;JrRr8b%=R2HXN~t-G&%`PRp+M5MmLVi&(P8 zh=lkW|tXlya+MQj!7RngcM#3Hs2v8o#T0I`UjM68;|UaPS%%6_ceA7y4&R7rQr zuG9Y1a6NbJT|fFW!j_VYl76)dqRqW99e>kVW5v5VN6g)2S5(Y>#jcM2NXg!41wYAU ztuyzCT_5=)HepvcQ!5-xxqBCWQ$}qr>eUIG`_)}59TAhyA+=F3r|MX@HM?u(9%KU12B=BibG4de zI@hR4UU#jUWOCQ3N$z&Nnq+G?sL3^apqgCm2dPQEG+0eCq#YrsmcA(a5cFbyje~1r4ee9A&pd%4B{3wxx*Z#CihOG)#NT~jGElXh1BFOd90e; zSB+DXJE;;ixpyj6le?wyYLfF!P?KzJqMGDqx2j1-Hc74Do@_H&Z7}RMwK1?VwJESE zYLX$9t4U6DyP9M{cc@8jGga-rJ$R2#Z8q#KwU=Obt6k6lzjmW0+01mc3Y5H0Z6|tm zzuE!V1GK3)o4&s%KkGrYZ}wc2^@y6;+u8YqTJ^mhvu3F^+q=~~r8cCXnRBjMo4p&& zGirnL4mh4w>xkI%Y9AzBmNj3k=iXjf3)F`0y(Vjs+JwD>vzDkmuy;h(Qnjb{PRe>k zZSmfFvsSCE-1|sYh1#~gv$NK#y}kGOtc^6eu6(-JYqqF;wYNCRdgOI8TQ%0T!IG?P zY8_E>yPEta*A6xLO|D8c`Ax1j)#Nw1_Nd8ka_v)--{d-=CcnvbNKJl|>ut4f_Xf$qokR4XSuZ^hVA+DV6e&f|pV=cw4H9@9|fCw+M@>r>ASmYIjKM4x%a*fwn69p-aS znPmwj`*2s_xzCQ>xo)ij&x#zxT=AOT1%wWb0 zW@5}>3K=0P6NOD1i%g5KQIx`B8;h7?qZEovi!xD^5p8@LOENoSBl0I?L@`kjLTURw z-`9O++_u`^{`q}=kKgb6*m*o&uh;wizW$u+T<4tYocq4!T=z$|CvOX!)IH(U`*0|s z#@lL?Rvu0G!cN<2?5RAN@Kvq%N#%uvvz|k`7TI^^UOcCQo^_V}JMTGHn-+$5*-new zo`L6TtozK$*gnHJf7RB%sog?prIC2C*4tC*P5idjldb>F6W+L{=b2yeBnLg+yTN4> zYxbzdlRb({beK}g$s2=vD(fY>YCWmbvOU?OLkZs6w9?AVL|?79r?N$2c&#VpqRjN# zw%nK)ZRXl->9>8min*%J8c*7CYhqk&Eqf||kyxkJlRA^kyxKayRLNJ>Qm-~=Y31FC z4QjnTmG>s5)_PJ)BePp=EzDb(W9^p7F=}EyYJ2myi#Of&UfQ087wn~APh`~ADcifI z)|2futMz1iIaifyQJYp;`CwwJT5nI~#KdcBJt^1LoL$?_KO|mnF1FjUWBc61cIL~r zw{JU7faWUOJG#9SUT8b>YU?bmd?E3MT5nI~ONkw8J=tCtbA3piH<@K2b>3u_2R(iL z-E8i@%DcCTY;lTewc|kI&E^BPchinAb&EMsdy`e)9Y+#xF^lcA5j&12b~Sg~-fzj7 zZ>DAhYniUSj@sLzo+W3#xg%53wx}0&e3^KwS!H{#;dL{=vb{3A?q=LI!JIqrZZog9 zz0*6+CEjih*4|ciamTlbJ>f2 zb$gj_+TQJWcbL1iw?z%y*-71LPGylBMm{x^a=$cB+1?}C`xY-nJ!Z|^8D006W=!*- zw*c=hvzhI^y|aGZKITofw-c|gdAIF-zVn*8zcR<#-UYmV=4{)G{ouN~{ml~FYlJtz z{Il(K{@}*Ccbf-nuNU4x^PKIC{^0hy1!j15uq{*Z?lBwNUdac)s{3oRgY9j=8)Wve zy^lY*x9(tbwC#O~H^hA0_Ui2#UH4vdiS6a!4K+95Nx$5@Ylbn*JY{=#?#fcb&4ip_ z+Q?luCjQ3kVta+VSiiuWVtcd6d7rshdsEb6(ngqn(%u%Mbl2FrBg~!Jd)Ih(*YE0% zG*8&xo?X-G-fsq%`JAGT?fOzZV7}Tywl`T_rj}9WG3`C3{JX_tc{cvUn^||1xm0_c z6QqqctyVhCx@LCNVy5-y|x##rxV@-w%2^m&1#}K*7mxRHqk7!yp zX0h#U+S?Xyz3uHIZK~;SZSOm2Q_XbS^X%&oKh4Z*6HH6k*99;4`k;5izSrwMW{$DF zJNLbb_mS<5*mtvcN=C^o{n+ffMo@0MY^@Q2g_G0&k;r-I~()M@48&d0Ss5{df zRqOq^?jOvzZ7*~G&1#NWp}nnEbM2kc-el`~?FDX-?M+d28<*FeV=mO*WYu;5&brT- z%{oZhWOdj66~?n>5A8jshS8RJW`8?vy!OUvZ;E=HI_H@u?6lYR@2fk{?ATFi3EuJM zo30zhlV^=EwZQaW<;B)|S)|pg^&*mVt! zJFjn=4Q)@}d41E&v^{y}^-Z&x?a4c@Z<^V*C-1zjGq1HhdFS;l^Jd$V zcV7Qw_OU(vMzJ~2_T-J?x6ONPPu?irV2-jqd82rv>B_ zqj-y%XnXQT@w;YHQ8>yd~0xf`b}i> z72A_HPu@3QwLN+BWVgB6_T!E*Ah$!>Fr?a8|)ADXY&p1fFXXWCvTS=Fym}b-Yz+0=GvaTmGZGU*!JXIlOtx2+k)lfU6W&GU)z&+2R<_kY){@D z_`)1&d$OYGS@SoxCo7tsGe_E}mniFhKRy6(2oMd~lqUmMxQQMOhO}{rM+n%gw`Zx1Q+mjVde=wi2Jz3FI zS#xbqRx~xNdA27jnmVinwkIo^I<1AaCo7t|ti`q`E1J5kKiZzGXzH<+*`BOuYFf)} zPgXRwtXFJLRy6fmD{W6!G!3&}vpreS)Mu@>Jz3GzZ@poAvZ86YRcd>(qG^QnrtQg! zrjgcq+mjVd1J<8xPgXRIvNqbDtY{i-mD!%GXc}Yv+4f{b(^zYZ?a7L!an@GblNC+l zt!=g^E1K4^Dr`?yG)=JnYJ2k5O`^5K_T=52MC$|Flecw}tlhRJZ|fvmdu&hM>q)lu z*`B=jQr{YOd+>~u_g+%1FKtiWdr7m-*q*%i(#Sezd-C2(6YGNQ$-B9k*0;7N@8(`( zeXqUXJ*TN<^^h$*t8PDZLsC;~w(WhpuX9o}YhkU|EvdQX>KV-W1!*m;$Xc&=QY$N^ z*1J2YwY9ldFsEbxZ<6w?%35!9QhRIg9W`mcP3mBMqP?e8|3g!gI$2h4Nt>gF9(p|K zMr*$9jXCsWQfEt+6`gU2k5=;cAFz?aug+Xm&yOQNSAS^Ef7SkRo&RbLKbQZ$MK)r%FmVhx%|QSmDJLY zrG|}~#de6z5!qV9q*iKskDW)6T5}cK^$>}&k3}#NMWn;F(44ZBbJXKd?!z(;#KJnl z7Gn=zX%BgV5o)MCpF>Cf(D=V+2W$ILS!r`pNK2X=4sE|m3Ek_Tv2~rYU(MM&hsxFa z7__q+2lw$R*7@y7(Ee9Bv}bCsi?({ZH6zTGzO5OHq=mO$l}92q`TxIQUuknqt3vxt zTG(6n@BrAUR@b|dzjw$Hlsy00eht$#472MDZ9}LnTN$a_GfL;Lv9GkMW-tEL_JnTb z|Gu_IuG-%#`GaR*VMx!+)~#(G61m!zv-jDn_F7sV9PM8SDfP;a^8D1EhVF&b)9k9T z;z~PzzO0mbUAOs9HCt4n*P!B0^2n2nL;cy#6C8!2)Rl;gY|}!{mYSA?w(1|*p)LGp z%5DqktD5|FZ~SEYch=-5b?;#rEf4-v5ovR9wE0Az1E1@@`m&}hsXvai*H0#Y_f*Dq zzt!7yRw?e_kyZB53C8K$x^~2oVyLv5RO}{Ia+hyaCD&tJ*rhuBC^f$(qWGP~5c>}D zJ5+yN_C7l<^^Xg&C)C)=P?K$2VehraRmuN&O&t5FT3hiasSE6g*e}(l8tRQI($(7` zk+KlG9NVFGheQrlImmyM{dKBSRZitn-@tD5-M^4W+Tc7Q_mrq3(r@+uMY{?4Wxu2c zTGrUq*6xVx%L{KP+I9aBDqFnUw&iTO_lWfQNZ6@<8xog@gNVfMrEPrv()`pB zxptQ7)K`eezDqspb^G5V&gToAdP0}|Mn~MANL(U3|LaIB5r@ivovOV~{c+?wYIdmZ zA$fX!BG_mTj4~9gKvs9G&Q+(((yxo$KzXw4w1)IU8Gr)X*Ws z?*6m2No(s~l`32ROQmz@c_)H8M-$-jt* zL%kFddDXUmt_NhhYijaim;IDY&41O~J@~&;oAlE0qfX^eXG6Ar{HPp3S&-MMyvKq) z6U=Gbw5o1R96KY#&N(JMe4QQnxqT1q?V$a?cl4#^>vgMSB&j(MZ?ao>CDJ2gF9zDS zlpR`QD?^Q{$%Fk!NW8|DUV7x1^xp4ae%}{%skwH}(DO>{#diEk8&-tmeDi1Qw~xu0 zw)L1|TRZfA?T7is``O;4Ee{UWa~L0E&uwb zY+8OBocbn4+x15(e;eh zZCIiEZ3PQ^GX8|*Dg0FSUCwI$BZ-_Y)rqCW-Rddgp4t&cuH{8`so=g`>7~UXwY~JI z9J@6kkqy-2P~}%eqz$2w9V{^FP&H4d(!;0L2I~*quEg80WU52$uc?hzef+5${m*m_ zXKY)p_ZnMLFX>dzXJW^~4wVW!Rpw_`j!R3O`WZdoP{-FwZ_p}wXbK?L1QF;;U^+)qaBhIh#_opXGlp z&%Y6W=`-oE6`#qq@Dl7$t849Gq=wh&)OT0{mi}R{xk9lWYM-``gmCaoJE0?Azz%g$ zm%5*`*HC}^tcD%RJTAQ*eq3sMN#|^U?Ns~UkY25VYvO5F#jmusNo`p^t!VpN%|F+l zqf6zy%F}sn)XZ2!3;k2X_X`yX9uGZCkH4|b^!?Nk}Zj@q`7B01$;ZFf+5?*ukawy?YQIp40c z_Kpxb^88Dq7TZlbE@#DM>UZk1TJAEkkB$@42H%M**HOd?83F3r5xHubgrv6A`EMW( zPrM=VU+7Z542j%*Le8r}C!FLQepNhlzoh<}XA*^7Q%dT;x|Fo`C7uMhf7!L!Z6@-l zZdG5deW&6nh@<~x$QC8;&~c}l_Y?6e^)PzS<`=0=Mk*=ASc=`3rTl(syR~;fQs30~ zixT$QP;0MlAvJ6~QFDcIR)n{QL{xa`YyI{%ITS%ms4-;nLzrnh@nwe*yChvo|<#%pNU`D)>b{1*3897{eRVw1F+McNes>>2DxS{Ki3kw zW@V^Pso~1#7uu>&Tk_O=`+B8SKed(6+Wu?*x3B(t4*c`yz(1e!Kke0jV@%UyMX-em zyXF&4+MH5++SPj(TI%1m z?Vi-Fm92z*epTPr#((ltd}u0VYmSB8OQET?_7Fa?>i<_^-&=hypIfhm-7-rO%%fTM z^wa9l$baqs_j|xd`TPH%_;DK~PiuWncG2f^Z~OeY67Q?ylIl{SslUD|XRv1ZEcswf z9J`Bc2UDfaNz~&|Q?80jsTrTkr?V&RxI~__Z8?`}wkz>sJ1(DaU;A8YD}|kE12wq# z+#1}Lq*CY4q&iXzRc_ZK^_Nx2cL+OcBBX9SA!S#5cBSPT^(WjTY{gI?B?#9%$pmfT z(Ektl&;BFs%65Np9+qv@)E~@wC4X>+_v-H@q-{iCzPnJecXAc8ck~;d?un#T2~#J0 zhAY}o7c~Ep{Ca+eocA+-L=8G8vpLv5kcWAylVXR%4*AaZDw{cC;x3)jPzgHcsY=Nc z9Bo2tXb@7v75k@ZXsqk`_safzrA8k9_xJbF?f-t+zx_;K{qwyYy1z13*BqlO_D}V2 zuI}LOsp?w(b9 zUj1*xd+ROUrFn?v;FP9#iVTM}A_k{4r+TN+ZIlsaV^@)zB9+cyrw(QEW3!Vx8cx)N3N1jQrQ_Y0+ z>@f8#((&Lp#*8o#<{9Biy>(NMQOtU?M-v#SWY$~CGS|jaN-LfJgl-ix-IS6!ahc7O zwlSND%{(T|JTlA-axMQAoBy}bk>lEChL_Z!tth4EcI}9s&&6iuj#Ag@I)Cz;cJlBY zdoA;wId(8-JNiw&X_xkY1M6?vN#(orT9z@~p+|3-^^<*Z=&_w|$g%luoYcDdJ6^sO zCn7yB->XZ_%oY)8sq^1J9{mkD5xyHI58sVrORvherjq|ISiUutmdu9bTT>PM*0eUK z#O3=^$+;Ak?@J|T@cYu>b@6{Tzo`53ygtX6Go@$RFow%F^J1%0V*B}_LZ@ngP5cwMg?U%}>D&HSd&DSt?w4RRo9zT~(awkB(N|jfd1Y^*FC(KdyBmnqfSyrlMoO z3@{UPA=U@<2K_-Hv1VYU%2W%o?vBq?*4jz&QN}dyyrfh(Ol4|rp}8%br8;TO*W62U zU(NSu92yVAk?M+Fr0&ps&*>F)=BNixe~>Audnh{&dye`YT%@L+Zb^^Ng6F7b zPanxi&YWx6R`1bd z$Av91bvkLgNY{|B?KzGI&Wvugz%k>@*jD-KnKP{Apq89Dkl0pT*fNR8sxx2mvf#!u z*-87=wln-XsM?|J1DZcOGo3uL%0n;p1!a4w@6J5as*}U|T5<-y&Q2;}Teqqbhx}Si zi9>#+CSS=aKCe46zrGn;-q!8pc=q&jlxp*JF}2CM5c#Uh*QKpCDfu0+d?jl`tyY^HDW~5df6>?PwtCC4=<5n>St%l4uMm;1R*-)(H6LuXU-!l)_V+k> z%D?95tG!>}s;Y?`O4y{1eLcEvzWUYcQqI3P($CG;LzU@Rk&$YUw-Z{HI_mV2t{GsL}nm>nAozuMM zb6da@uk8ePQo>nE>YUYXCv`s6u9tl*IUh-3G;)^VB63+HyVJL2%3KS;dcdCA}Q{8!k&I)A>M9Mc=?J1V}ZWLtZ`*_CH0 zKfjl3seqae$Euld0>5Z%sbuvmoT5|Hb!vuAZKhLmbZRcY!eFU3{EC95^0-x6sw2N* zV5u(r3W24%sz|uIiiLZ!iod0LtNL&sl?L}$8E^qB<6CO5Y6%Zht>F=@Pj9JFsuMhh z_2Df>*>3PeR%EvrMel^CvLd?0NIMXo$%^Ebn$3#hmYU0o;Fg-tir$u5$co&SDrQA( zOD$zZY)dU?MQe-kcP6}=6{Rgz%8JmITF;8kmSW8>xQrE*E#6~)1>VMr#+IsNMPf_s zU`1g|?Pf(_OYLJtUrQZiMP5r)v7)ZUqtgfQ30AbVxIG?(PqU(|rOvS;tfelhlkjDA z8dk=6*kybRTgDHt-*9>8f5QvM8WC`U5d$Y132=&04^B54!Wl*rxS7!m&M{iRxyE&H z8>1bZr@5oi5xa|V6WrCf74B~IfO{If;oe4HxQ}r++}{`k7Z}6f!Ny2_?Qt6pD?1~Q$`*5w2=&-Gg9G;Mq~K0(G*sW9N6W!7PcJM!+u8xIN<04$2#)i z1jp@gvf~ao#nA^&cMO0t9KVK}IflYHjuCLKgOycO8^vw7@hUvb@diA?u?`;P*Z_}lY=Xx*w!#w~6>y?NAOI?VR*LV7(CZe4bOLc2`_Y0 z^^SOWgChwpbELpq9F5>@yj4s8JF?*&j$C-Rqbajt}Oov*`foNvN;&bQ%?&N8@*^If>B^Dl6B=lgI^=We*Sb3fe2 z`7zwzc@!>io`45Czkr81zlKLRFTkUmm*Fu^!%P1=J@7=Q4=!{D;Hl0yc!sksJk!|# zp6yJB=Q=at`OfC>LT4+u*x3eN>TC}$cisrEblw85c6NtLoxR}o&R@bCoc-W3X92v$ zIRxJ3{0&^`d;s3z90Tumj)(U-e+M6QPJyeOGvH&+S?~$xQ}8M0JovP8A$-pHB7D*L z5`5XY0#>fou*nev6Tz`d=UAy2E*FHGibqLOIeF8Ug9fxyV zr{G-I8Muw>8#vGP9o*5yYwxOy%MEvRg~8ojk#J8}EZp0b2={T-hx@zI-~v|$JlK^5 z4|BDIN4Q$Uqg;9L7*{8Foa<(IqN^KR=;{eib=?WiaQzCN=^6;nb`6H-x`xB^UH8Ka zT@S&-X?V*K~NbYbIRkngg$QJqvGeJr9?;is3D;W$-rFD{!T26}-b$ z3h#Ek1@CkH4}8$I8Lo0|gO9nk!zWxHz^7b$;nS{z@Hy8J_@e7G__FIHtlXzzm-{?y zxxa<|?jPWQ+vTJG-Cj7s9RVl1W8f5b0-Wxy2WPk&!p+=G;2d`|IM>|*ZsWcV&U3ee zJGwii#pl-u)iD!CeWLxp%@_+ zR*H7RDV{Jm-4h9CcsMew)0_zBcm)$dRoHWJ+0xM zo;rxV=Ab2HrE(+w{0^n?d{W>a>Urw2U3GYlT(83~W^+)3&<&sgk7^Lx11GaX*)nF%lVJV-q&J#(;Ed!B_$Jqh$Ei=F^{*%JpVvo7p18^D&C4*ShaIAAu1W6f4@g4qU6HrvA~=8bT=c?+Cjc88mp zz2F@4mvAo3Id4jP@=R%4M{Rd8rEOhJIVZcD{m9ePEP#7!yN@{pyTADxxWIe>9&C<* zhneHy5$5mUQRWnQj5z}yXU>8rnoq%nx`wIdJnR|fLU^Y6B0SrC37%`Nfaja5;f3Z} zxY+y?ywrRLUT$uISDNMUYV)sfsksYYZ|;LPn1|pp^AmWBc^uwmo`NgQGw=@c8+f<* z9lXzEkq~vzbi-9<7<|l(gin~U@F_D9K5f>A&zWiPMKc4wY-YjAY6-in*05#e!G5a~ z9I$SNW36s*g4GjFw(f*etY5+D)<8JJ8VonHhQm45{cx`J5ZuNZ2j^Ln;EvYs;V#y6 zxT`f2?rzP2ds@%Jy{+frK2|Z@-&zJ2Sg*i?tySu&g*H3+_F4TCRRBVpxz5O#UT!j^X;?DtNF1K!8rSj`FEC$N*fv*8r)GjO{1 zIXJ_+7;ffW3g>uB;9T!(a2xL$IM2Ht?&#eJck%ui?&^IH?(VIGdwO@my}f(jKHdXx ze{U6B;QbUH?EM@b=8fa*8sYs4dzAMaJjQzo9_RfVJkjfnr2oAZJk=Wx&+taWGre`- z+1_M$t~V8)?`;e(^frZyy*cnw@3ru9@AdFXZwGj_w+meA&4<@}Z-+N{?|{p^ec&zL z0q{2Oui;AXPf0&&4fv_jBW5eXSNC=yYog5}tM@rZN?DR0*|6wm+ zHw%-akQ259J2y=FxlPz|?7T3!(mRH|irpnl#)qz9Z(w&1)8kLrI_%zIGD`Fb+ko9a zOvZ|Wuua&5!{lfV3)_l4B1}e=QDGI>W5Q%?85gz#dt%s!aADX-@YFE55@&=R#-14_ z=fLc+W7u=U1nB=TImfnznb?(Ka$fBS^JDK0lW}ZcSQPfbFgd%b!s4-yg~`ZvA}k5}RG5r! zr^8aP&xJLDFNVojcRB1DY~_;?&*jU;wtO<~`F*+A0iTS1vA(w02|hVjlYKW}r}*TI zP4{)i&hW|D*v!`zJI5y@WUlWv>^43*lk$@tmZ zcMoqOsgu?u}N#!mG; ziao<8BkfGzRP5P48E@zMim>PVWYk^g`vZ2dPp+?}zNfL5`(zwm>6?$e+9#uNsc#YX zdY_ER8+?DnF7wHixW)G}_BNkfkCnca*gJf3Rqpn^j=j$(*XBXro7h!8xk8Wm-o`%R zD}zt@W?z`{laM@SnhL=9jBG$NvR(u3xV4HvX@%^Zat9cl2Mt?&6p0y{rE+c6YyA z^*#MY6#eg)Yrl`*gWcaRBS3-QhdtOYtavz%g9jZ zZ-713FXO`ue>(O|zl;*I{h8Qv{W4a}_czC0=x+rV``f@v{W5MW_qWGh>Aw+P?Y{*s z^>>HY`+LC~{J(_D{Qcl9I{!AEztS&P_YS{|54-&`GVJrqcyiD$BT1EC#*kxv8Iex- zWsExImyzeRU&f_#ei@N2`U|M@vTl_MmsYvL<*Kp5hhY1|e**`?AAn=S$G{2U(&psw z@o-A`@8I~vK|0_H*d>1@Bd>=eF{17}pT&~uI;h$g^haZQRhRbNPJY25OmEm%2t`3*0 zvNT+-$MxZIC2k0pYp^U_uBT&}?#;c{i|4wq|iU-&8NJQyzHKvnn| z>|^2Iz$e1LgHMIC_?bE#?uO5W%hTP(@G$Jl;W8Sl2pOMU5i){V5s}3G5wUO}A`y;_ zs1GMZq`}D%8E{HO7Mvc@63&Qd4L6IB5jZD8uIStdxt7~R$W@#dkws4r$)%NKOiP(|qiu+gF~2NA?nGN6jEsP%M#|_nBQgeiW@G|9JF*@;H?ko-Ke7qDFtQn394TYw z(#RIr%OhosT^V^D_Ug!XaA{;mczxte@P!vhr5uZtXPXm|@>FvwQl4i{N6Hh?xk&x|6Ddzbmm}qQNd;si zbOq%3!3xNehCd+B7=eI1nZyRkLVeYyGHMT++X?xWW??tkg>WTAfx@@ zfQ<9Q0y3(P2*`bBRGJvA^0o)H)Z&kT%&X9pgH=LW{Y z^8*v%g@MU%ao{m{Y2XQXd0;lYGVlz%I`AA^8dwak4=jZ@1WMqtz-#c9fLur00&)da z2ISj}9RazfcI)^)Z6DOBRho|l3bK#tV8z#8~sU_E>}un|^Ke}-LA z@4;47CG3xq8IVAfd}57_lG&DoD4A_Zj*|J5lqi`oNsp2llZ+^tF=-YhGb1@sGBc7J zB{L&!qGUECFG@zXj!`nob%~NEx~@_34AwnLp6Gf;$z7~>lspagiIUN;f0T^L1yMU` z!{Der@UW-@@QA1?cvRG<@R+F2;c-!4!4sp-!G%#W3o|w9684O!zri!3oU!zOlm*X? z3Ww)MMZ*iD>cGWO$?(#sRCsw*V|Znh%n+@Pk{P1XD482tA0_id8={($S{5ar#J5Dr zC-H5XD|KW?lsrZ6j>;j=zNl;AgHhMRRZ$(_V^Lk;6H)o_si@oG(@}T8=c4++7o!Hi zm!p0StLUMyD|!TMMURI4(Qk*yu-yBt%bulcQyeDbaFuq({rukr6H5sx^z2 zS&y7(`Bp7ATE10l6J1FDyy$6g$LPo5F40fIU8Cp1-J=)4J)>o$?Hw&+W}j#oGy6x& zI9w1dh!y((Is)sIEXQ~HT$xeJ_%mb<`dy%*=AWdyhwEl;GE zqvctYrAT2{jDG%%kta`ojEo6^7`f_WW8_#QXikpNpMPUyTj?=!J!ZtnHP|dhuF4#p zCs(Jo(eXST@2KNlbiAvsp?i$<^Lbg98H@(t3k7`X;V#K<)` zDn_osF)?xtj*EGLoD*Y~z=bh#-cF5?*~S?$%Zbd4k@IZF-V`N5hL(Ep}vX}~ZOUw>Akq9+jd#EO~uM=sVi1y9{sV> zlYv;-_t;q3_XHhD){&Ihp>gzl>!F>4W2JwF#mZich?TQzRBT;%Ol$*qTx>c#F*Xw}jFtVG z8rue*5!)V~8G9ot0{SQ)F2#mcweC-i=uip?N$ zI#y<`&&A5j^~G2jpD)MC_^je&e0Igjm}$ky%(XvG#_B+vd}kgTC*Q^=#L2hr$#L?n zdrF+lXs5@?x9%Bna-^EY$(fcDC-d65aWb#nCQjzH^WtP)yJMWpYj=s0dF`%oau#)u zlX>l)aWb#nJ5IjC?-M7p+x_EYcDo=>X152&6~n{gmcb+9WOjR0oc@MCPG+~q#mP6l z6XRrdyD&~>x2MK!gJ;Ca?Dot!ncbcpC$rmg<79Swew@s1FN~Af?cz9@-Ci0ev)jw# z*T=~`!iG4R<1UMnIg2fEGH0jN1V)e?~arC z?tO7G-+eGn=DVxnWWM`YoXmHhh?Dv5Q*koieL7BNy3fVQO!vh&nd!b9Co|nDUS_&o z@iNnG#mh{$KVD|K1M$P)*m#-gPKcM8?&Nrx=}w84neOy>nd#1mmznNn@iNn$6TgHr zDmQ*P+$R22I4}MUxMTb}xJxNH0-xO@CoxMzF?+&g{;+$a7+xPSada6$ZGcyRnN zcvyTjJStwU!7=f24UUVKYj9$`oTY_2b%suzsZ(d`)VVr!zD_OHsY`Y0a-F(Tr>>5d ztFKh&*`V{3={#F>o^3i$rOvY>Uao@O@p2XHixk{DBcq&ENA|^EN4|9r)RCE>*gEp;lu$>;?c_Q#6O>ZNPpR}eQLrmf z@>_|r@BT#D_dufTdu*b#KOylOms_PIx{}-~J<$VaBwBE@#4tD~(Vvv5lsc($>NiK9 zSBLXNJF9h>qDxdvwrDroU!hiNe~tP|=j&(3pRn}~Tie+>$kzL8onY$}v@`W?R%4Sz zE7T;dyVPsR`S>SQ+xmm-^x@jSvHleFs5+A@x=S6=D&@tmQ0tP5biQu&m!J|Ctx(Q- zB|6@_{$}lG)f1KSqLQy%rw^!q)b>Ry)Lr#NC115pzqh`Vf7F!ii%L1s3N^W&sO0ma zC)ES>(`;W<@`+Zc*K}OUXXR*GdFgE9QMkOvRK2fPhv_kc5 zSdN}l%jzGs(?un}sN@r^P>(mPMo+4U22K{Ws!;DY6qS6UQm?4w_o63Nod#)Wh1#Aj zDsfTCpQ+PR8g#bfq7oOCdPFPKh4g&%q{?hC$W9lPdPFN!t470hddmh=>~v8{7p+hO z8j0$DK~Jip221R8(F*l>BT+dYOLY2E4K~~9q7^E(v8be%>-6Uv9M$m~8jDI?RJK>G z)0Z}II;GsO#-frgD(PPIqDwAivC~B>)Mt%FC0~(FuS{KHr;AElv_b`%l<4#iQ#Wh>`X-{X9Z|_wuG9VXkJ@q3 z3N^TisH9ix^p8`WE_?q_iHl#M{?NpWo>a$E)9iH73bnq8sN~Dk>8DdW>-Z;4L}mM; zlAf>AFQpE$eNo*HXod1;4A<$7hEwdgsFV|}P}gM?>2zPiC3aj?%8OR0f{YTK9^0@? z>$l09b^P&+a_#qQcvSnP8KP27RO+v`)17Xq=i>}fiHk};FM3jyHcYeQq7oOaP*!H9 zPT$zDvz;zlp;~5&O1^xZzO~^X9q*qhD)oy>`f#0oYg&=kJJL$D_D?I#J$< zTYx9kn`xO^-$~2Yx-D(E)}3iZT0crF(RwtkTn@L;GgBtne@C`PvVp53>E?+D}ZMqJ7SH?Key>(b_b9vmGzjer|fT*7oUMuWaY$ z^fdISG2M}={T}I^QE8WGh5F$dQGGmgdY|+`cDiVV%4{mCkB3gbCw+>YE-G=+3Ux=* zBAx!5^d&ldU1o{)A4=bB`{ml7n10mutF=EZ-5C~ak0|%crlL|W|9VUN|B#+$r;Apo zmz#=8dZtdFm)=>&cQzH3xTx%3zD_SrA7uNY73#aDqLOd8PA^HHV*8>}PP9TbYF4Dv zx$oNPqLMCJp?Wkc(dpcOwLiX@sHBTZ{pC8H`>*YbO1fx;TGFgqr@xWz^htj1Cn)!g zW}opn0*6IAkxR;XvQ@^yO8hJ&oPMV<@xMnWEFyX&rh^iPl%IDMwGLtqrTSZfxic z1lyCT^+=<9trwaN*E+jVkye$p1ob(_CYNa6n^mqgI;&c1QkFML>RHezQ)_xwzSciB z8m=`ft4QngMkQLW%PQB}A*)(z*DPXmCf(x^&nX}xMYUByU!8|!(sj%|>lb!)v$t%VIbqG#3NdZH)Q`}Oj*Zfj7W^+dhl zTGwV5YCTi0NbCP(muUS}R=L*qva7Z3$o9rcJ^QmWwSJPFuk~d1aINREi?n{9U82>K zQ?4~Kr&?=5jyF!qr{-j8y(TAL>-}lNwYJJB(wdi3qV=Yna;>-LRBOE}#~Ux@3vyDl zep@e7>+qb8TAlUtwLX|LT?(DcAaJPL)=F{c5crwg<9k47irCGQLMFo{SvJ$Ta;;SQomelyB1Yi_tme~+NA|A8&Lm|`d+QK zwaC=^REvDA&$k$^b!)>yt)JJg(t5VON|bV!>!)aSH^@X+7@k)7T3fX$N98)G(&}%vE;B{P$2Q2cebE(0#&sQays$yO zj&ncK@kg#3uJv`TQocy12X%!}r*(<#i>@$!+qzu)Jf~{EtaY{Ri?SbWyh)<%v<`Cd z+>I~$lZoEva<>&-VU)GWMRNZ`L2N%6+cD$u9QsM@2LIolziJS(0+W%aCC(cdA+D?zfi{;q!gi2PqFqh zQc7%JbcONQ^<_HVBBfmWYp)lT{8c)BeM+^CAH7~wx38YGuXBnQU17wx6V>h1@$M;^ zwlBKExV>FR9ltZBKOc;{}U-GTIZ&8)Ve68K zg<4mo6l-0dQl@oNN|n~Xq^Jf`epgD0)`KY>wSJmXp!Lg?Lai54inXfLGOga!Dy`9} zDn-gCrKV_2Pwl8RE44uDb*Y6~JERtC?V74mCI5uf0sa0B+ zr>cgM|Mk=qt$#}GsC9E{L7K#GX;`TBNOBo^miv#W#H;LhVY>L28WwAHq?Kv)r4?jK zJT|RRYrV9xrs6kFtJ0dC*0GuRZPLoLc1kPG6F;?)Y9HK=sBEXB)+5OUTCZtT*iqus z8x?Dv-6*A#_zM~pX#HcOLai$r6>BYRRHk)fBXy(X+uATCsEs;meZNt0XNgCrRy`5i zuBdF6*NM<0$yHjnHdM33-`Frk>%KK|0w!d^J1-EH80b8v3ZqNBbzUyNDs>{ z)EbjruvGly>?*B|vWs69zj=0<*4Ei6%f;`QU7$5TyHM*dvdgsg%dXNoIJ;wsTFY~)R!Y3Eg?d%As6~O+Bgusu z#Q(l!Rk`SqqIqGJzNPKsbm5Q6L7yfjS@&B&p)0dY}PzDw+lwVK+fD(WW2^ zWUD_WwE(TawV*X<3)+G9pabXxI#cc@^525ygKpq9&;#@WcYr&Um2?;Ai`@?l00Y52 zU=SDrhJxYXJ}?qI07k2&Ne_XCsedf~c(ykIOahNm-(+G_&}ry&v4C^{Uy4~zs4;EzTh0uO_+U_6)r zCV@vupNvic)3B$bMc@hSS?H7K9Q0}Q8FU`H0DT@^gf0dzf+b)Xco~#{72s8{3cOC< zHRxJ&9r_k{8*BvcfK9|Vqwk{cq2-_gYzOayonRN(4-SDN#>%9l?Ei7J8vTlLXXu~v z^v?zK68fECC4G@)}OgW9JJ=Zs*b@6L^6Sgo8*BMOuvWk4bT$4t65>lhAsg0Z7G9 z1C2lvkO`WCET@%}P5Bns*J8KEZcF}lpgpk;pc8d=1~-v*3-Nqn-O$@W573LWJHVab zF3^`)Kk^I!1HmBY%A_I0hLScM+~-`LG#WfiY%JRx4<>*~;88FcOkrEoz;sXqo**_0 zJV||Xz|+{zfO*uh06dSq2rMRT3H~zhGJXkVSAn(QZPGRpe+S)!ZYK6F_Iudnse$!D=Ifba0X2R~pNt{0M=F0Lii zM13FF`?0RSe@}{C`XcIIOZHi{0+2m<~-3o1u-yXXIc4zE->~837 zpa-#D=pE>t=v`=Ev>!SE9f;mT{vlwfYe4dS#72S#@JFK$p%0^D!FVtMe-ipAm<*b8axB$fd$}sum~&$FM=gt8F(3#P=1ALVDhWjtFYIgYr#6O5xfI7 zfz9AOP~j?0+6i`He+c%1{onvN1P)Wj_q5e;FHLf~nR`P`-~~Pq?&iJ^>R>0j`z0r# z^*{rV3erF$kO`WCEb?T77L;j)-x{<9?Ld3b0dyj*vwJ}DP40V=Zvpwlx>4pf>>k*? zXvZDsU7#;^KXf1%1crj)l)sPiBe6#VX33KtM#qCmU^19Oo@wNnjy(%J0~Ubii7i4G zQ|3iF8^qVIunPyx1s_rWgkA?5dy zXFv7<>_g~baD?(l(NEFiXf=8g{R*4~7l7g67yvggffx8dIEVyM9>y#*4y}VGqDh{6 zk{fvXC8v6ZB{xEwpjl`(+KN1_L0gZN)DCSAI)j@)KIlgLHnfLlaB?s74*WaOyU@Pq z0O}uzeGfJ>>PbV;p~Qxx_n{-v2Rs9kM}vp3A7;B_(eda6(kEd*iai-j!Jmdd9WA1+ zCy31gbBH|+<`G|jE(S}$GVn530bV8FDz@=D_8RPU=v(MU^c~7=M&HGM53K;(v3H`? zq@Be63Y@_{OJAMGzJOjL{W}l$3eRtnohJQl_Dl8xpLtJmIEW+`1!6!PNHe(?fFb59 zNkhSKllw8)MB01!<>vCF3hej6PO!`5dINjGesF-;A#fNRq1;jQQ}j5>JKRYp(XYsN z2Ky}bCGZ{ifi@Wy=Y_?+44Bwn)Q5&!{rHEf0m)Gy20xB?9gv8fL|Oyup5#>QH0(xb z6Oc))DVjyB1$Ha!Yq8s*?LjBXcLuj$=cC;~5A0s(9pFyTkNg9O4a6RV4gtf#NXtqZ zjXne(CT#*b34Iiuj7~wPp+)Eu=q&U}bPoD7`V5#y-3#zv1WUj&VlSg5UsCFtm34@;0QPhJ_W}?H8=^ruz02bXRyzL^Vk=_ zCG79O_t-xG!^<-Ta03%~fe(a(ND$@yV^R!=19d3>3OT@lIzXv~H8(|!O;07k} z0v`wmkztG%AO^&NIv^1wfqI}p*!{_=APqDEO+Y4S3bH^pb+iDjz_p+?Xbakb_F;TB zrjAZ%XZ)M6Zwa%K^0B*N--h-8y~4Og0q@Eu-39uBe)t1O8wl0*v6COpM(80`b^mJq?RECI{F%b%d#sZ-b54?|@BUGk6!g2g*SO*iN4J!A`IX zdfLG%y_$5qkp60#AZD;At?|*Dv`Q^jRPGbaXzt0DTU99$knoLKlM< z!4j|xybMaf3h*lRuL7@wHK3F_*Ajn|vg`2Q0&nAQAifd(AK%8zchEBYP3WJ|&FH(} zJx~rRz;^IH*a>!l55ZorpZX3^_d#$7`(xjL&iy zz}sLWcn53(o58!_Jx~rRz;^IHWp;vH;6t#N*nV&T90G^I5#mSDPr-3e4NemK0(=F| zfV0HTgA3pi_>S23;0IuYGp+(RFo75N!nwB4$Z*D0GzLEo)WJ^-=QBE*ie{os(JV9@ zZGm13+JbhVefWUnPH1OvOE_aDdK>5k?gRrUGY}n$4oB}pN1~(AhtP-7@#qBfQ7{>M z3OWs)PJ4=|^9kBF3w;vhJ@}-j(Pz+k=mPLOSVZ2%=!?Xcpu88K^fIv$bOrva)VYc} zUk7Wj*M|2?ek=T*4aa&oKLt(LX= zu+=B6zHa5r_2x$A#^u(}y)L&)?rpifa|?3Em%Y8ie$=s)Nm*l>YyD@iBySLkI zX;<0qSi9H2N{hcDr5|f6 z4p6tK@vIc~JJxQS%UWU2sDbKPb&r~-ey!H2L9E#|nAPfrF!%i+t93oB-c^sNt*jLG zo|>SxsYg}0`aSdHQ`L4gP5qTs7f;b6N26E6r#1he*&id3dYZE|chKBZb8pSR);v6> zl$_&Y*29I`ep<&1W2J_tG%t#k)Fs+pqwT-NNvbbiI8Jkl=BAq4XwKK%KVHiIBB3t5 z)-Rzx+%-B4zBeHQ9-SbmzfF*Ors~uuH80RyqWQ2c8|2XZ=Mr?w>q!m2*E~)0ta|rQ z^YiuYg@@`k+^_i&&671hq4{aeWtuBAzoPjC&2MUcv7WT;6V_Bqjz=c z2Rgo2M?TSfO7lg{?)uW6==##mWX+8==V-oOr{>p}ed%3aYEIVmf3CNFN%M6&Vrq`k z{Nv->Uzfd4^BB#+9&6lKwwtZF{xYfm39s-R&GR%b(!4}-iRM+B*J^%S^Cr#PG{3Jo zZJE@3NZZFWpVa)d=1ZDYm~6|`9HBW*bF$_%&DUsdp}9>kQYyXCvQ+BtSb8fn_P1*8 zUD^YC;d<%Mm)A?4*EGMW`JMH$tqN`L(|L|*{&Kw>sc$rYzh3Gz-x7{`OX3Nd>uOHc zoUXZ<=3LErn!9N3{+4WIh_-`09Qm%)7PP;6?_1{o9or-l&|GJmvF7HQuhrZ^ z=jpOdCGg+fn!kHP?4H`bOXnG=`CiQtW+BVn=AMtGUTvq@J9=Na~CA8dJ81 zjs*K*cBRDsrn%jAIbOlY1KXul!FcI*$@As*1^mat*W0DGApd2*x=}$AT@a zcR;q%@_?LmH)-y3K+d{*4_qMUc%3>^^CHd5G++8i`lrL8>ys>Xy@%h>Q|(|@#AY>L zRMb>O~s6WEIkHNbd0o4gMm~{0LUkY35 zMo$>=&ak1DDIf8dVBXyD_=(>H8|r25Kn}GW4yao^5v1M>^E;H>k@$60IH2-90peX@ zhgzwkNL>L3R5wpF@mpboNz@opU(>vrm4XemO7j|3hj=N>FBI}GD-QK0%x{XTB<#0f zL;XqB!+u-ypH%}Qn_vfbwp8qQRT}nI&HVo&k-xwWR;6r$y`8m$9o*kCv3GI*j59-}R68tq`O(H;&n zI>0eTCpgaNO#WEdq2i63;5x=FaDtH!CmP-0y2fpAJ);MlV)TL=8h21C6=uC}<4!ok zxQj>=&6!4DBG+hcYV^ZyW(Nt+|CUh)9m+mc|g`tu$Y23?-hc`8s1b z@zyY_R~z?Xx7FOv7)j)M&3VQH#M{G$y1^KY-9d9FR(Lj4N6j}H4-@aKxr;Ft`(|T2 zsW)l9#h5^(tL9scNyPJERvR}Sg>N?|6X{`0!S1QKmoW|d7shn>4xgsMSV6bwls&wa4%B2@srks^|t18u5ndw}* zy9CA(y8&afcvuaXWeksD7@k=N7|i1_z%V@EG3@&eHXeDw7~^gJ|D1@pac|x%&G(*K zbu!|d6Z?r1Cr-q@x4H0Ua9&(^3&NKKURn4CU@i-MWZ|2De~rM`F1!u+M*$b{?#^!k zY%P2nV0+;^fbT549pMlV->6>rZiM#%7lQ7>I}m;ha3Q$5@O=pP02hLTg&#n;FL1c< zPGANCU%&7}z>fg&)$@fPMtB0a5KI?-1mSCd3&Hh;A4T|vz{7aK+dN0B^112Y^2*@Sdd)0sjg>d|P_y!+>X&J_5{|z;jC<1?H^4^GhEC{yxCP;0;Tk0Q{1r zPXWGhX<=azZ>Yo%-Y~q3@Rthw@}--A`7*%8;47An1AgVwEr4IW^i1Ht3UD!a)6%Vg zU$b-@;MXqQ4)}FT&jx(+(sKd7e(8CDZ&|t%@U2UC0e-{M^8vqc=>>q_wDdy2Z(e#4 z;M+bb;H}GNP~yquvk2cN@b=~Nz?=ev-dMgL@Y9wb z1iW+k^8i16`SU@&3ve-b{_?8;U$C43=59dfljR)XXD$~2U$ndd_*u(Ez?Uvx0MAPR z7lW5Aml6JKKxmTXD#D*5@Sf#|fq4ZWG|6%u;WGlyE;oT$16&NwFJD6V93V8w@)d;d z1B517ehtD804@ffyZl%cz>h_7=kA0qsP0$;cMMZjzeY%RY5 z_#ME7puPM?ggbx>LAd-R!n*>y%U_1@W6NIw*jxT8z`t026X5%ozZUR=%Wnq%hX5CY zk1oFjaB1Zm08gxZ6X2~YZv*utAjW9rTM$0I@@)v;Dewg=-vP{L04@fPth^oYH7nl@ z_~^b&xO2yX*Icdh&Y!YzUAm3IQOBe1jbL%@du_f~!w_+3C~u$3P{cwgXS zD?bX%RY0_2<;M^{0E8Y}c^AS1z(u@8@h1>|Js|Yh%17fHv?j( zto#PTZxQ$nE58ZMTLpgO%5MYzO#C3_QJoUp*{p3^ce(E=#`h%x#T6p2g{qKa?xA3Bs!aJdv@J8r{{JwN$M}A+n zGL+w!ue?EiU$OFL`8~7p_IECU|Ln@U@O#t3`ITRN=P~@=zw$fs`{2qy0>6xRNaHn~ zz<>VAZ9ho9SFPNE-(VrL^5P$4xw)0IKZr+Y@P6r6$?wL>vtPz|ab;8J7gip|@3AMa zdw?|u>;4!3{(IgktVj(CT)^A@7>MHzQ*bXnp5(jxIo)?jCIF~Y@E8ArJvsLL^4}}V zgU+-UenGG~Ip`HS-N|5dPp8)likppcDYxJ1?}hbl|7tMk_YT{Gem`ta0!5bxeR3;j zcF;L2^umL%KM9yJKWI-SBKf4p)-Q6(Z(l@lv@>SRb_xGzTxo!VO`uqv~?Ch>P7&Gs%wz!$xbg7f$>WT#Jp-|Fof4a5AOx@ ztx3y^<^~4`t$xSmx`h(L(d4i)m~?j!MU30Z(d~?bYN?Pb=Zkq0C|oY&s#}c!LO!0f zAYDPHJ06lzgrIn^XNBT=w|{mmn6&noL#bLX1e>)&y;*7m`D$*nT5mLq`D`gyD&{Uk znDtU-BPf&#+u5Sd)Nh(@gFUoH(EQkH+#%M4dUg~xx`?eQMew3p? znzvOgRvH2Nb2u1>^>8xj_V>n&*C(T}bs(YXa5xxYs4%jdgYl$U+(h5^D7l6H^kBVO zD`y&oMoy!srBqV8O@j4CrjgGyGC{quQ7+_*&2muO3Pt95KV>SUHpwKW>_thU2i;$vjC)QgW4 zD1`hisZclx0J>D&*vga&jYc7eL?>78w}t_S2xZ{+dcQYlb*fm4M6YnosK>>UDR5`XLHG2#joN z?4D@WK_2h@fl^FgJ>1xjf_W;pDj zEVe!B1er5~v9v`Oqu@XULF}#Io;K|$bjR?FKui~e&k8&z@VvnL1l}+30f7$+Jae!9 zXzDYX{EVhQqZyph9L{JKXEcv9n#mc>WleKgGj-5h)-;zj&1FqMV`_FT}$>M;o$p*4&)!b!b7>JBFXLK)bd_@ON+QCaxystZE#ptXl# zB`110#1f5Q32TD{bWlj_w=o&U0hX;scLMPN&IPnIA?g~y0VhX1R=3KRq(~7kruvhi z!of}m`v9S>-gK|qms~SFR0x8M5e31Ep*q<;N3cO)*CVVA0?T$e?kEDv#aIdPSS{QQ zp~t1{(m>^q^(aC5(bDd2H|(%unza(q{6Q=~IDpMbgb4wc8w{>?rDseCxWbJgX8VAQ zHb~C>)@Y2C0$3Xa)>y(8!@Sit_Aq5kUzyRMu6MDrbsv`!8P18MbYS5*lx={IQ%&sH z>S232>P|#{pspr^_CRE+0!x+VV340492{N(OXvlA{h&Gw`$4V;YX>lFje>`#;poun zH#K$8bw0Mx=Y)>qWF3id75kkK`spBs4#~XY=*sIpnYOz1Uk9e z-zOg3XF`H&Ljzq^qy`1s+39%%7Zcjm@DS#KWTQcgg~cy&QSAdS5lb0zt#e5Dkg$9%|~c%gX`f9n4X%6i8zYv%N$8!LhFoLd#D1eWg$jUp^in_cyu3O zMtglUI1m$zIc&i)>rc#zgLq_JiVCXscf^eF8xq4vsn8RHSX+I>WPr63tGp4psDNOE z%C^Q~t~H!YMa^c|{WQdur!|?h+WWHn2ACHvJPs$@gZ^l6 zeT?N7^Cj3zA|ehbTI}jD@gg3FQZB6BJu}$K;~|s-Mj#q7Q6`&H0vU0(uC=;7S-mwo zGDf(Fk2zw?ogvJjT~t$<2S$oxSR+v5>>)KeGc}m(VNr%LVraDXgeN9e8gb$>pqXby zWze^yC3>O*pI3aKBL+L1gMMPvI8w;e8zs6EFdm71wEdRSBeU(+KG|=L*QImJC}W<8 zb1No9sySeMde}aCYCMF)XKbda9dqgw4kR-?KsUE!kTj%1BNNrw=)2vKZn8`+wGb=Y zNcW3cB{mzIK&^x1rCkxn!RBbf(#9?VQy9IIXopu@tw}PESb8m3){5)ch^tTzbn$Qq zw0FYY3Z$jT*-7yi3*EFNa{g(nxdem7OgZU&SVuaeY)lK57}p_>$f#0VG+=4JDAh%k z+6f&(=^jEkbXFv|5=fuZ%RqBf-UON&swMjz^uE_~gT8H>39%uAzAGNmAJy0jsYjhD zELM=%DHuvIO^}r}Mh4EXkPz$!`Bi(u)K6>#6BYx(goRmJpjFi%7k*6hnd9+X%U74rfnka9!i(Il|_Q%>#d=|39E!#L)f$(&BE4EG$LiDj|!{N zX-QEGGkpwG9vWRFw}-t$6vN0|>%zpVcXzN4*%OXFmLwZz#?ljBFL;e4St=1#z$-2) zDp`zQ1Z&(2`+Jjp=Oy3{ZX7< z)<*5dQg`MT#YpRFSD7EUvmBpxgISiOx5nZ@WU7Ih@665w6|1vE(Hd5~n>9*uQKec7 zU5Pg4XqYXIg0REuRC6SaD%H&`rMjq3<#hAOjC*vMuO40E9$n_PN0+!qceR$nO{`;V z87XKYdwgc0Atvs@(4V$&@IthUXtus_tp)p-aT}{u4=$yF98~16q+x5U7Rh)p9kp?K z(g|-!#;|<{qfTWCH-NU8CAlKCS9W(%YAM_`ON2xl);^P%IO09#&9J+-@3U`-p(btZ z;s9GyO`C43=e2nrWm33TwD-X6F zqW?7y8;fYNB1A-qDpgzM*;`mXrJ)|GZH^?RZ(4A3McM-@!>Wt8s!%oIL|uhDl4Va8 zV{#}mIEchfgA_Rpskmv_h?+)>m_%SIZ=~! zIF8JAvIc9=+g*YJXFr@WZ9_-8I0CksI&Py4a()0OA0}}isdYlLz-r%w1y6BPtb`m6 zOJ;;-#G^oZeHx>Viq+a9O3cyFChOK3tj^ACpN z^{SeQgWf$R2&b72c>>^=qq$)0j7YiSJ6S0uu_XcyDgY{^hW(0ojIx7i zpGOE0niYjdkuD`3*CUA+)3w+`fVt7yQ9TS+7had`5vZ9qHap`Bp>ZSIh}3weH#OrV zA;F2^tNoxs!J;$dv>uMa7L)-)K;#zBO7p>Ly5JhnU+11IKS3DPR_fU|=(q*Zt zsTm!^fd^+jo0y(r;li!P;mwBoI8}rZsRQhy;5LU&y6r{W(wZZ6|HJEmAp6sVq$xVx zB2Na$cAmzNHFp-N);Rb~)8O$yhN3Q6Y72+rVn&)sY-SoUwe`8dC?hqFx9xXkC_~Me{pMlIO|{&lRek;#iIdampgv(2s)3=>YXb+eUnVsBRKPE)^rO zlgQykL1p`Rh+~@}Vc@Z9Jr0>e0u$PUowScLQ<2y)A`>1J5G#SsRF4-!+*9fGT0}3nRK)Dn&wLV8qF04^H(e%Vr%89upr2p?4PHDkOD4Wh9pMOPbWk&sLsc!!emWinWUz6?GU;;zdy%(827P03 z1EJDjXMfd|zcIr6#VHVa*aorKz&Hm&1I<2ewsiG!*m%nXRf8IvAIo_eUFOtIm6UO#R18UtX2UuY)e6D=D{YVz94I&Nag z0AAyf`1Uq#3Po4Iwkt4i;~3$M@f2vkiUAhqEZ}G(1zmwf#Wv{j5Wj^cSIIU9J@^8* zeR|X*vmAE7Vifu{(g>>Q(HhRonM zdV`%-FP_ac- zjCjNR#>miVDY%x1CAABOz7?`@P{*=wmJ0MD^ulmw&>D#qWzN<_&%?JB_Ngnbg?b9x z>YMwH8SCJ!reK;yM@Ee`Lz7>i3s+F>*P5mu2e?^) zy9xH9DhkQM4+4E@^3qtHM-EiDiKz67t)PlW8OK=|4pbHaV{|zjn>`hG0`38E0hTK| zusG)9w(_LiB3L2UmQ1wjRCk&(iFZE6xYOY zaE`uNoG+WGIG|B>;RY=?VogZzlLpOxOD>j55e5gQGA5gfn-~hb#8YqYZJ-UaF(|-rQ${P8J+?eb|XcdcVo=h77qZA-PtYQ7-UJZ@OyLMf}dj*KdqaukvKsHAMvs!eTyN0A3zd8}le^%0f(WDmO6i-`ON~snq!nNz8dchMwW^j8!)zAZ(8chV ziuuN-W+xe}7qvdhl9k9 z(YKpGmblxg2Rn(G%(J0HU)Ps1$RCLcV7zb z{uJB;DYyqyaHULL2M2P^VfQ9X4#SNnd^~wq45YZo$0XRW8m6t8=f(0?wWfJh3YWGr z8`|UL>P6G_nM#hA(UFS!K?3zgt$3l(*o0Qt&^e-7}n<1}M&1fPu zueC$l8PT%{Pqr*7E(hz?QmJ}r8&!f@k&>VthivdR=rd&l&vnt6CMp0X<{|<@(^W`F)I+euUXG#v=8)Q09P6xQK?pp zp2zb#czQBc%)i|Y-}0DpM^r_e54TQjPWr#Uwn+t79Vp? z`ohQPOpz4=xn@etUzixkVhzFaj7MZt`W()w5{HSDi9=x}Rmp_ZNlub)eXEcwV&&a5 zJx8yP*W%)O%}xtaIEOMt?HhKg)#VIlP&>&Ix+r(SQfirevFZt4zE<6Wg2G7ZDnJ!v z!ya2Cyxu%MV`PwmUC!w0yN;DmORbjqn3OguS1aPFEYZlBizmw`!0Y zKI+sknmUuuV=AgpLM@wlkuP49TxIF@XIajRKo=o_n}Ip3zL0Mp1BP;;X4Dwj>suu= z#U&&>hD0G;d840eP!AVP|4BVLlJfW(2fRV+O`d8*WTVi?ma4f6>*a>+Ta8J&I#$Ka zV!nWAG+xa)8LoIrMBzRuMT3WR6tX)!QT!NC@%Am#CSxA)Np^1z<{hZvI z%q*dJFwBygeY;i6HJUZ;dXoKk{z|1@%VCAmZGc8$8>lLg<=M-vSl-Cg8jf3|j$5O( z0z_NYk|c+Is9kw=HH#6hut&981K)}qxHUyg*>>V@m9ILdylxf0($rrNCjSV9TqMI{~ z3c5*HpfSX*!Hk6-jiF$L)SaaT-B7zkF%%X^e;u|uDr)z1)bug4qE^^|`mSB^>&+B+ zNEeN2U=+2pDP0g&JcsMYu}3cC>nJXU*XbKaHLjozeqt2DB`b#G8WcmA9eE5_F4l7~ z#3O}TRkvAqI<`OOvZ6$0jO2W zGX%(Et{_+=-_cNA%GO+;QNd!&G3td(xqhXh)*nV24^lT&In zYg5SQOR8veQN^xVrw0nag78Rz(r&6E8WB&7!?#lBqTrc&v~{6r(n#n9Y%{hu3s$dc z+$v5(_FOdvL%m>>f`_4;Ngo|7mku|VvKqMd~!U#yFY<*2V$vD4k=BkHonrQOlESgaSb zMHqlrpoMkn3OQGY(*dolY;22jNs!Irwr{sKxA5$JLDaqMw}c0pX4|NBx<$DAuG_wX zBWo+(OzicrnS}j-nPZk8YHTTeb6gv=^3Azr5%)=tdWw6nZ z3Pc8jY#Sm%zObHwvrJ}|aF$V5bbDiad%akz<0pZo6Tu>}G-K(BGa6h9TMjmj)(_UO z$_bnYl0D~~3uKH!0*##zUFxxp;)*vz(ZI%!zH)Bs>Z;*$+ z;j1*Z3o2_SEdDI6xn=ApYd+CoD%A$|3UpRs$@W=|3Wy^sRc@qWd^z!CB@!EhLp`xr zAY5@WW$=oS2otM-PjD6Rk){GZ%2mKe#wwuAD(1IkTDchKmW#*)i^VXlVsSIo98RZC zJPO&6=@(($jB_ZRUM}j*ABW>^CyH<~xR}m_c+}2Nhn2bKVlpLNESioEm6+8I&$$+r zY-XyQs6<%R=Cnc~gHJtfHxS?u255 zMzH~}j-NFr4%ZFwl6n+>d*S$DrShBs`(9(f+KB)$5|_B+G)FxyzS(GO;p7Ewms!+y zo)g~TQ#LY=R;}nN7jYX&!QOUb&Bwwh(9M!dOI;5`1^z2cdn|@ALK(eFO&LSRn-pIw zVvGr?*Vhm^4rux6r6$~Ib(C=tr&UoYXnDhq0L+AlFk=t6+@!2nQ=uQt6!Xv`9iHZl zvWCdUbgH44H!fi?jJ8hT(b3pNG@<1a1h!!=k)0;mF<;6xO56F87!vhBqZc9Y5M7OA zH()b!x@fdg-PY0a5ZvxWWNaiv4hxr&wa1mmRt5X37}|ESIICR&vfNmb$r$qt+ZLQR zRA^Hw>lVD0<;*s!q$ZHdAY0hXTr5`MDt9O@X>|Hx01OhgC(Jmw!e{|nBeL08e;|!+ zq~9Y~aO?_0%@%>pMXpd?U*{esDi!ayg7L7$b2qI?9r6ZiLL-K~xQ=xNt9k`1FV?0Q zO$L>(&q6Cj?ejHIIK08}goJeC?~ocrW418$&AJkp=w*18x3Nu&$Dz7>I(_pNLC1md zMjIAu_nRoa0G2tgk}i~~MA54A8pJn?VMeGImm-zuRMIiIizPWr zPbD+CbvMm0;ItyOS18eR+|zM6lgO?eTB}()`ym|*ALKkjYBiWs`q+?y{R1{KGu7jX z&McN@&A zPRQupeHy<|xI%?(=PRPzdboLxIQ9r8BbgFDw;<%W+2@E7hzN_~uvt(6;+21xzbSRx zmJN+#<>ihB)@fYUG1Wb7G5|&5K#ZtI* zFKD*u6GN zBh`e>8Jmr2bH%UXY5A=!?6`6>wM0F{N;_+^=M!ccJxux&%)Yi&LCeOGH8Qw2B z2QpFF!C9KRwtccX-;Ha)B&p&Mg;!KuG(PLGPm!&IBg^TFi^aznS0VJqhohUli;LqR z)|29D1^bO6j&~eA);F+RGgo+W8s8qO9Cl| zj>8#OPE?$A^>gh?a>e__IFjT{&T(pWbm!!dViYBCzOJyXa4y)WWSQ`rvdFsZq+pnF zRN@h*_M@{U9Jjd2T#RRWxCIDJq<1@IbLl`zF@b-5yf9@aEVcE${9Ja zzQd%nF?B)+h@$o3%GO~{a49mzC-qj_(WMofS|1KK+lJJ3$yG@aNKUg#w1(Otn$1Uq zEZP=8-swd5M7nU17TI>SBK7izvTzaGs?BstEKM{&5=nf5pTai};z{BZKTXuwcnTly z^ZP;&PZ6h>G|-#zvQ67(@DaaXa>VUpBi@+3mq(S|#wavgI5Yj|T;h2u?N4R6fEaJ&hu z;hodcB-++EW-z#{)y|v|F@Ftrym6$-H*VKB-Xz*^$ITeWokSaM3Phq$jijegOd4JN zq6XQi5i^LKsH?6?FC&#^N|6yU{thRLrl?e!NoQtH%noyvN%%>U`OYKT&Wd?a(h^5L z7Dx5c`Ysknx7}?#IMxN@=qA1Kz&Nx?mP8wFmC%ING)Yovv2<}28cP-@nN+?PC|SW& znn}kW+`zn&oKL32d1RZ~+=cNBWGC$@#&aYCbUP)hNokLerUW8ABhTeNgOBmkLzR|& z`ntiqQcba0f>%n+sEpMsL2+r|>zb{Uk2IY0TO}D|ILk*T)(m3|X*d(hi5*k?_*Qs}mRxa5f2Iy~!$gx%0&7ZuwPyKK`)CRN&=*`-S-nw07LYL|8%*`)S& z-!4rYY0F97nY%RU8+WH&rRlN#yGxlyGG*#G%|YME{dv8oA*mnLl$Vu~2v@T+;2$jho4vC$H=Sh`q_u~adNs~b+m z5(}H_`&p8oDzQ-csS+fUD(UfXLpDn=DUOh*G?J~|T;Gc;Q60l+?in`^RA6VTX4*NA zZ0aDETja}e1<&Ap{+O%Blp_g9z`+oCahxpY$41O?|I&9DXSUsqdZWb^lT3}v>C}jc zJY&9Y{rHgi1QZNk9v&C*pp|5G`f?KFgqLcT8hNE=X)za6f-KtE6QNWx&%e_; z*Z35DeVdlv_q(Oh=hWR@x=kxu?_8x(lCqpAF=g`^=N#{w1J%);T7Gvpg2IpOkNgF?N3>Wvk zB=Sf&PE)A9mo!06ceA80&A3xicv74y2`=sJxWyJ@!8-{`c#PGZWygrTM4r-1Yq&ng ztG#oU8<26I#@viaOG`U-dbVLQV9aqeI8Lu%fO4RExh0<$@Vdo{n)asdI(RswUZ#!P<{7m@_vEGnN zEz>;rcLay_`}{?BZCg3!F58x2&Z=+8^K6E-ZJ5?cPe;7NNUmQd zd|_!EN!M1AXV#4s=g?<|%|=I`AV?h@)qF?wy>cAU_sTH0@0C2i@8u?q+uNj?1#8># zCWNPB(mN0d4_>@m;#SfTn;XakAGtr0gZnmPZ_yM=pH=4FDo@Xdr)qHD8&?76FUP1< zKA*e{6>p%6^85^L~xrH3l)g$#&tH@hm2*YOg=Wt~$n{_%gQFGELaZXCzlg>%0#5pOUTH$}3lTwNEQr2?uH9Hf(tC-=($y2-K+_w0)ahikA zdHY>%{S;^MV8>kJ-e=;g1Lx$Rs~44Og)ezYFUIDTCQ_Dm7SE3q@p_Mh|0^QTTlpi7 zc}su9F?UT*vZOBRKGU34-Df#s`aw)!2Dsf(50{ ztc|uN=eP0BM76E>f|U3w7%^%0INLk5y5~(N@~Px`6O;87xrk175|y33v^&F)JW`rr zm_6E>VM#xIn#1_H=F)p15~7oioMJ zoX(i=CeLT`oyzH4GtTpLwv@x4bjFmchUtuSG$c0O>5Tp&pUyFRA!t5d(x6J`oVBXb z`O>YNbl!9`Y(DRdEjFJu#UM*(R#}|cWv4UGS#;Bxjo&D~K&7+FT#PM2>3j**e*}|v z44clCTm;g&W;J&@U;1)z6z^=#X7MP~8pJd1*fQ{4mT{v}iE5mt>}r$@+i9*@sT@y3 zcI$M~YSPp?VYJDq^;7?m6f%b{FKe66fcI0tY(W>yNzNr;F1dawvo)7!JZW?3aM;22 znqM;}Ofj0ZV@RC!edO`3I1qGiJU?f?^=Cd6Ybajh(8Q?$-w_)>NwNj-eTfOW=U(#O zci>~Aw;n`T+v~BmSjC3-OIv!HUkjCyR=|XfGQ?}e{AWq6q^B^Z`pVMtobi|GTPUJZ z*S7yRSW;@HZ;e{pwr{o2hi;_OmSo;Qf-`2kaKv^;jN>R0UoBZKcq%HEQheD*F=X(B zs~dxOQdqx5yt3F=8n((9KfE3#m87p+PD{l12+o-GHb*=tj+YC@okNzUZr+l_ww>6HY_kwkwRkw_PNiYGx!IoXSn)8WVS z7sp34Frv(;v52H^lbDlE+2masM{&^Gl^n&W1iZ%{FTtNZhfQ*%oaII=crQWhK{XM% zh^#}JtbdcO$KjlUE-*Le3P*r1wuV3vP6KJ|ed$p*WHUo46{(7oa|@d^$*HX?~0 zjeSnLbsjxs!g;ALisyJ<+RY=WIA5KYFsT~667e2~Bd8Z^i3_1#N`0aIydop_)I5&l z%O;XNS*p(OMHP2{GJ6%{1w6c>Z7y}z;D{xTJ%OC8)Ql?ilFsTlk9hPHi`^WZz4p?$ z%ok;E6t=0BX6|e_>U@gYs|g(^ZF7n9`0x%sicGcezVxm2=9K zY{$bLR0i*Ejt!cl>O1PvX})VV-XKz9{W?od-hgx^#yv>!gmM9p12Mls?!LhM5#go0 zN`Ch4r>lZE=xHV?Q+&(kxcEBG`Gu%8b3`FHOmkm3N*z4S;b2diUfPE-72k@wj`BI@cbLx=b4A2!N88jiI9&)lhUjgdx~Yd} z!8yBPiG6}N<7RZt499F0V=VHzU#^LGQNEipEVxs z=-Q++rq(B&HC7`zz)W6ba-L>=o2EG$oYi_sKKYPDtcQ~vvL`x{!?%$ro&L)`v(@ND zO(KRwSldjEBPP*`j^#7#2Sf8cb_6Wuj6+4CHHSOvLg!rQybImuLifAS11{$W9qvJg zJ9Do?BIxQ66@BJRgpI0kW=*i;QCpJp*QJdrcII4!jVgKOe1wfEe8vk#l|K{J{!CPT z1Z`<+QT-8g*r@(%QT^AV`XlIgqb^-L8)2hXtVOL@i&}x8%OR@z+I*#J{6%} z2!!R_#GPaSVNVA5jmrRWpLPMSM|3IGKL-xnJi%LJh1nkY0*fHdPc@*e(6BTD!IEC2 zlM~x0s!1#@TgsI#Fb}pC-zmX6kQuARlbWa|wKSKs9A`FBWwtcOd^yf+qK26-pB3{2 zRgiAe2O?}tpF+P>$DLGt_hb2jZDfF;sThND0g?f;*<;XDg+Wv5885tMzF3S;3)?S0 zm+?L7)?V1?9>^DvO%&hdCaZotxiskSG1eFi&8N4EV+~yFj=T7-bztNAnd?rV-(tt7 z=fl=PwZCaTmyRqUUHY^-R%3a&-qT8TyAi^H{P zpC2n`W(fAXs5U-;-Z51&={z*kXl2?QUr zutjFm7s0D1J>;h4FzB0 z;@6gNy-FPR^2wJupMq&@;(IyhGW#nZFk=tOlZep<+`Nnf)8{c@{f z?b~Nf47a4PWS9uulqLu%a6#J*u;}!=9+pQhS;b=8c*U+sn9th)UL&bY`Spqo;aac3 z;d==tLg9i`1A5Fel)#+qlM@-=0Aa#@pap0R;78#rqN z=WO7-4cun~d}qALz&1p-kculBn(^-%BpiSy#4qf+aNUG1WNnssLAdL(QbFE+qzOwl zV^0M1ExtBu`tFq1es9#osC8@*H>NenWfd1QO{AK&O{rA<4tFo-w|uIgOft2uZNv_t zIRMcVwn{K9GIoG4`>9*;xQgMy%gZ(Nu=%aoWH_l*O05a6y9RBi;qy+GEmkYD;Wy0q z=B=$5Ty9nd`FO?!TPjT$oLra$^2U7=ZrVwUy|AI{7v_|X4Y!+e4J%a*+o^0}CYt}S zyQ;P|crmicfgjMcVflE8!Q0_z*d%rco3=FRj%dA7sluT;Mef*fu{tOU-p_o^7Z2K>B}THbVDj$%B|u|WV;TBd;wp5 z#b+9D7MAmI=6E=UqwNL}hW4C6^Xh2~soE%pV!5`b@d^Uu0}}vWyGY=8mYhJzBWwwr zdH;F>tKX(eAdzEQ4nU`}YtCsYl#-f=jnj|0tZzpiB#W_*A{&PVgC*I1W@mjHpC6Vu zb`ZL8KtOg4c6Xs$3)B}n4lnWN@r@k3$cas}Xic8L*cdJj0}Eo2=SPy%2j$sp?VWn} z@i6FIU+=Z{#`w(-rm&E6y)JCp&h=V24oBC*&KWPf7VKZ|cY*_BnO@&&jammmPk$z~ z%ZHQg8w7_zFWj93lff_;b@%os!OmbZ85{)donW_&)p;|e;l+AI?&gEy95(VF9fb<+LLJuDXwRyyTNGh`s2Zk;4r8kjj5yPX<1hcL7RTH#ZfjxL0Y?wP(8zw$CI5=qaJJ<;@XJVoZ$Q#8- zi^?G_ijkHNcU#jQOnOv~R6lM@jF%SW9p&VwGR?-9HqAz5EV~)o9oS!RXznTYC*f!? ztYcKW?Qnb#3TYe;5h!Z1dvZN$IhNg>;AeQ)7zDCG3HQ2#eozZr9e``$2pUd%`hPp? zdKg~C21md|#E#;K@6Mpgtx2F8shXB^Y1ExS+3pXnQ*mOz%VB@YUC<^rMaBN^Kxp_# z<7T%L;-@+6v?dIIr8=CTs@NQDwI=&Sw1$7G{ku-@$f zoo`KA)t$$}_9Uo?62ICVqPZBNpm#AG?F7By_;Cg*6xrRW&YHc^Ze{|Z*ck_{&b3|4 z6;!&9OxRS>TS22jSuot$*vWw02TH`S!yg1HxN0UQzIC{C> zx`rMAz+en};RLy$_POcE?I8QCZf?KT-wT6k|6(`1?jp6Y&l*FtMX_~MR@!4FCn$rXF>v@yzrByymB1FD zD3qlpwS0IQjt)&0!PY3;#B}O~g=^U0%XT*zFLb(-!AR(p!KAy3=?#&vn_`AH!=8Ex z>!Ws|7alMt4D@!U$L+BMbCXfehU@#?T_JGR)xybi)W6v3O+#Vyt%GjwkQ2v? z8CrdEh;cO}jTnki0fuB^hIT2GrOePw%;w0o)Mm)A!CM^Ty54|E1He$V?~Mji%oU)$ zSd8YzM8wp+bS59qsY`0&j$Wb(>!=cQvkUdio zFBZ{URSebD#l)k^#1T;rwmODx>tmvDq_ZT7N+cK@#^o-RNpN{M$EUSSF#1Tx$r>j3B9!C0#LWkLR2!mE zM@2mo3=ZRXq?QRT59j!_k_kp1={Q-<1Yd-5TyAC4n!B}4qo`+s!C_nuQp*IFhjV;d z$poX1beybaf-gdW%e6`az(n)ign*MA)_Vh8y}TG`IoQ)9j+X|2$#=)YUQ3pL8w6HP zfx5je3~exbG0;lgv6dk=8OU*j&taD&X5zRU(&u!GvSV{=vctr3k=1M;J0LDsvS3__ zV#pceMSlLU9HXJ^uV05ps6ua$*@VE)m1DOzxK6AK1HaYU3$r)^yP6H5y`|VB%IC`L zVm)OZj!7}#$&JU<>?GPCQ+98JJyUfTws=>0GD*ZzoM1>ACmj-tM8uCWqV}Qd!GtrSM%6~BSa(5BrgDuz?TOBq|L&Wv4Q6z@Hh#UJ9m?#7f3D!1|**a`i z>7MF!9{br%0}?_`Ti9-hDd>l}@vipOlr0_%2cwCc1#XVQU6yNqqui|k7drvAcAA8t z+7w2wZtx6JBZ5Z-%3-J5VwNsIiWH_hxxvVeZ8Ba8`+Lxs*l%D{tsB0=!4T7I4`#aC zDN4oSG17PG1saPtq@&&udIfOeNn#u`24)-)O%Pa~3J<1}piNC+Bds2t741QPw+oYG zh#lKdw}?6knLSQ$)#hVlA1YulIz%SiGPA6~FyyY7L@(HHUF+_(z$!el-6n?%3}v_j zrjVrLu(vCL38pPM;h*YY7MgraQE+YWm{-a&VW~oYr#CfK(4baf`(Tn@DwN0 zj=JNclq*Iz5v7Eq5t^lS(6Hi1a1dZuqXZLC%D4^ZcF$0}NXV`IVCONRZ1==*9#L0Dyu0hIy zi%CtfNtXQKGu#cGA8#;=4sV3*dVAD`uxNSNLlb~UjP4Qh1GM%8;u-*kJp=`)ekLQ? z2^m)TRT*^hXJyZbStMd2RYsyjkc{v^szqJ~Dii}9a>V@M9`w!V!nG$OJLsFi8}vbh8jL$jmCD!a}Ei4``rTclV0xTD)$ z9n%VfMUdk_wg;-$$>7H$y3zF!gF%p^Kd425?;@mV?^$nf6f+I*D;ukqUk44F;-cJT zLNRAfmS7)lPHBI4T%|%WKO4H@n5B-3j~HooB~nAo#_ZzP-~v->9a2*w1MOUx!@br} zeS~mA8s{a*&3?BHCswxG>5|*!Z}O(YPY%HvgRMcA-evIt#!-bEf-JX2SEob6))?s7 z88a}(S%Oj=+xt3n@&+!rc$`e zRRUNkrf|E;nrez?8drtQ))=Pfb<>r)q;ZKA_xYf&>%EnCYz}R(eIsZe2E!Iz%47P7 z5v)uP3g*zGy}K^j3`Zy(_>wc@Aqow!HK!$akRP-KtO-0T@SMQ&ftILuokUt_HJCd> z7&}vb_7JXSk5cTwOm0ou``g9-wZYYJTfML&_=p(|ikb0Yzl|w?6N^B?xmK^Y1Fuz( zg}1(M*x>6mp^5t1_b@?>+ui&ew5KE5K(-^ukw9@)B~Xbd#?3YAU^~1f4c(j^^u)_( zoOQ{#&;ol3FofsZREbrHVk|w1MWF-rc?NJJkAnk1Db)TNA`?e^feG%Eun1$&rgWoS z+7J6u{Xoz-c=OUW$Qopk`g0g^EPKP!! z3gytrM(r;yJ<3UpD$EYfjWmt{#jS-yY)7g_ooS63H_F)}w$P~)nPyUX@&my`9@YYf z#kO`Ps-_=OkAg0mUmovc=+QzrkZ}m|xSV>)=)?zeyTOxbwJc;r6+s|d`gvY=rsl{;ytBqbN&=sgTh8iK~9FnH;mJsFj5XvEgq!$A0vZ9cfc4Vf`6k8}pGX#uzpk`W7?Ouy`)$2$lSqBz0&(w3ECPZ1>m4arw92&V`ka^1}#vP#(+*ltIjKFLTM%~9Dc;=YR-Dq&7$bp%l zV~HbltQ2f4aOs2%i*ZNj7k^_#tXECT4L<1drTg4fXZO~x?^jZAQz}WUc-`GKp<$$%DS1;u$R3A_0eQ-s7T@+$_lm>wMfjc!D$=ij|V&M59H|% z;|dAzmbhXu&<)4fh(o~sf*Kl6hjh+EZefzDC*O!>rr&7{_V(c0ulB)swNFi2xWT;^ zeE=*D7BluG2iqMhyw~XIXmM0Sv$5@FI@h{m43}&mx@t4n7)+SM zOpbnZ$3?l7X2PTvXEJ>W?j|0m0o?WCRmV)Xm;JUQ;nAXbO`{Xy1r~LDFj0Ipm=M&v z-EkH#>wWK^qk$bC$3Ef@mLV}R;(5|zZHRHXdXNj#RYB(3ne-|$*XFUuKW8SbhRg6B!Y zp*(eqi-EWjpe`+D)IuXAEhD%?*$Re|A94u#yinN1@`)u>1H1V!90mi-j!}iXeA7-@ zjI>JVIM;2+(M6;T7t=d;Jrylf8V(~Fs$i();35|eAosZ=bn_zD8nSbvZ9C6$hT<3x zZw$Gi5?2~#Rsg5akWMXJQpT;%2E6LnW8x+=re(q05rmxMFbypf#m|mg$2^mBADvq4 z57#lx5nQg~f8&g##S-Au3CBuM3A`qY+qD4%SNZ`%9*kvy(<89q4xEPYZ3lflbC8>_ z@B$H6f-9F2aJ>aOWF2UmV6kDBw#(mN~Rz4^fQ>ck#)0u3H&(d_NETj+;J07+R zZ3|6?Hfr+P-|G!_T0Kp?TW@2PmEx90?+r(7h@g1m8J1HF@pvnP*m+}d{ugkh zhMBfYYoBYYc*p5-L;yD=+WYou^l*4^HQ1$n84PzI`{T!{SaB6ZW;8~)fD>v+7TBO- z16<%%RfNT_kMqf0-gw7d?-8nD&Yp&Pq;p*#NEqsRY1QobafBpmUY4BJ;nYH>_J(Cd z>zmU zve5E2Fr^9^wdJq`znf~82`UOw8D$4I(4|F}SM=BiI&Oj^bIlSPG;|oVlaRS8&%T30 zi!DGcFwC9n1)Qwnz+%^Bh|+B@HjBnjyDNilB14Qh23A@CU4-TEaVOP$O2mtDUFuxt zu20vSfFpeX2kKRrEkp1A{;up8s6S*?>*B0sCotnC1yLULz$8G;bG>nwr!7#%2i09! z=izl7NdQm9p!dx=%#d9Mr3yPtwDduD3;~0V#vx8HWODSx1SsC0fGiDn6~%KS7n!sv zc9vU7cuau&(1hZmMO~t!Em8W`io+;SO4SeyhI`X)CwI`Y|>4~H-ob&MWPb$HygZ=Qw6!p|*U73-GP4p+!V zIBE!n_Gx*nTe!-Px^cc8VACx76AT>s$i5km+X_j+ApkPh2eS8=@ozkFDP)4A8((JSNVJI-LW)~*E|5M+hw zT(6G0II#+bz(9)a%Ey$5%F2wgT9fevet^*~rJ9NX`Eeq$)7p6c2#Qvoic%xP#kx3) zr**>3snOJO=!={{BWA36ymQW&s9x1kt0Z zU>*;{QfqAiJIqDry&QT+DnqFJUi}&*0M8S_J~B^*$Wm>?Lcp>~<3vV?0&JfN8FeuW zhr??|vv&K1YjTSZvWZN1nS=_UN9hxFiRW=9BU*+s(XUH>LgjT5T)pBF!JrjK>U1$Q zdPB!CH7*3OQhz{;$%zXF$qa>7W)qekS4PS+e{~lL@sx->OF%PH=gq-5YzGsbML}>n z;V$?C+^gbc7x3VO1Y?PSHRJbDMdr(25Fte{u5s$Gbug*z0cem>N`qP3|jc(5DE)=;uh!LudlBSE3@)9^_kxW@E&5C#WUH^>?K)IT2|?#7S9 zyB*%Zfkhz}`amD5ItVBG19*W0Tq4&KWHTJtukofbR7wZCGiXrk5Q3|iEYL8aJRa1> zqMBp3bTBHgSYf)hLK^Uq*F6YPOfU$b_{JQ2S&^;Zh0lV)!j?ltX1;@6B8~X~R~7Mm z6^fL{#ehb$CU90`Gie0_+Y?C_U{c{-9j=mgwg+Lqjr{>P@6J$Z!B8;@zJTR`LQbuL zr|!UsYZANIACAJ;PtmoUsJMC|L`MUcmHm9s75$tK_HlHAK7y}}tE8Oiil05OZYG!n z9US|aLtyOF?8e(Npvv%PvjebgJwveOHpJns@wniWe~f3QOF+kWrfqM(Yb(L05TUmBQ%I2FPI!Q8C9~P(u${nmah8CU ztaVt2(Kt(jcBb5<5-3cw1apI9mcV>wh{p2(f9GBw&oOq}W4Hx(rh9wT$x$APgM?E> zkKOQ?M>sj{kU8{^2+WwbO@NTuiPgDvLqeYS!aSf!HjsAY=5tgS(0UIvhB8Ve!fil) zqgc^OFcofuW?nueAi31tiF0{KwYo*Pz1$7M`n2DU^7fFL3R2EFgQ>6=ag{~Eph2D+ zBEng9oA33KZKknzcI}=HoZFoHCJ3Y5gkWCw!=8yuM?ILF!fetZM|iGBkYBwG6xB%M z7qEea+i0?db>I;^fy?k&Jp;+YQ*>3l+;YjA*q}G-`57jWUMn7^BMrdHNUL3Ha)?o{hnv zw==j=#Qm3uyU@SZ9r3AJXj*uXsc`yxTCy~?TDSMBwlF(rhGQ+3x|^ucrL+xr%IDv- zsP_Fk7EGi^*OH#bDp8lPeSitfU`d0joN*8(MzTo)JqB%KB8@>b@|(1_Wwc}t>um?- zhJmp6XfQ&B8!%Vfus%pKI~E4*!VkyJ5Sw2eaTm#srsI8R5BWun+7mdI(6>yf+pP!( zWz~yf~dj z3R_zTwi-`!c=ix9br{gDYrG!b7}$JyD5UODs&F{y;k?kURkuHT$Ji9om-bMAcsVLC zfd@qSnf$}Z5h`d-HH@$*ak=gyI$H)bp`M?H5gEy`5*GBSr-;RX)rW7#0Srp9UZS%G z4iv_S4*ulnKs3(vFB8$|bI^L- zj*h!*9_c<&dDYFN#92Xe@I~dIH;ZSGGOKXKRQw7U-9b;7xzm!HRMeE!U87zw_;?Qv zBG|Fu0TAdf*dn~LWPgPsekcxZ6vOGrHl;+As-RttW?Rfl5ENBsk|At#8tROv4w4BV zPFx%AI~VY7T-)xhX>%%i9k=5xmbEb&7x_99uMGDh9<$dCdiD?#iHzCq9`;d0z{3$jB6NLJ}@R#urzY}bLx(MGLv_ZkO17Jp=VrPZ;Cz~<0ec2mbqzi7JqIKA~ zqxXsFvzE6pJ$r(^@^}nWLCOPSp7&}q%3ajr5Ix;RPqHV1JL8lbxS1DA2%a0Km4Mx4 znim$qLm3$%Rt3}=akNUvnQ{`m*ym}2pAwV8_tHElZPbqS)bX@(*hUK6ZIjxdC!Wjp zYR%Y(IA6p`9oqJy`8jC%4q6<1UJg0+r5==-J*4Ds4)rgK3~}ragr|cz`yAGva0Rei z3c)$ZQ3m7Bv3)rt;6bF#7&*v6Iw>2(QV!0^zw?Nn#oswe!*mPJ-bBunz5@D!BP;VL zCTC~<|HxVKLDX^`e_7P-Ua3m~@pZ^5CH7wYvCa>mPIwnKLabE=|M+_r*fYT18{ChY zK87B+hCet9&=XzE3ykX0-H;ge>KOCt75E3wI$FXJ#8Dx}s0C@KUg5mM>sq8gG4En6 zzI+Ox8{^ZKkJ;-v0x8GbJDgji`M1P@_RvDI9?C7G5QyR;8up#ky{CK zsDRm0Kpd~jMEG)mH(?=712B*IM@j{$8bJ|qgI7JGKP;{Y3i)c17t7I{h`%Vg7m-H> z^bO2wrec{z=5Z@$$W@U}JduX}s-O?40q-`w>(7s&j0)$UO6mYyCG>g=@#I_x3e+mh zi@bJbsdnY4>Fi1?MYTQW-$4+(A}tr{FP1r*ItYGYIDP52|IJ%Be&j0$pTGZ+51a^A zf9ml^FFx^_;?c>H<_=cs4m9DmCw@ztybAt>6Q{N$*{Lmd#~rID znR4|Ga4f8zI(_rq$5v0Ro;=l9Tttx!9_OeWUj^^+Q=L;CROx16eF!;&k!2wdG6_JB z6a6U5z&HwPMQ$@YF+#5DEMsTjp@W{IV3uNh;*>+&Xdh z3MAvyqv#f9cM4JY?VyhA3zZ1U3%c%(XQ7u)o_gZT@%O~3Cy&Yh7&(m2lmAJ7j&bCU z9~a>T>ld@d zPrg!1e79Bsh=gv}5}YAeBRETN zj^I4OeFXOtJV5Xu!RHcu9>FUKKA+$V2wp|-5J83@OOPWd5Nr|@30_TrH8?niWiU8a zCa4fp3AP9xCa4kA2^s`Vf{O%~2rd&`A$Ww~H3W|myq4e#3APDdN6;ep0}RNqEC%FQ zjv!A^AXq2ZAlM`*61 z;B^Eof?a|=f_;K6!D9qh33>zv1bu=5!RrY|1Y?2;!Ia<{!F7Tg1cwBV6MPZD7ZbdJ z;7bVJNbm%~lLTK%@Z|(wLGYCXUq$fM1aBhv8iKDS_&S0&6MQ|vTL`|D;M)kko!~nN zzLVhX1m8vQ-2~r5@D76SCHOvq?Hg8xA9BLx4E;3o-wir}XSeum&b6Z|Z}&k_7Q z!G9t61%h`I{35}BCHOUhUm^Hag8xSF>jeLu;5P{VAA;W`_$`9pCiou&zf16Y1iw%4 z2Lyje@J9rHOzX->1g8n^BKUNI=M&sb@B)I*Ab26cXA-=K;Ijx`Oz;wd zmlAw7!94`8Ah?&{48a<~S%Px}=Lzm3$P(lTN(5zs3PF`%i{N2`8bO_)LC_?)NN|bZ zGQkysM+ja+@F>A+3BHhEo8WZ>ErK0_HbI9VB-ka`BiJYC5-=bRjZGv@bsSSevm(kxL_#=WpCb*M?|H07j68s*)?-QIR z;Vy!g5j>wDPw)t3<5q@F5_}rLr|{pgPZE5B;Nt`zBlsHRf9xHs>CZ9r^8{~W^jo3u zk9`}#w-ez1CysrJ07m^2#})_{36=fDv{K|L{L6 z7NAncg1ZSGA^;<33j~V(aFXC|f`=g)JcHnw1Sbe?B{)fN8^I}p z+XX->1g8n^BKUNI=M!LK^aK`ifX^U!A;Aw~V2-_$;NKJc z0KxYYd>_I061;=pdkDUp;JXOkPVk)s-$C#UjPbEs2yP}gPOwUF6Tvb8#o*Wy!6Lx| zK|t^+X7EXZPY`^Z;9~^;M(|OBee;28wZBsf8ED*@&G*lh%-2yQ2M7QwR#o1pk5HM+p8S!H*LBCxRa% z_&*8WMeySUKSA)51V2Ua(*!?5@Sh2Omf+_IexBgJ5c~qcy9s`g;Qu1{C4&E(;Fk&h zE5WZ2{3^k(5&SoTUnltQ1iwMB&bj|SDy?rMxWMSYP`Q1C;9m*eLpAqag7*=8jNs!0 zpCDK`2Czu*0Y*Pa@F9YKCipPH5~Fg1UC_^5*#PEh2Um_XAnG--~_>~1Sbh@ zBREBHJHfLE-p}lx&CqiQKFaF;8^Om2evhj8cL@H9;I9e(hTv}r{*K`92|iBdPY}F- zxqJq}3kg1x;6(&4CU^#oJKEW3d{OL00%%2ea z8Noks{{Az;`v^YC0l1UX>Ry5~1ZxCm3Ce+R+y2<{{}O>h^%rxSb@!OI9x@$}U8FVqxg4<4`}q6(=889A8$&`)0LJku@XThMM zsLWI%f$vNvkw_rR46@8*@C>nH2^v`MOj?UDh)$b0E`FjY#YZ1O;OM(hRmwm(6pIvF z6foUz^v+}(aI!H*~b)i4BQMDy2Id-pvUP9Xvzs|dYY7yH5W|;KgCs9(`49E>8HixOo6b; zkY5EGwskM%L=*VFZEt-Kd>QDnfc%*RiUiP**db|@%1lk;%ig*LTJ4sYt7Iw}1igWv zH^9~*FaNDM)WJ&3fjH`icnU#feK!&V*@sKQ_eaUK{8h46odhf%NRrk!{qlT1z}r!q56 z3~&nkRfg2Bbzs6V2cpooe~G+WvQIWYkCJCos09vep)lLOipt=}EyYUAq7kU)dosL5~LDa1^Yy1C|Z0DZP_OgQ@k_+aW;aZ z@8M`a#k*nHySrg`!?3#u!*q%N9IDQ4gKrh{VHn}V-9-1ouzLstiOJ~|dpq#}iwq#b zadDkvwbJK!eVyawbS}tqJJnCWol>FcZI%2sXKRk24UZ7ug0)-t>#|bR1^NowxCR+X zp9?zlWd+Sieg#2b=`W*eMZnRs?sH7~PmGE$;yVGpL(KDxaNIa-|NQ{t{$cwc1o#8u zp9J_Pz}u6;+mpm#rjd600BUtjg?%@av3vAUibL$sjft9U5m79rkT1 z=LR#Oj9`|D-5HZhn0bouZj2P^ZHJe)eG@6wktvxAdhsCzyiM)ih{U3}`E5HGr(zDv z!qAxdPTE^OD!uhO#kVPLQ@jM>{~fMD+_gBDWG0RnJ}#1pxWS#vK9uBRgWr)UJe~w1 zGbY+c_RSdLA~azl{IYLO1%P$LoF{Ib2F*ZTk-6wxRPEk+)ta?FWBt4pw;r}WXMJ|- zkHHOZeRuzTx(oGd@Y8v@zoHC|)D{}p6cg+n#)}AmPX%khc4EvsA5Svx^j8QT%`dq8 z$0%Ahe005g?dnGB(!6sV@55Q^U}f+L_(EGh+I9=QVz1oG87Pz?umf_TwmYZpDn=jRC zh>7fKUZsGTb=PYySKS=mNW0q-uTmV^5?Z>dIjvm*TD$_ZdIf0t_7&zw*;@W&YiYL& z&~_J~eJoH40j*<&&^Q)Y3;~T~g>ZN#z#*CdhiL*FCkk+^D8TWe0LO;{wA%$Zt`p#h zPJmXrKqUk;)D^-3-+;18)gc`Q?WIAlv^44kXwwVOq!*xBFYtH>I7CzkM*#vH1PE{l zDS&GgpPfEfaXUlL90v?a%Rz$x2Mz)pJP2^aD!}ok0LPpH9F+=iWGcXcsQ`z#0vvw~ z)T)##46PL@G^Hh-B|u6`fV7qXSuFu_Tmq!H1W0oUkm?d3F(*KpPJrB(0LeT7+z0~@ z4*`ii9U_}2Kt@l1teybb8-Yluu3rcbk(JXSGIIiC`vk}b3Xl^NATKCD{zu?}5F7}> zR0wc`58{x%QRG7*I2;0UJUT?SXh8qP)!|)~V??Fp5K(}`L;(&J1vp$3;E+*(!$tuP z9R)ai6yWevfJ0CLjz9%Cx)k6DQ-GsP0gf~UINB88h;y(lt@hBqM3P!*??eqgJ6DI- z8PX4RWA@X#3EJ+^!pIk@Fw%trBoB8>ZRVOyWK!c31^4n=O-~fw%WKQ^hFen-5;p=Q zZv;r-2#~N5AZa5&21bA^i~#u;0n#r5q<#cQ{|Jx*5+G9~KpszkOrHSRJ^@mJ0;B^4 zNC^s%ITRpQE5uA+IMu9!h{*lmH1W0TNRJB&P&OPzjKv z5+G3}K(b1Jgp~kED*+N$0;H@2NLvYzwGtrXC_n;JfFz~>*+&6VodTpg1;{@Nkn<8C z?=^7ty@I#@*$+EgGoKsYPsl^56w*)wrIhN`(Msv%VK3}!-{5gYx?81??G_-#EkK4_ zfGoEFnQj5`1bn(%;cbZgw+@j+7a(yqSZ#0AYL~i0s=cGeBCMu;FSnhTC65N%J{M*f zv*%TN`zviXW^2TH_DZ-9?0X`Zr^^qFGgxXaO+bixi1^EOJuJBxh*=pqW^Lq{#gSu{ zhR3Yd^Yx|WikmHXd9QyjqkCXIltBLJnF6 zwN$M&Yqh$Y&o-LP9QC=Bt$2-P#H2n89!3S>aDfA%yf>sL2M^0RjGyp{JQ(8`I7!1L zy@Erw{|Hw_a`*@sjmG)KF=cusy;8J{8+g&!bg%=~!4^H|N>30wvH9Ljr-QwaeXlo8 z4;xArjA>v5f!z#W#3r^NSr~W61t4;0U3IQwuawhPuB%A9p?m{J1^eZKeJ+7(z)^Ck zTE;_NHt(+tD;wm%mIcKIRYEIKKB+)3j-Ul1)6;3c*k>RU>hjBlX1-8&v&&wgKccHt z3%pW8dm*NS;`<;a61P3^c2BV7=k4^!68odDNd5#jH3Vo8L0$Z#;QXH zLcmq43gOCC0j^#Z;L-wttq^c=fI_$gK!7U+1h|YqfQtnLxST+M(~kmMA@D=M2}m8{ zB%}aVE(PG_FyxgGaI$gtLgZii_(_c)NYkjo8C%Oy#w5-jNeaH3Nooa_|f zgr@)}Jq0-NDZt530ZxDp6kRHnh8E5FQKjV^sQ~9m1vppQ&n@WZrTzQ)&fTD}TpQuq z5%r3P)V_)h^X!$X-H~Iijux|-uhvJcXK{qmX*Rk!cZlr_rXAZ@;+Wd93>TXjGjEyC z)3A`y0*5nujgj@fgZx$J>J``$M=ev?YlYBb3cPqb_oamK!9-4&15!r~W-*RMF^l0p zjrou{+GyJete{I@&S3TaWZcr6jKwKr%ps$$m<5c-F^7XWhqQkZktQ(_@-T9+{d3B# ztK8N!vE+Bt{#q1w)~NyI1YS^FXTNDS#_Q5c()0^gTjNk-$5 z*iNg3B3;D5* zKY`paXM-!;z9~4Hv&?)GZ@bxa;2v`wHY_$m!x~)MlpTl@u(s~3YG1i?8SWKu4roN% z{%bE-=4<`Q6l}c?-g!aSB9|86S^&GU>3t;F!Hqr1+z#K}n0JB%|DPF>a=BIP6ic~k z!RxveQ2&7~|DCgzIlW_D^PLaa`7Z057W%5wzM)>(H>Dl82VlJv9-88h z@a^cpU4>qx!n|PZW5@i*tLUutoOK+;_Gd@0u5##zhNoi{p3*w>>SG?YOc4&D@XlQ9 zk!AvTPQok4oenlow-99mt=K^BoesPJqX0H=9WNb1gSwV^Zcoyyt@iMA4ixP4T9?pz zRJjQfD*Q#k<4<=L zxp+Cf2Yr~&#XZs4O*nw2L%=;Tf7vqCJu%@Yr{BSm1bz{59l+N#dog_6>Va_qJ&P~6 zzPK4&EPIm6WehuRgHDB<4tp8ewY+l5fwPz39N?TCH^#Nh7xpA=IlPatJhl$+Hgnpo z4OW&Onb(c^s%5^iCxPk!eW4%oic}v$6>)a@Y8)JE5z|Xrt&swmfv0@c_Wy*|0l)e9^|4~f z@ZpyB{}jYe21{FB!xKM|(UW}=mV)j7ndA?+ztTU6|5$8e*$)HodFr3U{2bQUy!M%R z0?QQqH*Ehlm-XPmzL=l^kyPrxpTa}mzlQ>UBz_5YKs-K?pgnMq#=$#SKwDF1Opg;kLFZ2WL9R>6bRK(v|k+S^7L;PtC%OYax#(hq^ny;nFO7y7l~p z*7dX3uWVd|L(5M0?Cu@#?3MPH&i0+h3=;#dW^}WsFlMoi- zCxkQJWKyc${2{aL@TE_+oh$lKxblF)QXNcu{#4-%rA83ipN^^TWyi{9o=7 zoB)BDnuK$j{`X@#igo7r9>`Xq%a9gwrFWkuyxP!<6g?I7;LC)chm`6Bj?!DuCXUlX z${LQY>$ov*PQHT%S*R1eVbLei`A^8{dx}G^I>A2=-f*A;_`Sl8!=3ocD1Fes&Tcsl z;#R<{?#4ZZxbSZ~P?xeKJ+uh&!WL{B(*B=mPGGbm!P-4FDU5zejh{& z1`hM_kDnu|BfUMr$1lR@`{m2xYGce<2*ak$H8DvwCMPzXS+z@0@B5?6GxG)al zzTvK@xI|H7jM12=iMYfi?kj5I_7^p3j7Fm-8rKN#?|15MvtZ))J>T~{-}}8ibI+}F z>eQ)Ir>agZciZQn3sh7o6~nP(hf;Ur%-?u{KMd9*y0rG5QgvtI*}iv2ra#+v|09>> zbE_Qt2xsAn+@ggmSK6y{hcC%FYgXo#t;|iFxnFLDy?Duxl9FV9SM;n&N==VM)hF%C z_VsdmTb1@LikM3MHlh_{M9w|l294SgH-c#DFTWg!_~(!1QmS13gR_fDoKjUerDie= zx&3tlH^w^|s@Mzuh;w;PslpKdV&GFk_>k30j#~}<_PbCX#7S9Qy*)ON7YuRo&LR** zH#2)z)1np9QhEQC-?7yR;H$f!Jlg-*G zK}5c$vv5`2(5Y-D6XLH;)F$&4%rfoEsKPH_Nm>t|=D_T$Y}9~Tjw(CrhwUl^-7@t= z(5?pX%EY*QO($yZG>EHRo$p0@Zvbt8jNM1VQYyPP6wdkK9NMj_Jvgj0**oh@no}R> zOuTmY+H5#W(!yCfL&@LQ&nj!9o}e0ynRV3>!`fOMhI5miln=P(GtMaMcv_py0ZHQgLZz~}>`$fiU zTOm3-N!DvyAv$}E-$qGC>k73vP3hR;NOKMd%tgGX+u|6O7T2Lw{Re6{t&=HoC$aVp z2sa9ntK3?k1^T!hnPIOHFkD+*6D|cwRhgCF@lkWDG#c=L2G?Uz!5G(py14y(mO1XZ^9>}1t zn>C22GYo23;xV1s)KEJX1FB@~!9m&~5@fUU$PC*;&RAq@>|xgSaLO-R00rJH)F$H9-%qzvbOsNXO|w4lzF z^AXT;744QBF`REYawiPU-5oiSKOv&b870e5;z(xbU|f8msTcr-h{CXsUh}Yb8Tgj z=`=>s3D5-07Rq*UG)!|1Okl|DE<{{Sq78GJNIDHkw?YHM+7rcMr!+OuX8P5Pv0-a7 z_XH%5UIGwrMNY~&5(&HIEUqwEZAs^Ba2VDk1huBlZ97Y{0og|4hP9W^%lfUu+;cK0 zZvDeV$;RQCb1~zItcNLLq*pstF||s!)xV?j@wbkV=Pk>OWxWW}Slcg1CX|db3+XmX zIP2WzhpU`qfk*G@EcV0I&V7Ek#;Gtpo?gyUKiu27+Yk3~jJU^Bn{W;Zkfd{GfD}2& zLZ7YJnI9k}&g}tG>ZpXzR_4qIkaFje07*HY1xST6E$OF8JDUTf()l_-dN|XIe71~p zO@L&bPXeUM8CmSJ^>oe)kZR|>0I6}BOMJFo&e;Ld+j%`e`Z!jp&sOW8mAO?>n{)0C zkiOOw)VVzsK-W}lou*9lDQpAjrb5Ltsyk&=C=30}Y+=VT8!Me;nOc=S7jx%Gea6^q z?TwUqbaJ?Cq&rHDfYX4FPKigw$Z{#zYwUf%&{7WxM#dw}04Y1qo{5ulHJGFaCY!%R zK8ABk*HoIclT;5%s=KGnO{GcURIdc7_Lo$D>6%KD!l^zDQuUEk z-*-)=N#Rr>4L?8+G@N*O7aM9)I8_Qvt_^=9scO5X(xh;zkcJotk=KB(sWd5^YS$pI zy(HCyuBkLBoGPSYxun{=Ybs3&rwX-=*V%xa*I-Rt(ydq-lkJy$n#75&; z>i{oRmgDs_gTuFJNk0`@i-u;+qApWxy1TzsUCkJ<-n0_Sb_f)5kA6jwba zH#{&OFpcOmnN-ytJX%lsrg0)`uFV!TA5Cqd)3WpSkGJFy&J=Y{bLe=K)8#Q65sO)b zS!@<^o(#zyGw96h<~yikzR_uhp0AyZ`I@r@wl=JTP=-9_A?8}u>e?dOo)$awG1?@M zZYof;UXs4i>I>c^JmkSr`0)73FeZx}cGX3OGdQJIMPp(BnKs5`gpSGp%?ZBnH5k!K z&ghA7t~d;7`NJ#{GX%2*@)+hkLeE1`GaezBgEY!Go^DF3lbIMlqgC3|PoYEp5NNvA z6{zPwcTqK6bSlh9=Fo~w6HNIq^eZP`;j?(@$zmT0VX@Ju1LaI2ix?!AmeD@2tq@-{toe}G3KJ-!cJOHIs^C0uG&M15hm5A(joKxnF}~nDX?tW~ zB+K-iucARHlrrTuhUm1SX3kc0v+~*=S373w2dHo(9-S6HP(~l?Fyxsu^8*mqs19=O zKuHX1Ag~Q1(4WLIp}w&I-0kR%C_}o*lzB4pQBiH+6x6^dE$!wm%mu$?463H-^et^P-ND|Y_Y}KuH0^3i$wZAyT(UFQC-uY zilWjF!ivW1#lCI{g_$n*j8jG{HK=SfY)oU5&X_bN%}Wu|Wu5@komWej$|O0L7%5g} z8Ee$rNR4@WP-kwBbftO@qpf4d&BM!?$!w9X+UCn3q_YQTAHA2Rjs`0h7@V4ybY^Pp zDAsE!;#$%%Gm(nfsQ)hBrF}e`U#3VFKVHMC?d)8%H)~ylre-z`*2t&GQcl8EF$WquQe*_HL#fR37XODI*(7~NHU(BI(9Rz3uOv~s^1w+HhnC#o$MqwBbvV#0 zRigIr(P%R`FC9Gu=jP)9%s%#VmZ^C?k=lfdIf5l!3@sRO#V&>+4p@ncO#ud7vh%9N zC8T38ZS}nUQ?XnWjnP^G;pu`@!3$~AOqp&PxGZf`baO8cki1%91v!_Y59B8!eyu;; zEZB}Fp>0n8!7`vhd40e$NNrum)``Z8dcm4CKME%}J-vQ6{q;NN?1++I$n$yGN(=CX z=SIItALwuq~~Ih8>G>llIoucJ76hYV4ITlkjWX)2*ODN#Sqk!2f8#&!(XHv-w;&lbU&B z-9$A~rOxwR64lJxKjS8fx|0!wJ&RJc213i(_iW_99KDh7J9b;?7OaT=JQ-#q$!CNR8K_M5} z^Ew6Rvv8b`<5C<~;#DQH+H44WV9DCxJien~@18^LSV060?7H1cMg9Yv?utnfFfs+L8EpWELxdIOrxJckKfwsV71#-`@(cxZT zqth;wQv{wR@O*)n3cOO_bpme^c&orW1a1-dfWSuuJ}vMCfv*TeLq;y|3j9#urvm>a z@H>H#9^{D&ED@L%*i&Gwzqt`L|Pc)Y+9 z1)e7G9Dx@KyjtM(0&f=hD}i?jyjS2u0v{LntiYE9z9#T3fqxPBk-&cl{7T^W0;3t0 zJt446U=M*c0{armRtZ`H!iG2t*;CHz{z+foXp}`_+_?jiZi>mCCi`pcTu!NEPmgSB zWUO}X{zl9vq?-n)+tBXdfKrBR-WrmZ-bpu+LT9}W4kFgdao;%*N>sbMJ5F&H+er0U z!#WPGVsm{}beedy&GkKFI$&Y&h4;gvQKzi=uT$1nOQxH(1k-}MHH+dFN`?8FQ;Cda z$)jhILx9FZJG3qXrV8eoGPp|3b==OmR+FnF;k?~Z?)FY8Tn3Q~gel}N zbr$Lr<3Trd$`sD~(8JvzuIi~)Nj2&^wAxr-|8H6QdSo7|#k+upYcb&ngKr>Ri(l=W zD{Sp(X5ScxB>BxvICHB#+hd6b+Y2tDlc>lRj$+Xebv3EH%4P1Ga8`6mE4ZY^1YD;@ z?fO)`g+CB!=c2kMNUbO}M_>0cqV4FnF(cNFK7%Pe>M^0lBKIDwFS#@Z7E}Xn%pkN+ zV2v22tR6GxLRv&-Z>HUjh<5a^n2~8mo6xd~WUS0UR*qN3&fNq2>mec*LXj}Gbx%ad z1&G=zdmXdDf(27#Oh+~q7gpLQf^;JjmsCWp^*~-o$1vHY%-w0Lb(EQkollm;NrcTP ziz3SojPW_OU8(U^WMpn2gQ^Y-v14*y6gSUXHtrmmS;~BMCQZdT=J#MmE~)%U)XcC? z#;M52?~VB4!aQaQ$&ze3*8DWsxC%QJgf?1r-DwC}rvtRyjJV2lL1o%B>@z^H&jd&p z7&hh@$=2S8HSDtybWUOAo?OgFsr((h z4rvg>xtIA!PYCfr; zaAai(e90wL5*kf{dy(ng<2aAQF$>4HI0|rZYu9nlzs31R97Ujgi1VvBAVh8*;}T{e z4pf|Ko&bi*lIA%$8P>kgbi*{LRMI?22y;lFu}hjq2!UnUFhL0YI&)MAVJ;VmJAggz&P{m6k?DrDR*gpeM;>`b__GXd=gxrCCSS9T;E z*_i;PT@EfA&t-|zW+okPP9Y+N#-Zh1lR`g9$5ZiC!MOL)DpF=ib1!f>7oyd=)wE$M z66+ZO=FQ2q@kAaLb=yw?+lStZX@gcVqh6XyJ+7>X(=ab=M0}lYGeB`gRK0S=%E2MMxa;_2{ z*4 z{sHnt7_HrGM_-E-I#1JyT@NwoSSDT2%!O?#mMYk^x*n<1*s3yZtb@2Uf&OXQ(-|&6 z%R<{r;lk}WF7FdYqK%R*G*;7|43@ZFj^+`$Eklj;ax@*6n=IhKqR8=$SW7YDjF`0? z>6(WjY~2954R4T47aFNTx!%x{M1;fTL~{b6RAHt{Z>};G+nu+jU4<}OkgVI7DSzpv ztgQJM&i@Q@*Ta>>wi;~sdjfU-#q!_8h|?GW56~q7qe3`hho1tYLu~7Teu`|3C+bW_ zpf$Lnruq?QG2+l}BF<*Sd_Q78KLy5@SY`eo6m>nu4i42QQ-R!rP{a1sb|I)qv&cAs zfq2xq1!Y;i0Fq4JT{=y5JoDhtl5mBhq5L(fKm)BlGQ?_P@&)?hEC` zNTu^-z{@v|-4)Y9t?sP6-KUj&e;{o?bsy}FAwRW_#+NNhqcMLw%#<{<_OEfae*;hy z*E0pwV$x}6-Q9suD<)>>iyetAbs#z?fyYgACpZn6JsbHw&~=KN$CKkyaCobw5GU45 zp}eqg((7*+}^eyDpklA>QRvzWVeZzl6IU0o^8%OLw!wm~w!?duADgCJi zYdh{`^zq9L1S>@^4R z+INEh`WBp8-=KRaMWTwx_DmtFP`d@gz6Y^+I7?hHT7$eJEqj1Tlx~Bjv6fw#yTsV{ zQcyo1&)TT5q>iiHZXN*{d5p_R`}Y7^w-VV>!{n5@rDGx%Q^D0>O=*nNE3*L{qUDRe zmeH`5S{*h*x%(hMC6vDaBIqQIcFbkqQ0)hhTch&sFZv@iZpKlJ;?V;988}EAf@3KT zk6zPMFZ)rosE?@qAmp@cMs(DEh(UV1sQoa58zlG#1Z$^{KM{zw1MWtW3e+ls9@Dt^ zLrkTm8m*I{uxUR+IVmIsnc*N#QpfYy1mk6oM-kW1^_D7A?qZK-?Z*(`=qfu!)DmUK z1R5Saz6pr+I5QOWw6Y}$tz061By!?J(tZLgo=EyX&)>r@%Onx)%D)$DzR|`4hQ>(i zNveYDAEaZAP^{*HKL=apvB}2qw7n1J#YP+2Tg-~Wg_zsThY^#18VPwr{XpKJKM;NV zIS?{qWjxDpxJ}v{VKnJd&0ul2Jb0~TozAO5pbY+p|<++xWX89Vh@ z4_~E>4&*6NN4T5!Vw?BKk7j5OZ#zZLHm6GL1s)Q6uhQIewhV;AGTP}QZgNTDSw(I z3uhe+m(@*J(^M(8Ltd$aL^*vmC}yC(d;Dokuj$Kt72+s8lbVUy1ly3o~#FND+DP&H7U`y_W|v_rG2=!cexB;#eE&@Yf<|}-KOS* zaa=n@yEGf5t(B{_;O{SbGKu{XQsm(~Wz%6W;&jru{U^|L$`)3%8Kz4ua~S*C4=oRjGmws)0Oz5T0l| zd?ouujwhqNFHUa%r@=Dka<18!e;Jw=X}Yt3E&3G@*!);@X@2=fAdh2-*^Y%Q#uB5w zKhH7g7irARr9J0gMM7Ee={BwFNj50#*AT@`2x+D5bxe(g;db*;NY1~GNc(>Puv)a= zz}aux?QGljHjrQjDdRmj@4_-ZCS{DZ*Z;^;t?)~Q%NuT~cKI(#6YZ`b4SqqM_~C+_ z9WKaTQD->}EgRJKo4Ro6rXulc&<_4}6{7X*#=aBrhW!?x%+ah9(70fX8t`N1fc+VJ zZ*bsdQkHmdA8&)VSXSe>x%SUMO5$cBYPEw0gm*w_eHZHJiI1^8Q{qp2;+P-6`5Ta1 zi34_)Yhk50^HN<(FzFJYy)p_kk8?5`-!Bkpax*NJkq!4eCOD>apqNYrYDd`bf~6?V7Wxw;mllda z`aMv$Vnw2tJfoqelEEq!+d2@L$YLvF{{>vU+jmen-Dp6^} zStZv{_jFOJNZ;c&L=;RFidK$jm<%*bB~r=GD*F2^+?resHDhbo!CScT8C%U@x;RyA z|COcO51@54RVubW@Cl7NPt6llN2++;>D|;vcd{_7xxzcjy2h(o$U37NS+O+-QdPE{ zRPkzt(xlsZwdcsWRExll#6vVv2QVL6~>9up7TQXs)R;Y*Lh^%3N;y??^K4e5sa00$mtP zmuJ!`txLK633W-?pLVNDxz;5W(nY6OhqfE&qT|E5q@YU*Kh14_7U%*KL|XP2yD*rp zNLASXKy;{yRM`LY32wD&9;dvw+hbD|>(1%c?8j34HxQqHlHN9*O2<}{)^5RbM#WX7 zE1S1~p`ucJRk}z1DRO2~nN$yPEbRm6WHW6%wMw@}VO1*KMiDOE{u~;nv#G4U2KWUq zSs~`1rmU(|RVv*+knB~dO#2`S6nIJLS{=(TNmdrY?TuhEyiBULo6pd{Uk+cCs%m3g z{wmKeL2>b^qkW%R8TP5LnCDZcV=n(Zbgw}v0-rihod%Bxwp9LKPz7tp<7l)xFdC~F z#KiwgM3e&sVLA7Ccj09Dn7U~_jdEml~O~woR zTf`RXeKO9}WS^|i-6zvCGC0L3nBFk7v(Jlo>cFQww0LaUjQ|=1ODD`! zsDOx)Ot|}`Gx3V3pSMaSy(0DwGGWmEH#7MjAYG(0DbkrpHz_t##X+%BMV&J#a!XR8 z_Zv&RjfF!Y&%rgERki)??UY@bDs6#BRB#hJfNx!otYxgyI~vO+%8_}Ym@T4PCXvefnl*hTA-nc=laC(>cZLVE6YCtLfF(WQ>`sq92? zbgPrtm%@ADKlfZvI=(FqrgY&pK&U8PU|+^!ve)q;G|u^^lMDCy;8=l!8z4*`b6-v1 z(I>cc6h6Xsa4n9zam)jqa`~%iDp&X5j0sjsYEE0wE=F;RnpxA>d@BKhJscXOB!jD= zGeO1$$4$7%si#tdLExn%PNfROK-i1Nz;5aRKzoq_Z2<2w6Q?~-posnzN#Hm621#gx zB*h?5p_Jx5+KcA?Uj>v8I)P^s)&OmS;Z1D9vLnd7Nugu4CUi6cu}KQ}6*zu@!}IYM zVS$Yq6t^bO)p>#)csf;|PQwWf73-TM*Kh0-DMN0f#LS-_L&8OInFgAAiY%iP64f+S zDAX?Z?65ai#!^wg#%R}BZ+3SbW38gdqXE399L05yM*l1_;<6PhyQJS#)?4n8BQt+oldi*gD0QoCw((>Pwyn8&a5$*kJV5+&>w4B*!&nv#Ky(dq`wJqDe4#ks7pJTnp|C=m#fP{PR4@2j#=tAaY4u6m*a!B@gAyKB4fu4~kf+{CaIUQ(}EoQdf5*>lkVhoaap?jbfS-09T-cRk@>B51){4pUuT4sa9QiK1d<50{0L zv@&h&$-)@EDiBHlryI%>R|RxFxGIo}>B|CPSdaUrd8#S;~S;+H8Ib(cD+q#C?Y!ZMJk_^L`LeQK;>f!1H@Bgm={gn-S=) zNpU|Ypog9f8cGOMhkB+GZV?lKxgb)Cc%5Iw!XGSR%ESyEgF&hQUTdJ+P9|J}x`BQt zqFpS*`2(Cip8`}(1O98Azhk?>+4I*Poeqg~&o{9Oe~$w`tb-i(SENV z+ta?Bnx<-n<%2?hPep^vm^RXSo~L$1<+`3gEA47PfAb$cFJ@!2Dj8i5zo##BWZO?d z(A0MBMG@;E+qAK{m2AZx0)kQn&>-2m1UMdGuC%eOrDvK&&UEP>@C4`{Q9Fl-%@+2# zlG`|fV2Hs^Q*sTW4SD283{D|-h0XKWflDT>{(vpJfhHll9%y(|Heq3B3fs{^AM*Vn-MNJg zucVFjlRF>j0YUD3gcB01v@kgjU1NV6X)r?3*YnqagME}fpE z>21}ZaOrpkz5Yn%6i*dy;s#B3s!Sk5LeIOoOB2>aBOy(aVNEn5?I;DKb1x{x&2VlU z`P#e-197h>U7SgmG_!A~ic=+^prLksIv8rsp9F=ZF3$UHcP_Tbh z-^%vTAgge_j=q$fvHY%(-M*3Gg7(XBLO!P4--9-cYXFR~v3#Jn(0#;=ZjYepqyI!z zU!3_f+L%-}qxAD~8prf0=07io>pje}k$r~E4SlbB`FcsqZfZ)<-VNEyrGgBuFfb!C zs%6PVY`3H%!6b9&qHM9uD8+YV8w;tc*FVs06jXKr?NQ-^QUx<= z<7CP+cCeqQkj6ZI67qyw;ypw^rFIr-AD8A@1j5mo#&+`#obs4*qQ6_Cal$JzBzla5 z$4Yn{psvd~>U=by=8(*2EMtu)7cMzreUWUT6E!l{ueyqdSHT5hE&e76Q#`!sCV10e zZe;HP>gpPq%|hs&z_R06O?j%1D^vN2IP=o&-it$rg^EQ`gWL2;*IGF(R`x>$*j5fio;k=IGl*kZg+eYJaLoj2lHU#Wc7 zAAAK(#pkkEy^VN(T&OKrQq8=!M+3I7j;*<1TU`rtqFqo`Y*)<#$vzOkY)obvu|#J3 z9xKmgwK5GJ*F|J@{Oha*`(T8n-f)@MJ_HDEHrr`+b&d+E%Z>5tBvi+pqe9gsS7P1j zGDFp6+Cg=hc2HfW9aNWT2i0YEtS(OBP)sR}u0a@=&&67Z7!4cb4@E(7<8)oibqs@b!`)qMN?nq?MNM zyhExq{H$){5Hl>0WVIJVZRhDvgdA=389Nd}IKO<%@ z2cc>_2Tivnq?^j*xwA2B2iHQ&WPSyBit;M~iw)DZakf_hG~|y4EJ^6rXgfe~zZGD@ zUd`xup^ZC~lGxwjnBHGE4PsSWu;|Q&nke6W}k1)pOUFC*oCUNcx`0ze)oGkl5;pUUuQ0Bmbx>F-WwgvGWj_j_R9fzKyk{6~Ax_v|s?-Lsd2)}~d6 z?Yy1bqu6~~__5^b|1$0MUcLkejb6SC{K$Mer~To4 zF-~2JJUCum$20CBJOj0FpXs)TX&R5(XMrGhA~)i`58=U;e9gqMY6#lMIJOaMgU6UO ztK4V3qFDCFHrwYSMkh5TDL3m@YJzwDFS^-2&r9#?a=y+6{jWf-r;nF>E+8KrGTaTD zs@YgA&QAAJPJj4=SG^F7POcWyl8X>(zZS*xs0}_<3J-q16XS9w#Ltja!HlRfo4?qX zAY!%g>`Op39182oOuu{ND(;HYr(lWo4*t>;y<Zzf)4UyoBfJc7so z!);IJY)=F>*8>?TyrDBlgo}kT?&NQP9NsPDyvbBI0!tMX%9P3e84%OHNl0OCEXYS;?iME!zl8<$(Y88mOrNLA!FLjXgzY@Jp-Pv z?Te0N@&(8{8`HW^E57!>O#2HjUj}|;zMa$ln0#;X@@3#h=G!^#kIDC!UcL*7b0gT}Wt^i4ym4-i#}e%mZIgrJnQTIh53OI1{Pv*vGIt_A!I5%#xYQ%&^PMe7iDJ2XCNcxbr|+<*!C4 z3Ns2_%N<8ds^pEBWYb~zId9C=wJc+%iLnl2CMj~KK=)%NyP7-BFzAglOy!Q5l^iqg z`JpkBp2d~H;E$A{$4qtsR|bPWQidKg*?nCZ4E`q>|Nk5_7qD0S;F!4-6DsV{lvw6poR2cAJb>|k2IWHh(Xu*VakN3B~CfxT5z=4g}H&)w)JJ0wfWtu}HU zrN}uMipBG{A>~^1f49APd!-~`;E{uSlttJp_4A}qH_vGuGWr$O2y`ajy4yk1`f+YR znf$qBwSSG+V2i@~4bas+aLE8gSDo!br_~Nu?b(Gv-X_`EE*D(Xp&|vaFn8v#hjDZ!h1dZU}a#1a~0; zd1>=NkHF?WEo5`NBVag^VYd)Fw|qwc_J?UdjArfE<0Ttun8WPJG@qVaWuEl6eGE#YW8cB3itPM!+d@4_i6FCf-zmG%~j z)Jg6^(7rdo?_)4y-H%gq9EHc;8pB4O`z7sITHs;_p)JcY4l?=QBSw4sP|UYGjp6Xo zISqDat5LxG0~GZj^Al0Q;;LhoGD2>)9|B{{ei$&>d;xUDyXXD@1b6WZI~T%n{RG4# z2(}b}MJ{={@mz%AO(ZOX%l0TJg$`AZ%R?AeFOChQMqQ4*K`2Sc(>jF?OOgn9LfIC| z0vY-|hP17Vagj;iX0EnpGX4dAT?1|^RtegPcOOY1>KB8dyxXM|XZ|`|L$$irdr)fo zaY%D3I8>pKpT?T?TrCcD$Teft`1QbJvXqn(*-wBfyHxJo>DU**H7B+ymx~q?F7b`s zCbep4x#&ywhwJp6B~{0>>V+pG-AT}klWPij-4ELW>bV)A~f6z`VB z8jujLnLte^+wVpaBVPm`(az3c@Fv(~I|h0$cyAEAF9_Zr1b-g{A7HSJBHiz-NPl|< z5)Jn|D~$6#eIb0sP@=Al=gc&;{u=_Or}Ka>rT~!-MyE6vkpj zi`qb|ayhc@hbcs2707OGJ(;W;0M5dX%hsv&FYlS}9GCl}p;Qiooc_Xq`%M(4^1ckg z;%97lAx~lZc|Yub4TMa+?X7-9mHmPrmitP3o;%;&p{CVkPDq<$B5t(N;+yRkB>{8R zhN*HtC8G0x$rsnNXV@-`b&`F3yJ+q|`rP)P5X5U!UiK-u=U8H_$UBsn>AbIRu;GZW zuwRi>0sd-$S254md^~Hv?uToSv;RjBHaqb#uAl(df&`xt2qNwYVmqxZx8D#!M0AhU z8U?r(B>1U;Alf)w0>STLyyh4D;g0-X#*CBK*}H{cHTjAV2}*$ZuWbi@>>vtaaXH+*9+GgUZFh97L)d0 z5bNE(tgm_D&VXbqd=bV4VS67O)?W!e0MKS>W08uQ&k!z#WuPx^o(n>SAp?C$LPlxH zz|@cW4@Yc5kNM2jrS=jb4?;*n?qUd~klViF3At|sVr9I(+8?j+SXg+x#-adzh;nQj z<&L}IqiBOFRSTrUsX^8G>9-wBx`vck2&KPeVM2^yq_?A{^`66(`{s{KSjz?{|me6$jW7_IypN|WDSA@Le z71oq4$1;sWTK+ni;JJ|S8i{<61!nadZH&}8Os2iu-phNx_XF!r>daY3XT&z~AF9tm z9^F)*KSwl?2X)5!)33jprjykO%!#IPZP4~|NcnP5HAOVG{tmxg#@)91{mz@{ z@7O!_WSOnPzw7iB^a>xLot>Y9J9zrr`UDai8o^Smg%-L(x3auNhzx|vZFsy>ok9z< z2Nvf~LZ&4G(=q+luWULV$31Ez*y?eMnkX1@A63-bqdR}>n8!D6WQH8IW9(1a3T7e; zJ{D8BDMZEhDRu*0r1K6p=RIFie+cmiOKFp|5VCkyW)#pWeU~B<#ark`Qw8!R8Qg}O z(3f|6gXnw!aUe7!K^Ie{66pdw!KmLN#+pp&kI~@%*RY6+em^Jzk7>FxQt{082<`xO z@3$))`v`6nPS~HJ@VF|$le|pK!6%No)>|fxb<;y^&<}$#UEGXoB&woV9BsP9bpUMk zsgmHSa(Qk?)>TJ?yE0vt!814(g3zhl{s*nTgx00KAyQo9nrKxhKw`bXEDjG?&OvNBMfx#GjzpbXpz9CBCu-;AjSXWlKw$qveU5>o6pHZ2Imu`p zgkrC-sdO5+bBNV3))%a|e*tJ*SKODtIex_beW{rJ6==032O z{5fd-_VENV;oYGf9pGD|8E9uS$=mJQtel%MRq)dpvv>I*pAvLvjstjo7%$JDEehsqy0CHg|9*!An3cLpo<_ ze|f0fK$1>QFkoB>#%&`38n!h7rVDhc0=wH(t;CK}_z{#iY1&m{H z3HEHmbo5hs*ZlzSbH2qNHX-F;{`|2oAYOiYKGAU|^AJiFnrHC4dIQ-f_-?3)kTqS} zUU&us_XUfPqR06nxdPedG1MA_ZaJh^M4v(d16ry!Syp2oXo%*acSf{2uG>FdQ7AufgHb zYnm*1MsOe2f%6S);Y?}3b2E4gP7yTiH9jX*;ZJDu#h{|U`$aEm?g4Rl3Xi*%_|%P* zyU;EH8;IiB-}1G`qj{KgxsT@Q=~AdG%ll~bQMQq<%#c3hSCg(F`24Z-`DL)2RSX5z{RL?Ur|>efaipg}Ur&{!j1$@|qDvZk(Zc|A`nCZ}-GdOe$l?3S@1LM4?z(FbP7v(Q~ccnO8C z41Bth+&09oAL-dahc@IbSN!$Fp%8s04wTBbv%eSnFpBE##WLva#bUm~r7ir}n8<4| z6Mse?Z>LYT{{d`9zKX#|g5Z-u@aZ7BBwLJ;myBNzsGJVC3~vMs7z#YL@aF39t^~7aYwc{XuDuZcQHiFId zy^J3jW*W$=6YN=W94nGuT2;-wL=K`vAz((3WwE&P_fa*+VTocvpBzJF>_KR z;i0dRlo7cXk($p zB3a)c>=d4YjCPtSMJq_Wo6Lmm@E|kd$PA;In^~O{g_50<18Kx_7j#iw*zOCYu|Awv zgJi_JQ9{_ZcT5H)8hs_ur(i!;s*|()A`#Cat?CsvA8Xv15^xdkCQo5IoNT&sh$Bxd zMLSrT&Bi%1kVd>4X~MQSkVYKR26U3fw%4i7=!U#HW3=;XkQwoAG84A#L1x4=Ha_hE z8&RB-8Q|N9cozpvTd* zNROkZlpaSv=@pSeor41Xh<8&&VOtfbNE|9+Yo|lAq(08cfi&W|zjbMr!uDVwjX0!X z;@hFFSt#fIKpOFGqzPMNqi;UqkT$%NG+M@)M>gF7iFYGS*f4X~MQW(2Y2x?bb;eYs48b(ASN4H`0V{1KD&#Ar5IHJ4vJebe;&L5%1bB{bh3C zuQ)z>4TI6nXMqsn-82kgD<9;mL>wv&^;OdTijtjXvT5TJ@5WyVTgYG0>pQE1WW>9c zgd>7;Rlr5O8&!qvH-W0ep=v*0Rp^c$%TdL-FOWvO8)?G!$3Pl!NbBE88b|3)9){Bi z&&rH;-VQP&UOTztuq8ZS200N&PJR8Hw23L!DIDyZn0PlP7PgRyIeW<3{l!@^ELU;D zJ1-Lhk&Lfh+)+Eyg54RtuLJFd_}bO`qCpSyszNsoR(VkHyG?jkx1OxNC}xBUZz0h;VBT=vi3kf ziFYkoGST}EZS=IxF9RzP@22w#+t*~%otHQ)GRn7zZho8;diM)3oWYzdR1T7=@YB<` z9-=#GPQwttEW~9xmpg}6=tV2^_Bpfs9xH6jalx6wRJuzN&;3<(9KGw5dT>0ztZpv0 z>MVZdWnm4VSoaDn?PCuN5vWrK!XJEso_|_{XymH=V4V0_I$XP51?BX$Tjvt$*_YHR zYX})(xdvKpDB1Ce4itzIy-T?weF*vWrCh@z(umT{5ABk;%dk~gxbay~xsJ56cz)Au zDALDet@$9eKMLuPFT;8dWjP2MH|-S+y9?xFLhHTI8(k~6N3gbqQke6?@Ug~`nlGx~ zHZIo?k!7+G_nPsHE70$Q4OgIroAIi^tnZSd$ym6n|`}IVC2a}h&&xq#`o(Wq; z@mMq@0y)7}#h*GJ>>eETfgRkKbESnWv&V*tSC`r^gg#zAJ+>uK8> zKyGk;&epO>tbP!T)p@5JGZtLmaG!4<0f9h^aiC+!{#^;q;ooQ=JSZG3J5q!949`b+ zHuTKzMh%TN+SVS4a8WbbCN~I10V(F&Nt+SCsRgI}3^Y_5uLIzo5MD**eq69rQf$va z0q=E9_U?#9d+_$~(eLHkf>UuOJAd47+!N=0r5%a}V~{G^G7Q8hH=t_~;M;e!euc7I zRH)x-%>6z83Lv+BxR)Q3cbVySO?lA@W#j6Beun_QCf}$w#q?W?q`>$>GR5GN_b{TS z*yBKG;I~nALkrsL$B>8i`gfdAE-#*C7>VTjp$zLjL0qM^7cc-P z5&0y|Ml?op<#*9oWloh75%> z*_#YCsMwHR!wqXO6CVfwGHg>O-@(`)dPe!g7``JN+1_JUh>fByj{u>eBGUE+a=_`I zI2~Awz`r#9Iq?#ck3Hk{>tWUEQtb+mdr|%4F6}Y1I4CJQ23o0+W zFOR@ieaWP4+X18YOvYCstq$t9I?e(S4iNtXBN_XCS(AS&?3lvqn=Xtt5_n5Q()lB+ zZ7D)6{UJ!lMCC=Ic}1B-}cRg~cQv z8Z$?;jbT0F;H7!EiOtMA0M-fs-b=pSJh~%|?;&3Xz2H-DE$KUIJ)4E5pNTf2W|o6r z-U$+IjN(myaG#O-tyrYES4j5-b9tl+PF{a}Nxmke6S1d-sf~EYQnHy}C`AO{?|wSY zbD6KT5}73Bx|e+{ynwwQq!u+#L44faA7MOLr{7$SO(oPT*)>64?q8CKI&Z?t`g1u? z!h+Uyw09xW<6~dj=vmwk(%i}|Nh%hX+r8cI&}14@?B|~U$|C+y9IJ7Vm%kc3H}mkp6HF z>Tn$GI6VEiZw-xQ9w4dOE`TXp%Rmy;`2YrNCoPE88nPFLXxI9xiUcRu1jEzj`1apV zagvw8o4Q2sM*cqTHxTXa<1*NFANO$eEgKzvMjkbnY-fWu@&};$+u1HLF(CEd5;Ph7 zJ_xeAdN;%}U2R)!eR%#!n$rYT-FY+dTtOt*GsAF(k&$F?>yUY7ZL}TG8Lmy&9uO8u znlmL3Nj!HO)UWLkp1W!>dhRMo<}(SqxfYwX>m7vAIdLy@hLQPCI%WwxwoiRFH}T_s3eG?eIfoX4EC;E}hm%h-bZgzULef08k8DzN4W{uLB))j1FZyaKGV4?YNF`=G#u z9Yo)op{nkyZ%w%e5|>S*Fg&k&qXOsxEF5enui_v-e>M2FV-huWkk|zQtl8E=wskOa zX{iQ>(Pm&&a!!T*sPEi_{2|Q$Pyh_-JE(0`2ABMNklK}unS}OXz?04UKm?wfSO5gO z^%Ny<8IQ}S73_r|H|TGC#Pl6Kz5Ogh-13%jyhZMCutV4)oLc>NpjO}^3~1(k$nMHtuNN)prgxAhar+CPCjtuk)XKFUX`;dVnC4&<%I zFTCMEnsW(z9$J+vBZo0o<)BE14F__1;{d~ODaZLPWx3=@RkJqcl@KIqV+Q3t@_<1% zX`>eS$b-aT35T+%T4^NUNor~8lw z!*&%E$=3jQk7xMQDzwul_UQ0HLy4 zvI0h3jipD#UMc2fl3XbT*HLh&W*O7DsH8a$2Q^E)c3G`^K?hycv%Wio2tSrt-asre zZOqqQK5sZ-4OF{|Gwcn}LhtZIjHXm)!tIT;@Q_U$7g0J4*`#@968>jcioVoXHy8`6 zhNOY|*!c+7(f)b_%UG*e8h2kyDsLbK`Igh0RT=AOvSloXC+8Dnu1Bbhl_w=@t>#Hu zvA0Pj!iG?o`@F$khPV{{RVu9Kxq#ssbPp)apJA<`5WX_awCB)ipALX0Lr-IP6M)>| zip>%Ki>Sp;=>Q8x-wwzi1@m(Vm@WqEnW-h3weY*kwDG zk(8a6@z*TlZPX6$oU~3u^Fz~zo=HAW!u^C)v<34R6_pi)o&+1f@jm7J>EK5DJp-ql zis6n$Of4YoOyG_K^=quN5R`4CY$M*h$7=vIhjli{n4XtIvqrVAVd2UTIt5X`CwAsd zb>tyhOpPTUTef>5jZaL%iNzBd&S$AftEYyTwjGc@|0ku0&MQ=+VxziE99O z*Efz`aLD6h@ls8_vtXfi%EIei$=^)3r{m<4*=`U^etu^8F)W@mB_m(o*2AOD zDbtumo#`-bTb;ieW7=AO-x|91LI%{?J@e6e{XQeEwQ&6-Wt>n0mQ3w-s}XCw+U>g< z_|EMXaN)VHw%&-+AG{Mkv=wP|d6|ag%VJWqc`u*aGG?ILsyGy{vL(-`*E_^Jld6L#nn~ z0O>s;+#V=f$Ndpyv|*O3KZETuaQ-v^9`(161pxmzQp{ z(T1#J@&PBKZ4iS40FV}SAJY#if-3#rOT%`K!l}h*EBWVjyJ#N@c6|PG2u_B43I==5 zTM?HZ%zXlE*A0{lg@KHO>Lpg8U6{&-grwaB5EZE3yq;4@*|!{`bf^hmY8Z~UuaCf6 zPe$U(QZwFe8^|nEM?xkt!@O_=Wa=%F`yf-}vRmv%eT~lK?W72=-o*%#$ySCTyXZUJ z&S3LUcj9>NsZW28#fiEQ$MXG-&#zvxV#vNr^7a~M(UQC$+IPvq#Y>z)xfS_EwzGWM z;e&E>mN@xk_R2BChcxkTP;SpP%U7>)mW)}sWX)=4;qpPbS!)hozHHInOOD^)K5EIz zF^7*DwQ#pZyNw*yvg?Q?P0cO+x@NX!-8a!+@dM_Vy|{>174+Ys*>j@)_;KK zqnecZ+X6gOemSoBt-9)-*;sT%ZkjrA!v5BUix%V}w-5Nd=jUhK{KsKU!<#PNTvlAQ zW!~49E`5F5KVJXymp^^rvE}jTs9Tz*nyY&ByzR3$KKXLoaW{Q*;=OA=*-`(_$1k7q zO#QT7FTVPaP20`$cdQ&AJ><7{@0k0GvaheZ;pX&=t6qBaxHUK4bleGdy!yB8wWlsQ z_`dBQwzke#uz2yrqWH==6ZSfOY`@B3nWZbQ8FcS0n`(C7any=`{(I=?*WP{LnDuYX z9y#)ubt6U%|IMoRF8}nMD?k3`+^PH26*fGx{H9&!9{%fBPQ0RI{*L-=+xEF#$+_|Fn&lY`KQ#obB zhC%;4=$_N+X1{sZyn}Y%amN>HuY0HZ`5o0`$KLent1YpAn7_T@s>9b$zu@_zjlIs_ zF{pmlAs_tXu-0cjz3cX$-`#iYv#WCb>z4lV<9FAbw%b$RkK230cPIXS)u)G@z3H9- z6PKMH8M1QzfhBW)cj!CUt$S;?6}{g-`MxO^MRE^5{M1te2jB9+a}PiD*xpkHtG(|( z{nopV{t{J(hu0^~n0VVB3r@z)>K^+|!>*!khS*(I$8f;ht!dP7*&rxTt3dnZJbde6 z9q#_Z1rxPD!uzdu(3SGQRIgj{T*+|I4%koK@Rm}aVItmdkLC8^h`R(!cQ(9!lMk3W zk<9K7Z8S3Xr@tMSK>lhICLJUoxI4g1oH12UFXDIyM=9{%A$|eQ@8Up^^CK>RR2dHJ zJ1T5=$n|y1Pb41A7PA|yqHsWjO5kAAColIkaODS6LHHAuL$KWfu>3RwE2sI zS5yvWO{&@EVP;abo8-UHyb|Htgy&9ye-O$)5w1{$ai(pGkB%qRJ_45t<%IYtpllMj zS?IqM__Dxl0zZ#alNE*JJgbm$&KG#8z^epaFYsQ01qs?ABX9&@MomhzBri{2DFQXY&s6Qt^N}8%y5#=`vTm)FHt}nWxD5>r*qMi>IU5O7ezFzc~qCV>D zBGz~s+g7Hk7dQg2LM<((oTG)pO)Y3Eumqb!rpgK2P2f0zb4!jcG1W#1Zx;BJz|R3I zRL|0naQ&=5U{XykWv$IGWxX6xN;|KS@UI0vE^voHvut#{LLE`YGM-yTJ8T6s)wgA| zOl>(SBLH!uSoufEjM`96n?D4IR$Y!)E~wrqmCC3IDN@#^{vEAT7p2Zf)v0R%GwN>8 zGiqf8WB*)1%Y0ICm|3U3svu86ns8uxw{)GF446@i(&S$yuub3v0`C&|puqP5D^#MA z<;?-ssY#WTaFD>01)eYPDuKTh_@uzs05fVz59YE+;N=2u6}Uyv6)IK5`t6TJw5g61xJlqU0;{nu zH`OwM7Yckx;KzWas$cakky5n>Ap8$j>83gnFsXi4%^KNK{X{kH^}@p2RO1Cs7Pt(s zLY-JcuX2&V-wAviuv&dza|K#sy4PQdOf?*fep5{nI7i?TKzx_67j?c-C|d<4u#;h` zkpkxcCe^y$w8@#hH}+1dUm<)`^j^5)SEP3&)yKWr-m3bD*Alp>PrgruI0T80UZ2nUm})Rq`=*);SgOvcWvQ<~IH{hjW!rnJmRe2Ak>@tR2K9dK`&@&n z>HB>ysgCYDHrb#qK)6EP)%PQWKNq?&h??xP8#P(98~ehh-DtffBN={sB*Vp{2zv^Q zjA3p5VFKlE*@Kc>CrzJ}R2wFfXY&lEdO+aI0zVg6F_ZLx0w)SQOyJs?OnaWdt7bk? zU9Ik!N&oOPV(Zj9GiklgXR_ZF&3XcpyM|dTY3r=nvntfGS!~;<0M@C?XKn0Vr|tl( zP>;-dZB|l!IqN*cre~9|F*SnK36@ql!G-|45#KB5C)n=51_A4@PKuPPnZT9+Ymm5uBwZ!$^QFus zg7v^I4Y5^%Ww2X9tWDBYsWA$}ygIGladm%JRcbtBDs>*PCF*Fw%GK3^IdZRVx%zoO zmi<`$^=JyZm2vMQuEn@SoiEr9VC|7h)CKA~ z*r{j#sj%Ut*fk+%e_%_1T`Zc70@gQn1-_)fxS0}ng}O>ba^-3Pu-TET)U}e|k^Pz9 zwdyXx&Tz3U$^hpLz?K--s`~}|onSx1D;o^Rd;-`3kz3Vv!Tu!JZTLbX#xSZ`nj>Ooa2*ic|g)cb0JU?YKD9sK}rNq||@6p8yl zO_I3%1^Za-gDBKk{pm>eiJFOqSFUVe4@Eyy`w8c9!ubz1HxdQs>DZ!OqW+-{5p08C z|5S@2Nu;|N*qGQq)sd3!a-=K3*PM=wU{Z#Wk5<|tv%Yfm3yIsIjuFoL>o2eSS2P|u zAp%rA46JXgJaVPPy$7rS*iR)c+Q7I}VJz^(%}Cblaumf<#uBgVMrC2qIKODOF&>%P*6`oMY!@LTIqz#Re$2ar-d z;7P!~0<8hhB0LOmn7U}d7L2`@5BO85X?`)_!_qnH|BdjR^=9LrN;9gY@#E6j>yK;P zg8QaVY|LOz(|_RpfHMc4BJfs$PYK+D9n&6zs>(e%QwL2epR;~HfrkiOEbu6Ss|BtX zc!t1>1a1;|oxocJ-XZW_fsY7$M&O$QKNI+kz#Rh3!OXW*V5Pub0viMl71%6ryuir< zX9+w|-~xe51+El$tiW{wPZfBcz{>?*FYs1@cM1Hxz{dnWEASbc>q3J}>Zm zf!6_M)SZA0s!vniXi)V{tFclZ-1IoE$+a|nh_*Vh>1jxq)3g=v2*8LMIcy93^#p91bUmJBB;CIdY^6Fd*VOh&u!2SZ81@0s8t5(Ju zqY2XjYezqa@Nj_>15cYa*@Cr1^!;>FOGWvvHvsf z5x~EXdlK+#NmV?aGJ6SZ6*x)YVu7a%yj|dH0t+UPf8d1Mvne%h!gE;@tI{o)jpZg0 z9??qp6F{`mNl#X#)W}IMR(U*!45YU_XVTD~DRtST5rF?QXo4Bx!&0n1Clg*N z@TUTA1dOO(PJR^YmS0bP5>VHOw&b0Y>8l@{{2b`ohd(`;zWrr^+VTfY$zg4y`4>-V zL|BgktEP~XsZwgql%b$MGv#2wj|7%ZWq22XdrqZ4UpjRGC?`x^0=RMNPXK>5mEUvz z{oZWPoncgcy!VHtQT5s0N7O{sH+vri`0n%!wq5@|o%FA!Z^4dJ;XVsf0Vl)X?0q8O z9lM?Z{?kWX1bD7MO+S5CruuZB%S0wQw~V-ooI;PxxEA5`j2i)KW{mC;RrNDw12)b0 z1t_Cu{0eZN8FvCMoAD&zQ8S*aNk`VtcnR<?^J<|dEqhMNQk$P3IjVj&vS!oec>m2GE z-@`hh6JF4lA%`c*Msz+k8eaokO{LL$Hm7XEauqm8^PEy~fMTqMq*u|>ETn5klo?xu88muS2&{*L!@wCxX z{adidkb5bfvaH&bQpmXiSpN`Kt?;=+H}1T$8Z}R_jq1pOmz4EZi+$|MvRZY6i(NbL z`m#DTVuY9O_Og04QDcSo4SWHk*DM!%a^PKM4QifX8`WzAA41#(g0T!+%63t22&VNM zpuP}H+hu?%+)Z*Q9A*BoY=D~OVnfW=%No@Jjj3p#cY$5yV&lzMBZJg^g3)Fll?_(^ z7HlK(OOy>&6LE*M!g{B~{IaY`HOXGKw##reUNBwnyQ+CQ4)!d?M)U%~E>r^s^(x<0 zO=<_}H=Ke{4 z1m~IMlhpqr?_I#7tgijxwcoj9CWMg54RV8^ctJ4|?jR~52@pxRC5RUkhs=S?LHh?f?Nwqo1!FReY*UjM(f_I}@a zCkaYD{l4dWo{unV_F8-IwfA0o?X}mwyzfLBbO~ze6-7&En}gj`)Iz0=9LKf(T2U)a zaj+j3Eu*c1>3S}w8BLt>HFe`ukF}iU3wA4gb?WbmmeZ1Ej{AlBp1(GJQoV%V2^#nG zg6VICE~kux9S^Og>kYPS`a7X3sFV*quvWihdUf%Yv|t5egOr{=xA-c$M6jKKk54be z0pe8}qt8yipg4@(9ZtDZtoM3)&R~yD@4-#7n^#I4eH&OO?J?Mor{58Z(DyYK`0weL z6mOsxO9ic9YwCnO_`>!jG(d!zcni^xu_ zsh~r1S%agTINhSLz?CyTT^y%JO8bJuzc$aW8EZY&X3; zDR)!;%(F@|)Vr3kTWQM7T_sy-V4cP;nE8W}ep(RL*oS9& zOZ%x~y~e&ab8hK1w9R0LXD%t-Mh^jhx^4>LVR<4(^<4fc$x z%}LAy)lAT~XE(i*gGo|)#Va5)uc^dZuh2QBq@npZy%LfMCxA?kTSD@1r7veY1E1uxgWXPtnc3`)QKF zUM%`7uqlE)MWf~@x}O&4eDv93oOn^(#7&x0V%?8t2)MkbXr5phgSF3j1zfiF>bQ96 zz5XxJ1A^_K1bBXl9(AxPV6B@t5L9emV@tIVHY{&feV*-hp99gOom zK|hqzwGJL2ZBL4!33_Nc+0 z_Z`AR_0QTV{VAk;MPt-HufP0x`n7`%l>Zl%CeM$TAEoOJHb=0V4Av&t zEe7M>JWBT(Y_|U>@;$0Cx?=uY<*(DT4tBi!4Jx=!N~c@qTVvm(DT3+Ve2eC5OnUPz zS}U0D&9^8bnC{KD=n=tmZ@xu0<9-D6n)b~v8v7RQ5lr{yTXdhnxHo@Aj~I-5^H=na z!MHbnP4hp@Ty$^#h6W7Az4_ntlwdpQYiQB`p&tsSd-J#S$^hr%{#%}RoZb;^XW;kq z3+Z=MG{|u~1Am&|18kDPE(jFT@9BDjtyMk1Zqpc*pI>6VO%E7sBCayMO-~u@obxA* zeVg7EOqcgI6>Zlg%s;=7{y=9Mtoi&NVDs%btSSG8It<1>3ii(p#=iF-=`MryRrLUS z&|u5Xzq9-uI%2SO=l26E*dgUnFY5U&)f#LY>iI6s(HJCg-q?3(g~kHG@;l4_OqUpJ zUg?y)KhsrC$`xb(Ok16lMPvU;1Fn>Rr5l};ivCJ>X^h5SkU+{?ZqRi(^#X;%trrCw zq_Zx#c`T{SPLA767hW*YveZ_CEd%CJ+XU0AYp=RjFul6=siuz!Pqg9iSf3hjuwRbN zQ?Cm)NXr{So}ii`j=~`7f*T~NR~&^wx*Bn#)PTXR1vXmUXt0k18>8Ma*ykHYjSH#j zf8p}rvm>rV#SQjXU}fsJ1}j<^@{CpUKcQ2e3ammsYOwjhs#NJMI_`2{HEONFu3mWF zxC!begKb0HMD>cnJ_hVmHR;nj-UE95_B5BxQ|~x&ir++iKi5p>o2Nd7ogn(s#$aI_^BR z;!Bb*u(A2K1T^Wo~zVa zgZ&oRdev*Nzb~F!98qr?taQnXDynXKkXtxNla~CpVuQLwoWMbvwWN@`)b|C`BcMyY zW8!#cuUp};SMoJ45e#A5t3;e&>{Vi~+remdd1V%3?=Y^${RgMzo}OFTqguZvn5J|t4&%6QkeZdClk&AZtwySa9loIIhMNe1mP)iJU{GvNTJ5`5+Jy&_7x<#--%3Hd_ z_c8T~iBnUjdT&w%PiQVvmfjKigc|2y&sFYLmk2gUbCB;Awa3JL0n1IKd0s&ApFBDgM9a>>jm3M!Bckl?o~INxEq(gh_h=>XKT+F4942?yUP0< zjAs9-@_q+n?fHs&^8n{$`x2=7H}x06b_QNrT2l3}Ny%EU(_>@Iv!?2+4i}nzTGiJa zjCp=Tm3}MBbH6%MFwOIc9G*7DJf~NE%i%(^&#QXM!IYJrRALDk{#ETrdic-k2A zY^nO5!-ZzAtUBai%=1So?&A4lHQ?g;lDbV}V!>Wgdjxwe=xLoAdP&`9u-4X~^^$r} zuwSTS{t{qwp5(UwLM?;6en~YM>}5Qu_mXNAOpmIUREJ=%1&iA*DSk<av73w0GUEa2*+~wV9FkRlwg4yNWCfE*oqwOYedBhd>vf7`6J!Mkrfzn{y{2w6aqE}u zuX;`W&=vP{^@@qxvg}3mbG(&5TeG8Ts$e_l&Si>@qNf$Doy_nNK#Lv+^vEg5$x*7$ z;=D6muv5al0>9ycc+m?|e&Z|)r5u;=*=I{$K#TaNtZ;%WQ0LWfy({)Z65b_gvSAN> zY8d6;g`&CrLc%iv?Na_Gl)s(LHPLBo3a8N&PLFoEa%Jf@A9w7D!i&#kJ{mrautm=S zdgx`LYf5g|LhM_v*rDkaJ&m`BS`?VdDNCj@|M7qp&g?n7Rp8S?c}~I&^-O1I;aro$ zx-IVwwFIRI|V*0P;=81h8Ddc^ieZ7ubZNIP8GU_I}x^U2FWSE zDB;H>d`O@!_s>Gdqku>=5zwO30X@WYFKIf5v127^o|7~`lSw!Pj{@AWam8Q(*OIJsAmM$Neg#MxO5%XBg>uZ|I1-* zi~gUep_Wf})=;FwdW`G&NZUOPb?;;;_AH~*yZi3)MJ#QG7HtOf&{ml%Ic%Bm-4ecE zVjlwZ(xZSr`X->Cz73d1KLQNU%YZ?84NwstKmi9%>5-J0VngO>r_tf7ksfO*$;El? z@JA&4fToC@*JH{p=TSK2gvAr6Eu@y1+di9S7QH2OPB}d6IbkloL1J?l8h-Cw9%^68y?F_so5RV_eXjao zV@7JOy)w7V-BQhlN3!Jqi8@&H44{X;FSXJ<|Nq17*KOPjSt;d)voo^7Jtt22p=ISb zMJ>m#SXSeFc|1O+Abcu53-DHh1$d}%0d8_PAlyJ7!e=`^jDJ-H zP!{58#46n958;W%OL6PJ3coNHqLr!(kayZAQdBXYn^g+yXy((8Tw5fJdy6LT1L``Y z|0+_3=v%4^HGW0yK=?P{a62iB>s({)LjC7iH`6}kx|JTH_10a0H(Gateh275`jW+b zD%E{-0Hu5x6kU_&z#&A3Eky^BSK${B`QFfB%JV!7SmJpMu)?#SUZXQT2N0g=c?R%8 z&vya&))I$*M8_oWamsjJhlFqNyao6P+^`R-|M2_)C539T znu;4s^=hTJOf@LJy~NzctHYG?o~~MurU$kBlDAH+RF5NerTV#~NqJ|eu*4pwbA1;e z{T$ySz?q(9s$X5^>i~>-F9YoKtp`2s>q2;!FAn$_-*u`$YFj{0`*tJD=SBteE`0_m zQ{K<2-BOd=h5teNAM9?tMt{S3=3X`0zfYA)-cqXbe+}W;{wDz!_`d`AE`1*yTK(LL zbA2!3hCR#kFm3d|ituLt>*}D~(0WX<+?et!w0gAvcgXco{1V+konAfW{}b-H^Qq!% z>Q#TxI;h^I(FpS@{-9dm9}76!Uu_+e8Xi{#c@r&>m~~v$nD9B4vM$M+VZEz1=FPL} z)nj=VS`)1&^Qx_o^;}+yRV}TUYrUD*VNF8#GQipX9;?Dqfi%+OdA3?}Eq~x1RjGO1|A0dRp9G@zYiP${7c|jX``YkQrkgmOt4E0T9bl5 zv35&%uXSngm)1Tj7W{APA!~c^e*n3LGbDYzx;yCeyla(s3OveFnIH17c2#(Sp0o06 zJt5EX{3!^p%fAq?$DvI0$SC$akbk*nvgfP$>yhi5`7c5a&*rnPe$?OXnL^*gn^c?V zRe!%{hP1SaxOe7y*ph@ujViH%GpxM%|CRkK!rOFzWmx+T=Mt>MNdBv~H(oljrZFUI6qJ z{KnHEa_*2G+-(&UB@qs-Vm{DBhvP`v^_4Zu2;JXmUthtK2vaynrq!xunOTP^Dg%u zkiIxzv5h@oeY>EL4q86}JY>CHu-<#vn(glf*YIxA|cEN|dhdn%ABJ}amms!U=kBX(Jxo_h6mq1T78HYVRUgU-OMcDNn}#ty?ac(ufqHAnAw2e9dm&%?0sp>V!&UIX+s(wkF4_@z8Lu6p1vngwAOd8 zX?sc0M&x47hiPn4A#L)qoZp3RDC$Rehp*qeuqcR|u5Cpn)??P%q8oh&EDrCLG<&Tm zo=zA<%AKCQ7T>4Y<^598t-ie$-=^7Z!oNToPJa*Rb)m2LZudT!_b9@bhMw>}guFfU z7~pfD+#h-c9B_sY_%3df?6tlXDn#BNgn9sfF5%xum`CMa>m3REi;p8^sQ8b7)x})5 zy5cItE|BmV32!g{8)9!P4*K_6e4A&l#W#cYT6`mjYjQdu?@_XCIoE#}^-**Ta1Q8W zN*4Mn)cBGXKi9KRz3aWQWSM_A>Uo*J!dFFM|3UBPOA`KxzIQ1D%At~L0e@Ap9q>

8 zL2qr@A;1}Brvvi6s)OFk%D(Nt-Nz$zw{N!pdB3)qyHS&u5c{FB*Zlje8_Is^-|hQU z*>8}N$J9YD-+(#j{pILC`}ZQ3!f#Pv2S0Bwa+T&igm4uo-zkIF;d=@2pqFnzJmw3Q zzvh1oGMSQh(95?V4tn`6%Rw*Sdf4sj$w!IEdphm%ttg+C$KknoyL?w79P@pod|}>U zP%zv2*t0t9`${=H2jAo651Tsg6Wg*6y0<)UpY?M2A5inz{)-WQqx_1zW5^pt*gLi- z@3^mIYzF04j{U5UXO=Bo6A3qr-H9~I#(pC2HJKwGqRYpYSjQ+LFg|vN?-*THc6;8t zJ|4dz`ZS)U2+?Q9a!Xmam7hn)LGP1e{}nucF!l?1GsGr5A~u0#_%*4|f95?R_F=d1 z;d(xm_mFs}L2v+1ffau4_Yl>MJD7KjX5%#A7%dZc!?^E*@~v?{$vf`(_~@S^{Ks*> z0Q6RHnzJf?lh@#%S8+NWx0)+@0522Ba%=HlgEYsjk4Wr;6~E65`hQySCqPxH0xkZ+ z%0QsP&zcsbGb_gg4tcnxF=)$9&mojm9ym<(m2B;oRE`g9@?Tsz2{6xdRv<{7m7FV9 zIU_LW-#%(y;33aVNV(g(y>elIXR9U1`_aPXfohqps`Xsvf3va!^j80s;PVc+9k8sb z2%vbs{!^+p25$HBTnRZ;mB2d9sH&oU{^eE40Dg<7sxR=6zpv_a_yaua9q|8a)waL^ z|NT{#I_Up#)%HM(dZUWH1=jF={^Q7X*zc>p5wM{8&cJ@LtNZDV^6#tt;^XZHpC=X9 z_Wr})2nL%r&Lb~?iDTK`4<*O z`t-QKcLl0ErUwN+B$N={P~8RDa!(zwcwKPJv%7jS=2>p_0qds~bAtyw`e8}^=>K=N?|JUl%0V``32ZJ=JW?7I|C8wib7S*f{)=T;zC2H0N=SsN^ zfStjXyn{7Y1OB8Y&-=QxdO!5`n&7XYw>yJx)1PblJ#W)$0eteLr&RbH#*L%J`3LeoKjCydSF#?InB&5Vjidj?imDIVP0j0^b#=f};O` zcZ5QKc$Nhat6d3C7FaKEE+EcY0ITp;mnu5DCJeZtCI)zS%_czjFaie!?glIze>>nE zp}j(R2yox{#{e<1gmO^eA)y?W@M{8@CoG0beVP4@!+mi7U@O z0DC3@zy)eFV3R5aT%yJTwyJ8t6>1`2hdLeb5_LA9dMhv1aLrI0eHPy4|t>M0=!AZ0dH2D0B=#70dG^+0^X$t0QaaH0Pj^F z1-wsv0`LKK3*dw5cECr}=Kvp7_W$+7E^Vo9q;HgV zS07bRmVUUp(fV%bu4>FFWzXgxv`#Hk2%lXxt>&o3vB!jdOz6ji9`ta^py$-GH>-o5 zv&+t_nJkpa2shQVNVrA9F$wPyxX(c0FX5w}UzOfhebn>&(w_qUx%5pyPuYJ1jw%b* z9QBlxmDe1TltC|-I9Xt$mvc3GJ!Ne*jb5%{i_lxV%(+uyJ0-SLV&Q2Z?+&5wlJGqe z-Y4NFC45lAM|guo*L=}b;@WO8R&+4$NzNq;WGd(XYI zY}>?p&%LMY6BD00_e%&zrZOcml_}RxWy-w*YwJH%mYHyUJyZ4|{L;jGCH$1Y+G(FE z`^Bky0N*_A-f5iXDS@vG^iF5WB!L5XJ_-^Rctjx0X37GAR|(uB@Q6T~!?8G1!=X|e z=IK&=FQ>zWKQH{B!oL=d8FSW{sbiYPY#Ot3%z-h#8}qj@rxqI9dGB;yuL=7r$6Mx}>4xGbOKS$<>rr_1jzf2sU0<@sZ4 z#(rq*ZDaq>SpT?^agF0vjvE~J<#9h5_xiX$jvH5TVa4W(f2lZJ@w19QR^(MKs9aWg zZRN)*@2vb%<<~2}S^4YAWYv>ZxJr)m4KJOF_RYqQHQt~zZ4kGKJ}&U?Y2!f|Gj{-R zlE66v+XPNH?|RUu32YL$M&O2)BcN|<plEJ#8uA zzszPnI;`Q3X9ddfuE{xg{R`eoR|@#noJzpsb7}#P&N~43Yk{X%b4`k-d>fQ!=QI5U zfv*d+W6Q@9?nQ7-t`_+CsBEotJ)fO)Hqw0Ve1>MAl?dqcXYAO zS%5T816p|F=4eo!fgTmnw*f7jS&aeZ2=F4DEER!r7S`|q`Z+YK2v6}8gK{=BjD68k zP~HHL1^guR*}^-s&H%g>XKxn$E9zz81n?Zd zd*lsZpGPe$_~Z<~Ag?j~BJ|vXzdal9AZldMccA4KeHVIe!LPm$@EEinXWV%Emqov# zX24(Ly`y|Num$12<4h56SWrt5R)83fstw^hK)l~hEk`&AsNip}M0gY+-hrpu5gskD zSgl65M6CfVQRrz(>>;z^|%)z^|)o0l$G=i*lUH_V^Z1 zw&`_iSdl?!sG~G|Fxk0AomU{arrt$c-|Lynum(bk&UhsV+#PM!gU;Ynj?L1t8bK40k zN;Dat6$tktz~Nqm&qPKJe+uCvCj1z}w|O-E6@#J zFyFV*rE0Ecom%Pnw0hceJ3e>f6SVI2USWOMSLXSlf2F4-Zr+i-J)cwCru2gt}~Ow3;dFa zObWjv+ZD~M>xgd6kp24u)Y247_a@Wf_3^0TLYfk#4kosS`;&c{72!lQP7C`onPh@m z!|Q=Cn}x}()ZUlwjV2;G9W^96yOXK*On*F@rZh^^1PL}K<9$7e#w327z|C8eB@2S_ zXlDjLhafd|#iXe{c1^USzc-4uFdIov4S2rYRZY{(VQi%FV4;7Np-I1BomM1cs0mlH zHQ5=KQdfi{5xg*3h;89iS1cjHW#OKv1Xd-t468qABURoer^yaU6NC-7MFOaMOCl28 zDo8_LCMhvZv2Z-ug`aQ0FF{DmFoN`Yg36MkGG!9QA&CaE*i+L94n zjp3BWaH2CBH~hK4#&|56$VgL%_ZT<3$EY2xh^96`i;Z$EUw<{UgBns@NRh}iZ{>Qk zvgp@*Q?hqm^Ck!&mg%SFo?bxK_r~sUDoqTjCB3FQmWj6ahC89{ee2WmdT?$n`d<>a zMiX6`ZsIrAFHXfG7ssMoXiaqes_3S^XgXtS(6VTT8dK45CQ2=cU6D#|?U#v`Vf1n~N{<>hF2!SvCeY7|qZ!CYhtcS0xW}$i%W`+5 z9VbcjZ;r@-H9`LBNH!-hcz8su(!UqN;U(cj1eO5hFt#X_>@k#PQ+P1+I#2h^C?#NLi7aPC|{E zVqLKeH6`&wF;S8Vz=(?-4X66Annw8Tm~4r}WOXV=&FRi?FY8a(sOsuO zbSSAUn(0nP7A7P8cKsk;d*(5bY*tYbSJH+381Eppv^JzUtlP1?w~JUt7ANsQ`%JOxFilN%_LXShO8pClt zxi>{SvBDS)%O@ph3BY{je@nC%i>sQzkT^|NSUIMUJ+?lSfv+hzEb6VwHRAHy6&z@*jz zF*r;Cw~nN3fo$CH??@WGZ;GWbJ0$TNtIb<6*wPpRh9I(oNyP|vXy_4C&h`kPEp$l_ z23a^F6Pc(Fj64%Sm-ztGIQLg$HwFd5u;==Rnw*|7N@~aidjv^k`XwG2Z5&NWVvbJ5 zdS&c6SX(sFClodn>{;pQE<18COncTRIfkoePfv)4J4DT!F+R}CX&us58#7*FGk!FR znxgS&7n(0DFt39SdB>BT8>10h2p!#!ka$1ZRI;V%4kx;zJg>GSFazqDbyc(nqcEo! zHf$L<933f{SdE(%3wI@w=}fE>o)^b1O0gRSNjL$cY3u~R+t9knnwXXe+GPW{M#%(Q z0Mla*fxAnqKAfKz+duX&V8~XaqMLd4Mo?s9O9UPsM>i$6B%C;r8|!id94`Lm8rlAG zdv|O@hLh_0As_>uleI-+u(ndI?&KEjrAhg^un4Wr#Nds@;0v#ahcoQTXrr5MjV1cv zJ0lnDHD)5$aLzU{1u1K*$n7#MN6t;Oe1iQr~tT@uu=;*d+I*s85 zZPAWb+C^#U#3YzaAYFpdU|f&xsAvVt365IlMht@9IQMIdBXnd=^oa_y_2=1Zb*~5% zoom#b+sq=ewcfTzjeY4%vZo;f{a@dgK_VW9Msl2B1?yGrHcdbp=yPt#FX6dEfNiO5_+ zB5-t>3@zAJr}JF7G($7A(qiqFC*m$&K^7Mc=`^OGc)z2hFtQl&Hd&?)lrP`5HwBz4 zAR|AO(cTu9){gh&kyyu_d4} zD83yA$5~K_qL|@m)-iQC3D}p#ItiV{V}X6gmNXOwjV&+} z6D82bh}{Ghzn=KmVZeutk%=&_1(GlUm}V!VU1TK^GERr68c$+w932Bw8r=}nTLrEl zC)e{Or{SFpGY6U=QyXC{+Ih*I!7@uGs9XxCX~vQbKUJy63sesd6jx#da$78&hB$Q_ z8uWHeTNJv(N}VG^ZUIIeW^QTViG;}IoG1?dCv*}%FdRGGlhA`s3~&rSBjh!y7(0)^ zOh~@6QfBrmlH7Pqds%X}x9UuH!0nDj^e|y>%Jvwz&$I_iCLUV_VvnCt*30%tBGcLKcU(S6wkWnW8p$qrok;Bgp+)xIgVU*!O}r+U zfuzU}WoG9yy)VNkYwuQb7MUw0o7uv4i0&M^ZrW2%FM-wUmOWr6^Lxd+`EWNlnQ{;mYuMY1L3cjH z+5@B`3KPfcVXm~UiUc{iy<&0ZVb|Ki&2Aw!K_nB;59~GzvL+T8vVUv~N;l7`xJ?#< zo39x<4RK5>yzCIRSmOw9=}9JBi#T4>iTGGFP$jHc;rbc( zOjaj)Zna5EqH*}C&H;_>$MHl2PAT{ln`1CClvQVKWVt#Eu{PDJoUJ*A3_PTCI(MGq zIhs!a79~6Tw3gdif}NW*pOVR!wh(K=*qG8}mYNAdH@cYdLa<@7wqV$yckB@N2e`XQ zA~i$j8pEa0JNQd7nO^tqKI1x_v%@e1HH&uPXu6nvBWMY>+oKuSW}ctB<$O$Y_{${eXg4QqjiM;Y)Xe)*yxEfNKiduCgm#1!hRSeaF1Ibb zl_z)JbF=#=YwNP1Hn?QjtqbT&kJez8vbF_ooa0&Td75$igIp0;966JhOm=2*f{M8v zO!txnQ_1ESrZ5@Yaz+r2FG|WzJ33E?WK)P+2F2qIrtH2YL?BwXA{j6M3?l_twGFYZKB$@;*yX0cp)urvlg9|@U%e*TD<(OAS}(tYttl*a96K4F z<{-C@6SIb~!fF$h#?G8f`-0|ndn0df@h&R2PY@IfOWK1OUUuYc#dS9c)2HZw*=^FN zWX#~A-l*9Hz$}7ow4^pRd zwr*@`+nvBHwMbarwv)kB9%E)+V|C3b#da2h4EM5$)W^pd>X~FG*oy&>J7=rm!y zj^YC9@r(c21Q^_bh zo?IBbTv`>5@e!ptJ#X2tEXp1{Tus8kHnt6DKKuwQLoYCRT?8wU#o^vqT_cL@0Co|fg|7GuovCQ;2O+@x|MS(d_&Uid_YcwZm{qFg9%C3pdrwUf4EFMWYF9DR95g;-(gySn^s5U#prM zJ96WtXl;mX#+n4P#$KCE#MvzGzu0!e7Ve2t$Tom0T6P5Am&pjJgi#Yp?!=@uQXNK$ zlT5abW92YXz7s@C*7>M;_N4EE&UHL@iAOq>=DX2);-to0^Na-P@ifP28WKDpVHNtP z(R_W<>xi>`ODxmb%_Ax|<@A$IIb&GL;oN4PM4DMNpC|Qp%++y`lpJY7(Q+#``{a_% zIk{wWbuwOsiQ1=g3u}1q=!G;N+Yp;!P+PcT*<}?E4w?{-#nTsDyMET}$V^Ot=ggWG zo_fxVnX_k{6P`Y^{+wwWrq7uZo;7Fstj-PB(Im0LyybO1s@>TWF=IxbFy_{%(VcqQ zRO*CEiJ;Py8FC}Bp88_TmjdW{Z&>^^it}B?di^yG30W&zA|@b9)Gkbuwyq$?jY@n( z4no+y%&tCJ%k^=zE2kZlT-f6SGd+9Z4yN3*a7FF@1G9lMH|ugE%)Ku7TA0jb$L=x+l$WZo z$xX2ha@mQuuBb1=)?Cl$_Vp@4ZTN0vE>BZfF3~AyT@1D&O;=;;*7J25w_9+;rH=*J zkl^r5-~L-CvegnMoj8{0?aQ#0&QAReX+1*;OXC>e)G;2>YNIdq>D+*Pun^_Uvi(7l zP_}?s;jp=^6EdQ&vuK<*HQD(<$7HAz*97c@?nE0gm*Jq-zB-Gg1Gh#z6Kv?>egrII zFYkP$T{LPAXXG9vt|qYeqswd9kcw>#!~3EJc(n=K(W8bQXO|#! zv!myHx5r>__!Ku{$6#z=3I}r>DW#IILY(`WD5TPaI$)!0lbgdEsP}F3 zS|>`q-Kj9Dskd2d_L$Q6P~Jf!;+;h!?Xnr;kabBEOJms{<4F>;CiYu!^%y6182o%g zkymBBW!of7XPsjKd)6Vb-tE$t3Mjp9c_PXe`s_=L>2)1jl5WD#9L`>kZHv-% zu8U2$>FVm`Hix*_byHEkYl&?^P;d|+6_3o(m_CCLoiU)(w6H9!Pi z$}JH@%)42I@RZLhu-skH6Hv2PpmMXY*U6^+M0cVjHE%g#3x?AP4qrts4LSs#!RgoZ9shxhLILirkoptX>9yJN#z(E zv33iz;y|Bl57MPi(E8zv7K-r{&HG+93*^)%Z8pI?Vc?)~uou??_JHqsI1zI90t9i* zdigeCW3sp3iCzW6p2m_2DeS#~cs6LqHY6fC)|E^Xa$I7#Ybm}*YjaO$S68$?3P%vz z_#1dven>J_T{tjuwb0Is7Kioi5w?j@Y(KBc#4$x}OcRc9(@}AgdBK$JFEJX9_l>H` z>VPl;&5f9m*H^5;7?$wb`Mx1mV14TyCYq969w7k^uZCUVLhZ~2aURxuODnsD#4NK6 zS`yq#awR7%&sXFome~k*5U{B=G@lp@SV1u&859Fs)7QgJ@kUWkUKV5O&|1owApp$Y z*f!^Mnx8}BZNgZmeYGwpwT==;)W}0-L}ZncIjs@7ZmTBi>tVdjIrJ)7OS&x#mkX1s z({h3f2~~t9us4-~bX=F#Ol7#RmW1(~^*m?q-N<;d^#oT};p}5uJdJ^5_QI0-Q6OCR z!#zU#YMNYiZjs$jtXp`2p!ZlIQrV*A8Abxw={Fanp%@}TefFs(z}kYk5z0WXQ!krs zhy+h*fr8s(SZA0@^GFojHspNYTc^mOn02dmGt4qpPkm`DW%RYTMN1u1kj7>>yC`Y+ zDi|{(T}+Gd12&y}0|V0}SHsScU8FYQU}tkQ!d3x`K|a~&i$~y<>C+zBfrB~ErP{mx zX_+Vas)v1W#Xbc_J{vzS;$mJ+!0F29ojfKr^2N-d46}VWq$In(`s$TEcR*EGLexoKj2hbGh(Iifcfa^@^&my@&D z6OnN!a^l<*ofCnwPn2iK+{js+s*RAxi5psuUG)>?K{=wn80vCmgb|jWK^r2@zC2ff zQusj1B3~ZA3;Tg-BhP!<{D>cXwk>XnGLEc#h-csCS#O>wLO&x$?Al;-%f(jcpv}cm2W={i@}NY~Gw!h=BnTr*aYQJy3^iE7Je<6>=-;Ur;W_h{#JS#I7QRHTDXhOCHFzS39ZD(TDSlBC#GK zCv1sGH$fv@ymZ&Q2(GGSGn#6+tCU)AbXPnm^fq5)!4?Z{wYr}B!{!O}S+3E+06Jl4 zSGGv|IvAWLcE+TVEF`;l(S5g@CWMx>)W&9=MWTGt2bqur%=J6QO>iSG53ss5X0tEG zjyPd!$nnT|-hlhA8(n|msA(sTnhr-&KUJznHeZj&>UTYVIc2*qo7qpuX|b3m=nSIg z!ZdbF#f94d=g7IpVXsFJ$xf3Tzw4mBEu^USCGSN$=)-@en;|zDYTVZo#?}319tgvSJT6JA%)pxc2zZrD~Lt| zY@rbnI{Vx1W{s3~Lo6O|>eEj;MES@LC(y$=X6!N?EyL-~1sm3_3-?UwoQ;j7{wJuCR@s~?XqC<(xpmY; zoJcL5d|DClAOJ7xFn~lavp2CEioV1(ME!=<*4>NP3*;*u;#Fo>Q}3;Zrdsc-jV9em z>!j0Mdpr!Q`N=A+&FSP-*W@@U1vY8tpIApP=vlW8Cyno&0B4LRqg>1j2X-f$6lab9 zKqHtrjvxQQ95|8u2Xi#q^P$YsSV`kFAD8ek;ivGZFfUQV@vQopJxu!!DmD;tK+%hJ zkiLY(&Vey5;xX7^`x_@y_B}bcc{*%A5zKk9Fty{ue2$H@ZdchY;s^}YHkg7H#M3yNj3^3?LRmHQx$y`!yt=!lPIA#Gnxnv-D}`PVf7isRy|N;(^0E%X9E2VAW9}Hn|Kt@4TB@4q;>0) zczaHdoS9O(lQOu#00FXFij6TmiYJ~6WzWVr$P*zpu7;eKJ2A!>pcW1*?iArExA>TB zKMkM66oY*jdulT;AHbE&XjH!ZUEgq^|V8*^vP*<=)z*~1}s zr5^e6;r!t@VYtLa?gN=LTrIuj#oZ}aV%*W(%#o7l!;lg3+D-`$G=}j-f7@Pj_9h^f z4VXmvP%wk*{SdPwyc1U_8>8!y#hv1_BwoIa%+@UVMvfekO$3o;Iy~!;1e|?nC)m`q@*g8_hPg^I{q22oCq7=9?Rt zITsNxsOyr6N55ia1V;859^ct~pQPr2>XRtbTx=hy;_mY7Wb@}wnsmVh>(=2?m4e9QaEz1PuIJ^Tj+=oO!#nBg`Fb8Q%%pyrB-dHanQ8~>?Et!j(=<6R z3*fFYC*av@m-a&j9Wb-e;bctAop@UcAAJmu#6d;&xq^|R;UXmZheu!y9l`5whDY!c zNha*!Q5gCW?8c`yW}{$r%|k?4+Ty-gB#RkGlFc*wD*QeWS9R93$+memxv>v;s0Y`6 zvSe&HuuqXCG)33tp9Ekq;2$00YvNcXQ=Ltx6_c^5@&q(9JE$ zl&i{4J-VOZoO_2IWXRv?@JEl&86=U^Y+GrSycA|;=| z5aW%KqEph)=p5{QdE$+*qvKMpDPbm;jdzxy>@Z*yZ&YnWO|Z3y(3yaBpw=OL3T>bi z;AFgA+sy+U&mYcX8MyTfp6jCQ0oFKLs_p#>#V8Mo4=*qmrW1LAQ0H>AFc zP}>yBq6!^fJ1hmQoQpOs#Ah1bo!o?X!A^&4=im*>44d)p*SUBn>}-4%0&>cQpiV_x zgS=f_r*1^9IY`SXsb)1=u@Rpn-sqfwbfSP=s5SQ-jk$)p@h0abQqwe~rSV2k@ao!} z*i24r2hk`y?J_6aL2HNxzRcBIiI>whn7 z@q+Xw&{hJ@!V7TYP&hmq0%co@&no1&1P$(|%aA%woAJWiRrrgcDc2y+LR5Deni5Be zod_>N&e?#?X!J$+G!fovg|wGK6tn1R3B^#Cl|)OIp+>bxmBu%2D5Bh}AsQ^9LEQja zAE*(8S!A`Kc8jv`Egf7!kUVg%p=z~66NXZo5W|BfhMGaVHACauB^Cz*96NE<5T5Q> z;eYBBlrl6`Eov7QK9VLjG=3*{tLd z;l$sycm*;4)uNa5UoHA|2_(~lzj-JpjW`&HD|9}7LH-$_yjR{cknar1uS3k^3=Hx! z&@=A8T4;g(qs#x<++Dmc{pa#_abEM!EM5gK%{5TRc=h{}FyJKJU}lCo=}KGrWuM`}Flc!q>(1efs+3xw?41PhX!b zPZ!7c>Fbl@=;AlbvgP*m$?$V=Tl(Ib^Zwjiyc$0!FBgxMwjX*1mN;jKZ>mGg`wXl} z&Jh3fWGy5-*MVKydFI6cJF~p1;$=b@pUr@A(Ag1Qg{4O$zURPEo`!E+%Ee-a7Z6>* zcoD!0AYMT5YK#{M8N~APqZV)jAam4iJ+E$gCCYp`6|Yt6@N*}%v>HvoPej3;p9(jb zAq8vk+aPUBN2nPKAx?1)VrIHhG-Ekr(`UHojjr^wa_EvC9NSzeX1h|fX^u#-!j)o< zE5!<(!dHt0904|%dez%$Kx-3PJtSsY0~*$r(n5E-ONHi2HH zZ#IowW+#@7oF{DRk;=)%{8*28If;wU2;16_U6OGfdQrQKQz9?IP-5BD$TM{5N-KG9 zqz@X&Ew%M@gS3Pxxbi=&?)DNl+sdSCF-+%=R1PnZW8kIB$;zP?zw~rI%2@_2ZN(q; zWVvQ@fEl5) zj**Xd@yORDl#M1Ym(Tjjbk58BiR6nx##|QX>NXTEk?lD{ord{eEqr)KjeHw1ju>)_ zH%c8gO3IDWnz&GSvxq3jWgEVyk<>fnEP^sIR;56Dcl*hN?X^oSdL_w++oLUA6AyI1J5u(%nj_ z$P?mKaLW_YSu~mlKX;>8#B+H|-t7bEnQA!<1)BryEqA~MYfplLbx`FVltYsjVFP;I zu+GP$aPaI{>9qR5HU^ymFqRK5lE}?|B_6Ssk})vq+o39YrtE}T;YU0WgO}+d6%T2a z3tp7s;!435U{O|`vL*OtUxMrFa2(St%FFUdv+ebqiqCwa679{@;Y>>#s#7rg+cZtV zZ>Ec((rMUKA}1lY zK1iRt7}IgtGAInsTpJ;SCY)o*Nf3qxySjWn#tTf&3xzA`0=^Nm2P+55uopCz;}BXI z&zsC4HznQ$G&JQHK1S^Xm6t+WiK^P9rb*;%ml(YmVyB!+?6?(3!wv<~kLJE)MQ6vC zMz>g@wX`UHb=ZMbnjv5{)MXh>}Vl&sOge?SbDzMSw z6}=EDL5vq>W*Raxv&p^rvmm7ovt+u@S_2tLq1Oe}G)mK2Wad@K*JdL}hkw zxa&eyxvi@uSDy@t%gKicQBShAN3Az2XlyorPWqbMal>)h@k|qRtUYJ&gvi%9^eCSU zUF7t=uq-27ml%Dy+4KqHhrH>Gp|-^xTZ=wmZGgUcE=SMWwJ>v#2h-)`H7J|w#+!7u zm&f^X?Fp9Nr@2#VA8~|KH7(%fUI}Q8Wh(_;@|=zmTcEYM%Wd86+>HWQtQxk*Z1Z{C z*V24!?y(G6S{GoV|9mSN$3}p6NA$jyHa@(j=c?HgG4CcY#;I5sJUH~8Vl5c6A?IC| zDE@fhXjeg-ng|9&EmS)tUBNeSv}xn2+LLTt;z~SlI5JjBI`u z4o~vj&=ZxeTgQT^!>_F8%ZD1cdx!3Ru^Q=iv0K9mbz%pIJfn#Q+t}{#Os%(I*eYnD z^nm?lFyW0%-riy{jx;7Xr){U$8gdSH7J2hf`vW8C7pK&n#68Y=*iGk7v+dc5IB{Jw zBB~aY%QrDt40_uu0XxS$n76Jwk2!8p9H~a~+PL-{ryW&&)5GS-TT;3t_`nAyrm#?3=Q0pq=-TRRfw|@6N?ut35(aBynw}+rXFk)7iG?X?uzGY}1SR zRj0ANJPIz7R>4M`%9h^78ZdVbzs_Y}^BQiK>L3Bk9+TZX*w)&r+zN@hJrtVYjvdaA z=IZ4H&&@p4c(YY69JJs29xbXmQ-+Y9*WGzxSxV4YqdJokI z)Ou`g-4>xOvih%&Lw_!DbmSzoE7U4EYMng#`XFl;&k}m63x6^+jB-BDQg&ds?n^bbgkyZ7oDw8#|?4y4Uy+C21D4cDj=&=^WM-Hrlq`$^hp(U)tQ-oQ(Y2 z*|ypCz-%ksLu3v8F`+&82~NH&ukQQLO2@C+VMu%C|)5U#VA)e=Mt~IY9x%-Ay)bWw+B{4 zt`4(Rw0$_5px1Xe&vzDGdE& z`Lq794aVEP&`&&P@){+5GMaymmMeP*!@2SCvYQ`GWJzmZ-d@46HE?9-&bJQIXN$NFpP`n3`@%hTxP9wD;nNP@j^uh{hi5hK z0C4}ZuhJ+qzAwxaTN--xYWsJ?4_maeuPr|NM9?01I$RzkiOtcgQ4S7&W_My|VJ)e-v;9`+lx1nj%fX{2ldk4~(mSbn_UqP395W+aE!9=x{+oOpkMcf-1|*R%@Z ztYy&tT^47(vJYh0cjUF0&FM_Y9DYlQjq~wxmUj<&IafYZGt?7s%aTH!s8hm%k&!>A7^4bgp)?{<-;}tW!^7?g`rUpfP=rMNHNbJfcYK+E5Dx zu3{CIL&|lyf6psT-r=(!&cJ@-M7BZfhwA(7Lpk7qiPPLEhQ>QBu2>8nJUVi1Bx*2m z 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 IzvI9^0ePkf*#H0l diff --git a/DistFiles/Paratext.LexicalContracts.dll b/DistFiles/Paratext.LexicalContracts.dll deleted file mode 100644 index d2f45e82875d4936a7a53a16adafa007d134abc4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10752 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%0D9rJc# zAgnPrFrQd%Af|93+NTaV7uXQXv?MoiD zikZA)8e<=W-gD??CAoLe1Kf#K<>RCpPc z(y?g|+;l!(@9v&sGG~d9%3KtuPs$*2co&gSvAf5zxTm`?In9RJSErkjGiN`WbLMPL z8&E)Z1RUN)cy0lG6wv3M#fJ4*0ew!Vssb_>eRpco$5;cO0(>iA5Y4O=;CBmP_9E2u zwcHctD7x;rRvF)HyMluVKu(5#=Z? zilaL6dgLhRVhhaBCg7C;$~(U&XPh1T_=u$O{28poWw3+a)*#xPxa>F--lj9N!(UwSV`g zg^@-McQ&Tnb#p_vG&SaOe>?EJ9vkH*?KjoYs*KlIoWL;c=T;{SSCb>3z?a74y^3GZ z7QEfq2<(P$#a}c#n2&CTp5jZp4)E?QVAW8bw>N)J4(>JQypshrN0}_xsK-r^SsBBl z{w$n~=o}q-ZH`72{E6U6G^v=0A2ngs;ejl@r-yxt(EZ@}5IQ%sL3DbUrTNS0k`?_O zB`#v_=GeSjFPFVWJ?=%vFQtbtdR*qvX`&{$@1U64*+Nk6!JhD#wLj%~C*Gv;>1HQr zjC#vlRx!T&X-uqjF-S+^5|1X(@1qY9Zsvhg4UQGDm^paf4=XK zGcT%mjaqi`$*x~d26rbJsNX!Z4P@=qST&b)U#W4^dX;`}%#Q`HR$2Yg`18=kyqjLy zze|fb)eH6j|7q$WnN4f$+SL1z2BDPG z3@_9Kx&dv1#Z1K?SrF9d`k95^=2w$u#Xv{tOH*i(ten;;nXDKzXxa3*sG5z}cvgr7 zkas>@NyHu{iH5@NR;JzeIF)pmzXs(?Rj*~>KhRuR3eiqUmnC_mzgV;j5&70xs?g(z zR}8gUjrZ`rm0jGEdD3k0KHWfW?ZIw|K*^`LlBxG8aWu$wZ;@+b*fBe?O5r$`#vF@d z0^HjH&%xz@=_*>p;`pw1isQCuoMiDCrfN+t)*a?GPU4N4RAVFpI>6#&Nbh`L^A3>x zJ;y^@A?<)RY(lZ@;yN?J6~Np;*q>uST2{4c5-861YT0P%!~t`2WZD`N-#g#4L7C*% zjdrQmmeyc~wRP(Z%IKI5!C+kOX`E`t_7uI@=hlBVD~(w+UQx{OMohf8yLVzCQd|Tl zqrnSLjv_Y$HxRpNt2Z$vq40P5~5XQK>LwjnHC@Z+8djfST z#>rH%dMeXg>zRFMuYIhf4{POPWyts~()Jz$Oh-8M4SARjiq-jyAAtV_jKQ(N)(??W zbk^VND1CG+2#h<+d+5uOF5od3-Z$y9j;I#KEZb^fhku`h91bs4>|!>ykyOr1e-x2R zYYMKmsZKSu8o;b#_jZflTpCN$(qtS#@JsCZ(>zk`!f~ z&u1(+6Z{5BQdwhb|9oiIoPqR2+@Ki?>rfaPj05qLMz0427vNT-8Y!kdwcPEo@aAOu z1lq}KAJ1?5I5qor4?MI_7Vv%-=1$J>=E9i{%w(DM-}kA74!lY0)9QPq6 z2P+zTM>mU_Y;?v_>KafrCE&fUCx?}-`)M}bYP&`8RJw~6kJX3ZiydJXJc8VcWc50R zMQzQ#tp`ZeUo3Tmei0*Lf+Npu<iE8(UcW{ANPPfhg^zK54xFm{DNHV z;N0t_Gd;Fve&!gzURCB5EZ9muyd3=0{*EJf zo~F463UIHU@QI%A{@B-e^6d9mZurh}O@DD}t0U*Udy-T4uV&mt%8aW`vwZk!hYGm3 zcLy&77dJxP;FOi|=m|eT*n2DE(LK9rue>p)k8*N~o0&DU!?QC|iOsvxgI#2O&wU2& zX%2Hwv-Mo~G*>hQu^XYbf5(xv;1npa7QCLW(TUCAB)kQi^C7W(o$)PtZ=C_ra&P5S z+%`uajKb|=%BYQU(?`35D@H3=IFrfxJX$Hu8KdQUCy2FkbELtKpgiz`dEhB{^cNA$SsBuRUZ6BQ{S7OumMm;s%G&b^?{QC~s z*kY>%%`T^F^2Q|m;4Cny`0PoF0Vlxo0ge_5)2s90i)dk#9vKFPjs(jT=O|`!jsma80VIvlLkDiZLvfgEJ^^u-tk96z*P2JyNfwhR?v? zm|VTK>nX2V(e+eTjdwkRtNP_>Oonfu{kw0ehU>{>?Jclo&HU7JgtCzQ%R!_p_^BHkR@o#fim$%h-Ug_U-V0DvtMN zvJL**4j0T6YcF{nMp5AhT1&7>K=g*0r7kqvwNZ^iR%OQ((h zJ}eNPIan-}OE+Fr-WZM&9lN@EwU1&||7IiW;Cf`kL&zxi}db0hVq8`vh+&LAOBpM!-?(VbllruFo zP`uCT=W2b}@>L)GOno$59nN=@S9Q41QEt`Yp+3v3I_z~+RP;&Of5M4A)oL{reX8~9 za9b(2RjcDTl{kHp5SWur+ka8hFCknA&Wu!tclbZ=nemdK{^-XPsfTMZ`QJEmW!X*G3nPjSh^B4z_-w8Vyy4s>2;#&Zg#$MURXuG!{)_SJN)8 z51=41ElJGqp9njG`HFw?HbZ7IJGkEOhyMX@bo~>UD5*CwKyOy)nN$~}7w!dSGkZqw zQGl)VlYo^9=#T!E2Fx=NRMGO;Sas#Q5guqWv7?@JQ^O2fo>DT9*>OKjO7Vi_fS6S- z>VkSJ9h@UMZR4_+$S&mQXmzv}y_&e&s-q}x#G-MHN2`4UO~h$|EsoAQz+mc0^)#@h zQSEqx*@J#*Jrz2=t~%t%PMe=IQ*ok5&Fxf9_2?&*8^fKX=~N;^h2R`2F$^JELF;d3 zTxD}x|55;64C&KLA>A_#Ji8h^nbb@Zm`M$ug40!t%&hDC0-JkSFl*wOsYm<$jK;ei z_ok|wChchs*tupT7i;ZLs&V}KMr^OX4ZdTX0z*$LiG&t^VhFP$y#*Dlpp~vCO=AcD zv2G1MElCy`ShEtz64VMdR|2p}w^|q}hNv23O|3Y++6#V2=Tu8J6>}`27+nJ5aU)ni z*b9%$AYyLJz>>F_qSzX{O+8awtxZ^o&p57)Q-I zUsB_}dIXsjbDT}*5jYjhJh72p=M3>Mq_!8|0lvwhDfo*`(LOy;=uRzDg1()0onFK_cggBq zIb9hPqGv$@ag>Ezca`8Z7GA>?h1!^7nv&`pPhM5D;f#J!(^X`a{W3W|PLP-NN`+)0g2H{L+dyp%b{#z|$f zj`tP9&w*Kg@y3hlvzTGT2dv9`Kzx(}x^ z*{(}zZg3$9YO3E}9`H*J5=T_tk~?MhXlN>D_GuB>bLE4aTYZld#?BhF%G<-kUcOOT zJ!Z3GqN&?rwS6|*C#&_sw6u4X=7ssj1uP>me}I18flkXeE?qqlZ9fWXDd+J5 z9gs3Z8g9rf#NN_gFdG-#JUouDLhUONR@=&!q?tgbD?I)pjQg955?4<4yjh3i%VsQIfYW zhv>D{fCaj53N*@_-@HzrdzNIqWk7Zwhh^^dG2GczYP}1Z8K@7g`vmk+EN>Ofw>o4$ z+E-$g^=?9WOX%1NyIxs2Anue2Ep2JYh3b7-B``^asJKn4%r zkCziE`RD}Ef;30Qd`p`#V&GD3QmPLql|Tj$zRN1eLz90O2xXvZw5ViU;V!S{%PF3Zn-5}}2|_uP^C4%xA;HjX3}mSdRx(LujLHnwG#Ssm+deUPjM zd^=<^SkCCJN7ixvHCG+6gCL^?i_Pkvi$-qO&GcxaetopK?lbhXX;rR60N_PMFhu`@ zGDd0)qguo;_$(EPy#eEQRGgJUmLBJiM`BrXUwz3#KgKEPSE&xG3Pv_%|Q(~-)NHx7;xsrK8uh& zI#?aRi0A;)vW~*feAmUp+tQ9r%qVq&&bQsZd3wxbjQ;3m^_ZO!Z_udy}=KSUMA!i^L~3RPt0^VDLLT8z3{#ARo*A0zuQm;G>z`LLU6wPqbf zXW&jO3{E*RK++b&+dRnmvht_`vlhmVG}X; z_zNHq{rZlfx#E4#q+I>WqYgOw*U*4Ft`HnWF^$dPzq2VY{dljv z17utkTFx@ z@gRXjT6ddYS9D7Ay!)iw^lcq%>kxv zb%k+_{@EnWhnlIUYo3|j?OdfigKGeFuEd$@10$z`wG$Fv`*c>p&WN#ONjgODv5F;M z0WGqZ`D^LL3egegYQ?ERS@GJ+&RLcm@!Bfc@nR=DuvlIF+hlp#QTAS2sIZeMPxt@? zut8g8HSX{#aja?ULx|R9NSvegF7nai$;rL=IWv@xj!S*h%cC>!7zNgt#a=*cw`uw) zSv1jQTFz1lhf*EKTbjR-dO_M_L>2b?bcC#k81h0=Z|~O*MPH&iP!-*rA{ur3p6BLn z{B^D$FZI5 zl-9C#r>W+&>DQ`aQkAgLEk%j;n)7B0@7bge&ZjYJb1NHun26!i2-+#+S<-(uC%C_j zLz;h8-EygiPbWcaA@7IT1LhVSUPx$MxBYV~&QAD8KKD*F0{>huJKC~NW((E%jChtf zeMBSgDj9wR9D9=7PXQ~F6t_TbalfyOGs%#`Xbj5GLlEa{Wf>vvssxQyomr4xC0NK5 z8Vu{lNZYNCXMX0p$@D(oDcnq#{v|a4MpOcrJnwUKo&O?d4W5|+6Gy29Pb6qGxeKY;9avgJ89o!!ZN4C$8BhF<&H-tyKlUbu5A=s&h4 z(oJXOJ%)78vHJa6Z+RX=Z}W{wly@u24;au}1TuI>t>JBc zX%gi-CtB^Kjngp@uYJAZm=0qJY9l+7E1B7A zzc>w$t?7F3CbG99A}(b%aJt7NXv$!!A!P+BEO-Y= znFDa=r&oGyRZpg0^$p)g*g$D~mIZIAKFjj=W-G_#;kRzZhYHjhu^fJknwQ&eQ2IC~ z%VfW!;=Hyss@2t1%xkMX!R9)Z^EFmbF=9_6PhBEYN%#JWwvsBPEk?tpgtf`^Q(bmf z6xi)e&aGj^$UJ@X#<)<%lnRAUyp4WnHN`phW;+x4S#T_>yCDvC)>E!#HQ6=ur_ioM zw263#&LS}_anD12s?l31wD-rB_Vgm3*Dh@4<1XVZ1caY(QzLw#z-^H@jiE8~6t8^^ z#m=1OXnlGW0>1#%U@q;4UuSq4lG`P&D;8Fqg|xQGcB&Lg6na{j%oHXn&4!CIQyAw( zZs!hd8@EueG(DL!QV;5sw^h~FLr&Hl&#gSzjQ8j6&NfL8@4a3`VC34vfSKVXBE&LC z=XI2j@ots(^fdJKcoAl967)4*YZR*Kyiu^kD%+dn$+s?~tj^7fr9La`8*w!krb<+Kop`^q4^n5?)YZQ3HYzfpGYP{Qnztm5-HupCSBuOtyu z%OqOF7OK5o$?f7K)o33@TY@Wu?g^~b62P+sI57iwjsVAMapzLBR0K>hQ^a`D^nY$& z($`*@dxD|u>Ur3hy&HXvSehn_@^h{#;oNa4w z#9`fQXW~se7rv6S44Fj)sjel}%pF`-U$CRLTY6bNUO()fJN)UnA<$qv_vLiob_@8l ze#_zv+Ucl-xKmVr>*b2SSqGmTVc8rPJ9X;3wGrK>JJIeGjHX@;-cAE|RGXqd*18cC zJE}x9_`77?$eGIDX+d}m+$H!v82iz21cocg(`n0M1Ke+>FQr(}*K|#Y_8e8#K1nh6 z(2^c|QHt};Ma)&fNyO-}7qyL`*fP{x%=tn1VCSt}=-bSBtDtW;=WEHL^A2+kqx|W- zvkQHfIXSLY>3q-fm9I z_YQMfzIS$=pX)k5E2rzQ)~6U_ozDo+Ru4GKTWvLP>{J8CPBn1sR0GFORU>w)WakVH zrIlTliH$DH{!M_#chBX%bXeTg!#Fq^-D1bG(-DSS558 zwdJ4u3Rq0OOsKp~xWh}5&d9cmqDI%~A)I%l5fZb!3TvF*n8?<}V2RCTOZ++|eqJW= z2hFYSt%n~5DMvY8TabzH)-*KfKf$A?iEX{hV#_~1`NTPx8#If#0At}t(j?J|k4tNz zu*tu}mfg?oxPo_}f(i#%I595rnBUqeCB+erH~#nwtS!T`?Q+!C!Hnt+|DvsVldhgU#P^cvs_}=S#l$ReMVD} z*@tt6&@|*yWBHLd#bf-B5?X?AMkZjip5Ph8^burP&Z|y&Mf_nXZ zzNo0 z>Znjc&v-&r8Mq{%lsYqTi9@OJ$_!kxQEKcm1DBwbQfCG(sVRM?Bmn@oJkIQ4np zlF-s;Q!?=-uGN$0R0K~(sodj@h1q%2Kv}XBAbR)%DGQT7c`!xpormfFU!apqHCC90 zd&Y{eOU8-_GqqAGPck^=#=1s5J5UW)jwK{Z z@Uiabls_?VDL3=fZFA-+jhGZ+c@l)>9`C`=Ahq#Y*088x(dFz(#nX}ejSCusSri3J z+Q;I5wTqz!W?H;?F77dADo{_G2oOEcZ4>$H;YW?2<(|A;?b>6_)kXP$MbUsy%abRm zuG~rg$Zh@8!(IjLK}CSbdnm2D{Byg<62-k^@iV<6f6_a0(>tG@(>vlrDZ26`=*m5g z$d!>#4U`>c0z`Xu@sppv!G?HONDyoy#?Rs(rufgZwvs==Pj2x0WQyNyHd%=urufN| z;3xNZ3_mToU9$>P72ga zk`^dW(gSjjHzu=X8z|cY0z|**mM#C>9uO>%A}#)oZV$+x^nl#+^nhlx6hHG^-20e~ zU_A{YKs4}hI;`YRM!4MbG>*W@V?~-O(*os58bt2##wFPXF;KQa1c>(RmM#C>1~FJA z9y6BUvgf8_M*gHl%99`{cfx|?c2mTKS%d}dX)FPvgSrUIKbHp?tUpHB z5@eW={0YKxgYXy9LGG3^5++iF&2w?%qAXT|^iAk{N`Ddk6BtJdbGcg%#FjHo%`=p14bEIRR=l-T5-OKb*P7~^9JJ|_HKGfAFKaWK!tlQ+#NSm2&U5Fq+~w-Mx@ zXJlD+!*Rh{rl$qTlT=pj@yV~vDbt{HDl1rYVwW1_Z(PwkvII-CKNkPdZe67jNKuey zJmjTc=1x-;#CH2FQhV~tbMUd~*`XmoH1&tH<>jAz$4*1T(#1_6%|l|MUhbp?5}g-LF-PyF-yomKQ}M*v%Szp zd-DD{7%Ph&IuRf`vD-%S&(lT%qn&WGBf&{-o0@ux7qq8%0isWIifbr`F+sMt4Dke8L@$cTGIFdWT z!RHmtRW&$I*EdlwQAaB4EywS8xDlK`T z%}RzJz$m2IOu$aR_9cVM9l9t^f91e($6&WqcVJU0xY(LGlMLmKV{1etV7VRGJrKu% z1f8!ql)qjdbS{+L z3Y{P4Y{SPDkaxKiETh&P%-EPEZ+)Af@J>9qzni*S_asiQtrDWM)b!U;iXYxVv1#&d zl5AExCBLCJxy#gX=qldInXSkgD=cM%Dc2Q2I z?{xyt8d$HvE9yRfj43&Zns&XSs)4N~74`hNQ6+sEmCO)TGN1Dh_1$x#26uu7rh^tt z#m7wSRMV2^z9e4v8cARm(56~{W58oiYzH5%LGT+5{|WBKnYD_UDi1xmGQkHY!L4yZ z!U=vvBWjq0K#a(5-vVIsmq8?W3TGZ>iox-Gn!XDN zPsHQclHY!RH>ngYe)|KvN~(Z3sff~V^J-m!hDgtE-`WL;{QUNZx&X=Le*41$I8jkT zs^9*I0OG5zv;6kQx=GYAew!Edl2X(Oe*2?cKzEd#MmxQWfX#Oi$4Kigk=9)_{}zD^ z9&iw+x%n$ejISt$t^;ln$l!J{Fkr>qbbKZ=IK>*?O$lzMYpb2DRk_W*D7cHJj@w49 zXaUY|Q=-iIb5hODRTW)Vx=AFlS2OnupV1u2)vsKcbLSYhTjsUT<4BJmeubhq4ga4Y zuj9N$_uz>O4Zlj@+V9k0t;YWzfgk-FwAA{8Znj{6!t0zvCVbmZ=G!@!pVrM#D$OrI z`)vJKt45p=8XastVZ?6N$&iq4QwDqU6FyEqr$9ubL)f(*3Qxt!HTv*tl#UmyD>E{j zJ;W`OA$MVoY%bS1sarTFHMpb3<)Qddk4(YLQ-;J@AQ60)`oWf=feLIY!Pp^aQbjke zBcd-e?Y2L_M&A{$Ci9LpR&`*9|35nR^gFT%f6tFSc%rM0?#YvCza2ykFB0bcoN;~% zWtW4m%~?v#Hti9}Ivh2bT4#a-tf@+dbzlN8ph!_6fl!>(Dm zfa;Jgb1Bs!N|3eZJ+$X=wmk`d9=)$<)Sr)DbYUPY*cW*fOC3wEbXOR?-1^*;UgFN= zdATzdtiE=EozLSX2rszXGq+@i^XZcpY3%$yKC7p(!Of@7(^?&oXzL*YxL(o`(fW3o zw8nj?a9N=&h^c5CsT6K z(Qu6GRKAVRe2Bcrdmy@{$>lLbGriQ5%8)WXA~~WMzL*vc*Kr)OYm{mIkIB4Xlf?9r zV)$HQ6l{iQJ)MCYe4FOlaJxm(WYCQwhVP<$M^WBjQN;8UQKZ&U0y))Z{EFoDe( zFc~j8&}Ocy7B(NrPxwyqpVmcCu^!rmiK(*T9^EM(8u512`qRMH=LT-ebB4Iq^bJDQ*YXmYk!e><9>0cdg#e@C}=G(iJMC8>@kXaK3y z)X@YDAeE3hnxO6Sm#Bl*G}17;kjK!LFQzTMw$|?92Pq)Do1TldCqt(7C1wd)d58Z+ zHLM*m+GyfIn!=1->X>17p6Xloae5KsGh77knX0gAqseOX*C@`q>ubvOzbSHyKn4$f zL{Dx0dJ^O7it$~=5Xj)c{lp0F4ra_}+4`$6BHg)?5L~U)mMQa3f5NV9hGF zOnV2DW5zNqh--4(a3J^OAzYpm&d!gjxYyQ_k0Z(Ygr}+9z6Xk$=beqj+jEEK-MbK8 z?v&hDmpPtxY`kRPx*1ZtEnBa2p!^ls_*oD_m=%*s;?VB(JI!X;$%`co-D}d#EpGA! z-=LOLT&%rPoJK-Hq3aB{8q<~R@=S26FumoY|2Zw5J@e5+^m8`4p6<#=k9MI;$=n|F z%11+gPUGqswHP|tg=U{qv(TyKJdG^`QZ&IqcOcK>djoVwa1TS89%0fDq|1=@j3Fu0 znjVW&rE#XYCgot*DR@6#JkxBCL;BxOYt+8EHA@kzZ^6iIf}o{V_rY$3P?SZkG< z!vF`Og8R?{Lx(jpZz{wQ4rZR{A6XE` zkuP{AVw9F9q2e_ zgxgUm7!UPw3(2FY_BZ*l0>!L@Zm?B?b;tWfPK1kQG!16sL45}(qQXuj4E|kRZZ`Qa z?;RaY^KA3$K@pU<`Qx#FBK9wiZnN+uv43gw_(v3fS?o7!e1>1%?#TX>yj?9a_emRc z6!$w-H|{@z!p`?e=cZ%Msa(FRbd~zls@8UDyycr3U)|yMU-I719ieaI;PV~#x!ZmI z+kL+4KHt)(*7=@3;lpaaXLv#1fV67``_1b&{DVSH=VZ9@F64uQMl@6(5_EK*{u~Bb zb1xAu&Uchyt+H-8kh~v`QGx#2K(URLp2G53?(ztknSO3i7s;5LhH;p<-jR@7t}p(Z z;4AYI^2@y&f2;YslD~B~^0PCV%}oy07S$dBhRa9ve*{g5X&%)S(ATMOa;(8TM$rifYS4nes#-wXY_pl_a=Y2L3D!apep zO+YTGu=QgogVn(VvPk>S1%%Cg{|b|lz18*K0#{52PtaK78xQ&%zPt=MsXN;kw<)Yg zi#`Vwy$XX1AxDZUX09slkH_)V^~(<3VhIwMIs}Q2Uw4i5=~S<`gj%n+akV`jW47aZ zLwbF2JaBy&rc($#`UXrY>#jpwaFvfnr`HxM zVt|H!R61DCpZO-d%rUAdY@0p=6lE_z3}*bdGf)%9!uIE$lbQz9sUr+)VfR?8Q&+&=HIx{0b+TjK$tLkU+tw}m_?{g(K(u?I?59nb%g=h;Z~p9$_ehl9i9u83E*ACWQni+%j5X!Uorq@^5e|~ z_0Eqd#^X`6dUL^e=YHoYMmNxHn1kKQr}N_kC?7zDbsi9Q=vnhQi4CWKk3AHO*7BL4 z5^_Hn9ZkL%)EP`X?7>1HYidS9uiHx+$qnzG>{%6Z<9;s3vrAQOD&MD4$2vc8p9kIN z7w+>@_xTwg4xinZtTe)}vyg24NDYz?pHGo!6~{)3!3%KGIPG$YhQFU+VAlYf`7sO5 zBCjlKMZ$=z+*2D^cPRoK>Rd?y7kO<}4*T)>Qm~A+qhpd#sVGxn zO=9MH{_f*%_t<>|-_!WJlfQL8;KvJ=kOg)`?RUa{$N61%+q{A6-jRaW-IO|A@^vz^ zSB?eKpQ~1hV5%aTmnA{!p;R#Kmfobz&fk!>*_Ak53Tq20YYiPNB`>GSY%b^NN#xgV z7G9tVNPZQ}HJCK6X_K4^hLV3y&F6AD+cSv-bsK-L!jGZc+`5Sbd;#!kdmh(0&Bj*1dz z_4T>E+Cysp1mSZjwijVtyn8GNuTaXq=?w|e|7V?{Wn_}_|C!DhncEqdW6bu%>>iJy zR)uI8BouvE&8-e?9){x2I&yY8!x4L0xKMUN^b5rkjpH>3vak{sp-UWNfZHB&?IVBx z`_2QN=_+Lkv0Z^rU?R*An{Dm*0kaDV1%jJEldtC6L!60v%JDF)-i$_ z>)6!N8%1qzQLGcjY%pYV`At4U%(K%jC}#XAImb|&CAuUX%hV`FbFW~&L)T*yjbrz2FxQ%m37zPKr@j}M4nATtNt~CrD+CAJFNot6D9GNd~FplJ2usmR&sO?0vh=- zdygZ!WkKF1*h4~OYOg8@IeE#SvLfsJEvlcS`62;>FO|lpPX^YkjEII;uRH*t?a9 zxV6wNvdS;X&Gdycp!Q1ovk)F4DVF^f_mss9#J?ILw=szc8j61$q2Vj_a|A!ZmHeQa zWFY(qm&{c8(XV-5qw&X(%`mK(8eC?scs(9~AN&|8CKy5y(qD`Y10}QkoS3mEo-<7! z-IN3&SDS@$7W2HZWvoPf*sF5dO}3 z*tzL!jk&9I&-VhE-0*@XjFtD#F4GalUy(b;T0f?RgYfCIw{|y5FC45Sp5Dm|R>-l& zeZv!^=dg`4FF1nL@CN=&a!Azou|k1_3%DG&g*SX&0aA8A7C7SuijffiuQYzcxi~X6{9wL zV4misxTxrQs_Tb8AufV-?0d2Lk|?hx%FMS}2w=emfjV9Ykf&Rp6m$C=;O3hB^RBke zin(i}(<$>ew2>Wj;RV1Bnb`vpI)xZ}4*-VHDjWisV3WPFY1*;%dk_fN9B76ch|w&f z*IUj4(b>7r@AEsK2SbBH3DR-dJ(NNlg28QSiR56a_6GI>hgVbY&A+9wq?+)8G7&Ei zq?&lHfKbhkW2(7N`lNZ&7|HA+&D~~bb_-`nc$JZjl9@eP57L-hI9XDN-Y*{WQ@oqa z`$sW`pQ&3CT?Y7xo(|&+7q5CQ-oAg6IQlfy6khuR={J5(n$FX4MF$a7e+g6L0zG8f z7A(A!=G*38GqwKi%RP+V)Z^X4(&Y5>uV z{1~t>U5(*e0l9b3W5C-1phci9W5DN>Qr6_M!0!SKegW=T;4c8?4KP%=@uJ$ArEv~_ z1};eQ*o8~OD?}UU-;SE0H0Ii1Xb0I|NAHgpX9jrz@-KMPas=(h zi`IT2w*PJwY>xTST4JV!TYMDM6qG)`#v$p5I3<^v7ygOB>9+fZf5sE8qFY9Xn@^|? zhp2earO?nS-)WazOgw*4Ts5RKfWI@mBY3BLf z71u)G({0b*GH#pz$V38JoM*~$HF=cC z+8_}6M6o^CQ}o*OjT8hmZ{sssE+8kocb(Y8$!0zC6qg|SD52xQ-^fFD>cR_QbG0?c zb2QAkIU{!wAd~IpJXAQ^KU7$8vLRIMcX`hB+mkM(Xa{AOB&p+))2CDi!rPIR>fs&y zx}5dGTMQoWf-Te0!EP~wbBc-maYK9@M57IP%G!sf!05a)9eN%R_cFt3%Sng$8HCxDj$JR(3|fC4|ke&T7H=^JFyeftRNQ&4umTnIFJqk_t; zyKL~k7oRJ@syDs5^$1f-f3bBixph=m%;o)6vyBe}Fk9rPPOS|#SW#90bFj{qNT+-= zbAWpjeD~qDS;QlB)$iSo$~oyDkzHaV}of6T@T$>69faL?s`p zPecKYmBj!UD+lx8_=AT?@N#G<_&vC$9d~_?i19B}$!lMzPBanYB3z(vXM~@|dTpy@ zh=JClRC#c-L>yj)Pp8UGfM;zmJVnlZ(cntMPBv}@RnMeX8ePPRC zHq_^2617`-tfNL7tMu`HaVnT_F6TkAbV5pLX0W`&|63xYaB)FGib)UUwh~XD=e`b& z68+ApYR-XF>Z_JS!$oE*i)M13?G(8uePZZEWM&&fPK?UsvA$+Y?0YoN>5Lyxrzc$R6TXjN&!Wxjg`=3o&z7IE3jKrd8u@8A44dn|33&-TRw z(V4`xsuxSf2ZIVZtla*DLcAmyiQY|&Lic%zVK4eJ1=bOOUyYV8uw7W#tuvYoS=(zHN%TSs;CWigJ+ zBaHK^G*)W0{XarqtL@mq6T`x9cb+dWhvko4pL-*1op)Kk{g5Q<{qv^BT0T3oi!w|} z#k=d|863h4C-sm{3>u2vd=7B=G*;~*qyC~YVkv7G9oo$(7=UP|516-fHk^4sRVidb z9wk_u{P84rkh&})#~t@a^>Lx|C$)#(!IP@-O`_v`fc;nuPDkJQ8mp5lXyElyUOKsN zuw2WxPv>m!wsJk+KEoX2Q46YDY}1q^{2DLc7V7R>s7*B8si}-Ej z370|lly_q2y%xQJ3_TYdU?WW+sY<8qWTm6h&}?yJu;bZp9w-1w{;Jx zc>nW#Jh12L@X53eT45x$sP-k*sP>IVcXaE4@=f*d(|Y)-ho7y7@9I(Q`v(>I<-8TC z_AQS7q?)k#U#Ee&O!?2NlCLBpMFZ9;UsTr5Lj5e_r;ips!Bu++UN;yNSH5WC3$)d4 zay4+JaihHe#cjqmTxHX-`S4#*V@9JWU{O+OU@|63xi8axH)rU>(Zc`>T}Kb4q#;Y= z(MjaF#OMKf5vlZTE04znQJxs`=}G8;n`xqlvTMfDE?aR~)FwYFrx{>pswgdX;e8gq zt@K!l13k1(?JRchL26?f{$Lx_HXi;J{R)TkI2Wps;%G5LU`}TnJYb3?+rXJ#$lV`1 zac9}iu5k?$T?g`RLa{!61Kyt8xCm5nZyl%GShFmD!pH^R5o3H(Ny{22Pps@$iiyh4*%~G7ndQth-n5t1LJAxU>B!L?(o^2 zF$ui~nn_U9;516_(o_!;TT*h`=2E-R=#%8J3pUvs@xON+QF_ch;RA2cxCqgKa%f5i zz9|ZH>2!DdhiSqSGtnudV5dgr;*}{Qr?Rb;0vp9Xu`cV}} zuGGctssZ8JaYgPY6?d;k_X9slOT1I6$t@W<@fdqwMbeeqSC1B4L~b)>}6MzrNLIjx%mVCD7Sk5y1#(A(H&!T>tM;= zs4p8Y?ubIl(Gki)$~v)ix9yyudg?#Se2VBRHP&pvt<*@?>CnZ{p&cnYE>^wj+&Qvn zu^!z*emKUf@=jQD;NbR4QVu>7hjv=a@`Q6oV+N}XDM8pcDD~L@DfM*;8k-&C(3!1N zY57BTaK|!LHYGE5^4;ofE-uh;dM1;v%iAuGAI4pw@GY21=v+d8R$>|h(1QB-skA9X zP<0iwU9ZbD`-{*}b2(+Q&${kXW%{rB(Gatdxy_F&?l0!RLEL%h#UxknRBg)9_&JHf z-mUSIt7+f8%4-}#w^|%C?5d~$7ZBp^?p_NL)nZ#{+hr$fFY$>=e)FU77L&`^yYgET zw9*!V3?BTP8NJ^(-L>G-j@r#BbG4o+ zhRXFwd*xTja_DBcROb}69yI^=d9L{f1({AW|wZj5_)Yxj5>jenS(&9SSULm;+O zs*bPaa?i)Fb;WP_8^W!BkYa8Vf1d_+0G_&l{7VMZ-0vo8+oH?7_Otj6?J*pCE2k6T zpV|}+Cxf6%{av*mC&aHLTAYJ9FUN26Gsb4~vz4b*=y5#dY47Z?Ci3lFy9$KLgO=S) z%$a85wVy)}3c8V;bvJohge!o$Ff$SqL%Z2CE`57*_&pkzeWF*rc+^ory6^RL)IbST12&EtYG&`(U{~=P?0ygF6HNgO_TuzV z?6Eh9rmMx7H3?uZI|#7(ZwUu@x;Vf!wA>bf3?7JeOciG?Y85G9u*{%Siqg@7IPv>?6Fc;q6ZvIvxKsz(n&sncC7YV&+9v;eTa`D_ z%p%9{I_-cU^{$h?w%g3g8CAQxH|~-{e47?_*Bff2nl-PMY{JC*Ju@oD0lp z?>c#M28R;YYb$a+Y#2wCJADGeJOhn^tnpXDCikSrCtpq*J4=4&qX|f|`AC{&G`WyH zBu?kYVdLR{r0%&nygv;|EG?>>T6mhy4H<&9aMBP|bsCkB^%Mc})Z zFaoXxCvXbKOUy(L4AbV%bLqci*r8{wOr4k*PGn=1!*f>&cBdDx8;P~V0EHGONrj&K z4Y6-f36G@b3YWBYgSbN!_S!3vzTioq(%m<5rvnF?i_?WZ;@J55VR{$Ru0o zXIs2q6L)d64~tFB1IrkA^0#)Bv+s6%2Q>K|NLaJPm#fRM!GQI$>R zwV#$wtS_hKFQOi2$6VpEXmBEwu#H2G>~a~3wU_*mNP%BKEw(tiY&dtB>fz_kChhyE z2Xw$#_1#^;{=!Ttx||&Po3#S3_(ngj%3Udp&-&4h5!`-z2wjigUTD9=_RD3KLeYBO zZ;#+^J<&9JD#y!xigLJ6gPv~>DmKZylAC>^XNOZOek0f?@Ee1x_VpWkY&_B@>SF#R zx=NI7#9vxE*SyMa9KLGEZ=AHM=r>NCy+}J#<5P|DRHHJrcxqzG3vYroPw(r6Ut~Lc zdfE&3R739Ris~;mR&G3!Dazzz=@R>t=^l-NsYX9(h1<*`7k8l4ShA{EYP4qyOH{<* z)K+hLH?O{GnK!;_!kbvN$XmRs>MdC{=q+7U_Li;c^OmFh$1DS3eV#S~>gl@njh<<> zJ4>MFbkD3VPoXoePhV$3q<)syUd(rfy}B1d)l<%EBS3K7ZdR)BZ>*-gwxw(*WuqZ@PISXDf5d7N#d$`n}*9J_E~)z}bmmucaQH$RTWY zV~Xs*#qPzWZRI6yja^>q1=o@$-eQA=&WxP(&MJM9ZOKVIm{Rk`J9`McxU(l8?xWYUelK{r+S=$; z1b3Fk(j>~GoVMT>bXF*7TUptbH0F4JDLnT@*WOtP6fMT$wTJq(mp7g@yU4Gq%=m~ z1WvY2s&#e~Dz(n;eDZnJR$klc)mF8XMyEUt?N4BN3W9c~S-1H%DMv+P)00?omB zv&YCU3$hHFsAA`->iBX zi)<#{_(S&waX$vXh84^|*QwhX*BI`okd6R&cCJ)HP~hKoudUwGL(|raFH!dNv~_q} z9ikxXm?TIZ_&-w;>0z4iaC-N(B#h^3F-`|B1g`^J**>z;3toXs)^Z#~k%f!?p~fA# z&dwv3a=*rZ3p`;l)N$6NP(4!?%QO^jyl4#;EW1OaFm_6e^o@qJRY3hcvcM%sl8s=+ z^rb`@~a*lAlXE=s1*pDcDNsQd~{`4USav!2S z^5J)Bc?2-)s*C80{&D!RqoaYMU&B+XmDF8y)<|D?F;PmIm&IhAEca&e>eu)QxvpNB z8Ne(8mIAonT&Z)`X4a$_XDgXgG%iwoV}J7!-z$bIkQmy3!hDW1ScpiYJn9>ZtCr{6 zTt_cV*F03+E}r}jy3bT$dPN#{&8XryZ*e1sk5`gwib9dXinY}*ucgvNOlN!Z{jkyL zA#`iTjs^j;qai4_RephlgK^2(A13rUUpl+6@(iWG{mt^X^#5}eP%_- z?XML=SywBBRr{T^Us+Zwga!NkGbsw;@wmgiG0Ge}dDcF2-j72&k3v7q{!C~g+|APO z&TsG@H=bmJVURIl__X$-y*dX|-E`vLAkUEBS+8&2U8v8EnthMiOXV$)boqg?F?CfXXQfGhrmOBU7x6)asZ(A5dxf-WS`prUg z45%K}y@%0L!!lpupy$TI{Pau6yYK|A;;b?+QRA^EmM?rBD`bGeWM2}$}`JPZ>c z%n9KKNyTb2xRtNRpi&)!4`)4lp}`D30;C@+AX;OUP3HJ0>D?U@QdtYMt^RGRecS5Z zb~RUfu}V^N1!rLW#9hbmgC{X~Vz<{;pR~0~a1c(N0SLdM^-i zVR*O_PVwVMx8V1JTc~;KQcmm`)OA|eRIF)!*z%lYvtb4&$e9@Lq7=hbinE#@!uR1b z^WScJa$CA9V5UT{kt{^=txxD|{B8VT5@QYVOW|7OAO-ngIjGt0vqMLm)0#^QsrFv{ zcx|qlZpQ^wTIP|ZtBh1u8UU8;0ULP zpQ*F=GC0EFKQ#;+uy1ADmSU?TrD>cKAbd|TmSJq)wL%fhecVlAOnzK+^CH-1f8Mf- z?xvZ;?~|y~T#p1~*@m-JJ%So8vnCDiC)kb>)PtKTc4nBXdx|ksXEyne5DE9iKl7P5 z&*i{fp6h-^*>UU(1^q8;&*^8B2V&?A33L=IK7AN7F3c&|PO>>2a32;znk$HrNyOYW ziq3jJ;UoJ9?wHTVu}Lu6jN&rhos@w%dd@$qqcrC>v1nJqrk2{8y{pC29JFjs*;Pwy zD6_?H>;DbZ{}bxp@ITeYzOyV~dN8%BwXdsO&2idpgnamIVn8SAyO4Z7Y2!xh&`ip+ zkZAa}2jaEGN`o2RIG9HKGnnJ9HjKTt(m!KG7sc2uHYvL9< z`#lpv-Pk@jH*-nC(+ar`ee-Fx&)>99FlWgOuQo(Q>RZjv%eg zwo<(q9z-NNOunr&UX*3q#5YlN`{X6N3KAVV&I$0=T4bzEDc{kmVvoIZr=llZa8z^^ zF_yPl)MSgQ1}#ZexDb5x4=LUbSPgMNbEq^_9;yuW4-E_r4h;=092&OS+#9NP4ke{G zG}3vzzHT19m3*V`^JB7Pc53{ULTVG)kg5DWqq)0Wk^i5{CqsQhe(*79+Z*bOYvup% zYju!_12j)>*cM!6Y zb}Hm#3`74?Vd)4Wqlh}vGG2hna6Eh^{h1#RpR5mO>+dA7GogG4ZgZd3{7$wHe>j?`tP?XnJt-=qHCnjZ4keQe3so2pvh&@-w z9Cc>LEO-ma0;+qnB~DKCYh8_%2v^DmxCrIFmp9 z#Mtuz)qVtFoy&->G(j>k?U+IA$0{UdxyG8q*>IhxwSyhpc90C?{e*#$&LuNU%?&6gF z_5wKP_^da^Q!LgG{>+eTw?*Oi=&I&XaVv@p{P0M+tiQNucFznnrpLJ*t}~Z{6)m5g z`}z5~^X_;0B%K?53+-?R?SM@b22L~$7mSNIN|bgqjN0y=orvQi&P^1;gNavLO$#r{ z;Nrj`7St=3YX~tmj*g?QJ)~$&6tJyOnOW-b$qMF147teX@q zbbkVld{$ad1zFaNTW}W(;bvv}3_#n5i_?sB6Icu3wSYM*6z!AD9RtmS;=Y!&3N6h6e1+McsTj{Y~2) zLwr8Wm1qobT!bU_hZp1X*Z-W#W^oj&T943{E32PZSRRdo&J2!KUigpW+c;=ra6DgE znnRWap!$)AHo_U2F~Ls_mPMy=z?oohfi|&@wR1e~>AA7zn0nJ>#Pfh7SyuDy zhiH9nCpo?)!k@~we{aeagR+pJ8kPi_dGFNW#kYg|G=5 zlgg*E9S*0mbGfnHfhXk_t^}3Cf|CepJ&iWlqMj3e8jD-`a^|?|xh)ZGySMCMMJSmmngJ)2PYfMNh~oEC#xi}#1srdEXizrwg)f#7=+>uuHoHH zkB$wA1aAFqYN3vXUmD*i(7~+{UAt^Pi8yv_`8!m>T_+RB;C7v?V`JX6_2!e4*mtL~ z1u}SeDox*Uy{0sa*j%@sT4eW0kOp;kuuUC4i%gNPG^4)wl>uj?+{r8(hp;ZMmI~gB za5x~J*}s-=keh8hI-tvp>6uCQEJ(KlZ({} zB2AA2iYy|VipnR75s^hf5jRvsTtPv^4N#&Y?i=C`8vge^r|!~|3G#i<_y5m7Pty0? zQ`@Oir%u(aI(5o>42|1RH?3Ct@}VTg_Ref|Cb^93+j5=t3&Cc~fV;WAH3I|^s5C#7 zKx`ZIDF!t^^#{yo<0M93kYjI#VA{x1=?x2t*n)SQ|>!EaW;~BExgjh6T!+&By z3tDI^s#w_Amuu;QSDR^Bu>msr)S)D>HHmIT3F=l-0XaR@y6V2|3Xai;`!@TpfjT4Xp#ma_$fu55id%bU(Q!o z)`uzkR46Qg(yb@apSpHHD@*>4u())v+dj2oO1X1aoj5y_jnVIjLwR|z-&6Ew`+^pdOyot?{eP1{tQ((^~#0cvUo$l@# ztxm!6t_-oEQWs7e8iO0(Ait}k!ehR|_I`#X1k}S`Kx%K5< zM*OZ^Zs(dQXrEc|wKgj^D>uVqtFL+xr)hL5HL)I|EHjB8aBd)n#)%SqblO`YrzegK zB0nBRCQ9&AB4;L!3L-xdMkY$|QDmLVt$|GsbZFuKaRfY0t|4SSkt%z&#z#t zUVbeA+&u?j!KXGgzEo(680*Koba42X2-P+$qU@YB`s_;E52z@JU9mJfIXBZN?Huw_ zBFFk07hxr++@{&*S02Z0q6e&Z0$hHrbI2FgU?i1gPnZ=^vlNCftssD9X3Q8l&$<@% z|0?RKojpEXoNfj(u_0jblVq`Y6(CCRywjDA1==yW!sHmok~!1kw#eB1U?K+X(A7a< z^einfK6AmI9L!~9kS{L)KrPTR^7~+J!lAkHW1QFbzKgOe-{Yi36-BSk!@E+Vm*e`C zJ)yLJykt(>?R%%|w&0`*`Jox$g?&r2!As-3kT@)eSn-`Ka7e)~9y{lK{_RE}foifthgsU^d3G%fs;k?mi>hd`y! zfEN*vsVSYxU<=_`a0ELBN2Ae-CR|A1yc3%PoNK~Rg7eGbI!7EQJL))j8(0o`NhOwp zo>io$BjImEUhuR$j>qQDU=79J51jGN!H*-Jmazmuhs((>d1$|*o$!3*u}Vx@ahK4^Tqy%?RgCRFr!7qb8@q|TS)6|sJ}waWn3hIJ={vZg>lGhncSxDnZ8HW8cnT9Qj83sdtgj*h(UA#NY7KU@Sxg%Fl%}Z(jYX z#KoxcQwSVX+wo5!kFSerNQYz<`yuCrr`Wf&kN7vWs z7Rjf&3^iL{6kFu=s006!TgGr;seC|kGoRvsLVr~yFR^&(1yVW17c8Cy+G3?g<%`#8 zazBFwO=X9GSaD!ng{3W$a;B4W_Sku4GL-9xyj2bBh?)Tx5*5*_xop*Q$IuzFUv`^2vH+KuWy8`IEmTF>p`@0(x2qTMjZ)9 z0B;jIxAw!NTycjhkWt^luT3zoq5UDoUpy7ep+vx6@!sz07;c}yEGDeLcdc6~1 zB~x_M7HG+g7w=OOdgVI}@yuRuX=z`(i_XMdsF8i`!C8Q{kG>znxHz%(k0YfQn?WcM z*-bX*90Z4zwd0urE4*3pfKt5MG28aW!MGEEcI30Uej>qz6p%#X*;VyZ`Ra91{{&zD z$0z+=Fn@Gv6a3u&C8SJfz_q5eixAr%i~@i4Qh~n?1Eqg{8G7v-;AdC1iw8$?`1ojV zN!D42V>Sf!sGlwby$)4?Z$6NvhkKmbB=BY{qwNbuI^JIq)*>X1y&5@d1Vz+-fs*ym zP_0UeUjb(Muf$J&7_$XI9nUxa1pH#L{6dx~zrMKP{v#%F*j2&t(GGqh6;WaMKYk6c z{)tFoqw)&i*`wG4WpZ0Gxn=H$r?rWPPy_J}WeKTE8T{2UpdCwa-Hb9iS;k4o7p|M3 z`hqefYFGx}Y#C(w^kqy)8T^gP&~rFlK^gG87%M}fhGp>0mch20whZsj6cy@Q$fB-O zPT_F{3zBRsIXi^oCDDrv0)=7hGKS$WpRx^dG8o{Wf}i~GE-_TzKa~Nm!VhkxC-`do zWJ@rC!(s?IuP)|m!Ym*a2I(FKpQ^nm5@uC(#>F9aX5j6LYT?XzUqFrb96QC?$hEC> zP{w}^0JK!d$ZlCUzC`!vpbAwk!bVbg0e+!~P$+;Qev#lqX`F%&MN{#dW8#{R#3SHEAuBb9;mAM0 z`|7!*{k8b1KxIY6{{>;V_p0^=$hhLWe1lk}o;VKvY}p4Gkk5LHNfKPdGutY&-E6as zsBg@c_^H_v*O+Ztvwfb~Zeh0P*=(cAH)c!x)NF}s%yvk#eSz7&j@h1XvyFJym@V;B zvn8$}TgUq&GQ^^?kC1dZ>6V)E{vKPDX4?8v`+V>?B4?~8(g?1D6`mYC(?Km}>^ezB|T!ptBO{^6RLTaoCPmLzG=kE#) zYCZDNzYt-VI`+ebR2?7)6)rM^boE~#U2SO)Ji%NZM=tO%_0cF7vdw=3b7@8{&E6zH z^j~2bbIHVWY4$D(a)IxmkA=B#?nB>04o(m3I-<6EPU4V6`TPLBE>XTu;S1oV->IDe z=JDt}pAARnG3KWd$IMD39;H64_Mx-Y8Of<)lAf)fDc~k7A=l3m@Hm2JM-g5t;D0f$ z5%6MATxYL$s&6E?IRdu`cogQPb@mjeDw(}TKq>8f0VT87N8kk!SQC)fp43Iqs{)E} zDkuV_q@N>k-%ZLWO!n~qxlv~4MIdDhn@y~E^-ZK&`z>qluSO0|jkUKRYi~i;-h!-# z1z8OXk_ZbjOaB0n?s%FdbMN-wE7?m)?*mxHa%I-Xpv?(Si0xj051zHvo2G_+00^Zm zpZ9N;7fGXd7M}0k5zmU}3p?V;g+d(P=U*yak9p?v@x$}Pm}lWz%a_yOLTQhGYed0q z04>!Y2IynyDy$L13aHUdYpTVB?rS%?|ij~%jusuET%Chav#y)I0X=VAI_g{gYprs6)Me=B66DLn&DS1+;mMWJi?Q92Ld)p6Z+UnLidr7&wLHHBTvzQ885xW0^NIn~TCq7yJ_?j06N? zC&cU^b|H2ev6C|%I!{!qMPc=ma?a#1lQJ`gX$jT|S&{Q0g>y!hU2#fz{{ z5o!>V5Ic>~g<;bO9m57_ry|}R;_b(f!1o5L+TUh|SaNEFd*;N2g&1>P)Pj<9 zaesR}YvSTrn{S^KI=3MALP?g{(qD$~d zL!TweJQP)f?*ksH(ccxX1JTwahs@qU>z_he<&LJBsD>{}Hxk9JeV5oNeU~V+Eh>`l z4Sko0>H9823byY`Hh*I_7fGQSrhS(L1btVC*`e=-*lGH%glXU9@EZ2r7@lKo*mq-i z4!q$|62o&84*PTr&mlP+N@949&xK$}B0kUogd24LG3M|)Lmj~PUaJEL@2CU*N7!lf zMVQYt`hsE8>kEbioto?o^#xx7eL=XVq3;o6GIPSgMUs{q^#yV9tj!$8SMgwrg+=it zD2i}T|AKfwC(4wgvLx-4vNQ`Fwj}=Qs4PlBSQcM`vIzI|uZ)*PlsO_QOVUm$i?~38 zNc_{HvM5<$St4dW+#N#GY4;~4=>8IQSwr_H%A6mS&i8>u?EbUk-Jj^7`x90FE=w7R02~R`c4rry19WA6!dR+s3 z#02z7)Mfo+ar%feH%IjGeH!|R?z8j}o`$|1&`KZYrr|Khmq4xQl70(+-mmVr4SeKMf(FgDvMPPoO2N# zn2QQGlt!#c)6bVqbot&tr8MFSw#g-a%rTdSeN2Weeq@9K$d^D@5blwoIL>Th&F3P4 zljN^zRD;9?>O$f_&iJYZ`R&qc*(%>LatEfa8uXvDLvf5^oVlUa<$M2(#^Q(zl!L^7 z`fPAUixVZ}U&Gmlu2p!)Q(G*+S&`NFIbu!qbKrvad9tG5-N%PhBYV6r5T5cucq7=?=$wEAx#%FLQDm6ZD3tIZihSpuLT=dWEhCTF+?U|Jp|U^06*z7nb(5xK z{bGhe{DbqL-{yKmjo4H{4+`sBQk~c9AxU_q-#v|;bMBS4=>5}$@evqNwz%*=ubbj2 zTIO-zE(ZtO9`5pGP`iyi@%SP~KNi+M zsWxx0k%q-vIpP&M!Pdjtf4Kf~G+^!D*nwzuQf^_~Ye7PL1Bm*fUfe82XOw;{ z{lbi|#s4vyBC?p%f;FQ0@M<8huQ^6ub5hI};0U_|dDy++OF`pzL8DeM+bqT@)-0vf zX-+qg#VykE>>0`uy^TflDy^IbX;IVBPoBv>uO_Es3NI~;+d1EqLi4V1yLnjYRKCVI zS#mYf{}xB#gyZjFi$i2%G+y<;!?%3{CgH{kn#sq?3qq!8{++UqJ*6uULC9b-^wpcs zmi9qcr1^_$1)#ZHX_mez))#8N*=I2#)LS4XFn`A(gOi{r2gQh5vw#n~yJ<_1OzaCj z(2iehyRxMPIKl&wPDRo!CX=qzE1N2e&vH`vk*o1nd%W@(HK2e;r(+(*51Hr!EP*ti3>i$qFowlZ&p*dFNw zZ5bcZI%$#1StDCKE*42CnK)rgtPp}bY8%TC3-Bh~ZQs4|hGgmn6+oP7f&O$we@dHr zlk6Ilk@A5-RN283LGCZ9o2Jn+!&Hab{B)adT;-jaY)z(Y6;PUF6{+k2sBBSrJlYd0 z@_-Z!?omvmm}@3~L#A+pe;sJR zZDAYPLOC2)8@Z4BWRCdY_yOpUi4|IiN&E@y3b&Q^gfpBs0BUu`5G+63;`U!?RVuvd zO>*m)BXa)=K>~GAfEq;7i}6zVochthA?0cP=yW6w+@$+e)S)@>oH|*lfO9$j24p|z z7AI0X{7ll4{)ssEKUlPHdT}OLDmr~vJRe70CN4qD*j?%f$6e|~Vqp9Wwg~B+>L)r5 zOp~S+g>L>&X`Wy?Z*DB7B;^o^a{jtwIaAU|IXg+yJMmUzQ|z6%N*~wov7jsO4M69z zzO-k+f&avlq~kh-;>Od$Bmr+2_v1`n4aljiHFt6}dK(%aC!I6ymTtHVtn`}VJYX+} zsF-zxCIM9`oEK<}Nfz!6qNq}@BQHXZ`8p%d!!R^SvIOVBiAuI|n0YkF5!Zc5YTkAh zx$rO8n>!0bZr=L~l1L<&ILzl5@(&?X)4d(Enwy@1(i}$6;I@fDZw>(S*8y8LuAs$+ zMs*wH0G1Ghy)$?_$2*YF?}Yx_mTf6x?k{Jsw=L{UnfCcXZFw~_RMwTCO-6RDwE2D* zVcV2@V-iVkAxf7^LAtiPy8y1@f*V+P*aJZ*Iq!cE7&MCR%|4$fMEkbHLU z$AhCA>{6O9hGqPT&?KdVG?*8H0Pk4jAot=Hil%LF=OodMM1sCLVZE9-^e9f(`1i)9 zkxw*1u_c=34|p`wC>PA90=D7SI4TM4 zgSqDF_u%%c(-l9hxaXnSTZDu-5hv$)Tz@8=@tqBnhpQB_<$1>JYT3_wVKn$T&~3AG z{e$TcWX8m`q#6E{P*SOL;xfLu;!6;Z8 zT(*$oZ?~y=I1iu8_P`XIssv!Ke2V~(i+d&+e;fG=Km6GhZ`bQvS{g3D(1vI&E$wL4 zR>&xE8UMYYYEbFU`0tY!HY-f8cv2oAdWlo;zY5&<@qY$j{t^E>ysyM_FmK;>)2wA)$-JRya@B=4Z}^91-i#aO zy-Q=>XHH)ymL=mZbYtSj%ySOX={+yxfirO_nrXC&*O>6#Ukyf7mfAPRKNPP}&hy;b zd*M&kTY=Up<79`tRPf^Z$Du|@ErQ_RgqG*+E^|ZTGVIq__$bxMlg3!{c8rBPVo)}t z%5p%-`$t21uS^2c-YD&hkrM)+tOVU@FQd)WZVNXvT-ud37b~4@06PQ_SgGicym(Ac}>=5^T|yM z-lTXZ@zti$f5Mp+{+z^Tn~rF8q>Hg%VCx|96UZ6PnxN*Qm6N)}hJz-QetxPs;_OtW zVJjw?iH4jHNA!$wuK5URBO|VjDHF3N0%X2_sdoiB>R>PtXxL#yXT`A*mv&%X;iJ~s2*frOeG$NZu%*BBx9yy+QOlU12@cXWv=)k6c17C0SdFj z$fDFW4}!X0|6&ZN?QqQ%zI3KqW)ETIc=k{;rVhhRIHuL#ilZ?tLe`7SSh4Bcymz+1`v5Lj_)x&z7CshmkA+VH z+-u>p0QXsV3*b2dZ||IB5w@gU23=wnvM-;UYk^-X%985-Eo* z8O=(Rb~BeMP%>95u)w@ift~=EW!|Tlv;~yaGBd)Nq-OmB!09ywz^go&rALBXOtqo~ z!mNkGE?GE8@^CsPn~u%osYP9#y|?Akm^WA-O5*R_Ni0aTlynZ|B)-^`{YFz8sv`Ow zr?wJL@2vd;C!?Aq&pmiXMVFs3YsHKLbA}uApjPj!+$EZbJnBcKo!KI`O4{2cWFP zarJK1Chx;QRi1$=Y}%gxbf}RvpGP5@fgicv#J~!jM)XebD^>MHr^+Y#`w%)hhDit8 zC)ND{Um)##0m7f5F4T{mHuD7Pdx7JLCvhqK@P9CTL~ zVLam8hN%h#Z#PhkSE0iOa!0 zr=!WglZZBbE%;Y}*)k7gUb`SK9DB)4aHwYDyBN3Aspc>WXBF%E9|h7auG3eULOFsf zo-FNG!9~wtTTxzAO$Xe-lXI8iC!HFuS%4$Jq>evu{)QV1Fp)_5dqIKMFifPp`J5T@ z@Tc}&&OLElCRg3n@`gEJZpMV(C~}>+9z@GrWF_9J4?%fM5+!&K<75de^gVC19cQa;CRkV$hz{gPH zbjH_fLf-;XMI5~FhER-it>$PnTeXO_i3?nrGsqqR)_M~7oXu4i+xjxKTjQ^{9HpW% zMONk#is+m1Qz*Vy8(k$X`d+a!0)EukSwCrebwC@xa%_~3v$^^4FZ8}Nsj;%`M+m<= zY)10!A%$s;WSmbWSSKtb<(y~*bP1Neb*)k|-0qTw>Yq4uhmAK{h;n%i(qW9sbxo4- zU6WijtKNf%lO(=+Ib?W};w^$VNoAxEDXM;g@hH%;{4QTx8p@BoIkGZ?B^1LEm4_NR z`qDWXM_Zn098Pr-dEo2@ioPU7W*z_fFpH26p^nh5uf}u~zsWh`^g8@PiR}i-7Nj9M#_!fj0^G zE@Iy=Ae4q%-%7AXgqpT{s}aGevAEErhc7-YS9>GNRT3eVt0X}Vmy!T9gi~Yjp)IQv zCD{eGtjsO2WmWi-$XbicTf0``yZZ;@MkRt$>*-6-mKxuD9Q^e^6p}n}D8z4IKTIFu zHakoj7}Y3zMOb2B+)6wwp4OvT)wp##zD2YUpbsbdQ%K~0T2iw1ahq4Z_a9*mUda*j zFbPwGSH2H)f+ibIMwy>R;d~DhlX>RPQ6S&@&$lVrn)9q-3}J77$ew=y1+XUX2lD-( z@I9~)VwgeyJa+*)=$d>_zWQ;nOm1Ye3D+^`A_t zL{?RN&-;gj+4LXRcn=}N`{!7LBT4*jCcY@lJ@2c*5oI-~DB*ZT%6p>mS%ZBga;9#oF-)XE7iFrbsfZgkC|CXOlxnK~jAwSzEk);<_^Id+@C zicUJ``@kdG%pKTxawH6Eu$dF=2STofM!GS)^n>7hNDME821dOxJoQ9qdq;f#l&dp| zi<|lLJvc=o`CxIX(ab-@vR*h5^I=2?&X$B>)!V0F2VlyX7`Tk0`4I-)i66_nl9epd z8d#_a-Tp};l7xGE;}R{HxKbg){5w)Ad>{BIdQJbFcyUDc&y5v__S_J*C+5*u6Js2p zj|$P4;kmFJBZs}?+2pA9OIVn(e^?8%Gg#%Df+~CWv&z=OOc?b55h}diiOhM5nOR>2 z^G(r`)0>&CLAdrp5PT#Fz7d0!hat$aHn0bi(jH`K)*h_rbai!k>yU(VFP_mm8f4-_ z5PP7UUDiKDE_kmKiVs9IJzJiX2|q5VOG>e+N{gL6&w_7c+=2rI-@g2MpdW3|PRDX7Pm(bp87Y>!!eK*gUc)aWx@Kvr6?_$v2gu8ez`dg~#gCc1_~eU+cFs zOz?!f2aq3T9P*O%_524#5L0(Z1TFR06gto6H{m|uV zG2B!l-vRz3hyt9fQ2z`cgHC*f8dNDw9f|p)30dcQNO+L)zXY266Tt~3OA*s@Mfa^a z*M%1j>=lO`_rHuh+DgM2e+U$9z7D%?*g5+Okmb3q|5ZFUr?9e*SrjXfmdTlXyxPOY zU)z?;Y{_Ej4i|g{`-iaN{4Qz~(49-HJWRH!6JQd1r+ z37@}IEN0UlcFPQ&O8x)@%2d|`p^fn7|+ZyBU7fY8M3i8F8>H09g8O?Ai*^e-|vE3sUC7yJB4F8%K9FKEp z3_msd_ahA1e<>Cvp7fV7d@QL+E{Q0P$6p-7$Kp#(SO$t>i2=i6NwHE8-ZRqWjdM5= z>(t<$s3h8h>p1-TZ!{)+g?E+EzT7L5Tq$4t#_LGIAq?bO+tzy>TD3gWJD-n?oAh4K zR(8$osFh%vdiD%=(;3wof?(f!p~i@+;P^heIY-x0TfTky2a|9**8-CwvCHb+^IE(s zJoaXQu2}_MrE6&@E|J&#(v14;$Dw?|&dBJ}oL*T~YBLu>69G9%;hwlHwl*$~PF5koZ|9?s3frgb=>r>XTQJ^ELuKvMX)F z9juS-V&7~FmJ^g-#`-&i>q znxS%-W6A~t$E^~GdK=PcA1Q&TPla#k+P~vO{XnuNYFeVS9EBy)f-ce~~|BnWiE zJ3}~KOWN?yggDp4!+9A1W#*4zc)FGXu5dzr80cL`qimyos#nHnadLzK)_tpvgilnf zYG6rn97li!n5(>kfb5I?5>4}`NMFq04R<*BgSj#$_n0fgA1$}XXk*o;+N4XhNjp3z z&gCAusFY;63nC7>(jJw7_Oudu*OnTiYQK+gYGygSh)$Qc@uql&g*L;D|8}zM?!MVg|9@4ok$Kd&>>2sVDoV^fGBC-1F z)yE|_!Jn8J`4om@Y60(2P!+E5Vxk}p(y`Hhud2t1+c4#k73g!oDRHViNtEE}%Bv(E zT9JeJFhw%&L`0mpJxJy=*%wgKBvFFrmzo;vz=}b=;l>KQBS?8}SRhdo{F%PMlUd-0 zgJiD_3nWVLu>wUlP6aRiOxfUP7rrc*f&Wg74{fDon7h9VP-_x)3aa1bBt}}?S*n%4 zn9{V_P~H7;ymuo}}!ufv&%I#v$H82 zrQoKBe9^U)_RZ+$Tyq8AZwoORmPa&t+W#wNM(S@x=kQ70wCQLF-w*AI&pnw{-qWz> zJ9{|I>*V;Q13FZ0`VvQ+rE+r`E`%`G|14p5g=H60W@U)XGdgJU#7&&z``=~>xBz)E zhPHw0FpeaTxay4L5&5eZ(thp)RAo@oq!KWEO2El;uy^G+MaOYupn_|`$OdnwnBp5eIh&WAbvi7Arc^8qNAf6ADo|8s1DmT?<^xJfJEMp&d_ z3ncALP(grV{mT%P2eb0RENt5FyJQve+ZXls9z*plRjGV-TiNlx156>iZNZ?qZ#R6K zHhzPIb_R$`9Tj}@^z|hcya&p8!Q9^JcacHZ7dJWHX7F%PB|V6R06@CWw0p3sz6B_D zyN^T4<>D~`My8GXdK>qiAg%!G8vFv{gF97p`B{87V(G7cIkY6&2o|4Ny0m48`Y^2F z<0++WqWT#47t(G%Yz<=;V#aOgy`jRh7lx?|^L$%E#EW!x;i z0JIq&p!9s%Hl6rB86|sRm^vnK%L?TBLd1iaBD1cu5XZX+n4}hy#+DwDjWw&`gO&_O z9;6?tDDgMuWj>GM^4=YiW5qJpt)aJZ+eJc?-iHyY`$(K)Yq}$=i7;Jxrlu(4(@s(< zK@&efF5Uvjb&#<*aU>O_ANJ}Yuj z*peU&d$Vrwp_iLwl*}zYhI`&obh$`h8;#YyAGC{xuC!~(dGBNw&BwBWtyReUmDmMM z`ak15#n?U~3F* zKxv$KoP@CP%MRRkdY1x+yGvtEJ@Z9Z$k$E%nJRnw0{@=~Eq*`Fn|`fMxiFQX-U2KX z(&F0j-ibnx?y7jYhGu#r41_B-cgi65Q>XM}bjV@sl~DtrdrD9CD^Lq%z9MsxT?}-I zWvFZQBT_9b&!^&pilHL)sW5HJR2L$7T{0w}dH(fGJo#ta@#vkjqa3kXo;2T}PH5Ed zy|5(vECg)Mkkp(i!Tf7?8?E3Eqew^F;9>+7(Dtgmf~StJ>mfh?V0-U^_*{dEbfI*d zI(tten%$?)pGGu0QJp`HXm+JKe;UzL|8@Q}qOnw(s`IB2P2E-Jk2bw_a_>ges};-L z@5eLU>!&y+O1tSg#|o{;#3#^*GM&5=ajHFzhtd9lh0ZM8%XwQ_;dFUHTAb+8%b`S4&$uEgxP4jsS$UbV%JtTx z^W)Cq-i$vEsCNi<%>;UeaPrZ+2|2>kuFQM{hRUa6w<;fRRL%B{{RKL9YJW*ql7&)J z_jtAhU#BAEI{Jk}Hhnfu!3P81BT{s6f2W2IgOn7l#>BMcc`eF%fxMH{;TU^dLvC0d zO_lfE0X6ZdpbbCDHhdVGYLY0ydx<7m@55vuMpr=6`@4d+1KSfgbefY(zO&UQ(atdW ze+UeaAOD9yOnelXx=z~v5nk*UB5B_RX>n*fC#f)0Pm?N%Y4KA?C3m4#5TE))@^j?g zVITc6yZK-)s&4BXG^_Ur&8fbKfbG4avx9kEcXy(bYuU6**$a7XN7>#m;`t-^acWmX zd5^*k=~a04Z^xx z>$CQG4B+J(@#D_3@rLGn!9eifVt}iL|YZ@kcvGY;RBB@(pTxzZr z&F}Rh4lFn|5?JX0AwpfRrEXh?WoW*28+!K$%E#60i8Z@{X3*UOjt}4oLr?Zg`Qus` z|1JiO|I_*k-?TMmUF@wchfG|6?+aRbVs(OJwnzpJIO=K>QlXC|5=EBDI{yfrLciU* z6Hc#Yi9H$SC#!duGY2jvM6M#)t5fuf=LBLQ?4)Upu$9NAu$B(tLSdBI{_TM@MuI2@ z8}`NxT<=6q{$DW{!T0;rccf>(qYlO4i=4O_-W`Nrht#9DvK?IzL(+HTY=v4l;y!4q*gN!E7q1&mO*E@1 znU`HJ8l(7J7tE5pE! z0k{JfOS>taeBjf^9(8udSbZp`1Lah%)>VY_!!4QVS4kxzU60IX(VF`C{2l}|W z4Y~^|@5iF}NPDMSIt=%Ll6Wj@3kiGcQ%Del`nHLWL1AY6c63&pP53noO3OVh{-cls z`RvDK4OqM4fY;f)tq-{giMN47+~yu95spMu9(xnVZBZI2N5``HNuzwVSK(bFo5c;h zax86_*DCP)AI*9ZKKaYD(v^Z6xGjM9fGk$kPU6aWzBN3tCi#qfC0P8k$86RmWx#?V z8U#y6ES0~rP(CIikiY5}goHlb8Kpt?QWz?C9I?ukxIor8uBo^36%;lOU?AHLTuwR= zw@-IPllp+BcTb_|ouH{1G*$ORPTC(B#eu^SJ`48a537Xo@uu~GN8ncd&=gYWj=TC3 zG<6$pbJ*_g70@IUwWrHj+#~c;1P_)Lwp4m-&N8@H_d&nm%}!4vxFuER_n~H-sk4&B z$ILw#+GKV+c^8D^Q4V?D;b?p>N-#K z*~5s&L&-_61+(PMFs*KCb1oznr-h*++SI zXZRWViYJ?K@X4Ds4-@xHBkqsHbwMq};?3R*xQ+%~{X5Ls+k%fH$NM*`<0Pv;M^5!` z5?|wQXxhe?JWm*5A|r6z{z~G*Z#uGwn_+$*Y5Wg>3pR=MJX`P{W?6afTYMC}Z|mbb zczEZ5mcl4pt7>^Pf^odlfE0U4E;5qE(lP=7@pU5D4yS7~;D!sLl0!$rZkLc#`-1!u z9_iyP!-U{23G>oyUBdG9`y`4qoCJ@|z}!*eX>)pCCz;+)!dR1pvF2Z-*&Od(s`WLc*db z8L)lE`W*nr`-i3AaiZbSqAmd9JrN)T0OH92Apj6R3=jeUL0+?n&)X-(lkcPwN|3zW z81j~E7dwsz2@IiRMst)sNfq20RcX2C$kUlS!J6nd+k1xQrg4W612=61TNzZ? zD9KmefXFD6Ijp)$VFs_fSTd2Oe-;%rdqQ>brYgGWkFW;^*!E0$2JXT_%=D|y@}I-A zrHuKbAoQJ#iaL8rJG&)$qjRA!;X-mm8{2ylm4mD*%WQP%`Ni9vJSe8(o<@DBa)5uN zZA>rU9M_;Kt!R&(@^+>bEnNAb>{fn^9E}uY#?nJl#9b(~-p82hUL~FsBvyKvh!SQ(7krP*%PO+VuNQo7<^T3Bo6q2s>KZioJ+j7HX3m zVleqt7-z6ZBstsaCULzLHNo>A4s{+)Ag!Ng=dISD(mAx`*(( zif;wi{|n*=W?Lsv#;l3fr(*Em0qZ2e7lRgLqhpLnh7~r+So;)jx@QFR1jg8e4uF1I z*M7oy`C+IwvOkYoe-;T%P(?}_e_KmiT=S}x*!-7IY8^Oa{}t<+=6wjjCgszUFaQ(t z9`gxc&|5eKD=$n}alqMyHsY((;{T0Zr1oQm;aW64c}Jt};hR^~0xL3H^-e(}k;50e zX4dP10N3n$egMZ6GEQ*VbuRw}fYWwXeq)sRvGsQlfe(q!W;^2Ln#b$Z5+N(e4V8|= zbaS)9+tcNys3M0Y>0kF?p`$(4zgo?MsCgAzVc84vpn#)Q&uBYrxnRPWoW1&!qFOlA z_`M*pFzgf%i-MUS*~6{uW<__XWM$0z8N?IIfqm(;e-;u5kA>gfPZ8q7M+1)sF#{a} zllhUwZUv4gB_$SD`*3xgq+}yW@>ohKdG_l2A-V2~d-1D7W*IXB4x#a(GgUslx%?`p z#<|37ocy*_t6tLy27i+xS?#3(6_FNh(P!zhiFIy~Nk$!8fl#eSDn_;fBkw!~F5~_{iZ{?aRU62Mg zh9(hk2)EoxBk6RBAR_$(RY7wpyO+O(G{)yvNhzy5rb(0jKM_4>2p(!KA5G5+J8i}i zPLi>pq%g@gATRVR&&9opFVTof4_y5OvqL+z$;;Gc=Pmj`tb_0jY3$XkSb?Q=>FVPC zM@B!&Jm+F3;mN<0|2%4FUW8o9GDG<=%>nbDXCRx^7ZB?I3qKa^|C?~3PDN-*t?@gf zfBSG7#EGEyI1)Pj`u$NHbP7rD&%gkhZ6TD)v4hOd%D1$LzSVv*98eTSdQ?1vITm%F z3L0z}EL$|84n0fOy!7zG&3R6eN3rDiYdpCd#q>ihj*GFKGfEwAIgR*VpesLoupJE{ zh$KEx zLhIR?6a-}Y0Xmo%X!v-TuPtZO85>)jbcX{wbD0*%c$^t845u=MjcplxR47w*z*RnS z3bqqkUuB6U8!BK2X_9^Jmr30X@8;iUR!vVG25M%k)M0)j)RC_`nNYo-Ow>Ui>|ekm za*Lz+OON?7#nb8SEbw1hY%4s4?;gTMkg57nKQ@9Z!_{!R4GK7=ePQ2#S1*qN$;Q^m zw8ZD|?BDx91@kZEui}Vv%PJViErnQ*;m9rq2o7mu*AVm`1%+dmNYo`*o9y>SXE-VU zL@a)JKPStIDPQn|5&jo({DKJo%Q$|1g#T3>-#&`7M(=gM;VWu5UYV!wRr9@vV zSu2a)H$i22mI{FfXDE7{vY>mXT=$!ae#iNM&ZW9>?1-(4;kgAfA5KL!W@WmQ9C-$s zgzcJ?JC-S9==@B!p|sdZt&?={i7*$J+M>%A zLPlqSr(LbK)tl0Rl->>!tdzbFV9H+uDF*9B6y~`wiPj-_RoJ90us`u%!&olPMfep= z-psKK%>!3?23|_>EdR(Iy9@d0o6JxYl(ABr$d2LoQvy4ujNYTJP8OkCXpczw$FpDP z;=?0oeCjM*B`ck%ve8x}(Qd0z-e2ob-rM#eZ)jf7n})h9v|tFCOAnhrn#Ucb7kr#w&SoJzIQUJ$I&h% z-@Fo>bG-XlLu>!vY))In?-efhiE}hvO;SU$=g4<0!u2oZQlMQbu*;ZsX-roPif8V$ z|HC3IzU+lMu@9YrC)`_L@|Ff|S+`sF5K&#(mvQF}?NyrPc)tU+B^V6;hEFJx3?kbV zkrsfXAWHRrsT~TAp{jz>HD!Gy3yj~2AA3gsyQnEQ68Q|y=%0eR$vWZRt$uZ?ZAej< zWfr}#jtiDfO_nWJqaQh*{7MnwLMWrlS@nk7*oZY3fXn`em{5~+4L~6_9C&54;OYh` zcf0!n1qLUHutJ6(Ej>6xER>)VO?U4`7}juxSg^X}DrE(ieGwmA^h3DuE;(Z2cggWR zxMzc~T=dhuV2AU*3>z3n9e1cGL+nKnNVe1Svi3Nvl<@!=XOF{*uK;r$_~{8hrxfDd z$++lke<$-YkYH~!IyW)ThZuM%wCuF!VC~`8W7Mq#J|lhvBH{euDLi6cCART(Uefy` zw)kcL8GA;F4$j-W6h5Op99%5Pme<L52EhJUM7^UOa%fCyIS>1%%*h7^9SH?q~Ni zYc@c)=K6W0w!HHGLpqLEn$9mU6>Xlm#-C?d zK8X<~w3b$2m6lAv=w-PuTPW?sub073rF*)N7K9+BaOv~l5}YMPTynf-1Y2IUB@Q@B zd3B#tdm7xY;PYBqfsB&7vgNHCZ_x9Mq2aPJ&me9}_8_#*7rQBWoi&T-@;XqIwY2Jr zz&r^sHd0a}!OIaNG<%Fkk@*=j=lZ_@Ks*y51OVda0YU)qk9wJN)-31G9>pdpY>VF! z?~#K^pTBw!yLAKQk*7(YzX2Y7Bq=_+Uy1zY$SE#NFEnGie0dNTHPF?FWJ#YdXZ?zZ zUdShMq0^WAAw+ner-ByxQVD~F$pYHB+Jymp@)xK=e@&dpK%Pv~v5228n8(nqwx+wy zlk)5_Ps_8{{6?OA<~e!JG0)3$u5nf~{ydYFXMc<7P#|l16=*dJ6lgO=1=`Js0yE4C z1!kJH3d}O=6v&w)73eUV6zDW3E6`=mRA9C-3gpcN3KY!63Ur$*6zDP6DbQnx_@m#r#HrMdmpL2F>}eCO7+c zHK!}!nddcVv2oUrVf{suRiI=#6eycs1uABN0z;;#z!Ec}z*4h9fnl>&ff2J#fl+g$ z0=t<_3M?}xE3mscQ-M8(;BeEcz!7GF0_#mtfg{a`0!Nt@3T!ZI6*$_gQ{WhLqyop9 zO$ux@Co3>+&QxHNF$x@KE>PeVX2XxAUavG4E9Q7}g#ss->l8TA+@QcoW~%}xn^$P6 zQ_Ss(In~^)z^lyZACL@BGxsXy)#d>OPB#xJaE5tIfiumM3Y=x0R^V*&8wFlto>Sl) z^SlCBP~S&bcdp4Q@LJQMfHA!aRLuefHk+aXTg-?8=b04>yw0pu;C!=Af!CWO6}Z4` z5@7N#)GISZufR*4@+gCjNlG&4m-0lnlqY(nJkcrTIY+sZnXAmn%v0WEpjU)9nf|QS zJJa8)_0IISX}vT3?ON|l{|v2nrrL|qVe+q$qQg}K=46uDQZPoI-DXmrJ?8E5>@_#b zv(J1^o^#AY@|%Zc<=xbEg8U%;ywXZ5~o!jrpzu zYt3&I*vI@$fqhNtKp|s4Gf#p2%~}NxFh+p`&7=YcnOhWCXC6`DV6#nuLrm%*$>&fr zM}fo4ZVDW34pHC;bE*RC&6^cC(%h=RQRWc^HkhXsINJP9fn&_9b&~V3W`zP9&8Z5E zn=2LAWbReqIP(hyUSZk}mQ=4aa}+q4ag97K8 z%%PIcYt5hn#vG|Y)ofN^vw5=uTg-I|oM&!T;C1Fc19 zxW1`-f-|WJsy+7xY{&RH%&z24Cc(i2|2CPMC&ifu=ZBKO@dptP4l8HjfjdAjE$_wD zEx+Bt+^R-Fvp||cl*W#v$+t0XzPXDeNZQ3~V83z;L zWq6kHUBmpb^6W8fn78_a?8clivM+XO?|~5`ZQK6~Pixyw5Vq~kGSRTN5lbEwDvIfXw&TAg+V-5bE$RAMXQ!6kfdVhiH?=i$d}L{@rh7!I}UiY&9{c%WSIRN+=Xgu~jc z5w&nhmmkQy zh!dgM+LKUT+@sfI71s$B>Y&z<0*arMnoRs1HIqX_%RxuAk7G7bg7;i}#(S`of=m1f z_BaPOErDUuS-cV%hL>SHy*WsTlPyx47$!J_XW%6V&1~I_4z@~2Pe*z4CO|) z0DEf`!+#VFU#M2G>N3e}Brli~(4vrb=2$nOoq2HND(&A76<6@Th+lsY>q?^ea1z<; z1C`~O6P%zq{xb+x#e)W=M0&g7rwDraEu6=b>$#x};ArDVNz&QK5RsDL3DcU4_1N|tLA~eUG)Gu+)fsO+7{}l1|A;~^-dPAQ#9|Gu z-+2UoZ`M;{fo|3lds5o(cT!w3TY_~Hi^utg!h2+#Ne%zLc*V{NNpcJQaN#8Lhgo)F z9DEeMz*4_7ANv)|E`1GFwtuo$f;KPD;33*V_ir=;bkBEHhL!|0dWRuj4uRONL9fsD z507H+7?x-ha*~$BR!~wc`hQd$GNY#=-^&q^x;DxC1QT$@fjuOlrd5919Pa?6#!P*9 zZnE49Cs0S=)h8|~zoV|V8ZX5>9C58t(sHS5aCKR^H7PaW+X9{^@Yu;an{~lnck`3E z=GI(u8)*wp9E7#|IBsXjx%h{FijZ3zq(#)=qs+DZjGSYZEjUr>uP{SBkUPp6C$ z0iQY&3zsRMC@VbANLfjGyC9DdR~|(gI6_~znlaqIi{MDu@UN3vk9gXJNDKc_d>}23 z%`~Qk?*s{35~bY>6{O~3`?fj6So_#z_$JW|bVCwvlx#9uATyetI zLsQ4*iYpONdKIRDl2yL`0VFN0h7UhHrJbA_QP-5`Vg5)6bHw-Iff*!I$P7}FE($^! zNu$PcLHphz^GK#`m`4&Zbsi}hMpdt~<~oneS-xN%X=`jN3q0G4e49UoZ?_;d`Sw9P zE#C+#-;S|-`w%d7{s`X=5BT;*TZ$6LOA7??VLgm1?Ne2e6bNn(5p)L1T|yfJOWGN?WxrplXS7~>mj9`TKQ0pDzm zZDlRrxEHk$;W}5v*}E>QZo)~aTBgeQBqR3lHvJY!B@RK_UBa~16F$EP>9?jk zoAWSMoQvx>UEW2<&sI1ZNA*p2D*(S_#nziZaGrDWzuUH_`u+dp6jufgZ zLFD8=F#zLI%IEpm-!bnz8Wy=d$nAri^kKV6Fv%BTl4T(gI+8KtC zvWMG9n|}%YO-C=pB*XB1!|*=LJ{V3+6nTXd&lF|@#is+{y>hY zo&|)r0PmZR0^cWvqYIprR|Q_%M)yZ|Mccp!Y;czO1m!%yv-!B#sX~Ee1uh!d7LS+ ze%iMqj0O&T`q!ory&*nKtX%IcK-U?;M!N>@#XFPW+7=QDyRj_b^J4Jp0@#Ct({L}2 z_r0jT7COc2X^n(pVmD`rGY7luB-OtXA6aD_oep2<8Wn+(3dRk%9t0mi6z*|P`@L9g8P`3ldOAPS?m^k`*&>;gdtn;Sf}y{ZQRkCU!mi@eHqH`TV2sQ;!(qbl z9TOUxuoH$aJLHP9UD{R*@kc?J%^oM=T%N%3Mo=dh5xj`-;@_s4?3EX**-?3Z%0B@X z3gsSaFEl6cfTRRn3VFFv!3MZmxO)MvnFtr>=2Hq2CH0H~!wJ20BD7#E{i)w$x|-fSxwR zmyGvzv;c4UT?rcexAA9R{CMZ#XA4Xnnp)E|S+coxB7d(AN`Pyr4uaM?E6@^E!~Z_` z(Bk?R(QgnbZxQ;%i8VfxdU1FKW?b2}Sdt8_8nS~3c?Uu&Phqb<758Nwi(0*#1m1(6 z!5G#YbA+vz=A=PdrL>QmHnVB}5d5l>c@KqYjF#>0iQr*%F))4+Kh_@Lp2V&{lx0tu zA8}mfw@lJsBp!rdGa*pz7;xN-d>M+lgtXWcAL);UxMHDZE(B?^GCaz%IENJ@&LCa#aeREP|#xEm%_c$&>j3Wx;qi|!^*!mvZBZl-3 zfsm;C$TQlwOzLCWhQ(k1hv=1s(Ml|;NDsUy`>#Pne{xDb>?rYza3M)jau&R@;EV{Q z{G^)w5tQW}i|nX>b?jW9Sapq#o#=Hb?@1Qp9l_gvgMI`1{f|MOlGQh`CvfiCoM8GQ z`@%^&x2iLSEAh;AU@%t8PG$>Nz$YFC7c-ou4Epj4$AbeT9Eq*V>p76{2Vl+UWf4it zf8LBzG;AGQM4<9odaV5a5j+hLkp!%&7p{|ZBAW;bTAwig9K{$A@&MfqJIs`gR%KPzu|i9qoL zA*(OCO5)ja7S&h~1_nMt+-{2FBUoKrbqHLTg5>HlAmt3p@-h@AmWKC6(ior#oiRL0IF%EGzLqrlD;Q|6t*77Hhv1o} zx+jpG>3nA<-`TR9(twJzNDVqMp5P)utgf?R^VQ2BOuWD$o5QICF28qZB}bmjcea)m zBC18?aA6^nbjOmkB1vnm6){+)k;n3#ZA_8|f_%ueX_7)LNgI;1<=PN~wHkR$3KWK* za0o+ZOOD6T*bu7@fJpoYYOy{9nnr$@OM7ocO*&zR+MH|m-U2w+&h?#C;#pL`LS2(X zOg%!_+U#Epec72V?cI^~-UzTQBfYVEs3V<`&gdV6Zl^2P8dMnSaCZno>PwKi@)?YM z>FxO|pzU=r3WjZuqW9;$)ySqD&ZeTb&J@qR5|2Z6=-&dlEx0C9=3($-f{P*vmiIEB zhMuqV_*AEm2SQqkD#dv~5a_;DRbSn-TrO^uliu6YWb_JR#- z=IAQ#48XLzAI5*e{G&hmFW|X^yk=*_dg^i-ltU75f-oy0ri>naLxAIO&?dENFRcoY z92jiG-2xmVW=0pa1n&}uJXCqr&u||HL9!#CMg`SZPnIg83 zdk@~B5GVgI{8U=ato1m@xe73rV%~*b2EWGm<#^6{&ad&rCl$_8NuqiiD0Ln^KJX4x zcq=xYa1I}*${4aW!#QuZ-Y&83fHo5!G8zlZ_fCx=TU#{N48}6=M)}?0buG_!@1g_hF!U6tASPUP!AMHr&Jf7@k&Nur_>gVZ`cZ&5N8Fgt{9 zIkVtX!tcbYV}b1+eBF2PB~|a_qq#ntj~S_Y9#43Heu=or=IWizm>4#sKq<_eoIc=$*K!&N&jZ_2mjMyVM)nQDNahZQX?2wcppN{ z%0I{ia<_PQvIgIUsX3$blQlRZOv$E^Y@)%<6z0dZyU@kGrHq=#`i(^H+1|t*Pms-| za{)s4v?gwul}L=D-MTuvs;6Kg-HEkL;iC{EV`gD|gbP`V1dj=t1`8jCmpC44v8aao zgD`)NI0EOYoCE0K_*+o2v93|N$-m(_$c_-s$n&AO6zaI8hpU;AXI|cNpeM>z@~pFp zx!GD%4nbLW9uIHc4nokO*~I0gLAY=NhU(c0mM9pcna6|uFX1!6?ab%$`(@B#5L)>U zW0yq9!6_-ce-8im#QXmEzkCo#$Ga7!E$;&u&&u2j|C+-1^4bzK-d%{K1=es`DJCn} zvCi-PbL8T9cOXn#X3y_7BIb^MW%(C@YRGx_Bca3Cq&T{#g~O9JvYEaJx(19DF?aO) z%XzJ!W3%)=io(l%5s4u&y`#Td4mSW%%)1eD#b_M!F=FNe(?H)*yW?wi3z~cdtSC_S zortyk1@O)BK0@%>2>iK#lpEnnuB$RLH+#E#D!=1K!J*EsT$euv01ITA7z1je&{le_ zRtYl?%5eAS>vmH8VVp<`Yt+5H32qA7TcX2MBo)_bAPem{+)s_yMcJInx0PT8ACjq! zxAOIz6u^b6%Gu6^>U$zogE5AJ&ONW)=4DW;8FyLA0hz0DiX_gX(yM$g7R@% zs-K5`@Q;S73$P!9#KX>o7G0PiYBJpXmhw-=3U=(niuXitVVnk6k~bq^AUFllVwi$| zc_Sk4za>QEZKq|&8LNZto%JE)`(;#k`8eWqVYWI|hxCl^1^+=v9`$8duTevYt}_4X zvC=(;HRXnA-8LF$En^Q&3G9jIv3Jlz#y&75T09T+MA&TgPtQixKbBtVBDg^zkyiCB z*%YVQ5v8>;AYDFo;jSR6)HD&KK$%d&i-XmAT54A(W*4eWrxx5jzSrcGN=(U`ip{*R zCQvs=PeVn#+GTjg*n!M=1m%lsDeSg-uW^bc0*9?*iOVCPC)sDIB8Z+8fvjA$nIr| zL3&DMb}9y^hhoss#7ANveVI+1fpOp0*u?XYCf@kbSUM&gQyMsoPV}IE%3|EdAzLzJ zOcEt{{}|}X@=~ke7`>+}QleIEW9vGa3-F%BKqE4KZ=8y$NylCXtsPGtkIY*v-Q`Ck zMjUIxp?hp5b)dYPli4JT38S*RIx(^NZ_54IVVnO?WwFBaI5}0Km7Ucq(pQBkGRb*$j42bnL3`g5wl`6N4<`yTA$tPjsl8+F~3?eNPZ-Ly5{0+Go1^n;E{~rAB#s5D1pL2u%1CZ2MndNYLoXB_1 zif3WM`F8mT{p|EVhM8hzMm!SSImP7665EsO$@iCT%=P$}a0&?vPkyvY>aOigowG^} zSs*-8yxqB(I|$FK`85=;ClY)ZJPb;fJ~5Qa&EnqoLuB_dr0D8|3jY67q2;D1w5a-X zf;v%G?Z61ET{SWy#`++ko#NmNjx6%ONp`?WIaGq|FP*TaoWhyH_z)U-$NoXy_6{xE zSx_0yUZzh}7+n>R#3JQdGJj8qLwVOYKKv44B+)tete5Tz8b!p<&UN%p4BQ08=D&~9 z)RF5j*Kz3hCCn!}d-I)rr8T+UT;C0yow-i)o^VjX=CyPUmAxmyhf)J7*XiS<*v<7} zoxd;Fm+OTk&!-AS6MeCUpG*2(w)B^3n{**a!CcWw7fljRQYN_3*M=^Q&~N(=L3;lg zR;h(?HVxTKA2{S?3{@D#vWT^gWsq(#T$>NpSmt1j<&jwLndn0#nYMfajjz)dq6DwQ znA2D6c8 zlOE-AEsFVZk!!^X_`Gi5AnHha3fPe+hQu#J$eW2d0Y5((@{=gRD?b;MLi}&VLXM4xSQ5V-3*Td!@bARJ;Z-vlLv8ve7>+t}5vUi! zL!Vo(1d;qpib(a19+}jIg{@FIdO)eeVr~sE<)K*1Ow0|0=~JOF5hZvLCderB$EF1r za`?A{p2k=ECk4Nw)};m=d-qEOnz!R9jF^Lzx5PVi@S!I?Wwc>6A_!vVP1f$lulB2D zwx)Lm>b5f9k%ec)`=3Q5v zF?SSB>7tAR{wV8qnJ#Dw>%fEylC-Sq2h}vs<1_F-^bGcIaR96etI2Gg0lePrw?I1H zy{I#;2}6M6(ZZ_W|Bm=V{aUFllzhk1F#froIUAl5&N4Ip>vDynyh&^y7Vvs5XAE`N9r_Q8 z{u-Gf>#^|1x6~1mc2UI{Os=nx_fKDd7z_+ zsh5bz(`>Szj$;wtS3oAm*;L|Ult*8R`K;bNqNj|+Pird{iMySQe61z*F_g+=OBwOZ zn1(aD{_Nmj9>3~tx*hju>Hf9%RpdXIjKA0riyIu&4QaQ3M7<4hltkLUHp5{e7IjonibCGy?;_rHRoy@GkMaf6&aDsjkKe4 zY8AY~Uyx&dfqHpAME><5pwJl^;?($}^QUE~88>j8+G61HZzT&vlVn|3L~)M~2TC#J zv>O|A@d`viJ~&l=(}|m*9G7z*kg6|5COBe6a&XjoJ^FZSdiLmv=8U62$K~LEo0FN5 z^3SB?x!E&mr{(oqD6F9kws_(yZ zZ*S8x6EaJ>XEGr@0twgdo=GNykc52^S=0wGLc$Iz$|4uL2?|XQgQ5rmf*TN718%sB z`+^`SE~vO6D#U$x^m%;TcfTtZFUoKknoizsYcJd06)cXNgVo3!pXL@u_ zZk4yVlFqaLVtbn6qfF{r@?5tg9+;>vQDz+;c?q;w8P60b_7|0awN4kxYd6E1}Is?>2?3O`1W=1D=N0U5WUru4QJn;rArjLtNTUi zhX0r8q8Dd#^_3)aO@A?yjqY51-`RlY2(Xf_7FZ0gsovB)oCn>*YiJD)KP-+87Wd}5 z5?RG(ihnZuOmQy0<9uIgm!HOGeVv`Fg61>zjg+{=p4=*A7f<&3_0whpUOWTPYq1c7Q_yx_oB>UEbSR+kp+Kxp=wQm61t( zk}~!YfBC_8=m>>uxz8>{cc-oAWQ+B=gg&~*U7Vh3=z5J{^fnv~1`QjR`zZ`^cVA4z|;2Poag}F(Vwvz-U zuy^g_r7ovl`>9?(PN&W*_;x0>dJd=aGBz*h&LQ}N?~-wCB0su2I`7Ga+4?0EX#;Yh z+MCT^rLo5>g|lpbb0=uj^6c$OMCi?S1xPoz?(jB1j} zME;CK6UO)C>mQ+v`9tnk2zM%MSk(xX7?oTji0}8L&RbZIPfgHIea5>JVYIOU-!-d) zX2UbE`4Ej*$=mu&oNaLO?RUK2yI4b&^9AQ1kt*KBfkE`^AmfdflG(J1)8#0U+C*h^ zBt|!Z^j|Vw8a4GvZ)zQ}P2=)UsBd;Arv);2YfoI>)ZTHFf3>3sWboEr7G<9}%D)xm z*9_Ft0!`_swZ@|C8%NpJ&PAXp{j}C9N_;M9wLIz8q&}I}9{Tw4P5)=$;{x`2Kf9T! z(cj{%!hf^ib+Et37=(G22M+d+cDw~`*k9YQ3@}qtQOfGKr^)v(?XXES#@HS#1wRH< zDR|aT)2TPmw&+`!7YU)M{rE8=KB0tlSZ`V&g9m$YNJdJPrq!#d`fLuL0AJk;KZMsO z1Q}TH+_G+mJ9k>WR+Zn;^p zR^9ZxwAC#tFuU0gRbZqr6b@ABVX9=~$kX|9e~>zfE$6;%C+Lpfn(L(F0z)Bw6K_ts zSrt=L#W?61>H%%KMz`}f7g$@VQEWBB6lnEtXjz7Zd7J20vx(%B(&e8{-9Y{aD*vJ} zoTIe(Kx^Ml+ejYFZ5u&%+%}zb$+p>1IxcO&3lc7g^3Xi! zT|Pl6Z-TB@$mS+zymL4^ot5_#(mCFfq)L>xhQ%7?3A*F@b{!Jh$Y6co?tQ3y4A!tTC{|1#otsm*7_ zKZWkGe=N~f&y}2Ihf;2{`?^v#>-ip(V*JeP03UVYWk%^v{={uEtNiivTu0AdtH(*y zTe42P&n!+-#A!|QU$zk;A=!Gb)w~R$kUGd@cqbg)*=eNY4cL%7WcdEf@5Tzp3KKrk=?=`# z`5wHT^c==IoqPt;EV_;(X?3RvpcCiE0O-!8dGUjbgfAf4#)+=j)sxSLF9fs_fWC=1 z3o3fQfwWs+)>|Lgu;9EAGe9isI7MfYU<=pz9jd0u!aEcdo8wZAijCpJF8A2WO9a9r z_6BD&vFr-3qB#Rzqb_WFCsm2n*-GxTfJZ* zjmL3zc~OAr(>g%zrhX&q?7@8$;2`1WjCG864p%Y!b0IZW5{Y)uhH{N4WP@LVA0L}i??(YkCU86LWDb&Ycfw=Nf-w7pn3=Y;lqB!96uZHm56w{S3U9`d>pX>;3trrZj6RRTbHm}w z^eKjDY6@H{Q+h{o^|xN${ZV%-_iPNFg;3m>c(@=}{~LYA-Ym$Kd&)hH_fks8c{!Sw z+j?X-6td)w+^+OGd1mw5vS;YLH6|%Iq)+Q6OI7n{t)a8w`((DyNz6m3xFn{&vBW%B zQaaugQGm9*kD$cX;ds2DL1C>U%y|e=u^BGDDHj8TRKY6`2TTaX%#vN5dDe4CFn1mz z=#J+hopi~0$djjg?!4s*y5sUX>5}EmNryxiHB6$L1Au5^0CNC%mH?-tK$b%)cE2T; z7apbsF%b@nBgo+*$Q4C6-fOC!n$+sc0J@N-hjj~5sl&j37hcfX z55@nGsv&+5&SHb^OwC`+IjNq0pHoySn~w?^I$^`vI8{6!l_E$mjk>VkUmmmo?2<}N z@4qpa!YR-teDh~-45s;dfn?jz3GQWL+qXJ9d%SdHBuX7{LjLUI2Qpm)+5W6c$4icu zu4{l1HU@1lP+x8!FPKW~;|WzOE+6|hm_OGz4LS~Vx%&5Y4PU*Ch8QUH6^gHyt1o-0 zeF`P#%|+fJ=gmjn@KVay+S7+!AI^&oljUPHl)FRs%haJ`3wl7__QP6o@DF}{rK)Qj z=ZCMt9bCpwt&3^gG8($N#Ias7OfMLZilgVG;<2y>S2YXa)5IflQ}X7X3*RNdLqp(k zxa(7|7A{_KdBO6}8U~zI@KZ+`wubL(h~tNs3&{m+s?Em1M(rU>NuW4AfqE1uoeOsNnojQ)p#s(jLaeU)4Sj3^7X+b@@zF)s|H5LT*)R)t|vVj|{YS+_G zz4)o*Q)rLE^JHikG>@ggY{;Wlg|S5JWZ0(&bN92qO_>ZWPlmhaOkZHBHXE!2<$@X5 z?C#_lUI}%=*YPuusjgz~dKJ!|yj3~ejZumlrK^X`hJn*8U&9zx%jGZ@1s4+kYT}PQ z$c{s1Tk*m6yDT}kQ<3FOm#mpUQ4ecVz^F%nSwPX7F4?37l*)po@B`Mb_PxUGRd}ge zQ!762-0@`OWWQ50ulW%s3AWM3*kJ8sviLdB=tyYPcrl|ptIn39l}f=Lyk>)~jF)K4 zzY3-fIBj2@+8`$A8{C#%4V@aCQ7KFdWboj7#0U=NNAfYrw;f7))^fFhBt-4yk1tPv z{E)ZI3LRFnpr8+aLt)FiDzAr}Eipo*%Z=v(&sINbUQ1|VF2HlS@7ty}e}pGsoe zL~QWrTcLH^e8AfQ`eB{$-s(wA92>Y`gK!J*;0}Ix5qMknP8@FP_cmN!Q`OCdZ|65# zpHeCBz{%Ux+p_P(;bOiEm)8_E^5I?llKJ^$KDHTN_O}(6w);W4yeND(5i-%2!>&pi zyjQ=C>xKIJ=Aq=b=ET$EQIxJZ2ke?=c;{5SEmtK zocr;&WE&qMI&bdX&1azqdTpEH3q{fQw7t6f`(a{v3p1^c=-c=xzpamToF6wQ7aa?& zPvBfAP5CErxXN#224tX5wLzbbV|}I#x<{Z42|wEgSweyCZG$YKK=-vlO6X)9=UP(# zVSFzvG~3oUv}K_+Q}{XjJ(yYYg8OmNw#nvv01zRc=VNA;ylusAwj0K^Uibw9d&$5L z9>it*&}ro_Dg!_GQk(%T%W=HOnt{e&lT+o??uW*5>eSTkmpeBHI-2Ste)wg6gRk%- z%U^2K@F774=&fTcuhsmU*rgd6+~#xSin*<|yUy{Qt_J6y`p?j%arbZ${NURX#0x53 zQw>+cQkc@!c6WZ~bGbLZNpbPPvNmf1zAu z!wZW1>gCOjFPx$~bP$p#5n`gE9!~YcZ{iBRC9hi}p^{Ao)}%85y& z2`I}x{0jWw}NQ>i--l@4f{AXZtPCXkacSTGDT5;LewOkcGn76bowa)NjfoON1PCq zPKuJZh(;%Qt<3P}xJr{}yD$S4!(S-$<`^S)Xy)*_F>WCSi?Sjk$ck)nfAk2_yr^#B zFZtOAjg|~U36Kqc#joQRC)KC^6M(hEuW>Yf!_Txp2A9eFda^P%acfXhu;N`+=4@raY36jmc{X`sl7I#eCWEF%tgx^dW2$>+vq!>)f zrz2gmhDo7sG5^1$H4~)BwPdBPbH6$C3;weX&?Tci|m~84~XmXrzO(L+$AFRe0 zJwaCWM>TJ{f(1gNGLiFMswBM%i>5eKpl*cFO8^C_9;kn^8|o9OjT9!6=h92e^W^lh zq0g90^b$?BM=y){f1h3*1R{DF!01&tzD=)oWn8BSXVS|;cR;UpYDceoczYvJQO%MA zbOqGB(|xcT9)qE;&dI%%Hr}8%4tblp5R4!RLXT9u(3uah*uX@KhX>RLYy=4R!xcTP z@x!F`9B#rZC_O8i-fFGOvg!77om|Gc(D^EQbsyKU)e%5&el2^no{!Z8pr1fX6qGcZ_R?V*xCW?mHL$l+W1m{G4GU%o2Z$1Bf<= z%p5;DlN=ObCXi-Y>vuYzvr@-D;OfoX#l~c<+djt_e7wmK8xV7p;@aODz-*OzVP2K% z;)i2|RZdD3aAJLEC=oMZceI-Kc&xsgI7DSXtuXcwYN#}7D5v#)Z2n}?c-uod8*h7Y zxbaq?DgD@Z8@!(-HI!Qjpg6HM7w&`uMMM$B!XligmGVXrhXc?)pkqIF>V_Y+C*uh$ zFknxcIIF3VTU_jFZxpxEus>lDi#7mNk8r+HG#sg694=XK$r>)Gz`6{VlFxIzwb-!`m=bQ@tg&_ zo)@nNGpS1nw{c2(YMcA;s43ZcMc)mX<<-F;{<+2JJj?#{IX)WAb&v{o)D1KXb{$c- zK#Z!QWH!PvQKJ|XPo%*|{Kx~esS}JJH5U&T3nddg34Zj#BH&_BQlJ+OB|XDQ&yu8P zq~ozgbd46Q{EG6vSArVFU{`~ z47dM~oLpHzp9a)ek#*sZ6RarFYBh9{HD*Og*+j){Zf}K&6&2WFMfqY@yg|u?3jMXn zX0vcnw=i5vMmL~sT(Gz|FD^3((#EiURFV~UA?tZqF_N{PPVM@`nEwu2uRfL*?h*9yLW4%0YK!>h0DoB0^9kLOEJe2 zHl>rmmR@IufnX=ESEi1?!pUpxtsDftCxNfO>632RIKZ;;c2+i+$S1*KK|O`jr= z=U|30|G0&~T=Ne7x+uFV%3$TUZl0751FNQ{kA7{jSHcvUoHos~xh}Yweu>Kg3p3%< zmD;VL&juG}w~?LCOl>IZkL5GgaMf%ktPnGLi7GPwIHb3Q!j~ZkR#bbk_0N8ulgVfv zS&pT{KT~Kj_E>LJYz)*9+R9XX{xhtSdrO$I6<3p6(^Bd0Jv+N`veAgU&m*j8urj5X zTzll#DL?wL1#ckz8i>Wxc>Mx+x^XH}?V?wDVHwNMV?|G98naEzH>amoLdD<`FedWx z^9Mi^?Xi8HudTV#kS!PkL9`|pn{IX-PkO2qtBkLg%2=x8X@LwLOq)2-vnci22xs{< z9Uf`iOU&R+`dLX9)jgOaiCsJR1y5ruoHG$#egF4IsfK5zN>5G21>evvSRjK3XdkP! zJO>Nk2MsFTkoz9$HHG@rx1d3AtEz8wMun9+MSUk&1wP@e)lhN7mm*ihLoy{ao zm&Wpb;}-y`3kHK_M1+Mbj}gA7cJe4&9yR*cJwz_qjb{4kg48t!mX9n;ue)us`g@3i%Bp=tI0Xav)wA5rf zN1YYMo{K*YrJgmKz4!MRRysMH>T^CPMXpdx#3c!+XxE9CQ?u2$34g0d$$YnJP*Ad+K zs9IrfTx4kVxRZMHQjgxK9z9l%bsM?dPE~r6Rq4x2T@rKljpWnVhkT|5GI+SJvdvT$ z?4h~QL~5Ux#&e^EsS7TP$0pO2M{}mzQ}6o^H%=|7|F)hw59#pW2cllZqc3+*h7O?Z zC&cfRXG!B-?(?2x(0k<>uRj_Ombm}ab~EWw)6*HmCl|vfFA$&XPo7dks?#+dB!ln( zAimRpt%t1!vTFh&Gmm^eKJ55O`?Y)^w-#xd>dV#tE<{(U+Z~Fp`-8FXx%hbf!-cK8 zmevNaI1XNSy#uU@jW4caik(`+!9BWEQ|dG8!iLP6cLL1?*MM9wN~eW!4+O{Je##Wo zMV6`QxIs1(&25VbWbn?mSibSKxQf;1M+F6UBLPixS!vaMb4;3Eufh%{KpTSLB-JZU z?1mlZbmIr@352 zMv>GSc@uV5Z9;&B8s(DFu@710NuHvM-W7gBG`LRHm9mwq%7lv?wPh{_gn67$K0j2< zH*{ihPpE2SiHe3czf;Ui_y_m-lM=i!PLQoU=?EBeug2Vcpv#M(OXr~@ulXs&f!=uf zB;V+bCpq04PZzj-)#j&xwDe=|7lc5OnfcT~=~U_r@^h&%>7YhH1D3jwKe43_SXODA z)A+ldKUN&6bzUmP>>~9U{=U!O@BCEioBXZ$4L?|rwbDH+(lO|zF@wI9YP&&Lpeg;> zAl&+l5N_&s?G{R8*)CjXkIJD&<<=(@w`8T13Xi{XPMP(C;<0?GW9?3=p*R(LuCp+$ zua8shJUi8JoT@lCRsMuXEmSJS@48E5WVhrS-&Y%V%3c!Z@-QTuNu}BIh(xN9IMwF4 zsdkTNAEntCFO5^ZaBiyAF~&ndg&lN`>+K4~`M31m;81#*K^woFiTuuShCG-t8~OEd zhQpRr=WU-tj?3a4?}J>k$nkUzbJ%2T$?S@iyW(V5CX%6lHGT=71^%V0`;hbY_-@35 zZTXHV?8ae4aV%6W#Ch$P$ZIeP?2ZEw4YTkwrVge=p#zZ)t$W3gm~x6 z=oe^8KONCuy83jGvO~%VL^ztxYapBEm5LLZ5s`}Qa$F+*;!&%e9x-zo@4$dJ# ziiNG*aX%l|V;Wl}(-9~34~Ae#}z(SLKXF*5hT z7Tq;xV%*ow=_SWsJWGz>55|(?pW_?JaXFFWyd8cCbkJPo^FUe;@MCiP6+mt7`*eu* zYS|mI)W~rpmC13Rfd9n3W*a|H!*cYR%E6`@4p%JKkN!)zy0@uYUr@PTQ=h3<#VmHS zSnNoMGA)q7gWVYIrY?(P+@cuIRt$j*9xNwD_#9xZFDcWKVNgAl+~p6StB?m3(nzP_ zz%R<#biV>~+X+hzRJ;Q!Z4Un-kb|}EQ;H$Wwp7@Cy|k$3FpVON#YIrle|@|Lvu)$;4`t2IP|U)B1Uj)+>w zh@<^6Ba#&Aj&H=T;v4ui;)s?wf@kHt`qSbG=9uSIrrxjTfQ&ECBMlF3!5f-ex(4Ts zC)eQasd8D67@B;hkG+V1gAUd8*;4dyxj4hP*m1_xtK+u5Rc+1mp)f6w!2{-s)rvo~ zKHw^L)y}{^m$F$^KUvwsHq18cW7%VT% z;JvFbrRC<2maP?Uh{Of>mfUdZSY?f`VX6b~qWfWG62f7JPZ>52a=} zm!vVVa*-oy`Qq6WwYT8OFy7-BImpvbJrf*voaeE`^}|Qo35!c&skng< zw^VdEBLh;LLYRv)>W|lewb$H8ib-w<$tsK2JRV{3da|S!6 zml9hWD1A&Bvz+uo0GwfLzKE~aJcD01lwIjSb5L~ej2@zUg7sJ@7XT_* zPT$cXpx5e4rCa6za77F-$FIGnVxpoA+FGDW!d*Z6S9$~7W<*-7*Ne|)5?Dlu$*D_d z`eI>Du2;snnq!?8d`4*a!Dq$wn2M4@%Vv$0g=Kd}fFrD_vn2m4%;dJjd>4P3ZtTY2 z0Drm`eJFoi%t=+x@Pk+BKCSzRiT&_W+HmSo>E?D3RuSNl1mM-gsNdETE&PdLfFWK% zcPC#XK&1^Z8*S=W(-b-nj#%0^9Mz3=TzZ_pwfr5zU-dclXT%GDO1-@nsMOoD=SpW? zQRytDDxLLFrL*X%)GtQdK;ZBtBD8Rdb%y??^G)Z+O*5mQQyN+iX_LS8Ml}naPhZoe zK>ooB*D3{=`gW|*9P8&qI8<_Qr{pYEme~GlyKpL}@|W>Fn|AXzUEs<`nXKHh_UqCX zSw1(;1mo752#J}Y^=5g}t+((I??AdjWJw$NS;ZOfuvvp5Ca!m$!FbzblqLhlIQxTw#2gx}F%eQTC`pcm}aB zEs((jR_oQ^?eIrAXs-dg`0wrDnBIzbkgv52Zi3h*LMjl=+@0V`IBO2JejR!G2*ajUQ~Fn1dVkZ)=?X2OnKfkfNPsbu)N~Hi@lQV21w!xF zDEGaI6SDFs)Ud&;VvVj*stucJU|KAYDv(KMEPc1)rNiAw zrVKBEbYosqKGPXO$L3}QX?QRP0E@e@9JGlX6Z;6ic`x#UEkUa31gFtLr(l zUh82;OGWdVU+32*CDit6;r%jD4(q}@qUB%s)=59u)3}ldyjH>>1!b`1y8h01<9+#gb46k4+ zRoYmnJ~si(+5`*5^Mep%>N}F69B(evRz#5YXvC2>BWNyBvaJ1XWWKlZeMMtP$<&Lf zN&_0WJ`?<$cCzUzrz6#7m@;%U(7>ocQG=rf#_A#UPsjZ&>$*?t@5jm0@EBmYr{) zGH%`cW?XLFtZ_qCdEkNe+E#hZSSzm}ywI+@&AEI)tgzdErruHho%Qn4l(%eVo}Klw zA=hb|mRiR2I~}YOHA^tBBbW-zNOCv((B zkf}qc^b|{#bofqsf93f4u`zSI2s6i&c>bb&TYu9#Sa7PR<2Y@?cfH@YH_o>|CvgY+@R(`=I3a&A)lgE{2ph)JV z%?k7d(1AIS;l&--jcxsulq$#ax8{C+-15UsdbSDcUKG?!dU!Awy+T61BCb@oY!U(I znTdc)6N%RD>WR*uGpWjOIZLXpjUXMVy8J1YgV;o)vhp?)v^tmYD{Av{>g?WTb@evk zs$L-Bx|lyU>{HdX+4?y#C%H2i)z#VhYi5DUtSe@LIN9-OKrW4|w!=2KfClN|TFuM( z?n)W_TXVo3Ps`SSM0^(qt$+Qu%24`+ux>|1_Q=-%(2gK2ekX>@UQac4VBr)?aUSS? zn4aF2>EiqSDeo1=_f5z5ldk?*+X$O%(^M@Oyuz5r<)013ss@62*ohA=B$UrZ?$hK` zEEWNL7pxl>LnACm`f#Nrw z00Zlj?k(>N)rL1Bq)=_N6eDZ#>OCjfTi%-qX|%v2SgG9BxdQxjn5R&zp13EytyDkk z5)1(&9KxJDS|emq??WnHq;htKlAK$xQwkp8-3=aKDD-2CK+VD8?muUqqA}^7TGX}vk2wVFRfIRgX?2bpb;QlIoxEe6@ zDNm;lYF(T_$aBPLtcLkh&8&$&PIR-S$1Eum1C@sZW~!&=ImK`(D2)|yd3cWIFi$by z{z@TyCGfsn^D>l=igq_JXMCsf)JvcyO#ce&Dms!d=_0=@jkh9dHd)+gtzNN2F!YrXB!5zGgR1o+wa$5IBx09XUR{Tr6bMRO; zd^JI|-GO$-fqR$`^>O}Knx*Ve18#M3ts7Z6r*7m=+p7A9IK4}(81vmNe)E;k#cO^a z-m)P9N!omsfqoE!Y<`kX)ku$F+P=nHjUWA%(qz*u#dFy*v$;te`5F)mIL#v+te;{< zlDe35o-4~`ABaOav&BUgA(Ra-C(R1y@x#}uhFo>Mf^SRV(HeSoZ;Puz_jwE~{6@cH zYsNI!e_F!#=BWQDO4cIQPj&t07Ge83Vav_+YUNN&mQYyp;a z75Kx(P6~_JelScLG<3m|=sTis{bH(-zUsedZ!?D3sIX|fNHS2$noEr4!D3=2&ua-+ zn{P_|PbcGWlEQG0pMGR~Q&l*)#D0>~$?PEC{awC(iltymb;%^^(hY2ozv_rqa62oi z9Lr)ySq?0?%BIpwhn1H6TeF2Si^72R~SeC}aGVvE*DOPuGt28)xG5)ajz85Kj7TAE*Bf|BZtEAMW09jws$BiOSbk%o)=w4E)UOjHbj-q7mAnkp z=Hu4miZ^6AaPZ`x6dL6hWoGR4Hl9DGmhK!tsr56`R9BLh94?39IEPOthp1Z1EdtLK zE1ruT>;_v-Jg`POpdD50mrAk3RqRMACcmrL&n++g8Y>1?v4Fe`G^=7G5n61ay3C@S ztXA*j5npQMmV$TUVkwy1@4p-3>o2i?Dr(JG6S9JGHUo`&+WV&xwfd`eX}@2zxunLXGBKs4a^8g+vSG|2)@l3H)wi!}m^Ch-qYuwY}<(6347LXQT?2wQOi4f5< z84}BP^$pgQ5!XA0_gi9k<8@Oyqk;Ps02Yz|$tM_6??UgW84F{8v*Gh<@@c$_YDu@O zXiPPgh!f|QXjc+3vfo9F2K}ZGAk3>%A7+d+9q>wm8z0q1tUv}24j_hx%%>B^4fdd_ zFVwB@Wl)?k&Puei@f^*HCm9iK+WZWnwlvsk+N^IBVGj+NRN)|HWqKOT_g|yF>}IY5 z1hBShkJF(FnEFVJ?ka+9@SPUO;BFWu&x8MWd44p`bE2K6KvVi@=XuEgF3*p}d9H5f zDbSRDT%Oc92e(CXxKmGAm42fJxm`Wqw;8rg&pSVjHDrl-ogyD6t9|K*+}@|_n;0Py zYYeUA#VXA6?#3NHPGuB=@6xzUBb%sTg1m0H2Nl<^b@S7+?-KSZpQ^7Hf!utvO5T);9SVbYGhw z85y{*%yfCP7udW2yM-p@#*m~AWHD{|K{Rr)p_*Luot+D9qrNV^;N|dlM|OD4|Du0t z9Q+O6XdIN&oz?k}^<}U5TOh6f=Evm0yMfw#{08JCb4%tnN)k=dq;&oze{6N7)}ZLr zz+gExl|gttO|e!>Kl-Tv#qb6o?mGGZ;0LUa1N_bb^l^aS3s7qPfzO&BQV6jv@Kh?@ z`lAAy`h|0wifViLt{ktaM6NLH@bf~lOL_yI6?5W5fgBPojIEDwa(M=atE^wEtddoX zw@;!P&dFuR)l&5nXtk_z%MDM4Poe8VUA9KK{kwH$&5>vhIzuzjG5a3EGakFtcufOz z#u96p4nMTS4mPKkzEQlwxDatcOI*+y5Z;bOx(`8$;7&wz?0y^W#;1UK%|8)4xCf_X zYsTL4c`f-3_BQT@f3!=HZYhq(ah8t~t+pqJqhEm|TPoTC)TuAfg~Gdmbn&`odRz9x z8aHl)Te#h@7u`EpBeCH1FX(4Ea~SdTP)zCS*P^SjLzB6@q0*P`;KI2{=9b#eyodT- z0X~Zhi@UvWvvRdZ`ntlm;_k^U9^VCnklzvtI!rOnd6e+FE~>jPRgBbIMP7{P2Y$^= zxbM>Co8KmNHp)Z?EbM)+WUdBC2S*U*vUF+etO6J3mEKD4j+6$cNNF(RYH~Ec?@qn* zZd>NrICeXAyOO&3=|Rr;AKjNb+AEJn?`JI5DjiN5NVg%S2$JFT7}t{An@F2W&laMxsSWx^rH{%i zALz0MMg^jF?$gi#z9aGg>*E3q;96x)5=TA* zho*$h)P}d0Jy?j=$)+18u3&MQSI;W59p*Am#&!_RU!}S~Nn@FtW$$b{Hh9l(^WNh} zi?i7Ik9p4lmPC!89jQCO(#U*r*3PrF?x7Q-PmL$<=8fkc$JalE-i4FQ#Bs-j{z|8l z?NC9+)KkqB=4DsJ#_(m}dA0iXCf1Ue4+eGw?1FX=P&0KcuT z$m!0I-0~z5nCmEZ^tHeNGCFC8|{2 z!Fr{Ml05RHg#?#d^xz78GJzPId7X}#DZ_Tz(8gz;b0S~;d(v#14~i`ML8T~qIimSZ z5zSG~Z+=;B{SZerbk%%v0tS}~%TGQj5*9Be#ktbVNgo|m_zYL!mnf@3Nh=uFh#F49 zlC0;So&^YD@>p5qumGQL(h{%%l#2 z*&LEphnZR$lO^=!+3yA;#<4cu>aR%JK3|&ZTAuPbEa7Pk+&~_NXCU21E#ogy&VgyKw zCoDu=4z^?Y?3hn*vEutjlnck_f}5DJoVj7Wf5hl7>0}d18$Xb2ONrI@l+^Ub=dL+| z4?qdAP6y`b=mNk+IPJ>U+9t3wu@F$LSMDmW3U8)JFQ}`Xr-@W~yJvCEDvy$>_{ORs zYXkC_{5q@Z70=q>#(ekwB+3%j4&unE>v&Q&sKJ#r&qwHWxU`V9*DP&Ls;}De@7C~nfV#Rv&#DUHcHJ0UK z5@}W71y>5S)n(^M#&Bs&KuuU_*3!m1CZbg4koNsgBM0t)dm$GdIlbzIOZD9)b}aK6 z8&uQ3ppX)V*73X8OzH^cVz1X&YtjM(%=ua3 z0%nV*&0T$6#q!FVnc8aFZ0}f3?8W(iw@P15x9#?FjlsA*x9+{7erj8)H14G;vSRlg zFw0-$ITXX?#2&*^weYQGrrt~!F|@hcVA*y`*H&P8^ya=oXVN~t^Xvk&De8*o%U#qJ zUyB&%?&~g=*WJw3Z(*)=nQl<*u8F<|qT0@VTwTE!j?CcI7V*^K>TdQWHwPb41I;aj zX?;{k_9Bl=l-lBJk^p1s%ngcx)YA2-5xx7M@%l)C_&4zrvrN3>Q3-7m@s`K`Rb@BfnI30o~fsl-r%l+S)GX2BMN1LW?$8 zDj{g5{?0{*;3`#w^wI~-&F7fy=2M!L&o#=2llaBpI?GYx#aZNgt@?{YEYxXx7}$4( zItr9FZ~!6D`emXWl9nY=69iTvcK&GxE=G6dyzmlYR*UUCqKUz5Y_4tNpz#>}ylm?W zMJC9Yx3Ka?f5G55>6b81Vt%7fn-&LI-1Szc=6WueXC z0Sv@rJ0mH?9mcW-x6Ru?vqedGt{O%3 zdVu`q&})!vZX_ld7Y#klNh8`B`?&I4?HgJi#1tJ%Q1ofJ;>2w7ZA9X6erN{yN^BB4 zOea;I79N@fh_a`xaHAt(jAPvYHj{(ve;HeIUZ;78Ngvl~wu^n>k9B2@4K_2m zC~odfHh!*yIajA_pfehJsa+zzW*%A8vxPQwGWMy(k8A0H!k_8UQ^^F@!0wLGCLW~G z`toSbl2KcS-QP0EiXC+?_pBgiw$;t z?IB{Gl*%n}=3{6>-}vf{##eV(*`YpqF?~1Qe8R#aPuofT;MWVz*dg_g_Mh45^ysjM($qtV!=*SEwe`{txHP77~^ z4#jP0ab4v0bQ2(kYck#O+KoRuNAi8@`exPjdsf%-ICGC%L1R(MR*v1#J?R0P1nwPA z0(nm3ZV4@*0nd%JAfrYTl5YwYRkv3XmMn|m>LLd;L}@&woBZeHKojCDd_ zMZP@cjHW}`mo{kH z*H^ga%>7SCr7VG@d6`GgU-l_?^h;-XpF>}Ki})x)x3{miSgzenwl>L)=e`U378-b= zfxEKPRRn|pEteZ_(PH9rv@`uh4e_vZW4{rUb(e^>Ax@bBu+_80nd z{oUr%>%Eif`?7tx$>;Xv`?{PQIamaA&Naly9>7JTRG+hUY2dNpKDUf_zHX9oa10vM zUQ!z9dHga(PXo-75oV5pcT;dJL(tZ9WMXI@xNzVE9%%?q#NS8h=Yj9m*AH3y`}+I( zAnO2R?OOz3QQxAzodEov19-(sUk{`<9o0s@`sb9bPQyF7aE6N2)PJ3RwKO63xWN`` zjpf@fY&%0M`YuA^a?WtYq`b7$_+EN)g>OvjwBEy+gr~>P1h=rRFIvon=?NuRn4S!h zDMl71ll1xvqcn`dNF6r8PoJ&Hj&n{}>jt+QIbQOHu69GKUQ#Hfw`7C&sr(X; zGn@YAB-5K7&q9Ew<9huFCiUs@8`1{Mr5$hs>VRUPO*kn-6G{MWnz7_?s@`=>$NtPl zTQOWqe-K}2oIjQC4b-W#_vbbLMl9_G|CMjF7c8ec6Ln9t7yNf1E&U+o|0(xBocrH$ z|I4|bkb9fl!s27vFV>#hJ5l%?Ccdx|5@)5(1eps6JOP+U=sWmdpgYwic7;JU* zf=J^dWYsFj*>t}uu%+60P2pstNsWvZcUW%AepEY`N7A)iH7wXHPB?oK z-AX!SIIVdRBp{tY&ZI=z<=d%2N`R*ORUp~`P54P9mhI6$wR#mC;mVue-xVS0QXv=lE1xBsY3BjYv%a9qDWW*f>rE z%^Og^;VJmXcxd6t6Ip{TiO}DAR*d^{DziMu7caiu@&a0UQBF;v9lF2S;N& zjQu)^6hNVTLpHF9 zQm5sxwfbu|(^6M;>n+bNlHV-+qb>PZR_sS!_sAxTiP_p7UP4RCzCn2`wipra&HQ6* z&@0zs)w)46uhRV>otG?pE^E!k;lX4?j}$~CU5m=1AEep<&H%7YE$Vqsc}FSMRM!ywwX@eGct@1te=lny)hJuSZqovUfT&opaw`T!`SmF1lCUO&h+JHq^iN zM(B4*t&O|y@lDtI_3Y1=D7tYzOYm?LKbhKYdaUOG0dGZihPUw}$o+!cF31*s$Rk*% z!(NY)k!`VfO*zN9y~e}DG&rd~uT*)4=imTFcRQ=iYb&XpPED~hlv+^t0{UjQek1is zH}4?h`ZrF)+`*SgCW{dkc!vevslbombb(a#K}9-i>Jf^q_1nkdqhbjyJ@uA+IGpcW z;h7@cRVXg+VFT*RRMmO8xdSl3iePo?P@#T5C1k^^pk*+v9~2_=5i?Pm5B`%>5+7zS zneLPt*ex}rdU(v@_u0>#1ySD_X5MfUWd_G!@u|injU`D``amypZWZtD>(qZwfsMCO zIXceURYz>)otJC817}bDGpEPy-uihjh}{DSdDSHRDij!4SRB}C%_u^$Z(-j~EL!s6 zJ4qY9iy!B#|Mi6nSj03RCrRTjg}s}f6;a?$FS5X`^9DZ61^#f}z)2VQqj>|L=>mT| zJMcXetwm?-j|no@whxaaaANL=QQ4QW*2LE!lchSBDbL=?IZcR6m06pq#Ey z#ppEA3R#T&2JB%MnEG~NO|%p1!iB7fzVq)Vp3oBP!W@cCCvgY5>X!@q=)LGR;}?l` z3|G~`cVJOKxqkYX8M^ItJ;<%c z4%E?m{^elZ0^dHqjHId0@n|N_)EIx~;kY>p$7}y~;rG?R-of9_xLyBCr5?gBdChxs zsrbGWPSeG0!SMiphvL^i!F%}IhND1Vm0SPf*}H5=9AFUQHhY-QI8pQosN^+!@i$v^ z;qXr!%CZ9}{-)LNs`*V>P=An^PEu_zuWxNXFZ3!4!Y3G_o@!n@!0Y+j%j-3fczql^ zd@eah=+}SQ#{B!+iSfryiXT9LtKLUirwZ-J-E;~qR_bPC;9&P)&mg9V(}M$<#=T6y z)cw;f5s|xoEfKdb+o5T|lB5v6UwoWf^BLNJXU{)?uaGqo*LHT_9H$dG)qWrO+4zF= zJe-8tO`@G5>6>?vJ{L#AZh~H@%We`;6iHv5b0nwx<47osTqKdCwqMpr)0bvfeOvY` z^e8J%>ZFht`p8Ss`Z5;$kb-&74r9%9zoT$~{0BjP-CjCFxUfIBt=NTS9M|jGbDX_X z4|h8o##*nvg*x8?-Rk}s3(gz16H%T5Qp6{bVES!A#$&s84qO|-Z`Jc znX|8h3hMsv17NzY50?b_Ee}qNxh~1s2?4e)E7T_`sbnQ#ug#5qTk^qm^bLkSj_hi% zX%Bu2ma1bMpW5ln)H2uiYN?a1a9!w7&xAsFH&_MxXm?%fUf*m$+)ACI;13h**H-va zP%g>kHzQCaOR^@hvf)PvHZ@}o9r=$m-YO5xM{gsK#y6=Nx4JpEQD|wHU<+46TRz>= zAePUxG+gDGp?s+&$()~2RR4nTqoUtVx#dlTLMeSJbJ1a`-}o3&Tf#G1 z;u~IRlN0Fg`|2T7?AT_r;TBZ`mr+Qfg`8~h57${_zB9Wb`j;3L>c=w%*!p7 zXHZ;ZI*~TYjFzIiUzX`7Orj?5&m{vxm z>7Vhtb+7LF9kfVp)?}{n82MNVE8Hm75?P8aS<1js-%PQh+v}v%UgC4@nKvAcj0t}t zh2LcHmUcQlY3-VS1!(H{v7+BxV7G7$^aF}4P7HB&D1!c35e>T968>dwLIYV8DF#vU ziEejN{vFWGSi}oH1)(-Q0B$^F`cLW_ei}fwzSoO!en!sl9)8P<>qiUnSwTh@?Vd`7 z_gdh6{GR`Lk|R8y!StL?l|^PX_Qc(r3&;74K17L=8ASJ1o^%?9;*xy$mUW(L%GY2Q zt$`ow%qV2ToxK(>^@7ystK7WU!!+8SSI6$7QqQ{Hx$7)t0}dHgWp|RN=b~LDJ1VVC zp?!$<7i^>(ypQjl&>_~5OJ83eznSad(veU726EcvrpF>Sas)XtdY)PKdPx3*IYWbjUE$*ze!iqzF84E=2WO>7QDo?QM-*gx?5(!n`&Y>fpq zAA-1To@>q|T5znkc9eH!;GjyS(9Bi^9K%qVH5!@~)CQ4jT2Vh{TR$fn;= z{@5no?K+IWuG-ozJ@8VfO}KBpA-2~X8`CzWmPfj*WmvMzFh21w!X6ikqm?5xzlwKS zg8x*eBRGDAV@0(ua&e}@g{^p8;w#3mD|{B2zeIQr&jV@EfQpD33~=~k*1^HIyUv20~f3TSCbug@qIh( z;s;-VInbB{71}eTK^P`3>&bu`@0BxUWubhr{ODtArpwHk`ig<0*IxS;_L1>TfKxm)I6E__R zPaA8Fb0S~;i`rVWcPCd4i`sg{?lr&^Z9O6VYJCe za%EaseVDW7?3-!j?VD|N@pX4FbVlVCCX%yxaP1pF)@!1TEQE|bg>V5iPM|V6xjI4@ zJ~T9UiO^;OZmBv$4-EPz+FBfI)##nvjqMCjP=2#xbG9`2OEUI}2>7Nd;7Yfy(qY|; zcYx#gc$X`2+2r$Q7o*39s8($s_ce3M^+hdO#YVRH^~nip&Fv!zU~ZA|8!>zqxXm9W zo4yID-f8_x!xeWCIBIlAEU%5*6Y||nY|Cw_uCoxKig5`dzI6iKYpNZ?0!D8eU+&@D ziyu7Brw0o$k^Fb@xE;vrT-oqz1on0{kL7S=SMxag-JpY#x``w8W;-`dvPQmc@(!Pd zU7+AV>mY# z&Jl|&j#!2R+cs5s1hTcGZ+z0|-%Un8_(`L`-=f#aj7GG}*NSR4qkf z-m5f7q5*v}tv-E(muvnpw$7R65 zYOZ9Qf-C5-@RrC@{`ch0_20)puelJIJJ-!tW}#3$GK%&u zqE%lKrJWlMiL2a-D@W>QZ#NblUj5;CaCx`-!wlLCR??s(>iFpmrH$8>3*+hR5GPiy z#+KFsE!_HYOv)`ne#3P)*}^Qn`ZwA1_`)3f$K~Fea@amC7jDWKt=t*wg64F=6STFi z2M9%sk$XW78ark&*y3?c*BO)ewX|Q7aN#6Kn;R#z&JtnD+h`|&{nAD|7RUo8+a_~S zsN|VweIE6DYUP&yJsvm1zsM#+p->%lrEnZqvSl@LOockHv;UC5ZuK|408NeNtLfC9 zl>MIBw2jh-zhskfu~4ym~Krq+J3qRPTy;w%bSDX#Cq- z97wPEI|b(Z($|$wJm6P2OPs?S<;YiNL)XfF;5e>x>H9L*tyqE0wGCQY=O%v8m+9K) zqb{)`l}8VdxOWk_3SC`XF7#!O=SbOg8_KITqJEB&cCB0_V0qQ*ynWYBJc4cm19!!V zvp5Ji=@$obPKfknS093wI%+B!YS?_`e}xQoh3w+Vb>)8*GJVt5WG%>`e90zK#k+{KyE96AEKLQ~}Zxs~a~J=MiHCeo#zY7b%{ zAE)q|LV3*3qhPQyYu$Nn{6+cYD?YsZ4)D`I4l~ngSZssQz2Fsc`$4}vrPealzd5Sk zpbt>}d3#2)=kRmPwY}!kIzhU{ZWHS$XqR@{@F8k3w#dac4`(^_c%;i?xkXfT7cplS zJ2`?7UMggYhJ~z0&c;*Y7c$-5XETR%K%gmY&%9sVXFI@Zttoc9$XeA^&vc!&W%b)* zIbGk1%nCFn6w8Z(EBUUdaG!w(UU~3HRZstTARA^bF1kj2`Ru-l3<861jx7^#nNJk-jdmC0S zpUK1xo{Hj+5|k?UHQuXeY^X)xV)*{HyA z5*@+n@9v;uaW>3EN3fv?9l2xbSlZ8a&~af79l1eg@ho)IqUAz(vr$lN%RD+=k}ocy7sg5N0v*;#uIEfLeJu#v4r@p!Q?N64kfWryKH$zwVa(D$nqukt?T2t4bhBFeg!50mWFY(Jo>`0%HP-q{8Jc80o+vM0rS47)VYVA&en!oy~ zGid80kVVmY^*BZgTkqA5@tTTNJ7TsrfCW2dKDBz6O3ArQ?QCcMY6G#d&=&Jf!Oe)E zyhdSD#*#I82-Ej zT&TowA!q{<`3R>N-dZ0GRKQiw7_QpK@r85@Zzb{<_A&g{HoX4zw)0$X%F_OkW@1=# z50cBnIxY^oL`@in$-_kI5pSwpr?C|YgvW-xsdlZDs!bA?s$DasYF9_8+I5&+)a7oN{tO56c$^Z4f=$K?kBBXa}Jf(KY=j)nDWTSGFu2uI8}5bufITb*dMv zpjx$c?wdd>{02oLRMwEzfwN)VW}R$?rrmuoH>)@T>C~=`Q7oEhOb}5M4Si=!G>o@% zse^KkxxK~+9j~QmUgHKiSDVu&6nk`>D%fkhRS`sNukk^u-cp^s#-H@Qp|AiMWz@I~ zTw4x#}HW-s?dGfsKp7FA0-**YA4$cUuS;gMt$ILPpD z10%*UM+;W>&uK3yNIQQ0J=l_qx}m~GpHTDI&%L+;PI(r>o;H%MxZbvZ zR5y3Z$0X~hT;iFq35oEV$ayEg%e@iJUBwg}S4{4~@LTPuBk*y8?-e{UT<(vk{#lf% zF3V9it}h8SdO3eF{C3-2U)*UChst-_Va4!~g!{V*_oHq1=rO9@j0v~P#w`lvhPn1= zGuKZHD;pBRYc-O2O)=w>PrjqJF9r)m*+?FIR{S?hAkCPKi->OGJRIDw$gZV>Q^n)O z;0pp3gVW@zKOIWAIrNg?L1S#CE`~OVwy`MGOgb9BUf^;_%&^f=yozw!t^6O&4p6JR z3lon-+9!W%Z*sI9i06qSzbDqTKn4%?)3G1+=BurBz?gh${(TTER$z|cHwCd*Ik`-o`H16?(syv3|h3+ z{AAn()DOkT)KE7&3J!6U#+=2?_2Y#4Dz%<%)}seHg}Ulr9J}_s*foTGhdJrS_K1Ur zSM5GGSSlZtI<&cd=8U3@u0@qY8@F!?89qE)yUs{&ah61JhRld0XJeu`C2wXtjh)JC zc%FDeR(LYL+n@LlZE8oeIL#zV*ok~>tn39ra+W4?Hrjz$@*c8Fyy(ZVZX)p)x$qnu0q+FryRv>8Gv|_3Sh-_wNW8cNQz7QK z=1dMPwZS8s(NgDq{u&id`8NK>c3Y+0eK7hO=N5MxNr5q}xhT)l=E`6v@<=E0@Mb3- zl987v@@xD}x1#05Hk*Ad7nfJC3{gUVr1EAb?lf&6s*vK;KKz;(T~GZQ-)A(M7RcZM zhZ=ZjrGBo=H(C7PJILzFcyJh3SjZV*gNSRoO$~Vrink0aYb-hLWelG2Abv?s9Q-trehXxTk^D7BRZ!sI;oLbq|?!z@J&p6 zbg5($hh-N?Eyg+EHv>Cge%-io$6{z?ohD_|&JJ9${U$Y9{T&eADcuH%K|S3e7tEl+ z{&sSPToy^b{w;Oth6PL^#9Qgqv-p~Rp+lvJU?NNK6DRGQLh4liZ}PEN;SVkK`FBx6WSwtsmUiO#FMVq9CTGWkV@Br5@9^32 zwo~q=rx@>bPch!xo?<+`eEn4Da{p7zugdWBRPy_u?c|p>TZkXk{Gks{Ei^brjYY%o z8+08EV{)Dl{}TFK_y-`Px6#PuDYKEIjd7k(Vr0x)?8ZepGL>a(JNyZ0bUCn}99LBL z#wtwEfGOxE>Dq2CO>ts`x1*Gr4evAflt;(AvavyGjKsLa`H%;03hS<-SmkoQa$%qT zspgW8P!{pvi`@HTX2$a6TkV{jRmKZz;ZY zNOc#+ZL<0wVqcB>ZQR=*9ksE=1Ub!psj1#F`h&-3c(;ay< zPL+Ei&q4C^Mjq9!yfE^3d*j*3Jlh7QRkNsqeK{<5E}}+jIpBrapl2dOQ_wxdZfol4 zjB)FuKStx!7x>$ondq^JzY}p^&);q&-=9AWU!~T(nIEs71p_Cle?qgeyj(H^(Cr%2 zmQe9)Xx;U`bGh1W2hE(ApA}psIA_5&Huco^1>n{DXn{^qUj6PF{=Bnl`TrB6<93Wu zI2)tOpE^eM+vkn@FZiQVo8S)!flB=&^F(#;(Rxz{Xa>MrS9b5GHlU#$PhC7`?5@WK zGL{2(ARS$+8QaI7O**4$lx_X78F+9KTH~%;^49A2&4Z6u|JsZsU5@bEspibMQ8oX^ zvb|sir#O79^h*8j^Ok$fj09f&mKpvCjh({<=Pl*J4)YD!Bb#0KEqz@jul~syDS-`n z^#^9dhNkl;7T~Ce%f(N(|?KVnU+ZEOqby| zFSQ!#6tqSU&qt#1I)i=dkBd;7fY^CigOyK-pJZ{`L-cl`>>WGHm%)WhVr=c0Nu5ca zpMZy5UbfDklPjzBS-DPX1#hq+PLf9Ny_moK=u0lPp#HOcbP76`PdAtY z`bj!{XstV)cPi6k@}M|x>YqX|JA-fOdb`*(c1tWyL+~t3DR>Z+?5fp3zIp)$4^IWI zWuYUYGbk?_+NHYE>5zf z8|zA!j?tmatxw}v=1T5V7ASRs)*ic*jbezHDd2=kATP4S`~of&rb~j}=!7L9u zGXb)INhk?jLXl2F6$At<56mQ>46`gYI#|$Gqo4-GPO~ehV8;ex7bAAX*Mj}E;Q#wO z_j#UqW|IK#|MPkGlgxAPx$WF@&+X@&>)4gLAlK_^pLSX4%%so7ald|>h<21RfOfiy z3*m~10Zrs;3&ye>7&o6u@!F@yo!3e0?N5K!CAz*dF41K>qUW zp&!_B9%Rl#u%6LA#GH1WerU(}td8?AIa|syyggTz&grk!7-nHZ;Vrqvdkf&MoA4OA zox5`jqhZKMIhTjR`|1Q-I98&2>;zm0$M@R_xUi4!$rEr@r4rqr3m)Cl$=!V)E=c3o z8XMmk*Ks(!{~=U#Il^WA(o(H zO{zXRnyk0Li$YO3;S*iV%RRP?=)=kTMnRJ@hVqZjkogmAVIs#yLdH;GRkWZ$RNw*}DES_vnG$f~pE1UWo8Q;_h3pM(M(so#h{!6#Xwt(%)tM7n6sTo4a6l zjVcc~UMUVWZmu{_ZQx!l8}ezLV3sL*{UFJPnE!At(p)!i5J2Adrs zVhQ$Ff-9_Fs;kFR0`f!{$UQt-NMayRT$l|ep)`gC z9N1l&U?3nI5)C0}<7FKj!z#qZ{{i2;s&jcQ0+(vi^?7Z+Bf?HqlS5Atckz z1%myB_7~Ps=}4aL<*-z!BG6Jr(}7N*TusxhduL%L^KeBsRu4|F9w30vTXflA1x8Lh z|7!A(@SF1W(WDyGeYe!h8WpmQv(VqCD@?K$oI`u$r63!94C-Llr}9MOlmZi`X}oMF$yr>4A? zdVg3UEB+L4V7=-D>2$`t3;1%^4ZcSZwa8NoX}`ciX(KmM3wW?fPz=#&pg*Odz|wj|=OP4rGVie+P7$I}4c&p%dnN<;;Qvm^wBp=(vrkrfqJ#0t?;)1fQTP`Q(vi~-6Oa`!Uc@+V{wRE-K>Lz3i zuEPc2-A;j($ragL>n>av(LMKR&rC$2w)NGMA&3YQ!VD{(g6)nQg5zSBM))pfraD}8SXjp!E zvrum*n9bcJ+~k82VgBo_MD0JaDQ@$_J0x*goqJ-|!Ey%wF`eDC$DPL7Hji3N;=t&(e7F^8rr->mjAq zkwwM^*Vy46?5A6c9qT_kr0cP%B~51^L;Ks;{NLd^6ya(u><|u)q|b)vKKc~shJ0{r z>KPYD_-5?Q+8y@?D=BM*?6?D*G_wQj)ZyY}2S{XA-6`VukxpFW_(Y_L#bt!+saQO$ z+v?QWxBTDp_Un58)>Lls*5N9`wTjdz+jd>X6A6^0QnZ` zdP;-mrHid2=s1C0xJ8jxK2FUsD!4Z9VjND4idm?)^W**=PKSfr8Bgl-VBQ&-gaxid zurrlN&;4E}GpVt1QKz>zWDm5ya}?OYr9a08Jw!UpvU(a15%0RXKkKaJ59oM&|@tZaK=#=0{$rNi-jA~{I$Ts(tR zv8O9$7V8JoG{{6c+kC&iEJU=9sFmF}%=AA++H3=p0@5Wm6%At}TVqn4_PWo;&(7>j z;hMu(`o*wp8ek^Rl5++-PHG+J6ttv1*zi zJyIA#Z5nr0v@%Ar?*1sJy2V75od;wU(0>Nx6Z zYlwHyOPW0JU7Qxk;65@Y)!J-c;jsSX_%J*~TfISMm%7f;WVsU4{;b(%9h)gsCQChs zXu;<+P>(I>Tq%4{k!mh`}mcY?%!wKFLiLAV|t;d)z)t3U=f zTsd?!ay8$lmh{~EFOxc(^6s}ba&wzI6id#>85=$3dYM{Z#>xtY86a$;o|nQDlZFs% z-1$(hzA#rC?y0A^Io^q4{ko#5G zV-z+mkipx}Qxu0-PkVzrnf59Aq}wO!gPG3t_RX|U;yYVA^7lvi1kZv}vwLbgAzZjO zt9S%7v4fhe%EsK*!noreUyf1 zs$94ZdyLVi{Tv6jswV=Qk4tp>iR?Y9GEWQ?%S{Y$X4|JedGvdu=oJ_JG(|7_p8)Kt z;1KXyt~|@FB@_@wo}hAGOGK|NbKmaBmRB;eDDhmPOERu42YYRmB>348T#f|%oCq#Q z1lRgHlNx8t)t}cAS~XS+`pSf5w$Z$ZTP-WBa})JyV3I{+K<-4m!y>BC>kj88WSj7Z zEnJnX&+%G9qLblu|K!xcWvIFe1Ea=aUQ7O`g-Ivk_A%*%CoqYx$u~zBqkCE@gRp zDb+4L_7 zD3x9Yh_i5Gy4%y=WM={DvWc?*Dyp*pK{*RxINbIuU}icy3)oS*2f|TcUN{Q;86@ee z8WF;dk{oV0q_l^>MRw@v@Z@-cGmG=P@m$Fq2%dt1C(=FJ;yE*&;kl!9S;TOsE+97> zNWZA=oo5P}7Rcaj6%~reMk<`oH_#;-^!*>G>zh>yb<2%}*dS*PhP4*~h*db{>8Nlj zmso{U9vZHZj4n?{h0}s~AIJ1GT@cUI*w|@7kqV~^ic~l)=;s!E#4BopMJyotAzF7bbC7*M-TGK;1QpY8C5r zT5Jbb6=R*w1YGrvuU8UqRX*0~Ou$8n_|8l4=nhNn?mH|&x)jR2zA!gifdYk@BOlMR2E4=)1`~Eirq1 zfg(@TqH1Y3@Wj~Ydt+v#*VbOede zkvr;XayuCwr_(9_44qB`CDo|~h;%wFeL|;G{wLAtwCE;t?{qpX`nEcq0!KQX8YJR- zIae8hqRPlULwD0a9o@}WFrm7+!s%{m+H(GK@F63Y5+rpuF2qM-pzH_KMRl z(4CDTost1NldrWp z>5^-$ZPK0V`J2^@{x7wr@R}ED3%QBh-TwA@;Ilz%K40sV+V1Wf9I2(QEuk<0Mr-S2 zA(-aSfY(8@!4=AoGjd)?M32^@If<>^2c0i`#O<4GO&2W3a=eG|^-sy4eX9QuIx;3M zQAzth0XD8hk`PJ<4eeT4zsVO|B+mosU>z(o+Bb>LrRr82;t=dn<05&zsXq8Tm@Q^c z`#%PboeqDk@PqGuO!hW-`NntQjb@~KWozC^>TfzImylbmgOYBbgL3_*R`Sqf%1fwR=)AP!Y{}_t@L$$( zw&k>QkN%9;o=qkhy-JheX*4}J!+U^wcHsby=


fu5B=g6^Eb9YqKOg0kXGR=bR~ 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%0A>mPO#{N8I!nSWHSL-)%)KyX4l#ku4@1%*H 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

b8{11WIB}@M10!# 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 C4Uet> diff --git a/DistFiles/Utilities.dll b/DistFiles/Utilities.dll deleted file mode 100644 index 27c4ef21dee6ce8c81a22a0e66e307a953446bf5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 442880 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

Xe{Ay0Z8wgQRHOlL7K_3auG_Wb+F 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

7r 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%0A?-J3cP14 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


ZI{B3w=AYt*1<`+@<%=)Pm*)& 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 diff --git a/Src/Common/Controls/FwControls/FwControls.csproj b/Src/Common/Controls/FwControls/FwControls.csproj index 48cb1eed64..4df5638cd6 100644 --- a/Src/Common/Controls/FwControls/FwControls.csproj +++ b/Src/Common/Controls/FwControls/FwControls.csproj @@ -104,6 +104,10 @@ ..\..\..\..\Output\Debug\ManagedLgIcuCollator.dll + + False + ..\..\..\..\Output\Debug\ParatextShared.dll + False ..\..\..\..\Output\Debug\ScriptureUtils.dll @@ -141,9 +145,6 @@ ..\..\..\..\Downloads\Palaso.dll - - ..\..\..\..\DistFiles\ParatextShared.dll - ..\..\..\..\Output\Debug\ScrUtilsInterfaces.dll diff --git a/Src/Common/FieldWorks/FieldWorks.csproj b/Src/Common/FieldWorks/FieldWorks.csproj index 24112d71f7..5f66aade27 100644 --- a/Src/Common/FieldWorks/FieldWorks.csproj +++ b/Src/Common/FieldWorks/FieldWorks.csproj @@ -129,7 +129,7 @@ False - ..\..\..\DistFiles\ParatextShared.dll + ..\..\..\Output\Debug\ParatextShared.dll False diff --git a/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj b/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj index 69d0ee5f24..49e47412ef 100644 --- a/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj +++ b/Src/Common/FwUtils/FwUtilsTests/FwUtilsTests.csproj @@ -130,10 +130,6 @@ nunit.framework ..\..\..\..\Bin\NUnit\bin\nunit.framework.dll - - False - ..\..\..\..\DistFiles\ParatextShared.dll - False ..\..\..\..\Output\Debug\SilUtils.dll diff --git a/Src/Common/ScriptureUtils/ScriptureUtils.csproj b/Src/Common/ScriptureUtils/ScriptureUtils.csproj index e08dbfcf77..b8911d61fe 100644 --- a/Src/Common/ScriptureUtils/ScriptureUtils.csproj +++ b/Src/Common/ScriptureUtils/ScriptureUtils.csproj @@ -120,12 +120,9 @@ False ..\..\..\Output\Debug\FwUtils.dll - - ..\..\..\DistFiles\NetLoc.dll - False - ..\..\..\DistFiles\ParatextShared.dll + ..\..\..\Output\Debug\ParatextShared.dll False @@ -151,7 +148,7 @@ False - ..\..\..\DistFiles\Utilities.dll + ..\..\..\Output\Debug\Utilities.dll diff --git a/Src/Common/ScriptureUtils/ScriptureUtilsTests/ScriptureUtilsTests.csproj b/Src/Common/ScriptureUtils/ScriptureUtilsTests/ScriptureUtilsTests.csproj index 0bf0023c13..3c40488b41 100644 --- a/Src/Common/ScriptureUtils/ScriptureUtilsTests/ScriptureUtilsTests.csproj +++ b/Src/Common/ScriptureUtils/ScriptureUtilsTests/ScriptureUtilsTests.csproj @@ -144,7 +144,7 @@ False - ..\..\..\..\DistFiles\ParatextShared.dll + ..\..\..\..\Output\Debug\ParatextShared.dll False @@ -173,7 +173,7 @@ False - ..\..\..\..\DistFiles\Utilities.dll + ..\..\..\..\Output\Debug\Utilities.dll diff --git a/Src/FDO/FDOTests/FDOTests.csproj b/Src/FDO/FDOTests/FDOTests.csproj index 2c9a8e226a..a53cd74595 100644 --- a/Src/FDO/FDOTests/FDOTests.csproj +++ b/Src/FDO/FDOTests/FDOTests.csproj @@ -169,10 +169,6 @@ False ..\..\..\Downloads\Palaso.dll - - False - ..\..\..\DistFiles\ParatextShared.dll - False ..\..\..\Output\Debug\PhonEnvValidator.dll diff --git a/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj b/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj index 993131f863..92829da4ef 100644 --- a/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj +++ b/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj @@ -52,8 +52,9 @@ ..\..\DistFiles\Microsoft.Practices.ServiceLocation.dll - - ..\..\DistFiles\Paratext.LexicalContracts.dll + + False + ..\..\Output\Debug\Paratext.LexicalContracts.dll ..\..\Output\Debug\ParserCore.dll diff --git a/Src/LexText/Interlinear/ITextDll.csproj b/Src/LexText/Interlinear/ITextDll.csproj index 5564f2bd7a..69b6b64558 100644 --- a/Src/LexText/Interlinear/ITextDll.csproj +++ b/Src/LexText/Interlinear/ITextDll.csproj @@ -136,9 +136,9 @@ False /home/eberhard/repogit/Calgary/WW/Output_x86_64/Debug/Microsoft.Practices.ServiceLocation.dll - + False - ..\..\..\DistFiles\ParatextShared.dll + ..\..\..\Output\Debug\ParatextShared.dll ..\..\..\Output\Debug\RootSite.dll diff --git a/Src/TE/TeImportExport/TeImportExportTests/TeImportExportTests.csproj b/Src/TE/TeImportExport/TeImportExportTests/TeImportExportTests.csproj index 26ab2abd30..5bc9592e63 100644 --- a/Src/TE/TeImportExport/TeImportExportTests/TeImportExportTests.csproj +++ b/Src/TE/TeImportExport/TeImportExportTests/TeImportExportTests.csproj @@ -138,9 +138,9 @@ False ..\..\..\..\Output\Debug\OxesIO.dll - + False - ..\..\..\..\DistFiles\ParatextShared.dll + ..\..\..\..\Output\Debug\ParatextShared.dll False diff --git a/Src/TeDll/TeDll.csproj b/Src/TeDll/TeDll.csproj index 4e59ca1e91..49cee632bd 100644 --- a/Src/TeDll/TeDll.csproj +++ b/Src/TeDll/TeDll.csproj @@ -174,9 +174,9 @@ False ..\..\Downloads\Palaso.dll - + False - ..\..\DistFiles\ParatextShared.dll + ..\..\Output\Debug\ParatextShared.dll False From a7bb1fa03a894657c1d19c174e77ee8ccf353afd Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 20 Jun 2014 10:54:50 +0700 Subject: [PATCH 137/143] fixed build problems on Linux Change-Id: If5ff319777ddb2c9ddf9d14e8eb63bcf111189f0 --- Build/mkall.targets | 7 ++++--- .../LexTextControlsTests/LiftExportTests.cs | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Build/mkall.targets b/Build/mkall.targets index 02988b736f..a06c25dc66 100644 --- a/Build/mkall.targets +++ b/Build/mkall.targets @@ -103,7 +103,8 @@ Configuration="$(config-capital)" Target="$(make-target)" BuildRoot="$(fwrt)" WorkingDirectory="$(fwrt)/Src/Graphite/GrEngine"/> - +

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

@@ -119,7 +120,7 @@ Configuration="$(config-capital)" Target="$(make-target)" BuildRoot="$(fwrt)" WorkingDirectory="$(fwrt)/Src/Kernel"/> - + @@ -174,7 +175,7 @@ Configuration="$(config-capital)" Target="$(make-target)" BuildRoot="$(fwrt)" WorkingDirectory="$(fwrt)/Src/views"/> - + diff --git a/Src/LexText/LexTextControls/LexTextControlsTests/LiftExportTests.cs b/Src/LexText/LexTextControls/LexTextControlsTests/LiftExportTests.cs index e5eeafce52..1726c10e3f 100644 --- a/Src/LexText/LexTextControls/LexTextControlsTests/LiftExportTests.cs +++ b/Src/LexText/LexTextControls/LexTextControlsTests/LiftExportTests.cs @@ -1092,7 +1092,7 @@ public void LiftExport_MultipleReferencesToSameMediaFileCausesNoDuplication() pronunciation.MediaFilesOS.Add(media); m_cache.LangProject.PicturesOC.First().FilesOC.Add(pronunFile); // maybe not quite appropriate, but has to be owned somewhere. media.MediaFileRA = pronunFile; - var internalPath = Path.Combine(DirectoryFinder.ksMediaDir, kpronunciationFileName); + var internalPath = Path.Combine(FdoFileHelper.ksMediaDir, kpronunciationFileName); pronunFile.InternalPath = internalPath; var exporter = new LiftExporter(m_cache); var xdoc = new XmlDocument(); From 3b2a463bc6218ed4e2390cf00ca21917fcbcfcc2 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Fri, 20 Jun 2014 14:58:07 +0700 Subject: [PATCH 138/143] added LexiconUnavailableException to PT lexicon plugin Change-Id: I128200cce3116f1934a44fb494e699773b435018 --- .../FwParatextLexiconPlugin.csproj | 1 + .../LexiconUnavailableException.cs | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 Src/FwParatextLexiconPlugin/LexiconUnavailableException.cs diff --git a/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj b/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj index 92829da4ef..7babfa55d7 100644 --- a/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj +++ b/Src/FwParatextLexiconPlugin/FwParatextLexiconPlugin.csproj @@ -100,6 +100,7 @@ + diff --git a/Src/FwParatextLexiconPlugin/LexiconUnavailableException.cs b/Src/FwParatextLexiconPlugin/LexiconUnavailableException.cs new file mode 100644 index 0000000000..10833248b9 --- /dev/null +++ b/Src/FwParatextLexiconPlugin/LexiconUnavailableException.cs @@ -0,0 +1,21 @@ +using System; +using Paratext.LexicalContracts; + +namespace SIL.FieldWorks.ParatextLexiconPlugin +{ + /// + /// Lexicon unavailable exception + /// + public class LexiconUnavailableException : Exception + { + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + public LexiconUnavailableException(string message) + : base(message) + { + this.SetLexiconUnavailableException(); + } + } +} From e4151dd145705916c0645bbaf378420c8050166d Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Mon, 23 Jun 2014 13:21:27 +0700 Subject: [PATCH 139/143] fixed bug backing up a shared XML backend project Change-Id: Iaf9d78458472676574d9798bed34147a8518b9bd --- Src/FDO/DomainServices/BackupRestore/BackupProjectSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Src/FDO/DomainServices/BackupRestore/BackupProjectSettings.cs b/Src/FDO/DomainServices/BackupRestore/BackupProjectSettings.cs index 04365329d1..4eb79e4532 100644 --- a/Src/FDO/DomainServices/BackupRestore/BackupProjectSettings.cs +++ b/Src/FDO/DomainServices/BackupRestore/BackupProjectSettings.cs @@ -69,7 +69,7 @@ protected BackupProjectSettings(string projectsRootFolder, string projectName, // For DB4o projects, we need to convert them over to XML. We can't put the // converted project in the same directory so we convert them to a temporary // directory (see FWR-2813). - DatabaseFolder = (originalProjType == FDOBackendProviderType.kXML) ? ProjectPath : Path.GetTempPath(); + DatabaseFolder = (originalProjType == FDOBackendProviderType.kXML || originalProjType == FDOBackendProviderType.kSharedXML) ? ProjectPath : Path.GetTempPath(); DestinationFolder = destFolder; BackupTime = DateTime.Now; } From 2f3d771d8e4637ac08da9015ae94754d738b17ca Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Mon, 23 Jun 2014 13:23:04 +0700 Subject: [PATCH 140/143] clean up project restore in Paratext lexicon plugin Change-Id: Ifaaa5034d8dcb5cf56b0c14b30dac8b9623e15f2 --- .../ChooseFdoProjectForm.Designer.cs | 7 ----- .../ChooseFdoProjectForm.cs | 26 +++++++++++-------- .../ChooseFdoProjectForm.resx | 12 --------- 3 files changed, 15 insertions(+), 30 deletions(-) diff --git a/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.Designer.cs b/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.Designer.cs index f53809e855..cc879601b3 100644 --- a/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.Designer.cs +++ b/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.Designer.cs @@ -26,7 +26,6 @@ private void InitializeComponent() this.TableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); this.btnOk = new System.Windows.Forms.Button(); this.btnCancel = new System.Windows.Forms.Button(); - this.openFileDialog = new System.Windows.Forms.OpenFileDialog(); this.groupBoxRestore = new System.Windows.Forms.GroupBox(); this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); this.btnBrowse = new System.Windows.Forms.Button(); @@ -68,11 +67,6 @@ private void InitializeComponent() this.btnCancel.Name = "btnCancel"; this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); // - // openFileDialog - // - this.openFileDialog.FileName = "openFileDialog1"; - resources.ApplyResources(this.openFileDialog, "openFileDialog"); - // // groupBoxRestore // this.groupBoxRestore.Controls.Add(this.tableLayoutPanel3); @@ -191,7 +185,6 @@ private void InitializeComponent() internal System.Windows.Forms.TableLayoutPanel TableLayoutPanel1; internal System.Windows.Forms.Button btnOk; internal System.Windows.Forms.Button btnCancel; - private System.Windows.Forms.OpenFileDialog openFileDialog; private System.Windows.Forms.GroupBox groupBoxRestore; private System.Windows.Forms.Button btnBrowse; private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; diff --git a/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.cs b/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.cs index de2267e6d7..20921dd155 100644 --- a/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.cs +++ b/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.cs @@ -60,15 +60,16 @@ private void ListBox_SelectedIndexChanged(object sender, EventArgs e) private void btnBrowse_Click(object sender, EventArgs e) { - using (openFileDialog) + using (var openDialog = new OpenFileDialog()) { - DialogResult result = openFileDialog.ShowDialog(); - if (result == DialogResult.OK) + openDialog.Filter = "Backup files|*.fwbackup|All files|*.*"; + openDialog.InitialDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "My FieldWorks", "Backups"); + if (openDialog.ShowDialog() == DialogResult.OK) { - m_restoreFileFullPath = openFileDialog.FileName; + m_restoreFileFullPath = openDialog.FileName; if (SetupRestore()) { - labelSelectedBackupFile.Text = openFileDialog.SafeFileName; + labelSelectedBackupFile.Text = openDialog.SafeFileName; textBoxProjectName.Text = m_restoreSettings.Backup.ProjectName; textBoxProjectName.Enabled = true; } @@ -156,10 +157,12 @@ private void HandleProjectFindingExceptions(Exception e) } else if (e is DirectoryNotFoundException) { - MessageBox.Show(ActiveForm, e.Message, Strings.ksWarningCaption, MessageBoxButtons.OK, MessageBoxIcon.Warning); + // this indicates that the project directory does not exist, just ignore } else + { throw e; + } } /// ------------------------------------------------------------------------------------ @@ -196,13 +199,14 @@ private bool SetupRestore() { try { + var backupSettings = new BackupFileSettings(m_restoreFileFullPath); m_restoreSettings = new RestoreProjectSettings(ParatextLexiconPluginDirectoryFinder.ProjectsDirectory) { - Backup = new BackupFileSettings(m_restoreFileFullPath), - IncludeConfigurationSettings = true, - IncludeLinkedFiles = true, - IncludeSupportingFiles = true, - IncludeSpellCheckAdditions = true, + Backup = backupSettings, + IncludeConfigurationSettings = backupSettings.IncludeConfigurationSettings, + IncludeLinkedFiles = backupSettings.IncludeLinkedFiles, + IncludeSupportingFiles = backupSettings.IncludeSupportingFiles, + IncludeSpellCheckAdditions = backupSettings.IncludeSpellCheckAdditions, BackupOfExistingProjectRequested = false }; } diff --git a/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.resx b/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.resx index 48e3e3c430..dc6e40a56b 100644 --- a/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.resx +++ b/Src/FwParatextLexiconPlugin/ChooseFdoProjectForm.resx @@ -210,12 +210,6 @@ <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="btnOk" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="btnCancel" Row="0" RowSpan="1" Column="1" ColumnSpan="1" /></Controls><Columns Styles="Percent,50,Percent,50" /><Rows Styles="Percent,50" /></TableLayoutSettings> - - 17, 17 - - - Backup files|*.fwbackup|All files|*.* - Top, Bottom, Left, Right @@ -594,12 +588,6 @@ Select Lexical Project - - openFileDialog - - - System.Windows.Forms.OpenFileDialog, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - ChooseFdoProjectForm From 9e8e8ba9c05ed0505dabf1bc50e440b767478d9c Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Mon, 23 Jun 2014 13:24:17 +0700 Subject: [PATCH 141/143] get code dir in PT lexicon plugin from current plugin location Change-Id: Ibea465e614e05387d02d387c9ae8f7e96c15e6d7 --- .../ParatextLexiconPluginDirectoryFinder.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Src/FwParatextLexiconPlugin/ParatextLexiconPluginDirectoryFinder.cs b/Src/FwParatextLexiconPlugin/ParatextLexiconPluginDirectoryFinder.cs index 40b56b0728..a12778e2c7 100644 --- a/Src/FwParatextLexiconPlugin/ParatextLexiconPluginDirectoryFinder.cs +++ b/Src/FwParatextLexiconPlugin/ParatextLexiconPluginDirectoryFinder.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics.CodeAnalysis; using System.IO; +using System.Reflection; using Microsoft.Win32; using SIL.CoreImpl; using SIL.FieldWorks.FDO; @@ -69,12 +70,7 @@ public static string DataDirectoryLocalMachine public static string CodeDirectory { - get - { - string defaultDir = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), DirectoryFinder.CompanyName), - string.Format("FieldWorks {0}", FdoVersion)); - return GetDirectory(RootCodeDir, defaultDir); - } + get { return GetDirectory(RootCodeDir, Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)); } } [SuppressMessage("Gendarme.Rules.Correctness", "EnsureLocalDisposalRule", From 1c70a4d4e301e2a36516da4bfce4f191c1c1ecf3 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Mon, 23 Jun 2014 14:53:59 +0700 Subject: [PATCH 142/143] fixed ParatextHelperTests compile error caused by new PT DLLs Change-Id: I0fad0b60ae4449afd3f61da1453be84391c41e69 --- .../ScriptureUtils/ScriptureUtilsTests/ParatextHelperTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Src/Common/ScriptureUtils/ScriptureUtilsTests/ParatextHelperTests.cs b/Src/Common/ScriptureUtils/ScriptureUtilsTests/ParatextHelperTests.cs index 0aa09b1730..380fc5deb2 100644 --- a/Src/Common/ScriptureUtils/ScriptureUtilsTests/ParatextHelperTests.cs +++ b/Src/Common/ScriptureUtils/ScriptureUtilsTests/ParatextHelperTests.cs @@ -205,7 +205,7 @@ public void AddProject(string shortName, string associatedProject, string basePr scrText.Name = shortName; if (!string.IsNullOrEmpty(associatedProject)) - scrText.AssociatedLexicalProject = new AssociatedLexicalProject(LexiconType.FieldWorks, associatedProject); + scrText.AssociatedLexicalProject = new AssociatedLexicalProject("FieldWorks", associatedProject); // Don't know how to implement a test involving baseProject now that BaseTranslation is gone from the PT API. // However all clients I can find so far pass null. if (!string.IsNullOrEmpty(baseProject)) From ecb169b8b5f690274412b585de60d778d68b6e66 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Tue, 24 Jun 2014 13:32:50 +0700 Subject: [PATCH 143/143] fixed shared XML backend unit test on Linux Change-Id: I149d562b4282f3c02a606d208351412d78e14db9 --- Src/FDO/Infrastructure/Impl/SharedXMLBackendProvider.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Src/FDO/Infrastructure/Impl/SharedXMLBackendProvider.cs b/Src/FDO/Infrastructure/Impl/SharedXMLBackendProvider.cs index 0bc87a3fac..492ab15cc6 100644 --- a/Src/FDO/Infrastructure/Impl/SharedXMLBackendProvider.cs +++ b/Src/FDO/Infrastructure/Impl/SharedXMLBackendProvider.cs @@ -197,7 +197,15 @@ protected override void CreateInternal() bool createdNew; m_commitLogMutex = new Mutex(true, MutexName, out createdNew); if (!createdNew) + { + // Mono does not close the named mutex handle until the process exits, this can cause problems + // for some unit tests, so we disable the following check for Mono +#if !__MonoCS__ throw new InvalidOperationException("Cannot create shared XML backend."); +#else + m_commitLogMutex.WaitOne(); +#endif + } try { CreateSharedMemory(true);