public async Task ParserValidationResolveFromLocalRepository() { ModelParser parser = new ModelParser(); string TestRegistryPath = TestHelpers.TestLocalModelRepository; List <string> parseModelPaths = new List <string>() { $"{TestRegistryPath}/dtmi/company/demodevice-2.json", $"{TestRegistryPath}/dtmi/com/example/temperaturecontroller-1.json", $"{TestRegistryPath}/dtmi/com/example/camera-3.json", }; // Shows how to quickly integrate the resolver client with the parser. ResolverClient client = new ResolverClient(TestRegistryPath); parser.DtmiResolver = client.ParserDtmiResolver; foreach (string modelPath in parseModelPaths) { // Parser will throw on validation errors try { await parser.ParseAsync(new string[] { File.ReadAllText(modelPath) }); } catch (Exception e) { Assert.Fail(e.Message); } } }
public async Task ParseDemoAsync(DigitalTwinsClient client) { try { AsyncPageable <DigitalTwinsModelData> mdata = client.GetModelsAsync(new GetModelsOptions { IncludeModelDefinition = true }); var models = new List <string>(); await foreach (DigitalTwinsModelData md in mdata) { models.Add(md.DtdlModel); } var parser = new ModelParser(); IReadOnlyDictionary <Dtmi, DTEntityInfo> dtdlOM = await parser.ParseAsync(models); var interfaces = new List <DTInterfaceInfo>(); IEnumerable <DTInterfaceInfo> ifenum = from entity in dtdlOM.Values where entity.EntityKind == DTEntityKind.Interface select entity as DTInterfaceInfo; interfaces.AddRange(ifenum); foreach (DTInterfaceInfo dtif in interfaces) { PrintInterfaceContent(dtif, dtdlOM); } } catch (RequestFailedException ex) { Console.WriteLine($"Failed due to {ex}"); throw; } }
private static async Task <IReadOnlyDictionary <Dtmi, DTEntityInfo> > ParseModelsAsync(Dictionary <string, string> modelTexts) { IReadOnlyDictionary <Dtmi, DTEntityInfo> entities = null; try { var parser = new ModelParser(); entities = await parser.ParseAsync(modelTexts.Values); } catch (ParsingException ex) { Log.Error("Errors parsing models."); foreach (ParsingError error in ex.Errors) { Log.Error(error.Message); } } catch (Exception ex) { Log.Error("Errors parsing models."); Log.Error(ex.Message); } return(entities); }
private async Task ValidateAsync(string input, string resolverName) { ModelParser parser = new ModelParser(); parser.Options = new HashSet <ModelParsingOption>() { ModelParsingOption.StrictPartitionEnforcement }; ConfigureResolver(parser, resolverName); try { var parserResult = await parser.ParseAsync(new string[] { File.ReadAllText(input) }); Console.WriteLine("Resolution completed"); foreach (var item in parserResult.Values) { this.log.LogTrace(item.Id.AbsoluteUri); } Console.WriteLine($"\nValidation Passed: {input}"); } catch (Exception ex) { Environment.ExitCode = 1; log.LogError(ex, "DTDL Parser Exception"); } }
static async Task Main(string[] args) { if (args.Length < 1) { Console.WriteLine("Usage: repo-client <dtmi>"); return; } string rootDtmi = args[0]; GetModel(rootDtmi); ModelParser parser = new ModelParser(); try { //modelParser.DtmiResolver = LocalDtmiResolver; var parsedDtmis = await parser.ParseAsync(allModels.Values); var interfaces = parsedDtmis.Where(r => r.Value.EntityKind == DTEntityKind.Interface).ToList(); foreach (var dt in interfaces) { Console.WriteLine(dt.Key.AbsoluteUri + " " + dt.Value.DefinedIn); var ifcs = parsedDtmis.Where(r => r.Value.DefinedIn == dt.Key); foreach (var i in ifcs) { Console.WriteLine(i.Value.Id); } } } catch (Exception ex) { Console.WriteLine(ex.Message); } }
//https://docs.microsoft.com/en-us/azure/iot-pnp/concepts-model-parser public static async Task <Dictionary <string, DTDLContainer> > ParseDTDLAndBuildDynamicContentAsync(JArray dtdlArray) { if (dtdlArray == null) { throw new ArgumentNullException(nameof(dtdlArray)); } Dictionary <string, DTDLContainer> globalResult = new Dictionary <string, DTDLContainer>(); DTDLContainer itemResult = null; ModelParser parser = new ModelParser(); IReadOnlyDictionary <Dtmi, DTEntityInfo> parseResult = await parser.ParseAsync(dtdlArray.Select(i => JsonConvert.SerializeObject(i))); foreach (JObject dtdl in dtdlArray) { try { //PROCESS COMPONENTS await ProcessComponentsWithDynamicContent(dtdlArray, dtdl, globalResult); //ALL EXCEPT COMPONENTS itemResult = BuildDynamicContent(dtdl); } catch (ParsingException pex) { if (itemResult == null) { itemResult = new DTDLContainer(); } itemResult.ParsingErrors = pex.Errors.Select(i => i.Message); } catch (Exception ex) { itemResult = null; } finally { if (itemResult != null) { if (!globalResult.ContainsKey(dtdl["@id"].Value <string>())) { globalResult.Add(dtdl["@id"].Value <string>(), itemResult); } } itemResult = null; } } return(globalResult); }
public static async Task <IReadOnlyDictionary <Dtmi, DTEntityInfo> > ParseDTDLAsync(JArray dtdlArray) { if (dtdlArray == null) { throw new ArgumentNullException(nameof(dtdlArray)); } ModelParser parser = new ModelParser(); return(await parser.ParseAsync(dtdlArray.Select(i => JsonConvert.SerializeObject(i)))); }
private static async Task NotFound() { string dtmi = "dtmi:com:example:NotFound;1"; ResolverClient rc = new ResolverClient(); var models = await rc.ResolveAsync(dtmi); ModelParser parser = new ModelParser(); var parseResult = await parser.ParseAsync(models.Values.ToArray()); Console.WriteLine($"{dtmi} resolved in {models.Count} interfaces with {parseResult.Count} entities."); }
public static async Task GetModelsAndParseAsync() { var dtmi = "dtmi:com:example:TemperatureController;1"; var client = new ModelsRepositoryClient(); IDictionary <string, string> models = await client.GetModelsAsync(dtmi).ConfigureAwait(false); var parser = new ModelParser(); IReadOnlyDictionary <Dtmi, DTEntityInfo> parseResult = await parser.ParseAsync(models.Values.ToArray()); Console.WriteLine($"{dtmi} resolved in {models.Count} interfaces with {parseResult.Count} entities."); }
private static async Task ResolveAndParse() { string dtmi = "dtmi:com:example:TemperatureController;1"; ILogger logger = LoggerFactory.Create(builder => builder.AddDebug().SetMinimumLevel(LogLevel.Trace)).CreateLogger <Program>(); ResolverClient rc = new ResolverClient(logger); var models = await rc.ResolveAsync(dtmi); ModelParser parser = new ModelParser(); var parseResult = await parser.ParseAsync(models.Values.ToArray()); Console.WriteLine($"{dtmi} resolved in {models.Count} interfaces with {parseResult.Count} entities."); }
private static async Task ParseAndResolve() { string dtmi = "dtmi:com:example:TemperatureController;1"; ResolverClient rc = new ResolverClient(new ResolverClientOptions(DependencyResolutionOption.Disabled)); var models = await rc.ResolveAsync(dtmi); ModelParser parser = new ModelParser(); parser.DtmiResolver = rc.ParserDtmiResolver; var parseResult = await parser.ParseAsync(models.Values.Take(1).ToArray()); Console.WriteLine($"{dtmi} resolved in {models.Count} interfaces with {parseResult.Count} entities."); }
public async Task <bool> IsValidDtdlFileAsync(FileInfo modelFile, bool strict) { _logger.LogInformation($"Using repository: '{_repository}'"); ModelParser parser = GetParser(); await parser.ParseAsync(new string[] { File.ReadAllText(modelFile.FullName) }); if (strict) { return(await modelFile.Validate()); } return(true); }
public static async Task GetModelAndParseAsync() { #region Snippet:ModelsRepositorySamplesParserIntegrationGetModelsAndParseAsync var client = new ModelsRepositoryClient(); var dtmi = "dtmi:com:example:TemperatureController;1"; ModelResult result = await client.GetModelAsync(dtmi).ConfigureAwait(false); var parser = new ModelParser(); IReadOnlyDictionary <Dtmi, DTEntityInfo> parseResult = await parser.ParseAsync(result.Content.Values); Console.WriteLine($"{dtmi} resolved in {result.Content.Count} interfaces with {parseResult.Count} entities."); #endregion Snippet:ModelsRepositorySamplesParserIntegrationGetModelsAndParseAsync }
public static async Task ParseAndGetModelsWithExtensionAsync() { var dtmi = "dtmi:com:example:TemperatureController;1"; var client = new ModelsRepositoryClient(new ModelsRepositoryClientOptions(resolutionOption: DependencyResolutionOption.Disabled)); IDictionary <string, string> models = await client.GetModelsAsync(dtmi).ConfigureAwait(false); var parser = new ModelParser { // Usage of the ModelsRepositoryClientExtensions.ParserDtmiResolver extension. DtmiResolver = client.ParserDtmiResolver }; IReadOnlyDictionary <Dtmi, DTEntityInfo> parseResult = await parser.ParseAsync(models.Values.Take(1).ToArray()); Console.WriteLine($"{dtmi} resolved in {models.Count} interfaces with {parseResult.Count} entities."); }
public async Task <IReadOnlyDictionary <Dtmi, DTEntityInfo> > ParseModelAsync(string dtmi) { string modelContent = string.Empty; IReadOnlyDictionary <Dtmi, DTEntityInfo> parseResult = null; List <string> listModelJson = new List <string>(); string dtmiPath = DtmiToPath(dtmi); if (!string.IsNullOrEmpty(dtmiPath)) { if (!string.IsNullOrEmpty(_modelRepoUrl_Private)) { modelContent = await GetModelContentAsync(dtmiPath, false); } if (string.IsNullOrEmpty(modelContent)) { // try public repo modelContent = await GetModelContentAsync(dtmiPath, true); } if (!string.IsNullOrEmpty(modelContent)) { listModelJson.Add(modelContent); } try { ModelParser dtdlModelParser = new ModelParser(); dtdlModelParser.DtmiResolver = DtmiResolver; if (!string.IsNullOrEmpty(_modelRepoUrl_Private)) { _modelRepoUrl = _modelRepoUrl_Private; } else { _modelRepoUrl = _modelRepoUrl_Public; } parseResult = await dtdlModelParser.ParseAsync(listModelJson); } catch (Exception e) { _logger.LogError($"Error ParseModelAsync(): {e.Message}"); } } return(parseResult); }
public async Task ParserValidationResolveFromRemoteRepository() { ModelParser parser = new ModelParser(); // TODO: One off model -- need consistent remote model repo for IT's string TestRepoPath = TestHelpers.TestLocalModelRepository; string testModelPath = $"{TestRepoPath}/dtmi/company/demodevice-2.json"; // Shows how to quickly integrate the resolver client with the parser. ResolverClient client = new ResolverClient(TestHelpers.TestRemoteModelRepository); parser.DtmiResolver = client.ParserDtmiResolver; // Parser will throw on validation errors await parser.ParseAsync(new string[] { File.ReadAllText(testModelPath) }); }
public async Task <IReadOnlyDictionary <Dtmi, DTEntityInfo> > ParseModelAsync(string dtmi) { string modelContent = string.Empty; IReadOnlyDictionary <Dtmi, DTEntityInfo> parseResult = null; List <string> listModelJson = new List <string>(); string dtmiPath = DtmiToPath(dtmi); if (!string.IsNullOrEmpty(dtmiPath)) { modelContent = await GetModelContentAsync(dtmiPath, false); if (string.IsNullOrEmpty(modelContent)) { // try public repo modelContent = await GetModelContentAsync(dtmiPath); } if (!string.IsNullOrEmpty(modelContent)) { listModelJson.Add(modelContent); } try { ModelParser parser = new ModelParser(); parser.DtmiResolver = DtmiResolver; //parser.DtmiResolver = (IReadOnlyCollection<Dtmi> dtmis) => //{ // foreach (Dtmi d in dtmis) // { // _logger.LogInformation($"------------- {d}"); // } // return null; //}; parseResult = await parser.ParseAsync(listModelJson); } catch (Exception e) { _logger.LogError($"Error ParseModelAsync(): {e.Message}"); } } return(parseResult); }
static async Task Main(string[] args) { List <string> modelsContents = new List <string>(); if (args.Length < 1) { args = new string[] { "." }; } string input = args[0]; if (!File.Exists(input) && !Directory.Exists(input)) { Console.WriteLine($"Error: '{input}' not found."); return; } if (File.Exists(input)) { modelsContents.Add(File.ReadAllText(input)); } if (Directory.Exists(input)) { foreach (var file in Directory.GetFiles(input)) { modelsContents.Add(File.ReadAllText(file)); } } try { modelParser.DtmiResolver = DtmiResolver; var parsedDtmis = await modelParser.ParseAsync(modelsContents); var interfaces = parsedDtmis.Where(r => r.Value.EntityKind == DTEntityKind.Interface).ToList(); foreach (var dt in interfaces) { Console.WriteLine(dt.Key.AbsoluteUri + " " + dt.Value.DefinedIn); } } catch (Exception ex) { Console.WriteLine(ex.Message); } }
public static async Task ParseAndGetModelWithExtensionAsync() { #region Snippet:ModelsRepositorySamplesParserIntegrationParseAndGetModelsAsync var client = new ModelsRepositoryClient(); var dtmi = "dtmi:com:example:TemperatureController;1"; ModelResult result = await client.GetModelAsync(dtmi, ModelDependencyResolution.Disabled).ConfigureAwait(false); var parser = new ModelParser { // Usage of the ModelsRepositoryClientExtensions.ParserDtmiResolver extension. DtmiResolver = client.ParserDtmiResolver }; IReadOnlyDictionary <Dtmi, DTEntityInfo> parseResult = await parser.ParseAsync(result.Content.Values); Console.WriteLine($"{dtmi} resolved in {result.Content.Count} interfaces with {parseResult.Count} entities."); #endregion Snippet:ModelsRepositorySamplesParserIntegrationParseAndGetModelsAsync }
public void ParserValidationResolveFromLocalRepoErrorOnParserCallbackDtmiCasing() { ModelParser parser = new ModelParser(); string TestRegistryPath = TestHelpers.TestLocalModelRepository; // This model references another model with invalid casing. string modelPath = $"{TestRegistryPath}/dtmi/company/demodevice-1.json"; // Shows how to quickly integrate the resolver client with the parser. ResolverClient client = new ResolverClient(TestRegistryPath); parser.DtmiResolver = client.ParserDtmiResolver; // Parser will throw on validation errors ResolverException e = Assert.ThrowsAsync <ResolverException>(async() => await parser.ParseAsync(new string[] { File.ReadAllText(modelPath) })); Assert.AreEqual(e.Message, $"{StandardStrings.GenericResolverError("dtmi:azure:deviceManagement:DeviceInformation;1")}" + $"{StandardStrings.IncorrectDtmiCasing("dtmi:azure:deviceManagement:DeviceInformation;1","dtmi:azure:DeviceManagement:DeviceInformation;1")}"); }
static async Task Main(string[] args) { // Target DTMI for resolution. string toParseDtmi = args.Length == 0 ? "dtmi:com:example:TemperatureController;1" : args[0]; // Initiate first Resolve for the target dtmi to pass content to parser string dtmiContent = await Resolve(toParseDtmi); if (!string.IsNullOrEmpty(dtmiContent)) { // Assign the callback ModelParser parser = new ModelParser { DtmiResolver = ResolveCallback }; await parser.ParseAsync(new List <string> { dtmiContent }); Console.WriteLine("Parsing success!"); } }
static void RunOptions(Options opts) { Log.Ok("Simple DTDL Validator"); if (opts.Interactive == true) { Log.Alert("Entering interactive mode"); Interactive.Interactive i = new Interactive.Interactive(); return; } DirectoryInfo dinfo = null; try { dinfo = new DirectoryInfo(opts.Directory); } catch (Exception e) { Log.Error($"Error accessing the target directory '{opts.Directory}': \n{e.Message}"); return; } Log.Alert($"Validating *.{opts.Extension} files in folder '{dinfo.FullName}'.\nRecursive is set to {opts.Recursive}\n"); if (dinfo.Exists == false) { Log.Error($"Specified directory '{opts.Directory}' does not exist: Exiting..."); return; } else { SearchOption searchOpt = opts.Recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; var files = dinfo.EnumerateFiles($"*.{opts.Extension}", searchOpt); if (files.Count() == 0) { Log.Alert("No matching files found. Exiting."); return; } Dictionary <FileInfo, string> modelDict = new Dictionary <FileInfo, string>(); int count = 0; string lastFile = "<none>"; try { foreach (FileInfo fi in files) { StreamReader r = new StreamReader(fi.FullName); string dtdl = r.ReadToEnd(); r.Close(); modelDict.Add(fi, dtdl); lastFile = fi.FullName; count++; } } catch (Exception e) { Log.Error($"Could not read files. \nLast file read: {lastFile}\nError: \n{e.Message}"); return; } Log.Ok($"Read {count} files from specified directory"); int errJson = 0; foreach (FileInfo fi in modelDict.Keys) { modelDict.TryGetValue(fi, out string dtdl); try { JsonDocument.Parse(dtdl); } catch (Exception e) { Log.Error($"Invalid json found in file {fi.FullName}.\nJson parser error \n{e.Message}"); errJson++; } } if (errJson > 0) { Log.Error($"\nFound {errJson} Json parsing errors"); return; } Log.Ok($"Validated JSON for all files - now validating DTDL"); List <string> modelList = modelDict.Values.ToList <string>(); ModelParser parser = new ModelParser(); parser.DtmiResolver = Resolver; try { IReadOnlyDictionary <Dtmi, DTEntityInfo> om = parser.ParseAsync(modelList).GetAwaiter().GetResult(); Log.Out(""); Log.Ok($"**********************************************"); Log.Ok($"** Validated all files - Your DTDL is valid **"); Log.Ok($"**********************************************"); Log.Out($"Found a total of {om.Keys.Count()} entities"); } catch (ParsingException pe) { Log.Error($"*** Error parsing models"); int derrcount = 1; foreach (ParsingError err in pe.Errors) { Log.Error($"Error {derrcount}:"); Log.Error($"{err.Message}"); Log.Error($"Primary ID: {err.PrimaryID}"); Log.Error($"Secondary ID: {err.SecondaryID}"); Log.Error($"Property: {err.Property}\n"); derrcount++; } return; } catch (ResolutionException rex) { Log.Error("Could not resolve required references"); } } }
public static async Task <int> Import(FileInfo modelFile, DirectoryInfo localRepo, bool strict) { if (localRepo == null) { localRepo = new DirectoryInfo(Path.GetFullPath(".")); } try { RepoProvider repoProvider = new RepoProvider(localRepo.FullName); FileExtractResult extractResult = ParsingUtils.ExtractModels(modelFile); List <string> models = extractResult.Models; if (models.Count == 0) { Outputs.WriteError("No models to import."); return(ReturnCodes.ValidationError); } Outputs.WriteOut($"- Validating models conform to DTDL..."); ModelParser parser = repoProvider.GetDtdlParser(); await parser.ParseAsync(models); if (strict) { foreach (string content in models) { string dtmi = ParsingUtils.GetRootId(content); Outputs.WriteOut($"- Ensuring DTMIs namespace conformance for model \"{dtmi}\"..."); List <string> invalidSubDtmis = Validations.EnsureSubDtmiNamespace(content); if (invalidSubDtmis.Count > 0) { Outputs.WriteError( $"The following DTMI's do not start with the root DTMI namespace:{Environment.NewLine}{string.Join($",{Environment.NewLine}", invalidSubDtmis)}"); return(ReturnCodes.ValidationError); } } } foreach (string content in models) { ModelImporter.Import(content, localRepo); } } catch (ResolutionException resolutionEx) { Outputs.WriteError(resolutionEx.Message); return(ReturnCodes.ResolutionError); } catch (RequestFailedException requestEx) { Outputs.WriteError(requestEx.Message); return(ReturnCodes.ResolutionError); } catch (ParsingException parsingEx) { IList <ParsingError> errors = parsingEx.Errors; string normalizedErrors = string.Empty; foreach (ParsingError error in errors) { normalizedErrors += $"{Environment.NewLine}{error.Message}"; } Outputs.WriteError(normalizedErrors); return(ReturnCodes.ValidationError); } catch (IOException ioEx) { Outputs.WriteError(ioEx.Message); return(ReturnCodes.InvalidArguments); } catch (ArgumentException argEx) { Outputs.WriteError(argEx.Message); return(ReturnCodes.InvalidArguments); } catch (System.Text.Json.JsonException jsonEx) { Outputs.WriteError($"Parsing json-ld content. Details: {jsonEx.Message}"); return(ReturnCodes.InvalidArguments); } return(ReturnCodes.Success); }
/// <summary> /// Generates a DTDL JSON file from an OWL-based RDF file. /// </summary> /// <param name="rdfFile">RDF input file</param> /// <param name="dtdlFile">DTDL output file</param> private static void GenerateDTDL(FileInfo rdfFile, FileInfo dtdlFile) { try { Console.WriteLine("Reading file..."); FileLoader.Load(_ontologyGraph, rdfFile.FullName); // Start looping through for each owl:Class foreach (OntologyClass owlClass in _ontologyGraph.OwlClasses) { // Generate a DTMI for the owl:Class string Id = GenerateDTMI(owlClass); if (!String.IsNullOrEmpty(Id)) { Console.WriteLine($"{owlClass.Resource.ToString()} -> {Id}"); // Create Interface DtdlInterface dtdlInterface = new DtdlInterface { Id = Id, Type = "Interface", DisplayName = GetInterfaceDisplayName(owlClass), Comment = GetInterfaceComment(owlClass), Description = "", Contents = new List <DtdlContents>() }; // Use DTDL 'extends' for super classes IEnumerable <OntologyClass> foundSuperClasses = owlClass.DirectSuperClasses; if (foundSuperClasses.Any()) { List <string> extendsList = new List <string>(); int extendsMax = 0; foreach (var superClass in foundSuperClasses) { // DTDL v2 allows for a maximum of 2 extends. We ignore the other super classes if (extendsMax < 2) { string superClassId = GenerateDTMI(superClass); if (superClassId != null) { extendsList.Add(superClassId); extendsMax++; } } } dtdlInterface.Extends = extendsList; } List <OntologyProperty> properties; // Get list of properties which have this class as a domain properties = owlClass.IsDomainOf.ToList(); foreach (var property in properties) { // An owl:ObjectProperty is used to create a DTDL relationship. if (property.Types.First().ToString() == "http://www.w3.org/2002/07/owl#ObjectProperty") { Console.WriteLine($" Found relationship: {property}"); // If IRI, parse out relationship name from IRI if (property.ToString().Contains("#")) { int index = property.ToString().LastIndexOf("#"); property.AddLabel(property.ToString().Substring(index + 1)); } else if (property.ToString().Contains("/")) { int index = property.ToString().LastIndexOf("/"); property.AddLabel(property.ToString().Substring(index + 1)); } // Create relationship DtdlContents dtdlRelationship = new DtdlContents { Name = Trim(property.ToString()), Type = "Relationship", DisplayName = GetRelationshipDisplayName(property), Comment = GetComment(property) }; // DTDL only supports a single target Id. var range = property.Ranges.FirstOrDefault(); if (range == null) { // If no range is found, we omit the DTDL target property. // This allows any Interface to be the target. Console.WriteLine(" No target found."); } else { Console.WriteLine($" Found target: {range}"); // Convert range to DTMI and add to DTDL relationship target. string target = GenerateDTMI(range); dtdlRelationship.Target = target; } // Add relationship to the Interface dtdlInterface.Contents.Add(dtdlRelationship); } // An owl:DatatypeProperty is used to create a DTDL property. if (property.Types.First().ToString() == "http://www.w3.org/2002/07/owl#DatatypeProperty") { Console.WriteLine($" Found property: {property}"); // Create property DtdlContents dtdlProperty = new DtdlContents { Name = Trim(property.ToString()), Type = "Property", Schema = _map[property.Ranges.FirstOrDefault().ToString()], Comment = GetComment(property), Writable = true }; // Add the Property to the Interface dtdlInterface.Contents.Add(dtdlProperty); } // An owl:AnnotationProperty is used to create a DTDL property. if (property.Types.First().ToString() == "http://www.w3.org/2002/07/owl#AnnotationProperty") { Console.WriteLine($" Found property: {property}"); // Create property DtdlContents dtdlProperty = new DtdlContents { Name = Trim(property.ToString()), Type = "Property", // TODO: Lookup actual data type and create complex DTDL schema or map to DTDL semantic type Schema = "float", Comment = GetComment(property), Writable = true }; // Add the Property to the Interface dtdlInterface.Contents.Add(dtdlProperty); } } // Add the DTDL context to the Interface dtdlInterface.Context = _context; // Add interface to the list of interfaces _interfaceList.Add(dtdlInterface); } } if (_interfaceList.Count == 0) { throw new Exception("No OWL:Classes found."); } // Serialize to JSON var json = JsonConvert.SerializeObject(_interfaceList); // Save to file System.IO.File.WriteAllText(dtdlFile.ToString(), json); Console.WriteLine($"DTDL written to: {dtdlFile}"); // Run DTDL validation Console.WriteLine("Validating DTDL..."); ModelParser modelParser = new ModelParser(); List <string> modelJson = new List <string>(); modelJson.Add(json); IReadOnlyDictionary <Dtmi, DTEntityInfo> parseTask = modelParser.ParseAsync(modelJson).GetAwaiter().GetResult(); } catch (ParsingException pe) { Console.WriteLine($"*** Error parsing models"); int errCount = 1; foreach (ParsingError err in pe.Errors) { Console.WriteLine($"Error {errCount}:"); Console.WriteLine($"{err.Message}"); Console.WriteLine($"Primary ID: {err.PrimaryID}"); Console.WriteLine($"Secondary ID: {err.SecondaryID}"); Console.WriteLine($"Property: {err.Property}\n"); errCount++; } } catch (Exception e) { Console.WriteLine($"{e.Message}"); } Console.WriteLine($"Finished!"); }
async Task RunAsync() { var httpClient = new HttpClient(); var digitalTwinsClient = new DigitalTwinsClient(_digitalTwinsInstanceUrl, _credential, new DigitalTwinsClientOptions { Transport = new HttpClientTransport(httpClient) }); _log.LogInformation("Reading model file {modelsFile}", _digitalTwinsModelsFile); var modelList = new[] { _digitalTwinsModelsFile }.Select(File.ReadAllText).ToList(); var parser = new ModelParser(); var parsed = await parser.ParseAsync(modelList); _log.LogInformation("Parsed {entityCount} entities", parsed.Keys.Count()); var models = modelList .SelectMany(JsonConvert.DeserializeObject <List <JObject> >) .ToList(); var(successCount, conflictCount) = (0, 0); foreach (var model in models) { var modelString = JsonConvert.SerializeObject(model); try { await digitalTwinsClient.CreateModelsAsync(new[] { modelString }); successCount++; } catch (RequestFailedException e) when(e.Status == 409) // Conflict { // ignore conflictCount++; } } _log.LogInformation("Uploaded {successCount} entities, skipped {conflictCount} entities", successCount, conflictCount); var f = models.FirstOrDefault()?.GetValue("@id"); if (f is null) { _log.LogInformation("Not creating twins"); return; } DigitalTwinMetadata twinMetadata = new DigitalTwinMetadata { ModelId = f.ToString() }; _log.LogInformation("Creating {numTwins} device twins of type {twinType}", NumTwins, twinMetadata.ModelId); var num = 0; Parallel.For(0, NumTwins, new ParallelOptions { MaxDegreeOfParallelism = 50 }, i => { var deviceId = $"contoso-device-id-{i.ToString("000000")}"; digitalTwinsClient.CreateOrReplaceDigitalTwin(deviceId, new BasicDigitalTwin { Metadata = twinMetadata }); _log.LogDebug("Created twin {deviceId}", deviceId); var n = Interlocked.Increment(ref num); if (n % 100 == 0) { _log.LogInformation("Created twin {n} of {numTwins}", n, NumTwins); } }); _log.LogInformation("Created {numTwins} twins", NumTwins); }
public DTDLParser(string root, string ext) { Log.Ok("Simple DTDL Validator"); DirectoryInfo dinfo = null; try { dinfo = new DirectoryInfo(root); } catch (Exception e) { Log.Error($"Error accessing the target directory '{root}': \n{e.Message}"); return; } Log.Alert($"Validating *.{ext} files in folder '{dinfo.FullName}'."); if (dinfo.Exists == false) { Log.Error($"Specified directory '{root}' does not exist: Exiting..."); return; } else { SearchOption searchOpt = SearchOption.AllDirectories; var files = dinfo.EnumerateFiles($"*.{ext}", searchOpt); if (files.Count() == 0) { Log.Alert("No matching files found. Exiting."); return; } Dictionary <FileInfo, string> modelDict = new Dictionary <FileInfo, string>(); int count = 0; string lastFile = "<none>"; try { foreach (FileInfo fi in files) { StreamReader r = new StreamReader(fi.FullName); string dtdl = r.ReadToEnd(); r.Close(); modelDict.Add(fi, dtdl); lastFile = fi.FullName; count++; } } catch (Exception e) { Log.Error($"Could not read files. \nLast file read: {lastFile}\nError: \n{e.Message}"); return; } Log.Ok($"Read {count} files from specified directory"); int errJson = 0; foreach (FileInfo fi in modelDict.Keys) { modelDict.TryGetValue(fi, out string dtdl); try { JsonDocument.Parse(dtdl); } catch (Exception e) { Log.Error($"Invalid json found in file {fi.FullName}.\nJson parser error \n{e.Message}"); errJson++; } } if (errJson > 0) { Log.Error($"\nFound {errJson} Json parsing errors"); return; } Log.Ok($"Validated JSON for all files - now validating DTDL"); List <string> modelList = modelDict.Values.ToList <string>(); ModelParser parser = new ModelParser(); parser.DtmiResolver = Resolver; try { Stopwatch s = Stopwatch.StartNew(); DTDLObjectModel = parser.ParseAsync(modelList).GetAwaiter().GetResult(); s.Stop(); Log.Out(""); Log.Ok($"**********************************************"); Log.Ok($"** Validated all files - Your DTDL is valid **"); Log.Ok($"**********************************************"); Log.Out($"Found a total of {DTDLObjectModel.Keys.Count()} entities"); Log.Out($"Parsing took {s.ElapsedMilliseconds}ms"); DTDLInterfaces = new List <DTInterfaceInfo>(); IEnumerable <DTInterfaceInfo> ifenum = from entity in DTDLObjectModel.Values where entity.EntityKind == DTEntityKind.Interface select entity as DTInterfaceInfo; DTDLInterfaces.AddRange(ifenum); } catch (ParsingException pe) { Log.Error($"*** Error parsing models"); int derrcount = 1; foreach (ParsingError err in pe.Errors) { Log.Error($"Error {derrcount}:"); Log.Error($"{err.Message}"); Log.Error($"Primary ID: {err.PrimaryID}"); Log.Error($"Secondary ID: {err.SecondaryID}"); Log.Error($"Property: {err.Property}\n"); derrcount++; } return; } catch (ResolutionException rex) { Log.Error("Could not resolve required references"); } } }
public static async Task <Dictionary <string, DTDLCommandContainer> > ParseDTDLAndGetCommandsAsync(JArray dtdlArray) { if (dtdlArray == null) { throw new ArgumentNullException(nameof(dtdlArray)); } Dictionary <string, DTDLCommandContainer> globalResult = new Dictionary <string, DTDLCommandContainer>(); DTDLCommandContainer itemResult = null; ModelParser parser = new ModelParser(); JArray contents = null; IReadOnlyDictionary <Dtmi, DTEntityInfo> parseResult = await parser.ParseAsync(dtdlArray.Select(i => JsonConvert.SerializeObject(i))); foreach (JObject dtdl in dtdlArray) { try { //PROCESS COMPONENTS await ProcessComponentsWithCommands(dtdlArray, dtdl, globalResult); //CONTENT if (!dtdl.ContainsKey("contents")) { throw new Exception("The DTDL model does not contain any 'content' property."); } contents = (JArray)dtdl["contents"]; itemResult = new DTDLCommandContainer { ModelId = dtdl["@id"].Value <string>(), DTDL = dtdl }; itemResult.Commands = ExtractCommands(contents); } catch (ParsingException pex) { if (itemResult == null) { itemResult = new DTDLCommandContainer(); } itemResult.ParsingErrors = pex.Errors.Select(i => i.Message); } catch (Exception ex) { itemResult = null; } finally { if (itemResult != null && itemResult.Commands != null) { if (!globalResult.ContainsKey(dtdl["@id"].Value <string>())) { globalResult.Add(dtdl["@id"].Value <string>(), itemResult); } } itemResult = null; } } return(globalResult); }
public async Task MT3620StarterKit_DTDL_With_Semantics_And_Units_OK() { string dtdlModelPath = @"./Tests/Avnet/mt3620starterkit-1.json"; string modelId = "dtmi:avnet:mt3620Starterkit;1"; Assert.IsTrue(File.Exists(dtdlModelPath)); var modelContainer = await DTDLHelper.GetModelsAndBuildDynamicContentAsync(modelId, dtdlModelPath); Assert.IsNotNull(modelContainer); var readablePropertiesGenerated = modelContainer.Where(i => i.Value != null && i.Value.DTDLGeneratedData != null && i.Value.DTDLGeneratedData.ReadableProperties != null); Assert.IsTrue(readablePropertiesGenerated.Any()); var telemetriesGenerated = modelContainer.Where(i => i.Value != null && i.Value.DTDLGeneratedData != null && i.Value.DTDLGeneratedData.Telemetries != null); Assert.IsTrue(telemetriesGenerated.Any()); var commandsGenerated = modelContainer.Where(i => i.Value != null && i.Value.DTDLGeneratedData != null && i.Value.DTDLGeneratedData.Commands != null); Assert.IsTrue(commandsGenerated.Any()); var writablePropertiesGenerated = modelContainer.Where(i => i.Value != null && i.Value.DTDLGeneratedData != null && i.Value.DTDLGeneratedData.WritableProperties != null); Assert.IsTrue(writablePropertiesGenerated.Any()); //Additional assets string stringModel = await File.ReadAllTextAsync(dtdlModelPath); Assert.IsTrue(!string.IsNullOrEmpty(stringModel)); ModelParser modelParser = new ModelParser(); IReadOnlyDictionary <Dtmi, DTEntityInfo> dtdl = await modelParser.ParseAsync(new List <string> { stringModel }); Assert.IsNotNull(dtdl); Assert.IsNotNull(dtdl.Values); var interfaces = dtdl.Values.Where(i => i.EntityKind == DTEntityKind.Interface); Assert.IsNotNull(interfaces); //Telemetries var telemetriesParsed = dtdl.Values.Where(i => i.EntityKind == DTEntityKind.Telemetry); Assert.IsNotNull(telemetriesParsed); var generatedTelemetriesContainer = telemetriesGenerated.SingleOrDefault(); Assert.IsNotNull(generatedTelemetriesContainer.Value); Assert.IsNotNull(generatedTelemetriesContainer.Value.DTDLGeneratedData); var generatedTelemetriesContent = generatedTelemetriesContainer.Value.DTDLGeneratedData.Telemetries; Assert.IsNotNull(generatedTelemetriesContent); Assert.IsTrue(generatedTelemetriesContent.Count() == telemetriesParsed.Count()); //Commands var commandsParsed = dtdl.Values.Where(i => i.EntityKind == DTEntityKind.Command); Assert.IsNotNull(commandsParsed); var generatedCommandContainer = commandsGenerated.SingleOrDefault(); Assert.IsNotNull(generatedCommandContainer.Value); Assert.IsNotNull(generatedCommandContainer.Value.DTDLGeneratedData); var generatedCommandsContent = generatedCommandContainer.Value.DTDLGeneratedData.Commands; Assert.IsNotNull(generatedCommandsContent); Assert.IsTrue(generatedCommandsContent.Count() == commandsParsed.Count()); //Properties var propertiesParsed = dtdl.Values.Where(i => i.EntityKind == DTEntityKind.Property); Assert.IsNotNull(propertiesParsed); var generatedWritablePropertiesContainer = writablePropertiesGenerated.SingleOrDefault(); Assert.IsNotNull(generatedWritablePropertiesContainer.Value); Assert.IsNotNull(generatedWritablePropertiesContainer.Value.DTDLGeneratedData); var generatedWritableContent = generatedWritablePropertiesContainer.Value.DTDLGeneratedData.WritableProperties; int propertiesCounter = generatedWritableContent != null ? generatedWritableContent.Count : 0; var generatedReadablePropertiesContainer = readablePropertiesGenerated.SingleOrDefault(); Assert.IsNotNull(generatedReadablePropertiesContainer.Value); Assert.IsNotNull(generatedReadablePropertiesContainer.Value.DTDLGeneratedData); var generatedReadableContent = generatedReadablePropertiesContainer.Value.DTDLGeneratedData.ReadableProperties; propertiesCounter = propertiesCounter + ((generatedReadableContent != null) ? generatedReadableContent.Count : 0); Assert.IsTrue(propertiesCounter == propertiesParsed.Count()); }