<commit_before>﻿// Copyright (c) 2015 SIL International
// This software is licensed under the MIT license (http://opensource.org/licenses/MIT)
using System;
using System.Collections.Generic;
using System.Linq;
using LfMerge.DataConverters;
using LfMerge.FieldWorks;
using LfMerge.Logging;
using LfMerge.LanguageForge.Config;
using LfMerge.LanguageForge.Model;
using LfMerge.MongoConnector;
using LfMerge.Settings;
using MongoDB.Driver;
using SIL.CoreImpl;
using SIL.FieldWorks.Common.COMInterfaces;
using SIL.FieldWorks.FDO.DomainServices;
using SIL.FieldWorks.FDO;
using SIL.FieldWorks.FDO.Infrastructure;

namespace LfMerge.Actions
{
	public class UpdateFdoFromMongoDbAction: Action
	{
		private FdoCache _cache;
		private IFdoServiceLocator _servLoc;
		private IMongoConnection _connection;
		private MongoProjectRecordFactory _projectRecordFactory;
		private ILfProject _lfProject;
		private MongoProjectRecord _projectRecord;

		private ILfProjectConfig _lfProjectConfig;
		private LfOptionList _lfGrammar;
		private Dictionary<string, LfOptionListItem> _lfGrammarByKey;

		private ILexEntryRepository _entryRepo;
		private ILexExampleSentenceRepository _exampleRepo;
		private ICmPictureRepository _pictureRepo;
		private ILexPronunciationRepository _pronunciationRepo;
		private ILexSenseRepository _senseRepo;
		private IPartOfSpeechRepository _posRepo;
		private ICmTranslationRepository _translationRepo;
		private ILexEntryFactory _entryFactory;
		private ILexExampleSentenceFactory _exampleFactory;
		private ICmPictureFactory _pictureFactory;
		private ILexPronunciationFactory _pronunciationFactory;
		private ILexSenseFactory _senseFactory;
		private ICmTranslationFactory _translationFactory;

		private ICmPossibility _freeTranslationType; // Used in LfExampleToFdoExample(), but cached here

		private CustomFieldConverter _customFieldConverter;

		public UpdateFdoFromMongoDbAction(LfMergeSettingsIni settings, ILogger logger, IMongoConnection conn, MongoProjectRecordFactory factory) : base(settings, logger)
		{
			_connection = conn;
			_projectRecordFactory = factory;
		}

		protected override ProcessingState.SendReceiveStates StateForCurrentAction
		{
			get { return ProcessingState.SendReceiveStates.QUEUED; }
		}

		protected override void DoRun(ILfProject project)
		{
			_lfProject = project;
			_projectRecord = _projectRecordFactory.Create(_lfProject);
			if (_projectRecord == null)
			{
				Logger.Warning("No project named {0}", _lfProject.LfProjectCode);
				Logger.Warning("If we are unit testing, this may not be an error");
				return;
			}
			_lfProjectConfig = _projectRecord.Config;
			if (_lfProjectConfig == null)
				return;

			if (project.FieldWorksProject == null)
			{
				Logger.Error("Failed to find the corresponding FieldWorks project!");
				return;
			}
			if (project.FieldWorksProject.IsDisposed)
				Logger.Warning("Project {0} is already disposed; this shouldn't happen", project.FwProjectCode);
			_cache = project.FieldWorksProject.Cache;
			if (_cache == null)
			{
				Logger.Error("Failed to find the FDO cache!");
				return;
			}

			_servLoc = _cache.ServiceLocator;
			if (_servLoc == null)
			{
				Logger.Error("Failed to find the service locator; giving up.");
				return;
			}
			_customFieldConverter = new CustomFieldConverter(_cache);

			// For efficiency's sake, cache the six repositories and six factories we'll need all the time,
			_entryRepo = _servLoc.GetInstance<ILexEntryRepository>();
			_exampleRepo = _servLoc.GetInstance<ILexExampleSentenceRepository>();
			_pictureRepo = _servLoc.GetInstance<ICmPictureRepository>();
			_pronunciationRepo = _servLoc.GetInstance<ILexPronunciationRepository>();
			_senseRepo = _servLoc.GetInstance<ILexSenseRepository>();
			_posRepo = _servLoc.GetInstance<IPartOfSpeechRepository>();
			_translationRepo = _servLoc.GetInstance<ICmTranslationRepository>();
			_entryFactory = _servLoc.GetInstance<ILexEntryFactory>();
			_exampleFactory = _servLoc.GetInstance<ILexExampleSentenceFactory>();
			_pictureFactory = _servLoc.GetInstance<ICmPictureFactory>();
			_pronunciationFactory = _servLoc.GetInstance<ILexPronunciationFactory>();
			_senseFactory = _servLoc.GetInstance<ILexSenseFactory>();
			_translationFactory = _servLoc.GetInstance<ICmTranslationFactory>();

			if (_cache.LanguageProject != null && _cache.LanguageProject.TranslationTagsOA != null)
			{
				// TODO: Consider using LangProjectTags.kguidTranFreeTranslation instead
				_freeTranslationType = new PossibilityListConverter(_cache.LanguageProject.TranslationTagsOA).GetByName("Free translation");
				if (_freeTranslationType == null)
					_freeTranslationType = _cache.LanguageProject.TranslationTagsOA.PossibilitiesOS.FirstOrDefault();
			}

			_lfGrammar = GetGrammar(project);
			if (_lfGrammar == null)
				_lfGrammarByKey = new Dictionary<string, LfOptionListItem>();
			else
				_lfGrammarByKey = _lfGrammar.Items.ToDictionary(item => item.Key, item => item);
/* Comment this logging out once we're sure the grammar conversion works */
			var grammarLogMsgs = new List<string>();
			grammarLogMsgs.Add("Grammar follows:");
			foreach (LfOptionListItem item in _lfGrammarByKey.Values)
			{
				grammarLogMsgs.Add(String.Format("Grammar item {0} has abbrev {1} and GUID {2}",
					item.Value, item.Key, (item.Guid == null) ? "(none)" : item.Guid.Value.ToString()
				));
			}
			Logger.LogMany(LogSeverity.Debug, grammarLogMsgs);
/* */
			IEnumerable<LfLexEntry> lexicon = GetLexiconForTesting(project, _lfProjectConfig);
			NonUndoableUnitOfWorkHelper.Do(_cache.ActionHandlerAccessor, () =>
			{
				foreach (LfLexEntry lfEntry in lexicon)
					LfLexEntryToFdoLexEntry(lfEntry);
			});
			_cache.ActionHandlerAccessor.Commit();
		}

		private IEnumerable<LfLexEntry> GetLexiconForTesting(ILfProject project, ILfProjectConfig config)<commit_msg>Slightly better log message for grammar<commit_after>﻿// Copyright (c) 2015 SIL International
// This software is licensed under the MIT license (http://opensource.org/licenses/MIT)
using System;
using System.Collections.Generic;
using System.Linq;
using LfMerge.DataConverters;
using LfMerge.FieldWorks;
using LfMerge.Logging;
using LfMerge.LanguageForge.Config;
using LfMerge.LanguageForge.Model;
using LfMerge.MongoConnector;
using LfMerge.Settings;
using MongoDB.Driver;
using SIL.CoreImpl;
using SIL.FieldWorks.Common.COMInterfaces;
using SIL.FieldWorks.FDO.DomainServices;
using SIL.FieldWorks.FDO;
using SIL.FieldWorks.FDO.Infrastructure;

namespace LfMerge.Actions
{
	public class UpdateFdoFromMongoDbAction: Action
	{
		private FdoCache _cache;
		private IFdoServiceLocator _servLoc;
		private IMongoConnection _connection;
		private MongoProjectRecordFactory _projectRecordFactory;
		private ILfProject _lfProject;
		private MongoProjectRecord _projectRecord;

		private ILfProjectConfig _lfProjectConfig;
		private LfOptionList _lfGrammar;
		private Dictionary<string, LfOptionListItem> _lfGrammarByKey;

		private ILexEntryRepository _entryRepo;
		private ILexExampleSentenceRepository _exampleRepo;
		private ICmPictureRepository _pictureRepo;
		private ILexPronunciationRepository _pronunciationRepo;
		private ILexSenseRepository _senseRepo;
		private IPartOfSpeechRepository _posRepo;
		private ICmTranslationRepository _translationRepo;
		private ILexEntryFactory _entryFactory;
		private ILexExampleSentenceFactory _exampleFactory;
		private ICmPictureFactory _pictureFactory;
		private ILexPronunciationFactory _pronunciationFactory;
		private ILexSenseFactory _senseFactory;
		private ICmTranslationFactory _translationFactory;

		private ICmPossibility _freeTranslationType; // Used in LfExampleToFdoExample(), but cached here

		private CustomFieldConverter _customFieldConverter;

		public UpdateFdoFromMongoDbAction(LfMergeSettingsIni settings, ILogger logger, IMongoConnection conn, MongoProjectRecordFactory factory) : base(settings, logger)
		{
			_connection = conn;
			_projectRecordFactory = factory;
		}

		protected override ProcessingState.SendReceiveStates StateForCurrentAction
		{
			get { return ProcessingState.SendReceiveStates.QUEUED; }
		}

		protected override void DoRun(ILfProject project)
		{
			_lfProject = project;
			_projectRecord = _projectRecordFactory.Create(_lfProject);
			if (_projectRecord == null)
			{
				Logger.Warning("No project named {0}", _lfProject.LfProjectCode);
				Logger.Warning("If we are unit testing, this may not be an error");
				return;
			}
			_lfProjectConfig = _projectRecord.Config;
			if (_lfProjectConfig == null)
				return;

			if (project.FieldWorksProject == null)
			{
				Logger.Error("Failed to find the corresponding FieldWorks project!");
				return;
			}
			if (project.FieldWorksProject.IsDisposed)
				Logger.Warning("Project {0} is already disposed; this shouldn't happen", project.FwProjectCode);
			_cache = project.FieldWorksProject.Cache;
			if (_cache == null)
			{
				Logger.Error("Failed to find the FDO cache!");
				return;
			}

			_servLoc = _cache.ServiceLocator;
			if (_servLoc == null)
			{
				Logger.Error("Failed to find the service locator; giving up.");
				return;
			}
			_customFieldConverter = new CustomFieldConverter(_cache);

			// For efficiency's sake, cache the six repositories and six factories we'll need all the time,
			_entryRepo = _servLoc.GetInstance<ILexEntryRepository>();
			_exampleRepo = _servLoc.GetInstance<ILexExampleSentenceRepository>();
			_pictureRepo = _servLoc.GetInstance<ICmPictureRepository>();
			_pronunciationRepo = _servLoc.GetInstance<ILexPronunciationRepository>();
			_senseRepo = _servLoc.GetInstance<ILexSenseRepository>();
			_posRepo = _servLoc.GetInstance<IPartOfSpeechRepository>();
			_translationRepo = _servLoc.GetInstance<ICmTranslationRepository>();
			_entryFactory = _servLoc.GetInstance<ILexEntryFactory>();
			_exampleFactory = _servLoc.GetInstance<ILexExampleSentenceFactory>();
			_pictureFactory = _servLoc.GetInstance<ICmPictureFactory>();
			_pronunciationFactory = _servLoc.GetInstance<ILexPronunciationFactory>();
			_senseFactory = _servLoc.GetInstance<ILexSenseFactory>();
			_translationFactory = _servLoc.GetInstance<ICmTranslationFactory>();

			if (_cache.LanguageProject != null && _cache.LanguageProject.TranslationTagsOA != null)
			{
				// TODO: Consider using LangProjectTags.kguidTranFreeTranslation instead
				_freeTranslationType = new PossibilityListConverter(_cache.LanguageProject.TranslationTagsOA).GetByName("Free translation");
				if (_freeTranslationType == null)
					_freeTranslationType = _cache.LanguageProject.TranslationTagsOA.PossibilitiesOS.FirstOrDefault();
			}

			_lfGrammar = GetGrammar(project);
			if (_lfGrammar == null)
				_lfGrammarByKey = new Dictionary<string, LfOptionListItem>();
			else
				_lfGrammarByKey = _lfGrammar.Items.ToDictionary(item => item.Key, item => item);
/* Comment this logging out once we're sure the grammar conversion works */
			var grammarLogMsgs = new List<string>();
			grammarLogMsgs.Add("Grammar follows:");
			foreach (LfOptionListItem item in _lfGrammarByKey.Values)
			{
				grammarLogMsgs.Add(String.Format("Grammar item {0} has abbrev {1}, key {2} and GUID {3}",
					item.Value, item.Abbreviation, item.Key, (item.Guid == null) ? "(none)" : item.Guid.Value.ToString()
				));
			}
			Logger.LogMany(LogSeverity.Debug, grammarLogMsgs);
/* */
			IEnumerable<LfLexEntry> lexicon = GetLexiconForTesting(project, _lfProjectConfig);
			NonUndoableUnitOfWorkHelper.Do(_cache.ActionHandlerAccessor, () =>
			{
				foreach (LfLexEntry lfEntry in lexicon)
					LfLexEntryToFdoLexEntry(lfEntry);
			});
			_cache.ActionHandlerAccessor.Commit();
		}

		private IEnumerable<LfLexEntry> GetLexiconForTesting(ILfProject project, ILfProjectConfig config)
{'fraction_non_alphanumeric': 0.08537623425263875, 'fraction_numerical': 0.001617296561116786, 'mean_word_length': 5.527222222222222, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3864487', 'n_tokens_mistral': 4003, 'n_tokens_neox': 3425, 'n_words': 751}