183 lines
9.2 KiB
C#
183 lines
9.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using JD.LocalizationExport.Service.Implementation.IntermediaryFile.Serialization;
|
|
using JD.LocalizationExport.Service.Model;
|
|
using Newtonsoft.Json;
|
|
|
|
namespace JD.LocalizationExport.Service.Implementation.IntermediaryFile
|
|
{
|
|
internal class IntermediaryFileManager : IIntermediaryFileManager
|
|
{
|
|
private const int IntermediaryFileVersion = 1;
|
|
|
|
private readonly string _intermediaryFilePath;
|
|
|
|
internal IntermediaryFileManager(string intermediaryFilePath)
|
|
{
|
|
_intermediaryFilePath = intermediaryFilePath;
|
|
}
|
|
|
|
|
|
#region IIntermediaryFileManager implementation
|
|
|
|
// For several exports and for the intermediary file, we need to export all languages already exported, so all languages present in the intermediary file
|
|
// That's why all these languages are returned even though they haven't necessarily been selected
|
|
public async Task<Tuple<Line[], Language[]>> LoadFileAndMergeAsync(IEnumerable<Line> linesToExport, IEnumerable<Language> languagesToExport, IEnumerable<Language> allLanguages)
|
|
{
|
|
if (linesToExport == null)
|
|
throw new ArgumentNullException(nameof(linesToExport));
|
|
if (languagesToExport == null)
|
|
throw new ArgumentNullException(nameof(languagesToExport));
|
|
if (allLanguages == null)
|
|
throw new ArgumentNullException(nameof(allLanguages));
|
|
|
|
Line[] linesToExportArray = linesToExport.ToArray();
|
|
Language[] languagesToExportArray = languagesToExport.ToArray();
|
|
Language[] allLanguagesArray = allLanguages.ToArray();
|
|
|
|
// Check allLanguages is a superset of languagesToExport
|
|
if (languagesToExportArray.Except(allLanguagesArray).Any())
|
|
{
|
|
throw new ArgumentException($"The list of all languages doesn't contain the list of languages to export");
|
|
}
|
|
|
|
|
|
string intermediaryFileContent;
|
|
using (StreamReader reader = File.OpenText(_intermediaryFilePath))
|
|
{
|
|
intermediaryFileContent = await reader.ReadToEndAsync();
|
|
}
|
|
|
|
Serialization.IntermediaryFile previousExport = JsonConvert.DeserializeObject<Serialization.IntermediaryFile>(intermediaryFileContent);
|
|
|
|
|
|
string[] languagesToExportNames = languagesToExportArray.Select(l => l.OasisName).ToArray();
|
|
string[] languageNames = languagesToExportNames.Union(previousExport.Languages).ToArray();
|
|
int[] languageIndexes = languageNames.Select(l => Array.IndexOf(previousExport.Languages, l)).ToArray();
|
|
|
|
string[] languagesToLoadFromFile = languageNames.Except(languagesToExportNames).ToArray();
|
|
int[] languagesToLoadFromFileIndexes = languagesToLoadFromFile.Select(l => Array.IndexOf(previousExport.Languages, l)).ToArray();
|
|
|
|
List<Line> newLinesToExport = new List<Line>();
|
|
|
|
// Exporting the lines from Oasis using the saved data from intermediary file if necessary (for missing languages)
|
|
foreach (Line line in linesToExportArray)
|
|
{
|
|
Dictionary<string, string> newTranslations = new Dictionary<string, string>(line.Translations);
|
|
string lineId = line.LineId.ToString();
|
|
|
|
bool lineExistsInIntermediaryFile = previousExport.LinesById.TryGetValue(lineId, out SerializedLine intermediaryFileLine);
|
|
|
|
foreach (int i in languagesToLoadFromFileIndexes)
|
|
{
|
|
if (lineExistsInIntermediaryFile)
|
|
{
|
|
newTranslations[previousExport.Languages[i]] = intermediaryFileLine.Translations[i];
|
|
}
|
|
else
|
|
{
|
|
newTranslations[previousExport.Languages[i]] = string.Empty;
|
|
}
|
|
}
|
|
|
|
newLinesToExport.Add(new Line(line.LineId, line.MasterText, newTranslations, line.IsLineForPhone)); // TODO: Use correct MasterText if this language is not exported
|
|
}
|
|
|
|
// Loading data from intermediary file for the lines not exported from Oasis
|
|
string[] lineToExportIds = linesToExportArray.Select(l => l.LineId.ToString()).ToArray();
|
|
Dictionary<string, SerializedLine> missingLines = previousExport.LinesById.Where(pair => !lineToExportIds.Contains(pair.Key)).ToDictionary(pair => pair.Key, pair => pair.Value);
|
|
foreach (KeyValuePair<string, SerializedLine> pair in missingLines)
|
|
{
|
|
int lineId = int.Parse(pair.Key);
|
|
SerializedLine line = pair.Value;
|
|
|
|
Dictionary<string, string> newTranslations = new Dictionary<string, string>();
|
|
foreach (int i in languageIndexes)
|
|
{
|
|
newTranslations[previousExport.Languages[i]] = line.Translations[i];
|
|
}
|
|
|
|
newLinesToExport.Add(new Line(lineId, line.MasterText, newTranslations, (bool)line.IsUsedInMCA));
|
|
}
|
|
|
|
// Getting the missing language info from allLanguages using the name in the intermediary file
|
|
// Need to do all this LINQ query since we return a Language array, not just a string array
|
|
// (in which case returning the names of the languages in the intermediary file would have sufficed)
|
|
languagesToExportArray = languagesToExportArray.Union(allLanguagesArray.Where(l => languagesToLoadFromFile.Contains(l.OasisName))).ToArray();
|
|
|
|
return new Tuple<Line[], Language[]>(newLinesToExport.ToArray(), languagesToExportArray);
|
|
}
|
|
|
|
public async Task SaveFileAsync(IEnumerable<Line> linesToExport, IEnumerable<Language> languagesToExport)
|
|
{
|
|
Serialization.IntermediaryFile save = new Serialization.IntermediaryFile
|
|
{
|
|
Version = IntermediaryFileVersion.ToString(),
|
|
Languages = languagesToExport.Select(l => l.OasisName).OrderBy(l => l).ToArray()
|
|
};
|
|
save.LinesById = linesToExport.OrderBy(l => l.LineId).ToDictionary(l => l.LineId.ToString(),
|
|
l => new SerializedLine()
|
|
{
|
|
MasterText = l.MasterText,
|
|
IsUsedInMCA = l.IsLineForPhone,
|
|
Translations = l.Translations.OrderBy(pair => Array.IndexOf(save.Languages, pair.Key))
|
|
.Where(pair => save.Languages.Contains(pair.Key))
|
|
.Select(pair => pair.Value)
|
|
.ToArray()
|
|
});
|
|
|
|
// TODO: Check if better with BackgroundWorker, cheap async here with JsonConvert
|
|
|
|
//BackgroundWorker worker = new BackgroundWorker();
|
|
//string s = null;
|
|
//worker.DoWork += new DoWorkEventHandler((sender, e) =>
|
|
//{
|
|
// s = JsonConvert.SerializeObject(save, Formatting.Indented);
|
|
//});
|
|
|
|
//worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(async (sender, e) =>
|
|
//{
|
|
// string updatedFileContent = s;
|
|
// //string updatedFileContent = JsonConvert.SerializeObject(save, Formatting.Indented);
|
|
|
|
// using (StreamWriter outputFile = new StreamWriter(_intermediaryFilePath))
|
|
// {
|
|
// await outputFile.WriteAsync(updatedFileContent);
|
|
// }
|
|
//});
|
|
|
|
//worker.RunWorkerAsync();
|
|
//await Task.CompletedTask;
|
|
|
|
try
|
|
{
|
|
string updatedFileContent = await Task.Run(() => JsonConvert.SerializeObject(save, Formatting.Indented));
|
|
string tempOutputFile = _intermediaryFilePath + ".tmp";
|
|
string backupIntermediaryFile = _intermediaryFilePath + ".backup";
|
|
|
|
using (StreamWriter outputFileWriter = new StreamWriter(tempOutputFile))
|
|
{
|
|
await outputFileWriter.WriteAsync(updatedFileContent);
|
|
}
|
|
|
|
if (File.Exists(_intermediaryFilePath))
|
|
{
|
|
File.Replace(tempOutputFile, _intermediaryFilePath, backupIntermediaryFile);
|
|
}
|
|
else
|
|
{
|
|
File.Move(tempOutputFile, _intermediaryFilePath);
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
await Task.FromException(e);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|