public static async Task <int> Validate(FileInfo modelFile, string repo, bool strict) { try { RepoProvider repoProvider = new RepoProvider(repo); FileExtractResult extractResult = ParsingUtils.ExtractModels(modelFile); List <string> models = extractResult.Models; if (models.Count == 0) { Outputs.WriteError("No models to validate."); return(ReturnCodes.InvalidArguments); } ModelParser parser; if (models.Count > 1) { // Special case: when validating from an array, only use array contents for resolution. // Setup vanilla parser with no resolution. We get a better error message when a delegate is assigned. parser = new ModelParser { DtmiResolver = (IReadOnlyCollection <Dtmi> dtmis) => { return(Task.FromResult(Enumerable.Empty <string>())); } }; } else { parser = repoProvider.GetDtdlParser(); } Outputs.WriteOut($"- Validating models conform to DTDL..."); await parser.ParseAsync(models); if (strict) { if (extractResult.ContentKind == JsonValueKind.Array || models.Count > 1) { // Related to file path validation. Outputs.WriteError("Strict validation requires a single root model object."); return(ReturnCodes.ValidationError); } string dtmi = ParsingUtils.GetRootId(models[0]); Outputs.WriteOut($"- Ensuring DTMIs namespace conformance for model \"{dtmi}\"..."); List <string> invalidSubDtmis = Validations.EnsureSubDtmiNamespace(models[0]); 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); } // TODO: Evaluate changing how file path validation is invoked. if (RepoProvider.IsRemoteEndpoint(repo)) { Outputs.WriteError($"Model file path validation requires a local repository."); return(ReturnCodes.ValidationError); } Outputs.WriteOut($"- Ensuring model file path adheres to DMR path conventions..."); string filePathError = Validations.EnsureValidModelFilePath(modelFile.FullName, models[0], repo); if (filePathError != null) { Outputs.WriteError( $"File \"{modelFile.FullName}\" does not adhere to DMR path conventions. Expecting \"{filePathError}\"."); return(ReturnCodes.ValidationError); } } } 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); }
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); }