Skip to content

Commit

Permalink
Merge pull request #93 from OPCFoundation/erichb
Browse files Browse the repository at this point in the history
Enhanced GraphQL queries without requiring database conversion
  • Loading branch information
barnstee authored Apr 8, 2022
2 parents 928d191 + a1bf591 commit fb0f619
Show file tree
Hide file tree
Showing 47 changed files with 2,702 additions and 926 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -351,3 +351,4 @@ MigrationBackup/
/Properties/launchSettings.json
/SampleConsoleClient/Properties/launchSettings.json
/UACloudLibraryServer/key-4fe0b423-c5df-420c-b3ae-6065476796ad.xml
/UACloudLibraryServer/key-f10e50be-5170-4621-b53a-63207cf7c4d3.xml
161 changes: 117 additions & 44 deletions SampleConsoleClient/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@ namespace SampleConsoleClient
using GraphQL.Client.Http;
using GraphQL.Client.Serializer.Newtonsoft;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using UACloudLibClientLibrary;
using UACloudLibClientLibrary.Models;
using UACloudLibrary.Models;

class Program
{
Expand All @@ -53,10 +55,10 @@ static void Main(string[] args)

Console.WriteLine("OPC Foundation UA Cloud Library Console Client Application");

TestGraphQLInterface(args);

TestRESTInterface(args);

TestGraphQLInterface(args);

TestClientLibrary(args);

Console.WriteLine();
Expand All @@ -77,36 +79,83 @@ private static void TestGraphQLInterface(string[] args)
GraphQLHttpClient graphQLClient = new GraphQLHttpClient(options, new NewtonsoftJsonSerializer());

Console.WriteLine();
Console.WriteLine("Testing objecttype query (the other OPC UA types are very similar!)");
Console.WriteLine("Testing objectType query (the other OPC UA types are very similar!)");
GraphQLRequest request = new GraphQLRequest
{
Query = @"
query {
objecttype
{
objecttype_browsename objecttype_value objecttype_namespace nodeset_id
}
}"

Query = @"query {
objectType {
browseName
value
nameSpace
nodesetId
}
}"
};
var response = graphQLClient.SendQueryAsync<UACloudLibGraphQLObjecttypeQueryResponse>(request).GetAwaiter().GetResult();
Console.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented));

GraphQLResponse<JObject> response = graphQLClient.SendQueryAsync<JObject>(request).GetAwaiter().GetResult();
Console.WriteLine(JsonConvert.SerializeObject(response.Data, Formatting.Indented));

Console.WriteLine();
Console.WriteLine("Testing metadata query");
request = new GraphQLRequest
{
Query = @"
query {
metadata
{
metadata_name metadata_value nodeset_id
}
}"
Query = @"query {
metadata {
name
value
nodesetId
}
}"
};

response = graphQLClient.SendQueryAsync<JObject>(request).GetAwaiter().GetResult();
Console.WriteLine(JsonConvert.SerializeObject(response.Data, Formatting.Indented));

Console.WriteLine();
Console.WriteLine("Testing addressSpace query");
request = new GraphQLRequest
{
Query = @"query {
addressSpace(
limit: 10
offset: 0
where: ""[{ 'orgname': { 'like': 'microsoft' }}]""
orderBy: ""title""
) {
title
contributor {
name
contactEmail
website
logoUrl
description
}
license
category {
name
description
iconUrl
}
description
documentationUrl
purchasingInformationUrl
releaseNotesUrl
keywords
supportedLocales
nodeset
{
version
identifier
namespaceUri
publicationDate
lastModifiedDate
}
}
}"
};
var response2 = graphQLClient.SendQueryAsync<UACloudLibGraphQLMetadataQueryResponse>(request).GetAwaiter().GetResult();
Console.WriteLine(JsonConvert.SerializeObject(response2.Data, Formatting.Indented));

response = graphQLClient.SendQueryAsync<JObject>(request).GetAwaiter().GetResult();
Console.WriteLine(JsonConvert.SerializeObject(response.Data, Formatting.Indented));

graphQLClient.Dispose();
}
Expand All @@ -125,9 +174,9 @@ private static void TestRESTInterface(string[] args)

Console.WriteLine();
Console.WriteLine("Testing /infomodel/find?keywords");
string keywords = "*"; // return everything (other keywords are simply appended with "&keywords=UriEscapedKeyword2&keywords=UriEscapedKeyword3", etc.)
string address = webClient.BaseAddress.ToString() + "infomodel/find?keywords=" + Uri.EscapeDataString(keywords);
HttpContent content = new StringContent(JsonConvert.SerializeObject(keywords), Encoding.UTF8, "application/json");

// return everything (keywords=*, other keywords are simply appended with "&keywords=UriEscapedKeyword2&keywords=UriEscapedKeyword3", etc.)
string address = webClient.BaseAddress.ToString() + "infomodel/find?keywords=" + Uri.EscapeDataString("*");
var response = webClient.Send(new HttpRequestMessage(HttpMethod.Get, address));
Console.WriteLine("Response: " + response.StatusCode.ToString());
UANodesetResult[] identifiers = JsonConvert.DeserializeObject<UANodesetResult[]>(response.Content.ReadAsStringAsync().GetAwaiter().GetResult());
Expand All @@ -138,9 +187,12 @@ private static void TestRESTInterface(string[] args)

Console.WriteLine();
Console.WriteLine("Testing /infomodel/download/{identifier}");
string identifier = identifiers[0].Id.ToString(); // pick the first identifier returned previously

// pick the first identifier returned previously
string identifier = identifiers[0].Id.ToString();
address = webClient.BaseAddress.ToString() + "infomodel/download/" + Uri.EscapeDataString(identifier);
response = webClient.Send(new HttpRequestMessage(HttpMethod.Get, address));

Console.WriteLine("Response: " + response.StatusCode.ToString());
Console.WriteLine(response.Content.ReadAsStringAsync().GetAwaiter().GetResult());

Expand All @@ -155,35 +207,56 @@ private static void TestClientLibrary(string[] args)
Console.WriteLine("\n\nTesting the client library");

UACloudLibClient client = new UACloudLibClient(args[0], args[1], args[2]);

Console.WriteLine("\nTesting object query");
List<ObjectResult> test = client.GetObjectTypes().GetAwaiter().GetResult();
foreach(ObjectResult result in test)
try
{
Console.WriteLine($"{result.ID}, {result.Namespace}, {result.Browsename}, {result.Value}");
}
Console.WriteLine("\nTesting the GraphQL API");

Console.WriteLine("\nTesting metadata query");
List<MetadataResult> metadatas = client.GetMetadata().GetAwaiter().GetResult();
foreach(MetadataResult metadata in metadatas)
{
Console.WriteLine($"{metadata.ID}, {metadata.Name}, {metadata.Value}");
}
Console.WriteLine("\nTesting the address space query, this will fall back to the REST interface if GraphQL is not available.");
List<WhereExpression> filter = new List<WhereExpression>();
filter.Add(new WhereExpression(SearchField.orgname, "microsoft", ComparisonType.like));
List<AddressSpace> addressSpaces = client.GetAddressSpaces(10, 0, filter).GetAwaiter().GetResult();
if(addressSpaces.Count > 0)
{
Console.WriteLine("Title: {0}", addressSpaces[0].Title);
Console.WriteLine("Total number of address spaces: {0}", addressSpaces.Count);
}

Console.WriteLine("\nTesting query and convertion of metadata");
List<AddressSpace> finalResult = client.GetConvertedResult().GetAwaiter().GetResult();
foreach(AddressSpace result in finalResult)
Console.WriteLine("\nTesting object query");
List<ObjectResult> objects = client.GetObjectTypes().GetAwaiter().GetResult();
foreach (ObjectResult result in objects)
{
Console.WriteLine($"{result.ID}, {result.Namespace}, {result.Browsename}, {result.Value}");
}

Console.WriteLine("\nTesting metadata query");
List<MetadataResult> metadata = client.GetMetadata().GetAwaiter().GetResult();
foreach (MetadataResult entry in metadata)
{
Console.WriteLine($"{entry.ID}, {entry.Name}, {entry.Value}");
}

Console.WriteLine("\nTesting query and convertion of metadata");
List<AddressSpace> finalResult = client.GetConvertedMetadata().GetAwaiter().GetResult();
foreach(AddressSpace result in finalResult)
{
Console.WriteLine($"{result.Title} by {result.Contributor.Name}");
}
}
catch (Exception ex)
{
Console.WriteLine($"{result.Title} by {result.Contributor.Name} last update on {result.LastModificationTime}");
Console.WriteLine(ex.Message);
}

if(finalResult.Count > 0)
Console.WriteLine("\nUsing the rest API");
List<UANodesetResult> restResult = client.GetBasicNodesetInformation().GetAwaiter().GetResult();
if (restResult.Count > 0)
{
Console.WriteLine("Testing download of nodeset");
AddressSpace result = client.DownloadNodeset(finalResult[0].MetadataID);
AddressSpace result = client.DownloadNodeset(restResult[0].Id.ToString()).GetAwaiter().GetResult();
if (!string.IsNullOrEmpty(result.Nodeset.NodesetXml))
{
Console.WriteLine("Nodeset Downloaded");
Console.WriteLine(result.Nodeset.NodesetXml);
}
}
}
Expand Down
6 changes: 0 additions & 6 deletions UA-CloudLibrary.sln
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleConsoleClient", "Samp
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UACloudLibClientLibrary", "UACloudLibraryGraphQLClient\UACloudLibClientLibrary\UACloudLibClientLibrary.csproj", "{8353C72D-E29A-40BE-A3EF-C59330FC270C}"
EndProject
Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{C7282E18-BCDA-48F6-99FD-EC7142A0397A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -39,10 +37,6 @@ Global
{8353C72D-E29A-40BE-A3EF-C59330FC270C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8353C72D-E29A-40BE-A3EF-C59330FC270C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8353C72D-E29A-40BE-A3EF-C59330FC270C}.Release|Any CPU.Build.0 = Release|Any CPU
{C7282E18-BCDA-48F6-99FD-EC7142A0397A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C7282E18-BCDA-48F6-99FD-EC7142A0397A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C7282E18-BCDA-48F6-99FD-EC7142A0397A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C7282E18-BCDA-48F6-99FD-EC7142A0397A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Loading

0 comments on commit fb0f619

Please sign in to comment.