FarmMapsApiClient_KB34_MAST/FarmmapsDownloadCL/DownloadCLApplication.cs

179 lines
7.2 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using FarmmapsApi;
using FarmmapsApi.Models;
using FarmmapsApi.Services;
using FarmmapsDownloadCL.Models;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using static FarmmapsApiSamples.Constants;
namespace FarmmapsDownloadCL
{
public class DownloadCLApplication : IApplication
{
private readonly ILogger<DownloadCLApplication> _logger;
private readonly FarmmapsApiService _farmmapsApiService;
private readonly DownloadCLService _DownloadCLService;
private readonly GeneralService _generalService;
public readonly Dictionary<string, List<string>> _dictCl;
string _itemcode;
public DownloadCLApplication(ILogger<DownloadCLApplication> logger, FarmmapsApiService farmmapsApiService,
GeneralService generalService, DownloadCLService DownloadCLService)
{
_logger = logger;
_farmmapsApiService = farmmapsApiService;
_generalService = generalService;
_DownloadCLService = DownloadCLService;
CodelistsClasses clc = new CodelistsClasses();
_itemcode = clc.itemcode;
_dictCl = clc.dictCl;
}
public async Task RunAsync()
{
var fieldsInputJson = File.ReadAllText("DownloadCLInput.json");
DownloadCLInput clInput = JsonConvert.DeserializeObject<DownloadCLInput>(fieldsInputJson);
// !! this call is needed the first time an api is called with a fresh clientid and secret !!
await _farmmapsApiService.GetCurrentUserCodeAsync();
var roots = await _farmmapsApiService.GetCurrentUserRootsAsync();
//Where to write the output
string downloadFolder = clInput.DownloadFolder;
if (string.IsNullOrEmpty(downloadFolder))
{
downloadFolder = "Downloads";
}
if (!Directory.Exists(downloadFolder))
Directory.CreateDirectory(downloadFolder);
//Get the most recent codelists
foreach (string codelist in clInput.codelists)
{
try
{
await Process(roots, codelist, downloadFolder);
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
}
private async Task Process(List<UserRoot> roots, string codelistname, string downloadFolder)
{
List<Item> codelist;
string itemtype;
string className;
string body;
string header;
string value;
string[] aboutArray = null;
string[] headerArray = null;
PropertyInfo[] props;
PropertyInfo prop;
List<string> dataList;
string clJson = Path.Combine(downloadFolder, $"{codelistname}.json");
string clCsv = Path.Combine(downloadFolder, $"{codelistname}.csv");
try
{
itemtype = _dictCl[codelistname][0];
className = _dictCl[codelistname][1];
codelist = await _farmmapsApiService.GetItemChildrenAsync(_itemcode, itemtype);
//Write full codelist in json format to clJson.
body = JsonConvert.SerializeObject(codelist);
File.WriteAllText(clJson, body);
_logger.LogInformation($"Downloaded file {clJson}");
//Write full list in csv format to clCsv.
StreamWriter sw = new StreamWriter(clCsv);
//Write metadata in top: when downloaded
sw.WriteLine($"Editeelt codelist {codelistname} downloaded on {DateTime.Now} with the FarmmapsDownloadCL application by Pepijn van Oort (WPR)");
//Generic, for any Codelist as long as it is also defined in FarmmapsDownloadCL.Models in
string typerequest = "FarmmapsDownloadCL.Models." + className + ", FarmmapsDownloadCL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
Type objType = Type.GetType(typerequest);
object clitem = Activator.CreateInstance(objType);
props = clitem.GetType().GetProperties();
//Lookup about info and write to top
foreach (PropertyInfo pi in props)
{
if (pi.Name == "about")
{
aboutArray = (string[])pi.GetValue(clitem);
foreach (string about in aboutArray)
{
//Add quotes
value = "\"" + about + "\"";
//Write each about to a separate line in the csv file
sw.WriteLine(value);
}
}
}
//Write an empty line
sw.WriteLine();
//Look up the headerArray and write the header comma separated
int i = 0;
while (headerArray == null)
{
prop = props[i];
if (prop.Name == "headers")
{
headerArray = (string[])prop.GetValue(clitem);
}
i++;
}
header = string.Join(",", headerArray);
sw.WriteLine(header);
//Add quotes because a value for field 'description' could be '21% Cl, 16.5%CaO, 1330 g/l' and without the quotes that
//would show up as separate columns. So per definition we will add quotes, except if we have a fieldname in the listNotToQuote, then value for that fieldname will not be given quotes
//e.g. not code "3" but code 3.
List<string> listNotToQuote = new List<string>() { "code", "n", "p", "k", "quantity", "cropGroupCode", "cultivationGroupCode" };
//Loop through all items in the codelist
foreach (Item item in codelist)
{
dataList = new List<string> { };
clitem = JsonConvert.DeserializeObject(item.Data.ToString(), objType);
//Add values of the cLitem to the dataList in the same order as the header
foreach (string h in headerArray)
{
value = (string)clitem.GetType().GetProperty(h).GetValue(clitem, null);
if(listNotToQuote.Contains(h) == false)
value = "\"" +value + "\"";
dataList.Add(value);
}
string dataLine = string.Join(",", dataList);
sw.WriteLine(string.Join(",", dataList));
}
sw.Close();
_logger.LogInformation($"Downloaded file {clCsv}");
}
catch
{
_logger.LogWarning($"Missing lookup information on codelist {codelistname}");
}
}
}
}