2023-10-18 15:32:38 +00:00
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
2023-10-23 10:48:28 +00:00
sw . WriteLine ( $"Editeelt codelist {codelistname} downloaded on {DateTime.Now} with the FarmmapsDownloadCL application" ) ;
2023-10-18 15:32:38 +00:00
//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}" ) ;
}
}
}
}