From 875a85f7f80604bea7551f6fea54b9d870391c71 Mon Sep 17 00:00:00 2001 From: Silvia Tzeneva <3305245+stzva@users.noreply.github.com> Date: Wed, 4 Sep 2019 16:10:51 +0300 Subject: [PATCH] Add a sample code for Documaster's integration to eByggesak. --- .gitignore | 1 + .../NoarkWsClientSample/DocumasterClients.cs | 92 +++ .../NoarkWsClientSample.csproj | 6 +- .../NoarkWsClientSample/Options.cs | 39 + .../NoarkWsClientSample/Program.cs | 740 +----------------- .../NoarkWsClientSample/Samples.cs | 674 ++++++++++++++++ .../DocumasterToEByggesakSubmitter.cs | 128 +++ .../eByggesak/EByggesakIntegrationSample.cs | 31 + .../EByggesakToDocumasterSubmitter.cs | 300 +++++++ .../NoarkWsClientSample/eByggesak/README.md | 48 ++ 10 files changed, 1328 insertions(+), 731 deletions(-) create mode 100644 NoarkWsClientSample/NoarkWsClientSample/DocumasterClients.cs create mode 100644 NoarkWsClientSample/NoarkWsClientSample/Options.cs create mode 100644 NoarkWsClientSample/NoarkWsClientSample/Samples.cs create mode 100644 NoarkWsClientSample/NoarkWsClientSample/eByggesak/DocumasterToEByggesakSubmitter.cs create mode 100644 NoarkWsClientSample/NoarkWsClientSample/eByggesak/EByggesakIntegrationSample.cs create mode 100644 NoarkWsClientSample/NoarkWsClientSample/eByggesak/EByggesakToDocumasterSubmitter.cs create mode 100644 NoarkWsClientSample/NoarkWsClientSample/eByggesak/README.md diff --git a/.gitignore b/.gitignore index 77d3ac9..eb4d800 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,7 @@ bld/ # Visual Studo cache/options directory .vs/ */.vs/ +**/Properties/* # MSTest test Results [Tt]est[Rr]esult*/ diff --git a/NoarkWsClientSample/NoarkWsClientSample/DocumasterClients.cs b/NoarkWsClientSample/NoarkWsClientSample/DocumasterClients.cs new file mode 100644 index 0000000..7954c5b --- /dev/null +++ b/NoarkWsClientSample/NoarkWsClientSample/DocumasterClients.cs @@ -0,0 +1,92 @@ +using CommandLine; +using Documaster.WebApi.Client.IDP; +using Documaster.WebApi.Client.IDP.Oauth2; +using Documaster.WebApi.Client.Noark5.Client; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NoarkWsClientSample +{ + public class DocumasterClients + { + protected NoarkClient noarkClient; + protected Oauth2HttpClient idpClient; + + private string refreshToken; + private DateTime acccessTokenExpirationTime; + private Options opts; + + public DocumasterClients(Options opts) + { + this.opts = opts; + + /* + * Using the Noark 5 web services requires providing a valid access token. + * The way this token is obtained depends on the system implementing the services. + * This sample code obtains the token from the Documaster's identity provider service + * with the help of a designated Documaster IDP client. + * If the Noark client is used in the context of an application that has access to a web browser, + * we strongly recommend choosing the Oauth2 Authorization Code Grant Flow supported for obtaining + * access tokens. + */ + + //Initialize an IDP client and request an authorization token + InitIdpClient(opts); + + //Initialize a Noark client + InitClientWithoutClientCertificate(opts); + + //Notice that it is also possible to initialize а ssl-based Noark client by providing a client certificate: + //InitClient(opts); + } + + public NoarkClient getNoarkClient() + { + RefreshAccessToken(); + return noarkClient; + } + + private void RefreshAccessToken() + { + //access token expires in 60 minutes + + if (refreshToken == null) + { + PasswordGrantTypeParams passwordGrantTypeParams = new PasswordGrantTypeParams(opts.ClientId, opts.ClientSecret, opts.Username, opts.Password, OpenIDConnectScope.OPENID); + var accessTokenResponse = idpClient.GetTokenWithPasswordGrantType(passwordGrantTypeParams); + acccessTokenExpirationTime = DateTime.Now.AddSeconds(accessTokenResponse.ExpiresInMs); + refreshToken = accessTokenResponse.RefreshToken; + + noarkClient.AuthToken = accessTokenResponse.AccessToken; + + } + else if (DateTime.Now > acccessTokenExpirationTime) + { + RefreshTokenGrantTypeParams refreshTokenGrantTypeParams = new RefreshTokenGrantTypeParams(refreshToken, opts.ClientId, opts.ClientSecret, OpenIDConnectScope.OPENID); + var accessTokenResponse = idpClient.RefreshToken(refreshTokenGrantTypeParams); + acccessTokenExpirationTime = DateTime.Now.AddSeconds(accessTokenResponse.ExpiresInMs); + refreshToken = accessTokenResponse.RefreshToken; + + noarkClient.AuthToken = accessTokenResponse.AccessToken; + } + } + + private void InitIdpClient(Options options) + { + idpClient = new Oauth2HttpClient(options.IdpServerAddress, true); + } + + private void InitClient(Options options) + { + noarkClient = new NoarkClient(options.ServerAddress, true, options.CertificatePath, options.CertificatePass); + } + + private void InitClientWithoutClientCertificate(Options options) + { + noarkClient = new NoarkClient(options.ServerAddress, true); + } + } +} diff --git a/NoarkWsClientSample/NoarkWsClientSample/NoarkWsClientSample.csproj b/NoarkWsClientSample/NoarkWsClientSample/NoarkWsClientSample.csproj index 4e44e96..e1e9944 100644 --- a/NoarkWsClientSample/NoarkWsClientSample/NoarkWsClientSample.csproj +++ b/NoarkWsClientSample/NoarkWsClientSample/NoarkWsClientSample.csproj @@ -9,14 +9,14 @@ all - + all - + all - + all diff --git a/NoarkWsClientSample/NoarkWsClientSample/Options.cs b/NoarkWsClientSample/NoarkWsClientSample/Options.cs new file mode 100644 index 0000000..ba6a73d --- /dev/null +++ b/NoarkWsClientSample/NoarkWsClientSample/Options.cs @@ -0,0 +1,39 @@ +using CommandLine; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NoarkWsClientSample +{ + public class Options + { + [Option("idpaddr", Required = true, HelpText = "Idp server address")] + public string IdpServerAddress { get; set; } + + [Option("clientid", Required = true, HelpText = "Idp Client Id")] + public string ClientId { get; set; } + + [Option("clientsecret", Required = true, HelpText = "Idp Client Secret")] + public string ClientSecret { get; set; } + + [Option("username", Required = true, HelpText = "Username")] + public string Username { get; set; } + + [Option("password", Required = true, HelpText = "Password")] + public string Password { get; set; } + + [Option("addr", Required = true, HelpText = "Server address")] + public string ServerAddress { get; set; } + + [Option("cert", HelpText = "Path to certificate file")] + public string CertificatePath { get; set; } + + [Option("certpass", HelpText = "Certificate password")] + public string CertificatePass { get; set; } + + [Option("testdoc", Required = true, HelpText = "Path to test file")] + public string TestDoc { get; set; } + } +} diff --git a/NoarkWsClientSample/NoarkWsClientSample/Program.cs b/NoarkWsClientSample/NoarkWsClientSample/Program.cs index e5ff91d..25f6e86 100644 --- a/NoarkWsClientSample/NoarkWsClientSample/Program.cs +++ b/NoarkWsClientSample/NoarkWsClientSample/Program.cs @@ -8,25 +8,26 @@ using Documaster.WebApi.Client.Noark5.NoarkEntities; using Documaster.WebApi.Client.IDP; using Documaster.WebApi.Client.IDP.Oauth2; +using NoarkWsClientSample.eByggesak; namespace NoarkWsClientSample { - class Program + static class Program { - private static NoarkClient client; - private static Oauth2HttpClient idpClient; - static string testDoc; - public static void Main(string[] args) { var options = ParserCommandLineArguments(args); - InitializeSample(options); - JournalingSample(); - ArchiveSample(); - MeetingAndBoardHandlingDataSample(); - BusinessSpecificMetadataSample(); - CodeListsSample(); + Samples samples = new Samples(options); + + samples.JournalingSample(); + samples.ArchiveSample(); + samples.MeetingAndBoardHandlingDataSample(); + samples.BusinessSpecificMetadataSample(); + samples.CodeListsSample(); + + EByggesakIntegrationSample eByggesakIntegrationSample = new EByggesakIntegrationSample(options); + eByggesakIntegrationSample.ExecuteSample(); } private static Options ParserCommandLineArguments(string[] args) @@ -44,722 +45,5 @@ private static Options ParserCommandLineArguments(string[] args) return opts; } - - private static void InitializeSample(Options opts) - { - /* - * Using the Noark 5 web services requires providing a valid access token. - * The way this token is obtained depends on the system implementing the services. - * This sample code obtains the token from the Documaster's identity provider service - * with the help of a designated Documaster IDP client. - * If the Noark client is used in the context of an application that has access to a web browser, - * we strongly recommend choosing the Oauth2 Authorization Code Grant Flow supported for obtaining - * access tokens. - */ - - //Initialize an IDP client and request an authorization token - InitIdpClient(opts); - PasswordGrantTypeParams passwordGrantTypeParams = new PasswordGrantTypeParams( - opts.ClientId, opts.ClientSecret, opts.Username, opts.Password, OpenIDConnectScope.OPENID); - var accessToken = idpClient.GetTokenWithPasswordGrantType(passwordGrantTypeParams).AccessToken; - - //Initialize a Noark client - InitClient(opts); - client.AuthToken = accessToken; - - //Notice that it is also possible to initialize а ssl-based Noark client without providing - //client certificate: - //InitClientWithoutClientCertificate(opts); - - testDoc = opts.TestDoc; - } - - private static void InitIdpClient(Options options) - { - idpClient = new Oauth2HttpClient(options.IdpServerAddress, true); - } - - private static void InitClient(Options options) - { - client = new NoarkClient(options.ServerAddress, options.CertificatePath, options.CertificatePass, true); - } - - private static void InitClientWithoutClientCertificate(Options options) - { - client = new NoarkClient(options.ServerAddress, true); - } - - private static void JournalingSample() - { - Console.WriteLine($"Journaling example {Environment.NewLine}"); - - //Create a new Arkiv with an Arkivskaper - //When new objects are initialized, a temporary Id is assigned to them. - var newArkivskaper = new Arkivskaper("B7-23-W5", "John Smith"); - var newArkiv = new Arkiv("Arkiv"); - - var transactionResponse = client.Transaction() - .Save(newArkiv) - .Save(newArkivskaper) - .Link(newArkiv.LinkArkivskaper(newArkivskaper)) - .Commit(); - - //When the transaction is committed, the transaction response contains a map with saved objects. - //One can access the saved Arkiv by providing its temporary Id as a key to the map. - //Notice that arkiv.Id is the permanent Id of the Arkiv. - var arkiv = transactionResponse.Saved[newArkiv.Id] as Arkiv; - Console.WriteLine( - $"Created Arkiv: Id={arkiv.Id}, Tittel={arkiv.Tittel}, OpprettetDato={arkiv.OpprettetDato}"); - - //Update the description of the Arkiv and create a new Arkivdel in it - //Create a new Klassifikasjonssystem with one Klasse - //Set the new Klassifikasjonssystem as the primary Klassifikasjonssystem for the Arkivdel - arkiv.Beskrivelse = "Barnehage Arkiv"; - var newArkivdel = new Arkivdel("2007/8"); - var newKlassifikasjonssystem = new Klassifikasjonssystem("Barnehage"); - var newKlasse = new Klasse("01", "Tilbud"); - - transactionResponse = client.Transaction() - .Save(arkiv) - .Save(newArkivdel) - .Link(newArkivdel.LinkArkiv(arkiv)) - .Save(newKlassifikasjonssystem) - .Link(newArkivdel.LinkPrimaerKlassifikasjonssystem(newKlassifikasjonssystem)) - .Save(newKlasse) - .Link(newKlasse.LinkKlassifikasjonssystem(newKlassifikasjonssystem)) - .Commit(); - - arkiv = transactionResponse.Saved[arkiv.Id] as Arkiv; - Console.WriteLine($"Updated Arkiv: Id={arkiv.Id}, Beskrivelse={arkiv.Beskrivelse}"); - - var arkivdel = transactionResponse.Saved[newArkivdel.Id] as Arkivdel; - Console.WriteLine($"Created Arkivdel: Id={arkivdel.Id}, Tittel={arkivdel.Tittel}"); - - var klassifikasjonssystemId = transactionResponse.Saved[newKlassifikasjonssystem.Id].Id; - var klasseId = transactionResponse.Saved[newKlasse.Id].Id; - - //Create a screening code - Skjerming newSkjerming = new Skjerming(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), "Description", - "Authority"); - Skjerming skjerming = client.PutCodeListValue(newSkjerming); - - //Screen the Arkivdel - arkivdel.Skjerming = skjerming; - transactionResponse = client.Transaction() - .Save(arkivdel) - .Commit(); - - //Find the Arkivdel by id - //By default the service will return null values for all screened fields of screened objects - //To see the values of screened fields call SetPublicUse(false) - var queryResults = client.Query("id=@arkivdelId", 10) - .AddQueryParam("@arkivdelId", arkivdel.Id) - .Execute(); - Console.WriteLine($"Found {queryResults.Results.Count()} Arkivdel object(s) with Id {arkivdel.Id}"); - - //Print a screened field: - arkivdel = queryResults.Results.First(); - Console.WriteLine($"Tittel of Arkivdel is masked: {arkivdel.Tittel}"); - - //For convenience, objects in query and transaction responses contain the id's of many-to-one reference fields - Console.WriteLine($"Arkivdel.RefArkiv: {arkivdel.RefArkiv}"); - Console.WriteLine($"Arkivdel.RefPrimaerKlassifikasjonssystem: {arkivdel.RefPrimaerKlassifikasjonssystem}"); - - //Create two other Klassifikasjonssystem objects and link them to the Arkivdel as secondary Klassifikasjonssystem - var sekundaerKlassifikasjonssystemSkole = new Klassifikasjonssystem("Skole"); - var klasseInSekundaerKlassifikasjonssystemSkole = new Klasse("07", "Report"); - var sekundaerKlassifikasjonssystem2 = new Klassifikasjonssystem("EOP"); - - transactionResponse = client.Transaction() - .Save(sekundaerKlassifikasjonssystemSkole) - .Save(klasseInSekundaerKlassifikasjonssystemSkole) - .Link(sekundaerKlassifikasjonssystemSkole.LinkKlasse(klasseInSekundaerKlassifikasjonssystemSkole)) - .Save(sekundaerKlassifikasjonssystem2) - .Link(arkivdel.LinkSekundaerKlassifikasjonssystem(sekundaerKlassifikasjonssystemSkole, - sekundaerKlassifikasjonssystem2)) - .Commit(); - - //We need the id of the saved Klasse for the next transactions - var sekundaerKlasseId = - transactionResponse.Saved[klasseInSekundaerKlassifikasjonssystemSkole.Id].Id; - - //Create a new administrativEnhet value - AdministrativEnhet newAdministrativEnhet = - new AdministrativEnhet(Guid.NewGuid().ToString(), Guid.NewGuid().ToString()); - AdministrativEnhet administrativEnhet = client.PutCodeListValue(newAdministrativEnhet); - - //Create a new Saksmappe in the Arkivdel - //The new Saksmappe needs to have a Klasse in the primary Klassifikasjonssystem of the Arkivdel - //Also link the Saksmappe to a secondary Klasse - var newSaksmappe = new Saksmappe("Tilbud (Smith, John)", administrativEnhet); - var newSakspart = new Sakspart("Alice", "internal"); - - var savedObjects = client.Transaction() - .Save(newSaksmappe) - .Link(newSaksmappe.LinkArkivdel(arkivdel)) - .Link(newSaksmappe.LinkPrimaerKlasse(klasseId)) - .Link(newSaksmappe.LinkSekundaerKlasse(sekundaerKlasseId)) - .Save(newSakspart) - .Link(newSaksmappe.LinkSakspart(newSakspart)) - .Commit() - .Saved; - - var saksmappe = savedObjects[newSaksmappe.Id] as Saksmappe; - Console.WriteLine($"Created Saksmappe: Id={saksmappe.Id}, Saksdato: {saksmappe.Saksdato}"); - - //Create another Klasse - //Unlink the Saksmappe from its Klasse and link it to the new Klasse - var anotherKlasse = new Klasse("02", "Klage"); - - client.Transaction() - .Save(anotherKlasse) - .Link(anotherKlasse.LinkKlassifikasjonssystem(klassifikasjonssystemId)) - .Unlink(saksmappe.UnlinkPrimaerKlasse(klasseId)) - .Link(saksmappe.LinkPrimaerKlasse(anotherKlasse)) - .Commit(); - Console.WriteLine( - $"Unlinked Saksmappe wiht Id {saksmappe.Id} from Klasse '{newKlasse.Tittel}' and linked it to Klasse '{anotherKlasse.Tittel}'"); - - //Find all available codes for journalstatus in Journalpost - var journalstatusCodeList = client.CodeLists(type: "Journalpost", field: "journalstatus").First(); - Console.WriteLine($"CodeList list for {journalstatusCodeList.Type}.{journalstatusCodeList.Field}:"); - foreach (var code in journalstatusCodeList.Values) - { - Console.WriteLine($" Code={code.Code}, Name={code.Name}"); - } - - //Create a new Journalpost in the Saksmappe - //Create an EksternId object and link it to the Journalpost - //Create a new Korrespondansepart and link it to the Journalpost - //Create a Noekkelord (keyword) object and link it to the Journalpost - var newJournalpost = new Journalpost("Tilbud (Smith, John, Godkjent)", Journalposttype.UTGAAENDE_DOKUMENT) - { - Journalaar = 2007, - Journalsekvensnummer = 46 - }; - - var newEksternId = new EksternId("External System", Guid.NewGuid().ToString()); - var newKorrespondansepart = new Korrespondansepart(Korrespondanseparttype.INTERN_MOTTAKER, "John Smith"); - var newNoekkelord = new Noekkelord("keyword"); - - savedObjects = client.Transaction() - .Save(newJournalpost) - .Link(newJournalpost.LinkMappe(saksmappe)) - .Save(newEksternId) - .Link(newJournalpost.LinkEksternId(newEksternId)) - .Save(newKorrespondansepart) - .Link(newJournalpost.LinkKorrespondansepart(newKorrespondansepart)) - .Save(newNoekkelord) - .Link(newNoekkelord.LinkRegistrering(newJournalpost)) - .Commit() - .Saved; - - var journalPost = savedObjects[newJournalpost.Id] as Journalpost; - Console.WriteLine( - $"Created Journalpost: Id={journalPost.Id}, Tittel={journalPost.Tittel}, Journalstatus={journalPost.Journalstatus.Code}"); - - //Find the Journalpost by the eksternID value - var journalpstQueryResults = client.Query("refEksternId.eksternID=@eksternId", 10) - .AddQueryParam("@eksternId", newEksternId.EksternID) - .Execute(); - Console.WriteLine( - $"Found {journalpstQueryResults.Results.Count()} Journalpost objects with eksternID {newEksternId.EksternID}"); - - //Upload a file - Dokumentfil dokumentfil; - using (var inputStream = File.OpenRead(testDoc)) - { - dokumentfil = client.Upload(inputStream, "godkjenning.pdf"); - } - Console.WriteLine($"Uploaded file {testDoc}"); - - //Create a new value for Dokumenttype - Dokumenttype newDokumenttype = new Dokumenttype(Guid.NewGuid().ToString(), Guid.NewGuid().ToString()); - Dokumenttype dokumenttype = client.PutCodeListValue(newDokumenttype); - - //Create a new Dokument and Dokumentversjon using the uploaded file - var newDokument = new Dokument(dokumenttype, "Tilbud (Smith, John, Godkjent)", - TilknyttetRegistreringSom.HOVEDDOKUMENT); - var newDokumentversjon = new Dokumentversjon(Variantformat.PRODUKSJONSFORMAT, ".pdf", dokumentfil); - - savedObjects = client.Transaction() - .Save(newDokument) - .Link(newDokument.LinkRegistrering(journalPost)) - .Save(newDokumentversjon) - .Link(newDokumentversjon.LinkDokument(newDokument)) - .Commit() - .Saved; - - var dokumentversjon = savedObjects[newDokumentversjon.Id] as Dokumentversjon; - Console.WriteLine( - $"Created Dokumentversjon: Id={dokumentversjon.Id}, Versjonsnummer: {dokumentversjon.Versjonsnummer}, Filstoerrelse: {dokumentversjon.Filstoerrelse}"); - - //Download the Dokumentversjon file - var downloadPath = Path.GetTempFileName(); - using (var outputStream = File.Create(downloadPath)) - { - client.Download(dokumentversjon.Dokumentfil, outputStream); - } - Console.WriteLine($"Downloaded file {downloadPath}"); - - //Find all dokument objects in a Saksmappe called "Tilbud (Smith, John)" - //Results should be ordered by creation date in descending order - var queryResponse = client.Query("refRegistrering.refMappe.tittel=@saksmappeTittel", 50) - .AddQueryParam("@saksmappeTittel", "Tilbud (Smith, John)") - .AddSortOrder("opprettetDato", Order.Descending) - .Execute(); - Console.WriteLine( - $"Query returned {queryResponse.Results.Count()} Dokument objects in Saksmappe objects called 'Tilbud (Smith, John)'"); - Console.WriteLine($"More results available: {queryResponse.HasMore}"); - - //Delete the DokumentVersjon by id - client.Transaction().Delete(dokumentversjon.Id).Commit(); - Console.WriteLine($"Deleted Dokumentversjon with Id {dokumentversjon.Id}"); - Console.WriteLine(); - } - - private static void ArchiveSample() - { - Console.WriteLine($"Archive example {Environment.NewLine}"); - - //Create a new Arkiv with an Arkivskaper - //Create a new Arkivdel in the Arkiv - var newArkivskaper = new Arkivskaper("B7-23-W5", "John Smith"); - var newArkiv = new Arkiv("Arkiv"); - var newArkivdel = new Arkivdel("2007/8"); - - var transactionResponse = client.Transaction() - .Save(newArkiv) - .Save(newArkivskaper) - .Save(newArkivdel) - .Link(newArkiv.LinkArkivskaper(newArkivskaper)) - .Link(newArkivdel.LinkArkiv(newArkiv)) - .Commit(); - - var arkiv = transactionResponse.Saved[newArkiv.Id] as Arkiv; - Console.WriteLine( - $"Created Arkiv: Id={arkiv.Id}, Arkivstatus={arkiv.Arkivstatus.Code}, OpprettetDato={arkiv.OpprettetDato}"); - - var arkivdel = transactionResponse.Saved[newArkivdel.Id] as Arkivdel; - Console.WriteLine($"Created Arkivdel: Id={arkivdel.Id}, Arkivdelstatus={arkivdel.Arkivdelstatus.Code}"); - - //Get all available values for the Mappetype code list - var mappetypeList = client.CodeLists("Mappe", "mappetype").First(); - if (mappetypeList.Values.Count == 0) - { - Console.WriteLine( - "Can not create an instance of Mappe because there are not available values in the Mappetype code list!"); - return; - } - var mappetypeCode = mappetypeList.Values.First().Code; - - //Create a new Mappe - var newMappe = new Mappe("Barnehage Tilbud") - { - Beskrivelse = "Mappe Beskrivelse", - Mappetype = new Mappetype(mappetypeCode) - }; - - transactionResponse = client.Transaction() - .Save(newMappe) - .Link(newMappe.LinkArkivdel(arkivdel)) - .Commit(); - - var mappe = transactionResponse.Saved[newMappe.Id] as Mappe; - Console.WriteLine($"Created Mappe: Id={mappe.Id}, Tittel: {mappe.Tittel}"); - - //Create a child Mappe in the Mappe - var newBarnMappe = new Mappe("Tilbud (Smith, John)"); - - var savedObjects = client.Transaction() - .Save(newBarnMappe) - .Link(newBarnMappe.LinkForelderMappe(mappe)) - .Commit() - .Saved; - - var barnMappe = savedObjects[newBarnMappe.Id] as Mappe; - Console.WriteLine( - $"Created a new Mappe (Id={barnMappe.Id}, Tittel={barnMappe.Tittel}) in Mappe with Id {mappe.Id}"); - - //Find all children of the Mappe - var queryResults = client.Query("refForelderMappe.id=@forelderMappeId", 10) - .AddQueryParam("@forelderMappeId", mappe.Id) - .Execute(); - Console.WriteLine($"Found {queryResults.Results.Count()} Mappe objects in Mappe with Id {mappe.Id}"); - - //Create a new Basisregistrering in the child Mappe - //Link one Korrespondansepart to the Basisregistrering - var newBasisregistrering = new Basisregistrering("Tilbud (Smith, John, Godkjent)"); - var newKorrespondansepart = new Korrespondansepart(Korrespondanseparttype.MOTTAKER, "John Smith"); - - savedObjects = client.Transaction() - .Save(newBasisregistrering) - .Save(newKorrespondansepart) - .Link(newBasisregistrering.LinkMappe(barnMappe)) - .Link(newBasisregistrering.LinkKorrespondansepart(newKorrespondansepart)) - .Commit() - .Saved; - - var basisregistrering = savedObjects[newBasisregistrering.Id] as Basisregistrering; - Console.WriteLine( - $"Created Basisregistrering: Id={basisregistrering.Id}, Tittel={basisregistrering.Tittel}"); - - //Upload a file - Dokumentfil dokumentfil; - using (var inputStream = File.OpenRead(testDoc)) - { - dokumentfil = client.Upload(inputStream, "godkjenning.pdf"); - } - Console.WriteLine($"Uploaded file {testDoc}"); - - //Get available values for the Dokumenttype code list - var dokumenttypeList = client.CodeLists("Dokument", "dokumenttype").First(); - if (dokumenttypeList.Values.Count == 0) - { - Console.WriteLine( - "Can not create an instance of Dokument because there are not available values in the Dokumenttype code list!"); - return; - } - var dokumenttypeCode = dokumenttypeList.Values.First().Code; - - //Create a new Dokument and Dokumentversjon using the uploaded file - //Link the Dokument to the Basisregistrering - var newDokument = new Dokument(new Dokumenttype(dokumenttypeCode), "Tilbud (Smith, John, Godkjent)", - TilknyttetRegistreringSom.HOVEDDOKUMENT); - var newDokumentversjon = new Dokumentversjon(Variantformat.PRODUKSJONSFORMAT, ".pdf", dokumentfil); - - savedObjects = client.Transaction() - .Save(newDokument) - .Link(newDokument.LinkRegistrering(basisregistrering)) - .Save(newDokumentversjon) - .Link(newDokumentversjon.LinkDokument(newDokument)) - .Commit() - .Saved; - - var dokumentversjon = savedObjects[newDokumentversjon.Id] as Dokumentversjon; - Console.WriteLine( - $"Created Dokumentversjon: Id={dokumentversjon.Id}, Versjonsnummer: {dokumentversjon.Versjonsnummer}, Filstoerrelse: {dokumentversjon.Filstoerrelse}"); - } - - private static void MeetingAndBoardHandlingDataSample() - { - Console.WriteLine($"Meeting and board handling data example {Environment.NewLine}"); - - //Create a new Arkiv with an Arkivskaper - //Create a new Arkivdel in the Arkiv - var newArkivskaper = new Arkivskaper("B7-23-W5", "John Smith"); - var newArkiv = new Arkiv("Arkiv"); - var newArkivdel = new Arkivdel("2007/8"); - - var transactionResponse = client.Transaction() - .Save(newArkiv) - .Save(newArkivskaper) - .Save(newArkivdel) - .Link(newArkiv.LinkArkivskaper(newArkivskaper)) - .Link(newArkivdel.LinkArkiv(newArkiv)) - .Commit(); - - var arkiv = transactionResponse.Saved[newArkiv.Id] as Arkiv; - Console.WriteLine( - $"Created Arkiv: Id={arkiv.Id}, Arkivstatus={arkiv.Arkivstatus.Code}, OpprettetDato={arkiv.OpprettetDato}"); - - var arkivdel = transactionResponse.Saved[newArkivdel.Id] as Arkivdel; - Console.WriteLine($"Created Arkivdel: Id={arkivdel.Id}, Arkivdelstatus={arkivdel.Arkivdelstatus.Code}"); - - //Create a new Moetemappe and Moetedeltaker - Moetemappe newMappe = new Moetemappe("Moetemappe Tittel", "Moetenummer", "Utvalg"); - Moetedeltaker moetedeltaker = new Moetedeltaker("Moetedeltaker Navn"); - - transactionResponse = client.Transaction() - .Save(newMappe) - .Link(newMappe.LinkArkivdel(arkivdel)) - .Save(moetedeltaker) - .Link(moetedeltaker.LinkMappe(newMappe)) - .Commit(); - - var mappe = transactionResponse.Saved[newMappe.Id] as Moetemappe; - Console.WriteLine($"Created Mappe: Id={mappe.Id}, Tittel={mappe.Tittel}"); - Console.WriteLine($"Created Moetedeltaker: Navn={moetedeltaker.Navn}"); - - //Create a new AdministrativEnhett code list value - AdministrativEnhet newAdministrativEnhet = - new AdministrativEnhet(Guid.NewGuid().ToString(), Guid.NewGuid().ToString()); - AdministrativEnhet administrativEnhet = client.PutCodeListValue(newAdministrativEnhet); - - //Create a new Moeteregistrering - Moeteregistrering newMoeteregistrering = new Moeteregistrering("Tittel", "Saksbehandler", - administrativEnhet, Moeteregistreringstype.MOETEINNKALLING); - transactionResponse = client.Transaction() - .Save(newMoeteregistrering) - .Link(newMoeteregistrering.LinkMappe(mappe)) - .Commit(); - - var moeteregistrering = transactionResponse.Saved[newMoeteregistrering.Id] as Moeteregistrering; - Console.WriteLine( - $"Created Moeteregistrering: Id={moeteregistrering.Id}, Tittel={moeteregistrering.Tittel}"); - ; - - //Upload a file - Dokumentfil dokumentfil; - using (var inputStream = File.OpenRead(testDoc)) - { - dokumentfil = client.Upload(inputStream, "godkjenning.pdf"); - } - Console.WriteLine($"Uploaded file {testDoc}"); - - //Create a new Dokumenttype code list value - Dokumenttype newDokumenttype = new Dokumenttype(Guid.NewGuid().ToString(), Guid.NewGuid().ToString()); - Dokumenttype dokumenttype = client.PutCodeListValue(newDokumenttype); - - //Link the Dokument to the Moeteregistrering - var newDokument = new Dokument(dokumenttype, "Tilbud (Smith, John, Godkjent)", - TilknyttetRegistreringSom.HOVEDDOKUMENT); - var newDokumentversjon = new Dokumentversjon(Variantformat.PRODUKSJONSFORMAT, ".pdf", dokumentfil); - - transactionResponse = client.Transaction() - .Save(newDokument) - .Link(newDokument.LinkRegistrering(moeteregistrering)) - .Save(newDokumentversjon) - .Link(newDokumentversjon.LinkDokument(newDokument)) - .Commit(); - - var dokumentversjon = transactionResponse.Saved[newDokumentversjon.Id] as Dokumentversjon; - Console.WriteLine( - $"Created Dokumentversjon: Id={dokumentversjon.Id}, Versjonsnummer: {dokumentversjon.Versjonsnummer}, Filstoerrelse: {dokumentversjon.Filstoerrelse}"); - Console.WriteLine(); - } - - private static void BusinessSpecificMetadataSample() - { - string GROUP_ID = $"gr-{Guid.NewGuid().ToString()}"; - string STRING_FIELD_ID = $"f-{Guid.NewGuid().ToString()}"; - string DOUBLE_FIELD_ID = $"f-{Guid.NewGuid().ToString()}"; - string LONG_FIELD_ID = $"f-{Guid.NewGuid().ToString()}"; - - //Create a business-specific metadata group - MetadataGroupInfo newGroup = new MetadataGroupInfo(GROUP_ID, "BSM Group Name", "BSM Group Description"); - MetadataGroupInfo savedGroup = client.PutBsmGroup(newGroup); - Console.WriteLine( - $"Created new group: GroupId={savedGroup.GroupId}, GroupDescription={savedGroup.GroupDescription}, GroupName={savedGroup.GroupName}"); - Console.WriteLine(); - - //Create a new string field with predefined values "value 1", "value 2" and "value 3" - MetadataFieldInfo newFieldStr = new MetadataFieldInfo(STRING_FIELD_ID, "BSM Field String", - "BSM Field Description", FieldType.String, new List() {"value 1", "value 2", "value 3"}); - MetadataFieldInfo savedFieldStr = client.PutBsmField(GROUP_ID, newFieldStr); - Console.WriteLine( - $"Created new field: FieldId={savedFieldStr.FieldId}, FieldType={savedFieldStr.FieldType}, FieldName={savedFieldStr.FieldName}, FieldValues={string.Join(",", savedFieldStr.FieldValues)}"); - Console.WriteLine(); - - //Create a new long field with predefined values 1 and 2 - MetadataFieldInfo newFieldLong = new MetadataFieldInfo(LONG_FIELD_ID, "BSM Field Long", - "BSM Field Description", FieldType.Long, new List() {1L, 2L}); - MetadataFieldInfo savedFieldLong = client.PutBsmField(GROUP_ID, newFieldLong); - Console.WriteLine( - $"Created new field: FieldId={savedFieldLong.FieldId}, FieldType={savedFieldLong.FieldType}, FieldName={savedFieldLong.FieldName}, FieldValues={string.Join(",", savedFieldLong.FieldValues)}"); - - //Create a new double field with no predefined values - MetadataFieldInfo newFieldDouble = new MetadataFieldInfo(DOUBLE_FIELD_ID, "BSM Field Double", - "BSM Field Description", FieldType.Double); - MetadataFieldInfo savedFielDouble = client.PutBsmField(GROUP_ID, newFieldDouble); - Console.WriteLine( - $"Created new field: FieldId={newFieldDouble.FieldId}, FieldType={newFieldDouble.FieldType}, FieldName={newFieldDouble.FieldName}"); - Console.WriteLine(); - - //Update string field - add new field value, remove an old one - savedFieldStr.FieldValues.Add("value 4"); - savedFieldStr.FieldValues.Remove("value 3"); - MetadataFieldInfo updatedField = client.PutBsmField(GROUP_ID, savedFieldStr); - Console.WriteLine( - $"Updated field: FieldId={updatedField.FieldId}, FieldType={updatedField.FieldType}, FieldName={updatedField.FieldName}, FieldValues={string.Join(",", updatedField.FieldValues)}"); - Console.WriteLine(); - - //Get the business-specific metadata registry for a specific group - BusinessSpecificMetadataInfo metadataInfo = client.BsmRegistry(GROUP_ID); - - Console.WriteLine("BusinessSpecificMetadataInfo:"); - //Print the registry for this group - foreach (MetadataGroupInfo groupInfo in metadataInfo.Groups) - { - Console.WriteLine( - $"GroupInfo: GroupId={groupInfo.GroupId}, GroupName={groupInfo.GroupName}"); - foreach (MetadataFieldInfo fieldInfo in groupInfo.Fields) - { - Console.WriteLine( - $" ---- FieldInfo: FieldId={fieldInfo.FieldId}, FieldType={fieldInfo.FieldType}, FieldName={fieldInfo.FieldName}"); - } - } - Console.WriteLine("--------------------------------------------------------------------------"); - Console.WriteLine(); - - //Create an Arkiv, Arkivdel and one Mappe - //Set VirksomhetsspesifikkeMetadata for the Mappe - var arkivskaper = new Arkivskaper("B67", "Jack Smith"); - var arkiv = new Arkiv("Arkiv - VirksomhetsspesifikkeMetadata Example"); - var arkivdel = new Arkivdel("Arkivdel - VirksomhetsspesifikkeMetadata Example"); - - var mappe = new Mappe("Mappe with VirksomhetsspesifikkeMetadata"); - - //Add three meta-data fields to the Mappe: - mappe.VirksomhetsspesifikkeMetadata.AddBsmFieldValues(GROUP_ID, STRING_FIELD_ID, "value 1", - "value 2"); - mappe.VirksomhetsspesifikkeMetadata.AddBsmFieldValues(GROUP_ID, DOUBLE_FIELD_ID, 1.2); - mappe.VirksomhetsspesifikkeMetadata.AddBsmFieldValues(GROUP_ID, LONG_FIELD_ID, 2L); - - var transactionResponse = client.Transaction() - .Save(arkiv) - .Save(arkivskaper) - .Link(arkiv.LinkArkivskaper(arkivskaper)) - .Save(arkivdel) - .Link(arkivdel.LinkArkiv(arkiv)) - .Save(mappe) - .Link(mappe.LinkArkivdel(arkivdel)) - .Commit(); - - //Get the saved Mappe - mappe = transactionResponse.Saved[mappe.Id] as Mappe; - - //Print the VirksomhetsspesifikkeMetadata of the Mappe - Console.WriteLine("Added VirksomhetsspesifikkeMetadata to folder:"); - BsmGroupsMap groupsMap = mappe.VirksomhetsspesifikkeMetadata; - foreach (var groupId in groupsMap.Keys) - { - BsmFieldsMap fieldsMap = mappe.VirksomhetsspesifikkeMetadata[groupId]; - foreach (var fieldId in fieldsMap.Keys) - { - BsmFieldValues values = fieldsMap[fieldId]; - Console.WriteLine( - $"GroupId={groupId}, FieldId={fieldId}, ValueType={values.Type}, Values=[{string.Join(",", values.Values)}]"); - } - } - Console.WriteLine(); - - //Update the VirksomhetsspesifikkeMetadata of the Mappe - - //Add one more string value to the string field - - //To add a new field value, simply add it to the set of values of the particular field - //Use the "AddBsmFieldValues" method, if you want to override the existing set of values with a new one - mappe.VirksomhetsspesifikkeMetadata[GROUP_ID][STRING_FIELD_ID].Values.Add("value 4"); - - //Remove one of the values of the double field - mappe.VirksomhetsspesifikkeMetadata.DeleteBsmFieldValue(GROUP_ID, DOUBLE_FIELD_ID, 2.6); - - //Completely remove the long field - mappe.VirksomhetsspesifikkeMetadata.DeleteBsmField(GROUP_ID, LONG_FIELD_ID); - - //It is also possible to remove a whole group: - //mappe.VirksomhetsspesifikkeMetadata.DeleteBsmGroup(groupIdentfier); - transactionResponse = client.Transaction() - .Save(mappe) - .Commit(); - - //Make query to fetch the Mappe - - QueryResponse queryResponse = client.Query("id=@id", 1) - .AddQueryParam("@id", mappe.Id) - .Execute(); - mappe = queryResponse.Results.First(); - - //Print the new VirksomhetsspesifikkeMetadata - Console.WriteLine("Updated VirksomhetsspesifikkeMetadata of folder:"); - groupsMap = mappe.VirksomhetsspesifikkeMetadata; - foreach (var groupId in groupsMap.Keys) - { - BsmFieldsMap fieldsMap = mappe.VirksomhetsspesifikkeMetadata[groupId]; - foreach (var fieldId in fieldsMap.Keys) - { - BsmFieldValues values = fieldsMap[fieldId]; - Console.WriteLine( - $"GroupId={groupId}, FieldId={fieldId}, ValueType={values.Type}, Values=[{string.Join(",", values.Values)}]"); - } - } - - Console.WriteLine(); - - - //Delete field - client.DeleteBsmField(GROUP_ID, LONG_FIELD_ID); - Console.WriteLine($"Deleted field with FieldId={LONG_FIELD_ID}"); - Console.WriteLine(); - - //Delete folder - client.Transaction().Delete(mappe).Commit(); - Console.WriteLine($"Deleted folder"); - Console.WriteLine(); - - //Delete group - client.DeleteBsmGroup(GROUP_ID); - Console.WriteLine($"Deleted group with GroupId={GROUP_ID}"); - Console.WriteLine(); - } - - private static void CodeListsSample() - { - List allCodeLists = client.CodeLists(); - - Console.WriteLine($"Code lists:{Environment.NewLine}"); - foreach (CodeList list in allCodeLists) - { - Console.WriteLine($"Code list: {list.Type}.{list.Field}"); - foreach (CodeValue codeValue in list.Values) - { - Console.WriteLine( - $" --- Code value: Code={codeValue.Code}, Name={codeValue.Name}, Description={codeValue.Description}"); - } - Console.WriteLine(); - } - Console.WriteLine(); - - //Create new list value for the code list Dokumenttype - Dokumenttype dokumenttype = new Dokumenttype(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), - "Description"); - client.PutCodeListValue(dokumenttype); - Console.WriteLine( - $"Created new code value: Code={dokumenttype.Code}, Name={dokumenttype.Name}, Description={dokumenttype.Description}"); - Console.WriteLine(); - - //Update list value - Dokumenttype updatedValue = new Dokumenttype(dokumenttype.Code, dokumenttype.Name, "New Description"); - client.PutCodeListValue(updatedValue); - Console.WriteLine( - $"Updated code value: Code={updatedValue.Code}, Name={updatedValue.Name}, Description={updatedValue.Description}"); - Console.WriteLine(); - - //Delete list value - client.DeleteCodeListValue(updatedValue); - Console.WriteLine($"Deleted code value"); - Console.WriteLine(); - } - } - - class Options - { - [Option("idpaddr", Required = true, HelpText = "Idp server address")] - public string IdpServerAddress { get; set; } - - [Option("clientid", Required = true, HelpText = "Idp Client Id")] - public string ClientId { get; set; } - - [Option("clientsecret", Required = true, HelpText = "Idp Client Secret")] - public string ClientSecret { get; set; } - - [Option("username", Required = true, HelpText = "Username")] - public string Username { get; set; } - - [Option("password", Required = true, HelpText = "Password")] - public string Password { get; set; } - - [Option("addr", Required = true, HelpText = "Server address")] - public string ServerAddress { get; set; } - - [Option("cert", HelpText = "Path to certificate file")] - public string CertificatePath { get; set; } - - [Option("certpass", HelpText = "Certificate password")] - public string CertificatePass { get; set; } - - [Option("testdoc", Required = true, HelpText = "Path to test file")] - public string TestDoc { get; set; } } } diff --git a/NoarkWsClientSample/NoarkWsClientSample/Samples.cs b/NoarkWsClientSample/NoarkWsClientSample/Samples.cs new file mode 100644 index 0000000..1f700e8 --- /dev/null +++ b/NoarkWsClientSample/NoarkWsClientSample/Samples.cs @@ -0,0 +1,674 @@ +using Documaster.WebApi.Client.Noark5; +using Documaster.WebApi.Client.Noark5.Client; +using Documaster.WebApi.Client.Noark5.NoarkEntities; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NoarkWsClientSample +{ + public class Samples + { + private readonly DocumasterClients documasterClients; + private readonly string testDoc; + + public Samples(Options options) + { + this.documasterClients = new DocumasterClients(options); + this.testDoc = options.TestDoc; + } + + public void JournalingSample() + { + Console.WriteLine($"Journaling example {Environment.NewLine}"); + NoarkClient client = documasterClients.getNoarkClient(); + + //Create a new Arkiv with an Arkivskaper + //When new objects are initialized, a temporary Id is assigned to them. + var newArkivskaper = new Arkivskaper("B7-23-W5", "John Smith"); + var newArkiv = new Arkiv("Arkiv"); + + var transactionResponse = client.Transaction() + .Save(newArkiv) + .Save(newArkivskaper) + .Link(newArkiv.LinkArkivskaper(newArkivskaper)) + .Commit(); + + //When the transaction is committed, the transaction response contains a map with saved objects. + //One can access the saved Arkiv by providing its temporary Id as a key to the map. + //Notice that arkiv.Id is the permanent Id of the Arkiv. + var arkiv = transactionResponse.Saved[newArkiv.Id] as Arkiv; + Console.WriteLine( + $"Created Arkiv: Id={arkiv.Id}, Tittel={arkiv.Tittel}, OpprettetDato={arkiv.OpprettetDato}"); + + //Update the description of the Arkiv and create a new Arkivdel in it + //Create a new Klassifikasjonssystem with one Klasse + //Set the new Klassifikasjonssystem as the primary Klassifikasjonssystem for the Arkivdel + arkiv.Beskrivelse = "Barnehage Arkiv"; + var newArkivdel = new Arkivdel("2007/8"); + var newKlassifikasjonssystem = new Klassifikasjonssystem("Barnehage"); + var newKlasse = new Klasse("01", "Tilbud"); + + transactionResponse = client.Transaction() + .Save(arkiv) + .Save(newArkivdel) + .Link(newArkivdel.LinkArkiv(arkiv)) + .Save(newKlassifikasjonssystem) + .Link(newArkivdel.LinkPrimaerKlassifikasjonssystem(newKlassifikasjonssystem)) + .Save(newKlasse) + .Link(newKlasse.LinkKlassifikasjonssystem(newKlassifikasjonssystem)) + .Commit(); + + arkiv = transactionResponse.Saved[arkiv.Id] as Arkiv; + Console.WriteLine($"Updated Arkiv: Id={arkiv.Id}, Beskrivelse={arkiv.Beskrivelse}"); + + var arkivdel = transactionResponse.Saved[newArkivdel.Id] as Arkivdel; + Console.WriteLine($"Created Arkivdel: Id={arkivdel.Id}, Tittel={arkivdel.Tittel}"); + + var klassifikasjonssystemId = transactionResponse.Saved[newKlassifikasjonssystem.Id].Id; + var klasseId = transactionResponse.Saved[newKlasse.Id].Id; + + //Create a screening code + Skjerming newSkjerming = new Skjerming(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), "Description", + "Authority"); + Skjerming skjerming = client.PutCodeListValue(newSkjerming); + + //Screen the Arkivdel + arkivdel.Skjerming = skjerming; + transactionResponse = client.Transaction() + .Save(arkivdel) + .Commit(); + + //Find the Arkivdel by id + //By default the service will return null values for all screened fields of screened objects + //To see the values of screened fields call SetPublicUse(false) + var queryResults = client.Query("id=@arkivdelId", 10) + .AddQueryParam("@arkivdelId", arkivdel.Id) + .Execute(); + Console.WriteLine($"Found {queryResults.Results.Count()} Arkivdel object(s) with Id {arkivdel.Id}"); + + //Print a screened field: + arkivdel = queryResults.Results.First(); + Console.WriteLine($"Tittel of Arkivdel is masked: {arkivdel.Tittel}"); + + //For convenience, objects in query and transaction responses contain the id's of many-to-one reference fields + Console.WriteLine($"Arkivdel.RefArkiv: {arkivdel.RefArkiv}"); + Console.WriteLine($"Arkivdel.RefPrimaerKlassifikasjonssystem: {arkivdel.RefPrimaerKlassifikasjonssystem}"); + + //Create two other Klassifikasjonssystem objects and link them to the Arkivdel as secondary Klassifikasjonssystem + var sekundaerKlassifikasjonssystemSkole = new Klassifikasjonssystem("Skole"); + var klasseInSekundaerKlassifikasjonssystemSkole = new Klasse("07", "Report"); + var sekundaerKlassifikasjonssystem2 = new Klassifikasjonssystem("EOP"); + + transactionResponse = client.Transaction() + .Save(sekundaerKlassifikasjonssystemSkole) + .Save(klasseInSekundaerKlassifikasjonssystemSkole) + .Link(sekundaerKlassifikasjonssystemSkole.LinkKlasse(klasseInSekundaerKlassifikasjonssystemSkole)) + .Save(sekundaerKlassifikasjonssystem2) + .Link(arkivdel.LinkSekundaerKlassifikasjonssystem(sekundaerKlassifikasjonssystemSkole, + sekundaerKlassifikasjonssystem2)) + .Commit(); + + //We need the id of the saved Klasse for the next transactions + var sekundaerKlasseId = + transactionResponse.Saved[klasseInSekundaerKlassifikasjonssystemSkole.Id].Id; + + //Create a new administrativEnhet value + AdministrativEnhet newAdministrativEnhet = + new AdministrativEnhet(Guid.NewGuid().ToString(), Guid.NewGuid().ToString()); + AdministrativEnhet administrativEnhet = client.PutCodeListValue(newAdministrativEnhet); + + //Create a new Saksmappe in the Arkivdel + //The new Saksmappe needs to have a Klasse in the primary Klassifikasjonssystem of the Arkivdel + //Also link the Saksmappe to a secondary Klasse + var newSaksmappe = new Saksmappe("Tilbud (Smith, John)", administrativEnhet); + var newSakspart = new Sakspart("Alice", "internal"); + + var savedObjects = client.Transaction() + .Save(newSaksmappe) + .Link(newSaksmappe.LinkArkivdel(arkivdel)) + .Link(newSaksmappe.LinkPrimaerKlasse(klasseId)) + .Link(newSaksmappe.LinkSekundaerKlasse(sekundaerKlasseId)) + .Save(newSakspart) + .Link(newSaksmappe.LinkSakspart(newSakspart)) + .Commit() + .Saved; + + var saksmappe = savedObjects[newSaksmappe.Id] as Saksmappe; + Console.WriteLine($"Created Saksmappe: Id={saksmappe.Id}, Saksdato: {saksmappe.Saksdato}"); + + //Create another Klasse + //Unlink the Saksmappe from its Klasse and link it to the new Klasse + var anotherKlasse = new Klasse("02", "Klage"); + + client.Transaction() + .Save(anotherKlasse) + .Link(anotherKlasse.LinkKlassifikasjonssystem(klassifikasjonssystemId)) + .Unlink(saksmappe.UnlinkPrimaerKlasse(klasseId)) + .Link(saksmappe.LinkPrimaerKlasse(anotherKlasse)) + .Commit(); + Console.WriteLine( + $"Unlinked Saksmappe wiht Id {saksmappe.Id} from Klasse '{newKlasse.Tittel}' and linked it to Klasse '{anotherKlasse.Tittel}'"); + + //Find all available codes for journalstatus in Journalpost + var journalstatusCodeList = client.CodeLists(type: "Journalpost", field: "journalstatus").First(); + Console.WriteLine($"CodeList list for {journalstatusCodeList.Type}.{journalstatusCodeList.Field}:"); + foreach (var code in journalstatusCodeList.Values) + { + Console.WriteLine($" Code={code.Code}, Name={code.Name}"); + } + + //Create a new Journalpost in the Saksmappe + //Create an EksternId object and link it to the Journalpost + //Create a new Korrespondansepart and link it to the Journalpost + //Create a Noekkelord (keyword) object and link it to the Journalpost + var newJournalpost = new Journalpost("Tilbud (Smith, John, Godkjent)", Journalposttype.UTGAAENDE_DOKUMENT) + { + Journalaar = 2007, + Journalsekvensnummer = 46 + }; + + var newEksternId = new EksternId("External System", Guid.NewGuid().ToString()); + var newKorrespondansepart = new Korrespondansepart(Korrespondanseparttype.INTERN_MOTTAKER, "John Smith"); + var newNoekkelord = new Noekkelord("keyword"); + + savedObjects = client.Transaction() + .Save(newJournalpost) + .Link(newJournalpost.LinkMappe(saksmappe)) + .Save(newEksternId) + .Link(newJournalpost.LinkEksternId(newEksternId)) + .Save(newKorrespondansepart) + .Link(newJournalpost.LinkKorrespondansepart(newKorrespondansepart)) + .Save(newNoekkelord) + .Link(newNoekkelord.LinkRegistrering(newJournalpost)) + .Commit() + .Saved; + + var journalPost = savedObjects[newJournalpost.Id] as Journalpost; + Console.WriteLine( + $"Created Journalpost: Id={journalPost.Id}, Tittel={journalPost.Tittel}, Journalstatus={journalPost.Journalstatus.Code}"); + + //Find the Journalpost by the eksternID value + var journalpstQueryResults = client.Query("refEksternId.eksternID=@eksternId", 10) + .AddQueryParam("@eksternId", newEksternId.EksternID) + .Execute(); + Console.WriteLine( + $"Found {journalpstQueryResults.Results.Count()} Journalpost objects with eksternID {newEksternId.EksternID}"); + + //Upload a file + Dokumentfil dokumentfil; + using (var inputStream = File.OpenRead(testDoc)) + { + dokumentfil = client.Upload(inputStream, "godkjenning.pdf"); + } + Console.WriteLine($"Uploaded file {testDoc}"); + + //Create a new value for Dokumenttype + Dokumenttype newDokumenttype = new Dokumenttype(Guid.NewGuid().ToString(), Guid.NewGuid().ToString()); + Dokumenttype dokumenttype = client.PutCodeListValue(newDokumenttype); + + //Create a new Dokument and Dokumentversjon using the uploaded file + var newDokument = new Dokument(dokumenttype, "Tilbud (Smith, John, Godkjent)", + TilknyttetRegistreringSom.HOVEDDOKUMENT); + var newDokumentversjon = new Dokumentversjon(Variantformat.PRODUKSJONSFORMAT, ".pdf", dokumentfil); + + savedObjects = client.Transaction() + .Save(newDokument) + .Link(newDokument.LinkRegistrering(journalPost)) + .Save(newDokumentversjon) + .Link(newDokumentversjon.LinkDokument(newDokument)) + .Commit() + .Saved; + + var dokumentversjon = savedObjects[newDokumentversjon.Id] as Dokumentversjon; + Console.WriteLine( + $"Created Dokumentversjon: Id={dokumentversjon.Id}, Versjonsnummer: {dokumentversjon.Versjonsnummer}, Filstoerrelse: {dokumentversjon.Filstoerrelse}"); + + //Download the Dokumentversjon file + var downloadPath = Path.GetTempFileName(); + using (var outputStream = File.Create(downloadPath)) + { + client.Download(dokumentversjon.Dokumentfil, outputStream); + } + Console.WriteLine($"Downloaded file {downloadPath}"); + + //Find all dokument objects in a Saksmappe called "Tilbud (Smith, John)" + //Results should be ordered by creation date in descending order + var queryResponse = client.Query("refRegistrering.refMappe.tittel=@saksmappeTittel", 50) + .AddQueryParam("@saksmappeTittel", "Tilbud (Smith, John)") + .AddSortOrder("opprettetDato", Order.Descending) + .Execute(); + Console.WriteLine( + $"Query returned {queryResponse.Results.Count()} Dokument objects in Saksmappe objects called 'Tilbud (Smith, John)'"); + Console.WriteLine($"More results available: {queryResponse.HasMore}"); + + //Delete the DokumentVersjon by id + client.Transaction().Delete(dokumentversjon.Id).Commit(); + Console.WriteLine($"Deleted Dokumentversjon with Id {dokumentversjon.Id}"); + Console.WriteLine(); + } + + public void ArchiveSample() + { + Console.WriteLine($"Archive example {Environment.NewLine}"); + NoarkClient client = documasterClients.getNoarkClient(); + + //Create a new Arkiv with an Arkivskaper + //Create a new Arkivdel in the Arkiv + var newArkivskaper = new Arkivskaper("B7-23-W5", "John Smith"); + var newArkiv = new Arkiv("Arkiv"); + var newArkivdel = new Arkivdel("2007/8"); + + var transactionResponse = client.Transaction() + .Save(newArkiv) + .Save(newArkivskaper) + .Save(newArkivdel) + .Link(newArkiv.LinkArkivskaper(newArkivskaper)) + .Link(newArkivdel.LinkArkiv(newArkiv)) + .Commit(); + + var arkiv = transactionResponse.Saved[newArkiv.Id] as Arkiv; + Console.WriteLine( + $"Created Arkiv: Id={arkiv.Id}, Arkivstatus={arkiv.Arkivstatus.Code}, OpprettetDato={arkiv.OpprettetDato}"); + + var arkivdel = transactionResponse.Saved[newArkivdel.Id] as Arkivdel; + Console.WriteLine($"Created Arkivdel: Id={arkivdel.Id}, Arkivdelstatus={arkivdel.Arkivdelstatus.Code}"); + + //Get all available values for the Mappetype code list + var mappetypeList = client.CodeLists("Mappe", "mappetype").First(); + if (mappetypeList.Values.Count == 0) + { + Console.WriteLine( + "Can not create an instance of Mappe because there are not available values in the Mappetype code list!"); + return; + } + var mappetypeCode = mappetypeList.Values.First().Code; + + //Create a new Mappe + var newMappe = new Mappe("Barnehage Tilbud") + { + Beskrivelse = "Mappe Beskrivelse", + Mappetype = new Mappetype(mappetypeCode) + }; + + transactionResponse = client.Transaction() + .Save(newMappe) + .Link(newMappe.LinkArkivdel(arkivdel)) + .Commit(); + + var mappe = transactionResponse.Saved[newMappe.Id] as Mappe; + Console.WriteLine($"Created Mappe: Id={mappe.Id}, Tittel: {mappe.Tittel}"); + + //Create a child Mappe in the Mappe + var newBarnMappe = new Mappe("Tilbud (Smith, John)"); + + var savedObjects = client.Transaction() + .Save(newBarnMappe) + .Link(newBarnMappe.LinkForelderMappe(mappe)) + .Commit() + .Saved; + + var barnMappe = savedObjects[newBarnMappe.Id] as Mappe; + Console.WriteLine( + $"Created a new Mappe (Id={barnMappe.Id}, Tittel={barnMappe.Tittel}) in Mappe with Id {mappe.Id}"); + + //Find all children of the Mappe + var queryResults = client.Query("refForelderMappe.id=@forelderMappeId", 10) + .AddQueryParam("@forelderMappeId", mappe.Id) + .Execute(); + Console.WriteLine($"Found {queryResults.Results.Count()} Mappe objects in Mappe with Id {mappe.Id}"); + + //Create a new Basisregistrering in the child Mappe + //Link one Korrespondansepart to the Basisregistrering + var newBasisregistrering = new Basisregistrering("Tilbud (Smith, John, Godkjent)"); + var newKorrespondansepart = new Korrespondansepart(Korrespondanseparttype.MOTTAKER, "John Smith"); + + savedObjects = client.Transaction() + .Save(newBasisregistrering) + .Save(newKorrespondansepart) + .Link(newBasisregistrering.LinkMappe(barnMappe)) + .Link(newBasisregistrering.LinkKorrespondansepart(newKorrespondansepart)) + .Commit() + .Saved; + + var basisregistrering = savedObjects[newBasisregistrering.Id] as Basisregistrering; + Console.WriteLine( + $"Created Basisregistrering: Id={basisregistrering.Id}, Tittel={basisregistrering.Tittel}"); + + //Upload a file + Dokumentfil dokumentfil; + using (var inputStream = File.OpenRead(testDoc)) + { + dokumentfil = client.Upload(inputStream, "godkjenning.pdf"); + } + Console.WriteLine($"Uploaded file {testDoc}"); + + //Get available values for the Dokumenttype code list + var dokumenttypeList = client.CodeLists("Dokument", "dokumenttype").First(); + if (dokumenttypeList.Values.Count == 0) + { + Console.WriteLine( + "Can not create an instance of Dokument because there are not available values in the Dokumenttype code list!"); + return; + } + var dokumenttypeCode = dokumenttypeList.Values.First().Code; + + //Create a new Dokument and Dokumentversjon using the uploaded file + //Link the Dokument to the Basisregistrering + var newDokument = new Dokument(new Dokumenttype(dokumenttypeCode), "Tilbud (Smith, John, Godkjent)", + TilknyttetRegistreringSom.HOVEDDOKUMENT); + var newDokumentversjon = new Dokumentversjon(Variantformat.PRODUKSJONSFORMAT, ".pdf", dokumentfil); + + savedObjects = client.Transaction() + .Save(newDokument) + .Link(newDokument.LinkRegistrering(basisregistrering)) + .Save(newDokumentversjon) + .Link(newDokumentversjon.LinkDokument(newDokument)) + .Commit() + .Saved; + + var dokumentversjon = savedObjects[newDokumentversjon.Id] as Dokumentversjon; + Console.WriteLine( + $"Created Dokumentversjon: Id={dokumentversjon.Id}, Versjonsnummer: {dokumentversjon.Versjonsnummer}, Filstoerrelse: {dokumentversjon.Filstoerrelse}"); + } + + public void MeetingAndBoardHandlingDataSample() + { + Console.WriteLine($"Meeting and board handling data example {Environment.NewLine}"); + NoarkClient client = documasterClients.getNoarkClient(); + + //Create a new Arkiv with an Arkivskaper + //Create a new Arkivdel in the Arkiv + var newArkivskaper = new Arkivskaper("B7-23-W5", "John Smith"); + var newArkiv = new Arkiv("Arkiv"); + var newArkivdel = new Arkivdel("2007/8"); + + var transactionResponse = client.Transaction() + .Save(newArkiv) + .Save(newArkivskaper) + .Save(newArkivdel) + .Link(newArkiv.LinkArkivskaper(newArkivskaper)) + .Link(newArkivdel.LinkArkiv(newArkiv)) + .Commit(); + + var arkiv = transactionResponse.Saved[newArkiv.Id] as Arkiv; + Console.WriteLine( + $"Created Arkiv: Id={arkiv.Id}, Arkivstatus={arkiv.Arkivstatus.Code}, OpprettetDato={arkiv.OpprettetDato}"); + + var arkivdel = transactionResponse.Saved[newArkivdel.Id] as Arkivdel; + Console.WriteLine($"Created Arkivdel: Id={arkivdel.Id}, Arkivdelstatus={arkivdel.Arkivdelstatus.Code}"); + + //Create a new Moetemappe and Moetedeltaker + Moetemappe newMappe = new Moetemappe("Moetemappe Tittel", "Moetenummer", "Utvalg"); + Moetedeltaker moetedeltaker = new Moetedeltaker("Moetedeltaker Navn"); + + transactionResponse = client.Transaction() + .Save(newMappe) + .Link(newMappe.LinkArkivdel(arkivdel)) + .Save(moetedeltaker) + .Link(moetedeltaker.LinkMappe(newMappe)) + .Commit(); + + var mappe = transactionResponse.Saved[newMappe.Id] as Moetemappe; + Console.WriteLine($"Created Mappe: Id={mappe.Id}, Tittel={mappe.Tittel}"); + Console.WriteLine($"Created Moetedeltaker: Navn={moetedeltaker.Navn}"); + + //Create a new AdministrativEnhett code list value + AdministrativEnhet newAdministrativEnhet = + new AdministrativEnhet(Guid.NewGuid().ToString(), Guid.NewGuid().ToString()); + AdministrativEnhet administrativEnhet = client.PutCodeListValue(newAdministrativEnhet); + + //Create a new Moeteregistrering + Moeteregistrering newMoeteregistrering = new Moeteregistrering("Tittel", "Saksbehandler", + administrativEnhet, Moeteregistreringstype.MOETEINNKALLING); + transactionResponse = client.Transaction() + .Save(newMoeteregistrering) + .Link(newMoeteregistrering.LinkMappe(mappe)) + .Commit(); + + var moeteregistrering = transactionResponse.Saved[newMoeteregistrering.Id] as Moeteregistrering; + Console.WriteLine( + $"Created Moeteregistrering: Id={moeteregistrering.Id}, Tittel={moeteregistrering.Tittel}"); + ; + + //Upload a file + Dokumentfil dokumentfil; + using (var inputStream = File.OpenRead(testDoc)) + { + dokumentfil = client.Upload(inputStream, "godkjenning.pdf"); + } + Console.WriteLine($"Uploaded file {testDoc}"); + + //Create a new Dokumenttype code list value + Dokumenttype newDokumenttype = new Dokumenttype(Guid.NewGuid().ToString(), Guid.NewGuid().ToString()); + Dokumenttype dokumenttype = client.PutCodeListValue(newDokumenttype); + + //Link the Dokument to the Moeteregistrering + var newDokument = new Dokument(dokumenttype, "Tilbud (Smith, John, Godkjent)", + TilknyttetRegistreringSom.HOVEDDOKUMENT); + var newDokumentversjon = new Dokumentversjon(Variantformat.PRODUKSJONSFORMAT, ".pdf", dokumentfil); + + transactionResponse = client.Transaction() + .Save(newDokument) + .Link(newDokument.LinkRegistrering(moeteregistrering)) + .Save(newDokumentversjon) + .Link(newDokumentversjon.LinkDokument(newDokument)) + .Commit(); + + var dokumentversjon = transactionResponse.Saved[newDokumentversjon.Id] as Dokumentversjon; + Console.WriteLine( + $"Created Dokumentversjon: Id={dokumentversjon.Id}, Versjonsnummer: {dokumentversjon.Versjonsnummer}, Filstoerrelse: {dokumentversjon.Filstoerrelse}"); + Console.WriteLine(); + } + + public void BusinessSpecificMetadataSample() + { + NoarkClient client = documasterClients.getNoarkClient(); + + string GROUP_ID = $"gr-{Guid.NewGuid().ToString()}"; + string STRING_FIELD_ID = $"f-{Guid.NewGuid().ToString()}"; + string DOUBLE_FIELD_ID = $"f-{Guid.NewGuid().ToString()}"; + string LONG_FIELD_ID = $"f-{Guid.NewGuid().ToString()}"; + + //Create a business-specific metadata group + MetadataGroupInfo newGroup = new MetadataGroupInfo(GROUP_ID, "BSM Group Name", "BSM Group Description"); + MetadataGroupInfo savedGroup = client.PutBsmGroup(newGroup); + Console.WriteLine( + $"Created new group: GroupId={savedGroup.GroupId}, GroupDescription={savedGroup.GroupDescription}, GroupName={savedGroup.GroupName}"); + Console.WriteLine(); + + //Create a new string field with predefined values "value 1", "value 2" and "value 3" + MetadataFieldInfo newFieldStr = new MetadataFieldInfo(STRING_FIELD_ID, "BSM Field String", + "BSM Field Description", FieldType.String, new List() { "value 1", "value 2", "value 3" }); + MetadataFieldInfo savedFieldStr = client.PutBsmField(GROUP_ID, newFieldStr); + Console.WriteLine( + $"Created new field: FieldId={savedFieldStr.FieldId}, FieldType={savedFieldStr.FieldType}, FieldName={savedFieldStr.FieldName}, FieldValues={string.Join(",", savedFieldStr.FieldValues)}"); + Console.WriteLine(); + + //Create a new long field with predefined values 1 and 2 + MetadataFieldInfo newFieldLong = new MetadataFieldInfo(LONG_FIELD_ID, "BSM Field Long", + "BSM Field Description", FieldType.Long, new List() { 1L, 2L }); + MetadataFieldInfo savedFieldLong = client.PutBsmField(GROUP_ID, newFieldLong); + Console.WriteLine( + $"Created new field: FieldId={savedFieldLong.FieldId}, FieldType={savedFieldLong.FieldType}, FieldName={savedFieldLong.FieldName}, FieldValues={string.Join(",", savedFieldLong.FieldValues)}"); + + //Create a new double field with no predefined values + MetadataFieldInfo newFieldDouble = new MetadataFieldInfo(DOUBLE_FIELD_ID, "BSM Field Double", + "BSM Field Description", FieldType.Double); + MetadataFieldInfo savedFielDouble = client.PutBsmField(GROUP_ID, newFieldDouble); + Console.WriteLine( + $"Created new field: FieldId={newFieldDouble.FieldId}, FieldType={newFieldDouble.FieldType}, FieldName={newFieldDouble.FieldName}"); + Console.WriteLine(); + + //Update string field - add new field value, remove an old one + savedFieldStr.FieldValues.Add("value 4"); + savedFieldStr.FieldValues.Remove("value 3"); + MetadataFieldInfo updatedField = client.PutBsmField(GROUP_ID, savedFieldStr); + Console.WriteLine( + $"Updated field: FieldId={updatedField.FieldId}, FieldType={updatedField.FieldType}, FieldName={updatedField.FieldName}, FieldValues={string.Join(",", updatedField.FieldValues)}"); + Console.WriteLine(); + + //Get the business-specific metadata registry for a specific group + BusinessSpecificMetadataInfo metadataInfo = client.BsmRegistry(GROUP_ID); + + Console.WriteLine("BusinessSpecificMetadataInfo:"); + //Print the registry for this group + foreach (MetadataGroupInfo groupInfo in metadataInfo.Groups) + { + Console.WriteLine( + $"GroupInfo: GroupId={groupInfo.GroupId}, GroupName={groupInfo.GroupName}"); + foreach (MetadataFieldInfo fieldInfo in groupInfo.Fields) + { + Console.WriteLine( + $" ---- FieldInfo: FieldId={fieldInfo.FieldId}, FieldType={fieldInfo.FieldType}, FieldName={fieldInfo.FieldName}"); + } + } + Console.WriteLine("--------------------------------------------------------------------------"); + Console.WriteLine(); + + //Create an Arkiv, Arkivdel and one Mappe + //Set VirksomhetsspesifikkeMetadata for the Mappe + var arkivskaper = new Arkivskaper("B67", "Jack Smith"); + var arkiv = new Arkiv("Arkiv - VirksomhetsspesifikkeMetadata Example"); + var arkivdel = new Arkivdel("Arkivdel - VirksomhetsspesifikkeMetadata Example"); + + var mappe = new Mappe("Mappe with VirksomhetsspesifikkeMetadata"); + + //Add three meta-data fields to the Mappe: + mappe.VirksomhetsspesifikkeMetadata.AddBsmFieldValues(GROUP_ID, STRING_FIELD_ID, "value 1", + "value 2"); + mappe.VirksomhetsspesifikkeMetadata.AddBsmFieldValues(GROUP_ID, DOUBLE_FIELD_ID, 1.2); + mappe.VirksomhetsspesifikkeMetadata.AddBsmFieldValues(GROUP_ID, LONG_FIELD_ID, 2L); + + var transactionResponse = client.Transaction() + .Save(arkiv) + .Save(arkivskaper) + .Link(arkiv.LinkArkivskaper(arkivskaper)) + .Save(arkivdel) + .Link(arkivdel.LinkArkiv(arkiv)) + .Save(mappe) + .Link(mappe.LinkArkivdel(arkivdel)) + .Commit(); + + //Get the saved Mappe + mappe = transactionResponse.Saved[mappe.Id] as Mappe; + + //Print the VirksomhetsspesifikkeMetadata of the Mappe + Console.WriteLine("Added VirksomhetsspesifikkeMetadata to folder:"); + BsmGroupsMap groupsMap = mappe.VirksomhetsspesifikkeMetadata; + foreach (var groupId in groupsMap.Keys) + { + BsmFieldsMap fieldsMap = mappe.VirksomhetsspesifikkeMetadata[groupId]; + foreach (var fieldId in fieldsMap.Keys) + { + BsmFieldValues values = fieldsMap[fieldId]; + Console.WriteLine( + $"GroupId={groupId}, FieldId={fieldId}, ValueType={values.Type}, Values=[{string.Join(",", values.Values)}]"); + } + } + Console.WriteLine(); + + //Update the VirksomhetsspesifikkeMetadata of the Mappe + + //Add one more string value to the string field + + //To add a new field value, simply add it to the set of values of the particular field + //Use the "AddBsmFieldValues" method, if you want to override the existing set of values with a new one + mappe.VirksomhetsspesifikkeMetadata[GROUP_ID][STRING_FIELD_ID].Values.Add("value 4"); + + //Remove one of the values of the double field + mappe.VirksomhetsspesifikkeMetadata.DeleteBsmFieldValue(GROUP_ID, DOUBLE_FIELD_ID, 2.6); + + //Completely remove the long field + mappe.VirksomhetsspesifikkeMetadata.DeleteBsmField(GROUP_ID, LONG_FIELD_ID); + + //It is also possible to remove a whole group: + //mappe.VirksomhetsspesifikkeMetadata.DeleteBsmGroup(groupIdentfier); + transactionResponse = client.Transaction() + .Save(mappe) + .Commit(); + + //Make query to fetch the Mappe + + QueryResponse queryResponse = client.Query("id=@id", 1) + .AddQueryParam("@id", mappe.Id) + .Execute(); + mappe = queryResponse.Results.First(); + + //Print the new VirksomhetsspesifikkeMetadata + Console.WriteLine("Updated VirksomhetsspesifikkeMetadata of folder:"); + groupsMap = mappe.VirksomhetsspesifikkeMetadata; + foreach (var groupId in groupsMap.Keys) + { + BsmFieldsMap fieldsMap = mappe.VirksomhetsspesifikkeMetadata[groupId]; + foreach (var fieldId in fieldsMap.Keys) + { + BsmFieldValues values = fieldsMap[fieldId]; + Console.WriteLine( + $"GroupId={groupId}, FieldId={fieldId}, ValueType={values.Type}, Values=[{string.Join(",", values.Values)}]"); + } + } + + Console.WriteLine(); + + + //Delete field + client.DeleteBsmField(GROUP_ID, LONG_FIELD_ID); + Console.WriteLine($"Deleted field with FieldId={LONG_FIELD_ID}"); + Console.WriteLine(); + + //Delete folder + client.Transaction().Delete(mappe).Commit(); + Console.WriteLine($"Deleted folder"); + Console.WriteLine(); + + //Delete group + client.DeleteBsmGroup(GROUP_ID); + Console.WriteLine($"Deleted group with GroupId={GROUP_ID}"); + Console.WriteLine(); + } + + public void CodeListsSample() + { + NoarkClient client = documasterClients.getNoarkClient(); + + List allCodeLists = client.CodeLists(); + + Console.WriteLine($"Code lists:{Environment.NewLine}"); + foreach (CodeList list in allCodeLists) + { + Console.WriteLine($"Code list: {list.Type}.{list.Field}"); + foreach (CodeValue codeValue in list.Values) + { + Console.WriteLine( + $" --- Code value: Code={codeValue.Code}, Name={codeValue.Name}, Description={codeValue.Description}"); + } + Console.WriteLine(); + } + Console.WriteLine(); + + //Create new list value for the code list Dokumenttype + Dokumenttype dokumenttype = new Dokumenttype(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), + "Description"); + client.PutCodeListValue(dokumenttype); + Console.WriteLine( + $"Created new code value: Code={dokumenttype.Code}, Name={dokumenttype.Name}, Description={dokumenttype.Description}"); + Console.WriteLine(); + + //Update list value + Dokumenttype updatedValue = new Dokumenttype(dokumenttype.Code, dokumenttype.Name, "New Description"); + client.PutCodeListValue(updatedValue); + Console.WriteLine( + $"Updated code value: Code={updatedValue.Code}, Name={updatedValue.Name}, Description={updatedValue.Description}"); + Console.WriteLine(); + + //Delete list value + client.DeleteCodeListValue(updatedValue); + Console.WriteLine($"Deleted code value"); + Console.WriteLine(); + } + } +} diff --git a/NoarkWsClientSample/NoarkWsClientSample/eByggesak/DocumasterToEByggesakSubmitter.cs b/NoarkWsClientSample/NoarkWsClientSample/eByggesak/DocumasterToEByggesakSubmitter.cs new file mode 100644 index 0000000..550b981 --- /dev/null +++ b/NoarkWsClientSample/NoarkWsClientSample/eByggesak/DocumasterToEByggesakSubmitter.cs @@ -0,0 +1,128 @@ +using Documaster.WebApi.Client.Noark5.Client; +using Documaster.WebApi.Client.Noark5.NoarkEntities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NoarkWsClientSample.eByggesak +{ + public class DocumasterToEByggesakSubmitter + { + private readonly DocumasterClients documasterClients; + + public DocumasterToEByggesakSubmitter(DocumasterClients documasterClients) + { + this.documasterClients = documasterClients; + } + + /// + /// Searches for registry entries created after fromDate in a series with title seriesTitle + /// + /// A dictionary. Each found registry entries is mapped to the list of its external id objects. + public Dictionary> SearchForRegistryEntriesInSeries(DateTime fromDate, string seriesTitle) + { + Arkivdel series = FindSeriesByTitle(seriesTitle); + return FetchRegistryEntries(fromDate, series.Id); + } + + private Dictionary> FetchRegistryEntries(DateTime fromDate, string seriesId) + { + var noarkClient = documasterClients.getNoarkClient(); + + // First build a paginated-query to fetch the required registry entries + + const int limit = 50; + var offset = 0; + var hasMore = true; + Dictionary regisitryEntriesById = new Dictionary(); + + while (hasMore) + { + QueryResponse response = + noarkClient.Query("refMappe.refArkivdel.id=@seriesId && opprettetDato=[@from:@to]", limit) + .AddQueryParam("@seriesId", seriesId) + .AddQueryParam("@from", fromDate) + .AddQueryParam("@to", DateTime.Now) + .SetOffset(offset) + .Execute(); + + hasMore = response.HasMore; + offset += limit; + + foreach(var registryEntry in response.Results) + { + regisitryEntriesById.Add(registryEntry.Id, registryEntry); + } + } + + // Prepare the dictionary which is to be returned by the method. + // We are going to find all external id objects related to each registry entry. + var regisitryEntriesToExternalIds = new Dictionary>(); + foreach(var registryEntryId in regisitryEntriesById.Keys) + { + regisitryEntriesToExternalIds.Add(regisitryEntriesById[registryEntryId], new List()); + } + + // Build a query that finds the external id objects linked to the registry entries. + + if (regisitryEntriesById.Keys.Count > 0) + { + var queryStrings = new string[regisitryEntriesById.Keys.Count]; + var queryParams = new List(); + + for (var i = 0; i < regisitryEntriesById.Keys.Count; i++) + { + var queryParamName = $"@regEntryId{i}"; + queryParams.Add(new QueryParam(queryParamName, regisitryEntriesById.Keys.ElementAt(i))); + queryStrings[i] = $"refRegistrering.id={queryParamName}"; + } + + var queryString = string.Join(" || ", queryStrings); + + Query query = noarkClient.Query(queryString, limit); + queryParams.ForEach(queryParam => query.AddQueryParams(queryParam)); + + offset = 0; + hasMore = true; + while (hasMore) + { + QueryResponse response = query.SetOffset(offset).Execute(); + hasMore = response.HasMore; + offset += limit; + + foreach (EksternId eksternId in response.Results) + { + var registryEntryId = eksternId.RefRegistrering; + Journalpost registryEntry = regisitryEntriesById[registryEntryId]; + regisitryEntriesToExternalIds[registryEntry].Add(eksternId); + } + } + } + + return regisitryEntriesToExternalIds; + } + + private Arkivdel FindSeriesByTitle(string title) + { + var noarkClient = this.documasterClients.getNoarkClient(); + + QueryResponse queryResponse = noarkClient.Query("tittel=@title", 1) + .AddQueryParam("@title", title) + .Execute(); + + if (!queryResponse.Results.Any()) + { + return null; + } + + if (queryResponse.HasMore) + { + Console.WriteLine($"Warning: Found more than one series with title '{title}'!"); + } + + return queryResponse.Results.First(); + } + } +} diff --git a/NoarkWsClientSample/NoarkWsClientSample/eByggesak/EByggesakIntegrationSample.cs b/NoarkWsClientSample/NoarkWsClientSample/eByggesak/EByggesakIntegrationSample.cs new file mode 100644 index 0000000..c9e778b --- /dev/null +++ b/NoarkWsClientSample/NoarkWsClientSample/eByggesak/EByggesakIntegrationSample.cs @@ -0,0 +1,31 @@ +using Documaster.WebApi.Client.Noark5.Client; +using Documaster.WebApi.Client.Noark5.NoarkEntities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NoarkWsClientSample.eByggesak +{ + public class EByggesakIntegrationSample + { + private readonly DocumasterToEByggesakSubmitter eByggesakSubmitter; + private readonly EByggesakToDocumasterSubmitter documasterSubmitter; + + public EByggesakIntegrationSample(Options options) + { + DocumasterClients documasterClients = new DocumasterClients(options); + this.eByggesakSubmitter = new DocumasterToEByggesakSubmitter(documasterClients); + this.documasterSubmitter = new EByggesakToDocumasterSubmitter(documasterClients, options.TestDoc); + } + + public void ExecuteSample() + { + var seriesTitle = "eByggesak"; + this.documasterSubmitter.SubmitToDocumaster(seriesTitle); + //var registryEntries = + // this.eByggesakSubmitter.SearchForRegistryEntriesInSeries(DateTime.Now.AddDays(-5), seriesTitle); + } + } +} diff --git a/NoarkWsClientSample/NoarkWsClientSample/eByggesak/EByggesakToDocumasterSubmitter.cs b/NoarkWsClientSample/NoarkWsClientSample/eByggesak/EByggesakToDocumasterSubmitter.cs new file mode 100644 index 0000000..33311c2 --- /dev/null +++ b/NoarkWsClientSample/NoarkWsClientSample/eByggesak/EByggesakToDocumasterSubmitter.cs @@ -0,0 +1,300 @@ +using CommandLine; +using Documaster.WebApi.Client.IDP; +using Documaster.WebApi.Client.IDP.Oauth2; +using Documaster.WebApi.Client.Noark5; +using Documaster.WebApi.Client.Noark5.Client; +using Documaster.WebApi.Client.Noark5.NoarkEntities; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NoarkWsClientSample.eByggesak +{ + public class EByggesakToDocumasterSubmitter + { + private const string EXTERNAL_SYSTEM = "eByggesak"; + + private readonly DocumasterClients documasterClients; + private string filePath; + + public EByggesakToDocumasterSubmitter(DocumasterClients documasterClients, string filePath) + { + this.documasterClients = documasterClients; + this.filePath = filePath; + } + + /// + /// Submits data to Documaster. Searches for an existing case file by the eByggesak id or creates a new one. + /// Creates a registry entry with document description and a document version. + /// + /// + public void SubmitToDocumaster(string seriesTitle) + { + NoarkClient noarkClient = this.documasterClients.getNoarkClient(); + + Arkivdel series = FindSeriesByTitle(seriesTitle); + + if (series == null) + { + Console.WriteLine($"Did not find series with title '{seriesTitle}'!"); + return; + } + + Saksmappe caseFile = GetOrCreateCaseFile(series.Id, series.RefPrimaerKlassifikasjonssystem); + + Skjerming screeningCode = GetOrCreateScreeningCode("N1"); + + Dokumenttype documentType = GetOrCreateDocumentType("Tilbud"); + + // Note that all code list values can be fetched with a single request like this: + // client.CodeLists(); + + // Create a registry entry with a document description and upload a document: + Journalpost registryEntry = + CreateRegistryEntry( + caseFile.Id, + "Registry entry", + "registryEntryExternalId", + screeningCode, + documentType); + } + + private Arkivdel FindSeriesByTitle(string title) + { + var noarkClient = documasterClients.getNoarkClient(); + + QueryResponse queryResponse = noarkClient.Query("tittel=@title", 1) + .AddQueryParam("@title", title) + .Execute(); + + if (!queryResponse.Results.Any()) + { + return null; + } + + if (queryResponse.HasMore) + { + Console.WriteLine($"Warning: found more than one series with title '{title}'!"); + } + + return queryResponse.Results.First(); + } + + private Saksmappe GetOrCreateCaseFile(string seriesId, string primaryClassificationSystemId) + { + // Search for an existing case file by the external id from eByggesak + Saksmappe caseFile = FindCaseFileByExternalId("caseFileExternalId", seriesId); + + if (caseFile == null) + { + //Setting a primary class and an organizational unit is required when creating a case file! + + AdministrativEnhet organizationalUnit = GetOrCreateOrganizationalUnit("organizationalUnitCode"); + + Klasse primaryClass = GetOrCreateClass("01 Tilbud", "Tilbud om plass", primaryClassificationSystemId); + + caseFile = CreateCaseFile( + seriesId, + "Case file", + primaryClass.Id, + organizationalUnit, + "caseFileExternalId"); + } + + return caseFile; + } + + private Saksmappe FindCaseFileByExternalId(string externalId, string seriesId) + { + var noarkClient = documasterClients.getNoarkClient(); + + QueryResponse queryResponse = + noarkClient.Query("refArkivdel.id=@seriesId && refEksternId.eksternID=@externalId", 1) + .AddQueryParam("@seriesId", seriesId) + .AddQueryParam("@externalId", externalId) + .Execute(); + + if (!queryResponse.Results.Any()) + { + return null; + } + + if (queryResponse.HasMore) + { + Console.WriteLine($"Warning: found more than one case files with external ID '{externalId}'!"); + } + + return queryResponse.Results.First(); + } + + private Klasse GetOrCreateClass(string classId, string title, string classificationSystemId) + { + var noarkClient = documasterClients.getNoarkClient(); + + QueryResponse queryResponse = noarkClient + .Query("klasseIdent=@classId && refKlassifikasjonssystem.id=@classificationSystemId", 1) + .AddQueryParam("@classId", classId) + .AddQueryParam("@classificationSystemId", classificationSystemId) + .Execute(); + + if (queryResponse.Results.Any()) + { + return queryResponse.Results.First(); + } + else + { + Klasse klass = new Klasse(classId, title); + TransactionResponse transactionResponse = noarkClient.Transaction() + .Save(klass) + .Link(klass.LinkKlassifikasjonssystem(classificationSystemId)) + .Commit(); + + return transactionResponse.Saved[klass.Id] as Klasse; + } + } + + private AdministrativEnhet GetOrCreateOrganizationalUnit(string organizationalUnitCode) + { + var noarkClient = documasterClients.getNoarkClient(); + + CodeList organizationalUnitCodeList = noarkClient.CodeLists("Saksmappe", "administrativEnhet").First(); + + var codeExists = + organizationalUnitCodeList.Values.Exists(codeValue => codeValue.Code.Equals(organizationalUnitCode)); + + if (!codeExists) + { + AdministrativEnhet newOrganizationalUnit = + new AdministrativEnhet(organizationalUnitCode, $"name for {organizationalUnitCode}"); + return noarkClient.PutCodeListValue(newOrganizationalUnit); + } + else + { + return new AdministrativEnhet(organizationalUnitCode); + } + } + + private Dokumenttype GetOrCreateDocumentType(string documentType) + { + var noarkClient = documasterClients.getNoarkClient(); + + CodeList documentTypeCodeList = noarkClient.CodeLists("Dokument", "dokumenttype").First(); + + var codeExists = + documentTypeCodeList.Values.Exists(codeValue => codeValue.Code.Equals(documentType)); + + if (!codeExists) + { + Dokumenttype newDocumentType = + new Dokumenttype(documentType, $"name for {documentType}"); + return noarkClient.PutCodeListValue(newDocumentType); + } + else + { + return new Dokumenttype(documentType); + } + } + + private Skjerming GetOrCreateScreeningCode(string screeningCode) + { + var noarkClient = documasterClients.getNoarkClient(); + + CodeList screeningCodeList = noarkClient.CodeLists("Journalpost", "skjerming").First(); + + var codeExists = + screeningCodeList.Values.Exists(codeValue => codeValue.Code.Equals(screeningCode)); + + if (!codeExists) + { + Skjerming newDocumentType = + new Skjerming(screeningCode, $"name for {screeningCode}"); + return noarkClient.PutCodeListValue(newDocumentType); + } + else + { + return new Skjerming(screeningCode); + } + } + + private Saksmappe CreateCaseFile( + string seriesId, + string caseFileTitle, + string primaryClassId, + AdministrativEnhet organizationalUnit, + string externalId) + { + var noarkClient = documasterClients.getNoarkClient(); + + Saksmappe caseFile = new Saksmappe(caseFileTitle, organizationalUnit); + + EksternId extarnalIdObj = new EksternId(EXTERNAL_SYSTEM, externalId); + + // Commit all objects and link them + TransactionResponse response = noarkClient.Transaction() + .Save(caseFile) + .Link(caseFile.LinkArkivdel(seriesId)) + .Link(caseFile.LinkPrimaerKlasse(primaryClassId)) + .Save(extarnalIdObj) + .Link(extarnalIdObj.LinkMappe(caseFile)) + .Commit(); + + // TransactionResponse is a dictionary and it's keys are the id's that are temporarily assigned to the objects when they are first initialized. + // The values of the dictionary are the save objects with their permanent id's. + + return response.Saved[caseFile.Id] as Saksmappe; + } + + private Journalpost CreateRegistryEntry( + string caseFileId, + string title, + string externalId, + Skjerming screeningCode, + Dokumenttype documentType) + { + var noarkClient = documasterClients.getNoarkClient(); + + Journalpost registryEntry = new Journalpost(title, Journalposttype.UTGAAENDE_DOKUMENT); + registryEntry.Skjerming = screeningCode; + + // Link registry entry to an external id, a correspondence party and a sign off object. + + EksternId externalIdObj = new EksternId(EXTERNAL_SYSTEM, externalId); + + Korrespondansepart correspondenceParty = + new Korrespondansepart(Korrespondanseparttype.AVSENDER, "John Smith"); + + Avskrivning signoff = new Avskrivning(Avskrivningsmaate.TATT_TIL_ETTERRETNING); + + //Link the document descriptions to the registry entry as main document. (HOVEDDOKUMENT) + //Subsequent document descriptions can be linked as attachments (VEDLEGG). + + Dokument documentDescription = + new Dokument("Document description", TilknyttetRegistreringSom.HOVEDDOKUMENT); + documentDescription.Dokumenttype = documentType; + + Dokumentfil uploadedFile = noarkClient.Upload(this.filePath); + + Dokumentversjon documentVersion = new Dokumentversjon(Variantformat.ARKIVFORMAT, ".pdf", uploadedFile); + + TransactionResponse transactionResponse = noarkClient.Transaction() + .Save(registryEntry) + .Link(registryEntry.LinkMappe(caseFileId)) + .Save(externalIdObj) + .Link(externalIdObj.LinkRegistrering(registryEntry)) + .Save(correspondenceParty) + .Link(correspondenceParty.LinkRegistrering(registryEntry)) + .Save(signoff) + .Link(registryEntry.LinkAvskrivning(signoff)) + .Save(documentDescription) + .Link(documentDescription.LinkRegistrering(registryEntry)) + .Save(documentVersion) + .Link(documentVersion.LinkDokument(documentDescription)) + .Commit(); + + return transactionResponse.Saved[registryEntry.Id] as Journalpost; + } + } +} diff --git a/NoarkWsClientSample/NoarkWsClientSample/eByggesak/README.md b/NoarkWsClientSample/NoarkWsClientSample/eByggesak/README.md new file mode 100644 index 0000000..6b7b5ce --- /dev/null +++ b/NoarkWsClientSample/NoarkWsClientSample/eByggesak/README.md @@ -0,0 +1,48 @@ +## Documaster-eByggesak integration sample code + +This sample code uses the Documaster's NoarkClient (a client library available through NuGet) to demonstrate searching for and submitting data in a Documaster instance. +The **EByggesakToDocumasterSubmitter** class shows how to search for a series and a case file, how to create a new case file with a registry entry and a document in it. +The **DocumasterToEByggesakSubmitter** class shows how to search for registry entries created in the last N days and check their external id's. + +### Setup instructions + +The sample is contained in a .NET 4.7 Console application. You need to restore the NuGet packages in this project to be able to compile it. +The Main method in Program.cs runs both the generic Noark sample as well as the eByggesak sample code. Feel free to comment or delete the lines that run the generic sample. + +The following arguments are required: + +* --idpaddr: The address of the identity provider services for the particular RMS instances (ex: "http://client.documaster.tech/idp/oauth2/" +* --clientid: The OAuth client_id value. +* --clientsecret: The OAuth client_secret value. +* --username: The RMS username. +* --password The RMS user password. +* --addr: The address of Documaster's web services (ex: "http://client.documaster.tech:8083") +* --testdoc A valid path to a test file to be uploaded to the RMS. + +The following arguments are optional: + +* --cert: Path to a client .p12 certificate file if authentication in the RMS is configured to require certificates +* --certpass: Certificate password. + +### Requirements + +To run this sample code you need a Documaster's RMS installation with version 2.11.0 or higher. In the sample, we authenticate to the RMS with the Oauth2HttpClient which is another public NuGet client library. +The Oauth2HttpClient is a small OAuth2 client and we use it to obtain an authentication token from Documaster's own Identity Provider services. By default, the token expires in 60 minutes and +needs to refreshed after that. This is why the NoarkClient and the Oauth2HttpClient instances in this sample are kept in a separate class called +DocumasterClients which is responsible for getting and refreshing the token. + +This sample code expects to find an existing series with title "eByggesak" in the RMS. + +### Miscellaneous + +Some of the values used for creating RMS objects are dummy strings and need to be replaced with real-world values. +Such strings are: + +* the name of the series "eByggesak" +* the external id's of the case file and the registry entry - "caseFileExternalId" and "registryEntryExternalId" +* the class id and class name for the primary class of the case file - "01 Tilbud" and "Tilbud om plass" respectively +* the organizational unit code required for the creation of the case file - "organizationalUnitCode" +* the document type "Tilbud" +* the screening code "N1" + +