/// <summary> /// This method will create a new Text document from the given BIRD format Interlineartext. /// </summary> /// <param name="newText">The text to populate, could be set to null.</param> /// <param name="textParams"></param> private static bool PopulateTextFromBIRDDoc(ref FDO.IText newText, TextCreationParams textParams) { s_importOptions = textParams.ImportOptions; Interlineartext interlinText = textParams.InterlinText; FdoCache cache = textParams.Cache; IThreadedProgress progress = textParams.Progress; if (s_importOptions.CheckAndAddLanguages == null) { s_importOptions.CheckAndAddLanguages = CheckAndAddLanguagesInternal; } ILgWritingSystemFactory wsFactory = cache.WritingSystemFactory; char space = ' '; //handle the languages(writing systems) section alerting the user if new writing systems are encountered if (!s_importOptions.CheckAndAddLanguages(cache, interlinText, wsFactory, progress)) { return(false); } //handle the header(info or meta) information SetTextMetaAndMedia(cache, interlinText, wsFactory, newText); //create all the paragraphs foreach (var paragraph in interlinText.paragraphs) { if (newText.ContentsOA == null) { newText.ContentsOA = cache.ServiceLocator.GetInstance <IStTextFactory>().Create(); } IStTxtPara newTextPara = newText.ContentsOA.AddNewTextPara(""); int offset = 0; if (paragraph.phrases == null) { continue; } foreach (var phrase in paragraph.phrases) { ICmObject oldSegment = null; //Try and locate a segment with this Guid. if (!String.IsNullOrEmpty(phrase.guid)) { if (cache.ServiceLocator.ObjectRepository.TryGetObject(new Guid(phrase.guid), out oldSegment)) { //We aren't merging, but we have this guid in our system, ignore the file Guid oldSegment = cache.ServiceLocator.GetInstance <ISegmentFactory>().Create(newTextPara, offset); } else { //The segment is identified by a Guid, but apparently we don't have it in our current document, so make one with the guid oldSegment = cache.ServiceLocator.GetInstance <ISegmentFactory>().Create(newTextPara, offset, cache, new Guid(phrase.guid)); } } //set newSegment to the old, or create a brand new one. ISegment newSegment = oldSegment as ISegment ?? cache.ServiceLocator.GetInstance <ISegmentFactory>().Create(newTextPara, offset); var tsStrFactory = cache.ServiceLocator.GetInstance <ITsStrFactory>(); //Fill in the ELAN time information if it is present. AddELANInfoToSegment(cache, phrase, newSegment); ITsString phraseText = null; bool textInFile = false; //Add all of the data from <item> elements into the segment. AddSegmentItemData(cache, wsFactory, phrase, newSegment, tsStrFactory, ref textInFile, ref phraseText); bool lastWasWord = false; if (phrase.WordsContent != null && phrase.WordsContent.Words != null) { if (textParams.Version == 0 && PhraseHasExactlyOneTxtItemNotAKnownWordform(newSegment.Cache, phrase)) { // It might be a SayMore text that makes the whole segment a single txt item. // We want to add the text anyway (unless a higher level did so), but we will skip making // a wordform. Eventual parsing of the text will do so. if (!textInFile) { UpdatePhraseTextForWordItems(wsFactory, tsStrFactory, ref phraseText, phrase.WordsContent.Words[0], ref lastWasWord, space); } } else { foreach (var word in phrase.WordsContent.Words) { //If the text of the phrase was not given in the document build it from the words. if (!textInFile) { UpdatePhraseTextForWordItems(wsFactory, tsStrFactory, ref phraseText, word, ref lastWasWord, space); } AddWordToSegment(newSegment, word, tsStrFactory); } } } UpdateParagraphTextForPhrase(newTextPara, ref offset, phraseText); } } return(true); }
/// <summary> /// Attempt to populate a new FieldWorks text with a BIRD format interlinear text. If this fails /// for some reason then the new text is deleted and also return false to tell the calling method to abort the import. /// </summary> /// <param name="options"></param> /// <param name="newText"></param> /// <param name="interlineartext"></param> /// <param name="progress"></param> /// <param name="version"></param> /// <returns>true if operation completed, false if the import operation should be aborted</returns> private bool PopulateTextIfPossible(ImportInterlinearOptions options, ref FDO.IText newText, Interlineartext interlineartext, IThreadedProgress progress, int version) { if (!PopulateTextFromBIRDDoc(ref newText, new TextCreationParams { Cache = m_cache, InterlinText = interlineartext, Progress = progress, ImportOptions = options, Version = version })) //if the user aborted this text { newText.Delete(); //remove it from the list return false; } return true; }
private static bool MergeTextWithBIRDDoc(ref FDO.IText newText, TextCreationParams textParams) { s_importOptions = textParams.ImportOptions; Interlineartext interlinText = textParams.InterlinText; FdoCache cache = textParams.Cache; IThreadedProgress progress = textParams.Progress; if (s_importOptions.CheckAndAddLanguages == null) { s_importOptions.CheckAndAddLanguages = CheckAndAddLanguagesInternal; } ILgWritingSystemFactory wsFactory = cache.WritingSystemFactory; char space = ' '; //handle the languages(writing systems) section alerting the user if new writing systems are encountered if (!s_importOptions.CheckAndAddLanguages(cache, interlinText, wsFactory, progress)) { return(false); } //handle the header(info or meta) information as well as any media-files sections SetTextMetaAndMedia(cache, interlinText, wsFactory, newText); IStText oldContents = newText.ContentsOA; IStText newContents = null; //create all the paragraphs NOTE: Currently the paragraph guids are being ignored, this might be wrong. foreach (var paragraph in interlinText.paragraphs) { if (newContents == null) { newContents = cache.ServiceLocator.GetInstance <IStTextFactory>().Create(); newText.ContentsOA = newContents; } IStTxtPara newTextPara = newContents.AddNewTextPara(""); int offset = 0; if (paragraph.phrases == null) { continue; } foreach (var phrase in paragraph.phrases) { ICmObject oldSegment = null; //Try and locate a segment with this Guid. if (!String.IsNullOrEmpty(phrase.guid)) { if (cache.ServiceLocator.ObjectRepository.TryGetObject(new Guid(phrase.guid), out oldSegment)) { if (oldSegment as ISegment != null) //The segment matches, add it into our paragraph. { newTextPara.SegmentsOS.Add(oldSegment as ISegment); } else if (oldSegment == null) //The segment is identified by a Guid, but apparently we don't have it in our current document, so make one { oldSegment = cache.ServiceLocator.GetInstance <ISegmentFactory>().Create(newTextPara, offset, cache, new Guid(phrase.guid)); } else //The Guid is in use, but not by a segment. This is bad. { return(false); } } } //set newSegment to the old, or create a brand new one. ISegment newSegment = oldSegment as ISegment ?? cache.ServiceLocator.GetInstance <ISegmentFactory>().Create(newTextPara, offset); var tsStrFactory = cache.ServiceLocator.GetInstance <ITsStrFactory>(); //Fill in the ELAN time information if it is present. AddELANInfoToSegment(cache, phrase, newSegment); ITsString phraseText = null; bool textInFile = false; //Add all of the data from <item> elements into the segment. AddSegmentItemData(cache, wsFactory, phrase, newSegment, tsStrFactory, ref textInFile, ref phraseText); bool lastWasWord = false; if (phrase.WordsContent != null && phrase.WordsContent.Words != null) { foreach (var word in phrase.WordsContent.Words) { //If the text of the phrase was not found in a "txt" item for this segment then build it from the words. if (!textInFile) { UpdatePhraseTextForWordItems(wsFactory, tsStrFactory, ref phraseText, word, ref lastWasWord, space); } MergeWordToSegment(newSegment, word, tsStrFactory); } } UpdateParagraphTextForPhrase(newTextPara, ref offset, phraseText); } } return(true); }
/// <summary> /// Import a file which looks like a FieldWorks interlinear XML export. This file can contain many interlinear texts. /// If a text was previously imported then attempt to merge it. If a text has not been imported before then a new text /// is created and it is poplulated with the input if possible. /// </summary> /// <param name="options"></param> /// <param name="firstNewText"></param> /// <returns>return false to abort merge</returns> public bool ImportInterlinear(ImportInterlinearOptions options, ref FDO.IText firstNewText) { IThreadedProgress progress = options.Progress; Stream birdData = options.BirdData; int allottedProgress = options.AllottedProgress; bool mergeSucceeded = false; bool continueMerge = false; firstNewText = null; BIRDDocument doc; int initialProgress = progress.Position; try { m_cache.DomainDataByFlid.BeginNonUndoableTask(); progress.Message = ITextStrings.ksInterlinImportPhase1of2; var serializer = new XmlSerializer(typeof(BIRDDocument)); doc = (BIRDDocument)serializer.Deserialize(birdData); Normalize(doc); int version = 0; if (!string.IsNullOrEmpty(doc.version)) int.TryParse(doc.version, out version); progress.Position = initialProgress + allottedProgress / 2; progress.Message = ITextStrings.ksInterlinImportPhase2of2; if (doc.interlineartext != null) { int step = 0; foreach (var interlineartext in doc.interlineartext) { step++; ILangProject langProject = m_cache.LangProject; FDO.IText newText = null; if (!String.IsNullOrEmpty(interlineartext.guid)) { ICmObject repoObj; m_cache.ServiceLocator.ObjectRepository.TryGetObject(new Guid(interlineartext.guid), out repoObj); newText = repoObj as FDO.IText; if (newText != null && ShowPossibleMergeDialog(progress) == DialogResult.Yes) { continueMerge = MergeTextWithBIRDDoc(ref newText, new TextCreationParams { Cache = m_cache, InterlinText = interlineartext, Progress = progress, ImportOptions = options, Version = version }); } else if (newText == null) { newText = m_cache.ServiceLocator.GetInstance<ITextFactory>().Create(m_cache, new Guid(interlineartext.guid)); continueMerge = PopulateTextIfPossible(options, ref newText, interlineartext, progress, version); } else //user said do not merge. { //ignore the Guid; we shouldn't create another text with the same guid newText = m_cache.ServiceLocator.GetInstance<ITextFactory>().Create(); continueMerge = PopulateTextIfPossible(options, ref newText, interlineartext, progress, version); } } else { newText = m_cache.ServiceLocator.GetInstance<ITextFactory>().Create(); continueMerge = PopulateTextIfPossible(options, ref newText, interlineartext, progress, version); } if (!continueMerge) break; progress.Position = initialProgress + allottedProgress/2 + allottedProgress*step/2/doc.interlineartext.Length; if (firstNewText == null) firstNewText = newText; } mergeSucceeded = continueMerge; } } catch (Exception e) { Debug.Print(e.Message); Debug.Print(e.StackTrace); } finally { m_cache.DomainDataByFlid.EndNonUndoableTask(); } return mergeSucceeded; }
internal void ImportWordsFrag(Word[] words, ImportAnalysesLevel analysesLevel) { s_importOptions = new ImportInterlinearOptions {AnalysesLevel = analysesLevel}; var tsStrFactory = m_cache.ServiceLocator.GetInstance<ITsStrFactory>(); NonUndoableUnitOfWorkHelper.Do(m_cache.ActionHandlerAccessor, () => { foreach (var word in words) { CreateWordAnalysisStack(m_cache, word, tsStrFactory); } }); }
/// <summary> /// This method will create a new Text document from the given BIRD format Interlineartext. If this fails /// for some reason then return false to tell the calling method to abort the import. /// </summary> /// <param name="newText">The text to populate, could be set to null.</param> /// <param name="textParams">This contains the interlinear text.</param> /// <returns>The imported text may be in a writing system that is not part of this project. Return false if the user /// rejects the text which tells the caller of this method to abort the import.</returns> private static bool PopulateTextFromBIRDDoc(ref FDO.IText newText, TextCreationParams textParams) { s_importOptions = textParams.ImportOptions; Interlineartext interlinText = textParams.InterlinText; FdoCache cache = textParams.Cache; IThreadedProgress progress = textParams.Progress; if (s_importOptions.CheckAndAddLanguages == null) s_importOptions.CheckAndAddLanguages = CheckAndAddLanguagesInternal; ILgWritingSystemFactory wsFactory = cache.WritingSystemFactory; const char space = ' '; //handle the languages(writing systems) section alerting the user if new writing systems are encountered if (!s_importOptions.CheckAndAddLanguages(cache, interlinText, wsFactory, progress)) return false; //handle the header(info or meta) information SetTextMetaAndMergeMedia(cache, interlinText, wsFactory, newText, false); //create all the paragraphs foreach (var paragraph in interlinText.paragraphs) { if (newText.ContentsOA == null) { newText.ContentsOA = cache.ServiceLocator.GetInstance<IStTextFactory>().Create(); } IStTxtPara newTextPara = newText.ContentsOA.AddNewTextPara(""); int offset = 0; if (paragraph.phrases == null) { continue; } foreach (var phrase in paragraph.phrases) { ICmObject oldSegment = null; //Try and locate a segment with this Guid. if (!String.IsNullOrEmpty(phrase.guid)) { if (cache.ServiceLocator.ObjectRepository.TryGetObject(new Guid(phrase.guid), out oldSegment)) { //We aren't merging, but we have this guid in our system; ignore the file Guid oldSegment = cache.ServiceLocator.GetInstance<ISegmentFactory>().Create(newTextPara, offset); } else { //The segment is identified by a Guid, but apparently we don't have it in our current document, so make one with the guid oldSegment = cache.ServiceLocator.GetInstance<ISegmentFactory>().Create(newTextPara, offset, cache, new Guid(phrase.guid)); } } //set newSegment to the old, or create a brand new one. ISegment newSegment = oldSegment as ISegment ?? cache.ServiceLocator.GetInstance<ISegmentFactory>().Create(newTextPara, offset); var tsStrFactory = cache.ServiceLocator.GetInstance<ITsStrFactory>(); //Fill in the ELAN time information if it is present. AddELANInfoToSegment(cache, phrase, newSegment); ITsString phraseText = null; bool textInFile = false; //Add all of the data from <item> elements into the segment. AddSegmentItemData(cache, wsFactory, phrase, newSegment, tsStrFactory, ref textInFile, ref phraseText); bool lastWasWord = false; if (phrase.WordsContent != null && phrase.WordsContent.Words != null) { if (textParams.Version == 0 && PhraseHasExactlyOneTxtItemNotAKnownWordform(newSegment.Cache, phrase)) { // It might be a SayMore text that makes the whole segment a single txt item. // We want to add the text anyway (unless a higher level did so), but we will skip making // a wordform. Eventual parsing of the text will do so. if (!textInFile) { UpdatePhraseTextForWordItems(wsFactory, tsStrFactory, ref phraseText, phrase.WordsContent.Words[0], ref lastWasWord, space); } } else { foreach (var word in phrase.WordsContent.Words) { //If the text of the phrase was not given in the document build it from the words. if (!textInFile) { UpdatePhraseTextForWordItems(wsFactory, tsStrFactory, ref phraseText, word, ref lastWasWord, space); } AddWordToSegment(newSegment, word, tsStrFactory); } } } UpdateParagraphTextForPhrase(newTextPara, ref offset, phraseText); } } return true; }
/// <summary> /// Merge the contents of the given Text into the exising one. If this fails /// for some reason then return false to tell the calling method to abort the import. /// </summary> /// <param name="newText"></param> /// <param name="textParams"></param> /// <returns>The imported text may be in a writing system that is not part of this project. Return false if the user /// rejects the text which tells the caller of this method to abort the import.</returns> private static bool MergeTextWithBIRDDoc(ref FDO.IText newText, TextCreationParams textParams) { s_importOptions = textParams.ImportOptions; Interlineartext interlinText = textParams.InterlinText; FdoCache cache = textParams.Cache; IThreadedProgress progress = textParams.Progress; if (s_importOptions.CheckAndAddLanguages == null) s_importOptions.CheckAndAddLanguages = CheckAndAddLanguagesInternal; ILgWritingSystemFactory wsFactory = cache.WritingSystemFactory; char space = ' '; //handle the languages(writing systems) section alerting the user if new writing systems are encountered if (!s_importOptions.CheckAndAddLanguages(cache, interlinText, wsFactory, progress)) return false; //handle the header(info or meta) information as well as any media-files sections SetTextMetaAndMergeMedia(cache, interlinText, wsFactory, newText, true); IStText newContents = null; //create all the paragraphs NOTE: Currently the paragraph guids are being ignored, this might be wrong. foreach (var paragraph in interlinText.paragraphs) { if (newContents == null) { newContents = cache.ServiceLocator.GetInstance<IStTextFactory>().Create(); newText.ContentsOA = newContents; } IStTxtPara newTextPara = newContents.AddNewTextPara(""); int offset = 0; if (paragraph.phrases == null) { continue; } foreach (var phrase in paragraph.phrases) { ICmObject oldSegment = null; //Try and locate a segment with this Guid. if(!String.IsNullOrEmpty(phrase.guid)) { if (cache.ServiceLocator.ObjectRepository.TryGetObject(new Guid(phrase.guid), out oldSegment)) { if (oldSegment as ISegment != null) //The segment matches, add it into our paragraph. newTextPara.SegmentsOS.Add(oldSegment as ISegment); else if(oldSegment == null) //The segment is identified by a Guid, but apparently we don't have it in our current document, so make one oldSegment = cache.ServiceLocator.GetInstance<ISegmentFactory>().Create(newTextPara, offset, cache, new Guid(phrase.guid)); else //The Guid is in use, but not by a segment. This is bad. { return false; } } } //set newSegment to the old, or create a brand new one. ISegment newSegment = oldSegment as ISegment ?? cache.ServiceLocator.GetInstance<ISegmentFactory>().Create(newTextPara, offset); var tsStrFactory = cache.ServiceLocator.GetInstance<ITsStrFactory>(); //Fill in the ELAN time information if it is present. AddELANInfoToSegment(cache, phrase, newSegment); ITsString phraseText = null; bool textInFile = false; //Add all of the data from <item> elements into the segment. AddSegmentItemData(cache, wsFactory, phrase, newSegment, tsStrFactory, ref textInFile, ref phraseText); bool lastWasWord = false; if (phrase.WordsContent != null && phrase.WordsContent.Words != null) { foreach (var word in phrase.WordsContent.Words) { //If the text of the phrase was not found in a "txt" item for this segment then build it from the words. if (!textInFile) { UpdatePhraseTextForWordItems(wsFactory, tsStrFactory, ref phraseText, word, ref lastWasWord, space); } MergeWordToSegment(newSegment, word, tsStrFactory); } } UpdateParagraphTextForPhrase(newTextPara, ref offset, phraseText); } } return true; }
/// <summary> /// Merge the contents of the given Text into the exising one. If this fails /// for some reason then return false to tell the calling method to abort the import. /// </summary> /// <param name="newText"></param> /// <param name="textParams"></param> /// <returns>The imported text may be in a writing system that is not part of this project. Return false if the user /// rejects the text which tells the caller of this method to abort the import.</returns> private static bool MergeTextWithBIRDDoc(ref LCModel.IText newText, TextCreationParams textParams) { s_importOptions = textParams.ImportOptions; Interlineartext interlinText = textParams.InterlinText; LcmCache cache = textParams.Cache; IThreadedProgress progress = textParams.Progress; if (s_importOptions.CheckAndAddLanguages == null) { s_importOptions.CheckAndAddLanguages = CheckAndAddLanguagesInternal; } ILgWritingSystemFactory wsFactory = cache.WritingSystemFactory; char space = ' '; //handle the languages(writing systems) section alerting the user if new writing systems are encountered if (!s_importOptions.CheckAndAddLanguages(cache, interlinText, wsFactory, progress)) { return(false); } //handle the header(info or meta) information as well as any media-files sections SetTextMetaAndMergeMedia(cache, interlinText, wsFactory, newText, true); IStText newContents = newText.ContentsOA; //create or reuse the paragraphs available. NOTE: Currently the paragraph guids are being ignored, this might be wrong. foreach (var paragraph in interlinText.paragraphs) { IStTxtPara newTextPara = null; if (newContents == null) { newContents = cache.ServiceLocator.GetInstance <IStTextFactory>().Create(); newText.ContentsOA = newContents; newTextPara = newContents.AddNewTextPara(""); } int offset = 0; if (paragraph.phrases == null) { continue; } foreach (var phrase in paragraph.phrases) { ICmObject oldSegment = null; //Try and locate a segment with this Guid. Assign newTextPara to the paragraph we're working on if we haven't already if (!String.IsNullOrEmpty(phrase.guid)) { if (cache.ServiceLocator.ObjectRepository.TryGetObject(new Guid(phrase.guid), out oldSegment)) { if (oldSegment as ISegment != null) //The segment matches, add it into our paragraph. { IStTxtPara segmentOwner = newContents.ParagraphsOS.FirstOrDefault(para => para.Guid.Equals((oldSegment as ISegment).Owner.Guid)) as IStTxtPara; if (segmentOwner != null && newTextPara == null) //We found the StTxtPara that correspond to this paragraph { newTextPara = segmentOwner; } } else if (oldSegment == null) //The segment is identified by a Guid, but apparently we don't have it in our current document, so make one { if (newTextPara == null) { newTextPara = newContents.AddNewTextPara(""); } oldSegment = cache.ServiceLocator.GetInstance <ISegmentFactory>().Create(newTextPara, offset, cache, new Guid(phrase.guid)); } else //The Guid is in use, but not by a segment. This is bad. { return(false); } } } //If newTextPara is null, try to use a paragraph that a sibling phrase belongs to. //Note: newTextPara is only assigned once, and won't be reassigned until we iterate through a new paragraph. if (newTextPara == null) { var phraseGuids = paragraph.phrases.Select(p => p.guid); foreach (IStTxtPara para in newContents.ParagraphsOS) { if (para.SegmentsOS.Any(seg => phraseGuids.Contains(seg.Guid.ToString()))) { newTextPara = para; break; } } } //Can't find any paragraph for our phrase, create a brand new paragraph if (newTextPara == null) { newTextPara = newContents.AddNewTextPara(""); } //set newSegment to the old, or create a brand new one. ISegment newSegment = oldSegment as ISegment; if (newSegment == null) { if (!string.IsNullOrEmpty(phrase.guid)) { //The segment is identified by a Guid, but apparently we don't have it in our current document, so make one with the guid newSegment = cache.ServiceLocator.GetInstance <ISegmentFactory>().Create(newTextPara, offset, cache, new Guid(phrase.guid)); } else { newSegment = cache.ServiceLocator.GetInstance <ISegmentFactory>().Create(newTextPara, offset); } } //Fill in the ELAN time information if it is present. AddELANInfoToSegment(cache, phrase, newSegment); ITsString phraseText = null; bool textInFile = false; //Add all of the data from <item> elements into the segment. AddSegmentItemData(cache, wsFactory, phrase, newSegment, ref textInFile, ref phraseText); bool lastWasWord = false; if (phrase.WordsContent != null && phrase.WordsContent.Words != null) { //Rewrite our analyses newSegment.AnalysesRS.Clear(); foreach (var word in phrase.WordsContent.Words) { //If the text of the phrase was not found in a "txt" item for this segment then build it from the words. if (!textInFile) { UpdatePhraseTextForWordItems(wsFactory, ref phraseText, word, ref lastWasWord, space); } MergeWordToSegment(newSegment, word); } } UpdateParagraphTextForPhrase(newTextPara, ref offset, phraseText); } } return(true); }