Пример #1
0
        public async Task <int> Convert(string input, string output, params IArgument[] arguments)
        {
            var inputArg  = new InputFilePath(input);
            var outputArg = new OutputFilePath(output);
            var args      = ArgumentHelper.CreateArgumentString(inputArg, outputArg, arguments);

            return(await Convert(args));
        }
        public bool Equals(CompilerOptions other)
        {
            if (other == null)
            {
                return(false);
            }

            return(InputFilePath.Equals(other.InputFilePath, StringComparison.OrdinalIgnoreCase));
        }
Пример #3
0
        protected override void Execute(CodeActivityContext context)
        {
            try
            {
                string       inputFilePath   = InputFilePath.Get(context);
                string       outputFilePath  = OutputFilePath.Get(context);
                string       key             = Key.Get(context);
                SecureString keySecureString = KeySecureString.Get(context);
                Encoding     keyEncoding     = KeyEncoding.Get(context);

                if (string.IsNullOrWhiteSpace(inputFilePath))
                {
                    throw new ArgumentNullException(Resources.InputFilePathDisplayName);
                }
                if (string.IsNullOrWhiteSpace(outputFilePath))
                {
                    throw new ArgumentNullException(Resources.OutputFilePathDisplayName);
                }
                if (string.IsNullOrWhiteSpace(key) && keySecureString == null)
                {
                    throw new ArgumentNullException(Resources.KeyAndSecureStringNull);
                }
                if (key != null && keySecureString != null)
                {
                    throw new ArgumentNullException(Resources.KeyAndSecureStringNotNull);
                }
                if (keyEncoding == null)
                {
                    throw new ArgumentNullException(Resources.Encoding);
                }
                if (!File.Exists(inputFilePath))
                {
                    throw new ArgumentException(Resources.FileDoesNotExistsException, Resources.InputFilePathDisplayName);
                }
                // Because we use File.WriteAllText below, we don't need to delete the file now.
                if (File.Exists(outputFilePath) && !Overwrite)
                {
                    throw new ArgumentException(Resources.FileAlreadyExistsException, Resources.OutputFilePathDisplayName);
                }

                byte[] encrypted = CryptographyHelper.EncryptData(Algorithm, File.ReadAllBytes(inputFilePath), CryptographyHelper.KeyEncoding(keyEncoding, key, keySecureString));


                // This overwrites the file if it already exists.
                File.WriteAllBytes(outputFilePath, encrypted);
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                if (!ContinueOnError.Get(context))
                {
                    throw;
                }
            }
        }
Пример #4
0
        protected override int ExecuteCommand(CommandLineApplication app, IConsole console)
        {
            var outputFile = OutputFile ?? Path.Combine(Directory.GetCurrentDirectory(), $"{Path.GetFileNameWithoutExtension(InputFilePath)}.i");

            Utils.CreateDirectoryForFileIfNeeded(outputFile);

            string output;

            if (InputFilePath.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
            {
                var temporaryXsd = Path.Combine(Path.GetDirectoryName(outputFile.ToAbsolutePath()), Path.GetTempFileName());
                try {
                    using (XmlReader reader = XmlReader.Create(InputFilePath)) {
                        XmlSchemaInference schema = new XmlSchemaInference();
                        var schemaSet             = schema.InferSchema(reader);
                        foreach (XmlSchema s in schemaSet.Schemas())
                        {
                            using (var stringWriter = new StringWriterWithEncoding(Encoding.UTF8)) {
                                using (var writer = XmlWriter.Create(stringWriter)) {
                                    s.Write(writer);
                                }

                                File.WriteAllText(temporaryXsd, stringWriter.ToString());
                            }
                        }
                    }

                    output = UoeUtilities.GenerateDatasetDefinition(GetDlcPath(), temporaryXsd, outputFile);
                } finally {
                    Utils.DeleteFileIfNeeded(temporaryXsd);
                }
            }
            else
            {
                output = UoeUtilities.GenerateDatasetDefinition(GetDlcPath(), InputFilePath.ToAbsolutePath(), outputFile);
            }

            Log.Debug(output);

            if (!File.Exists(outputFile))
            {
                throw new CommandException($"The dataset definition file (.i) was not successfully generated, the following file has not been found: {outputFile.PrettyQuote()}.");
            }

            return(0);
        }
Пример #5
0
        /// <summary>
        /// Saves the image to the source image folder, using the name of the original source image and an optional suffix to append to the output file.
        /// </summary>
        /// <param name="suffix">An optional suffix to append to the end of the new file name (e.g. ' - modified').</param>
        /// <param name="overwriteExistingImage">Overwrites the existing image located at the new file path (default == false).</param>
        public void Save(string suffix = "", bool overwriteExistingImage = false)
        {
            using (MemoryStream memstr = new MemoryStream(DataStream.Bytes))
            {
                Image i = Image.FromStream(memstr);

                string filepath = string.Empty;

                if (!String.IsNullOrEmpty(suffix))
                {
                    if (suffix.EndsWith(".gif"))
                    {
                        suffix = suffix.Replace(".gif", String.Empty);
                    }

                    filepath = InputFilePath.ToLower().Replace(".gif", suffix += ".gif");
                }

                if (File.Exists(filepath))
                {
                    if (overwriteExistingImage)
                    {
                        i.Save(filepath);
                    }
                    else
                    {
                        throw new InvalidOperationException(
                                  @"The save operation failed because an image already exists at the specified location.  Images cannot be overwritten unless explicitly specified, as VCVJ is known to cause irreparable harm to GIF images."
                                  );
                    }
                }
                else
                {
                    i.Save(filepath);
                }
            }
        }
Пример #6
0
        private byte[] GenerateFromHost()
        {
            var projectDirectory    = Path.GetDirectoryName(GetProject().FullName);
            var projectRelativePath = InputFilePath.Substring(projectDirectory.Length);

            using (var hostManager = new HostManager(projectDirectory))
            {
                var host = hostManager.CreateHost(InputFilePath, projectRelativePath, GetCodeProvider(), FileNameSpace);
                host.Error += (o, eventArgs) =>
                {
                    GeneratorError(0, eventArgs.ErrorMessage, eventArgs.LineNumber, eventArgs.ColumnNumber);
                };
                host.Progress += (o, eventArgs) =>
                {
                    if (CodeGeneratorProgress != null)
                    {
                        CodeGeneratorProgress.Progress(eventArgs.Completed, eventArgs.Total);
                    }
                };

                var content = host.GenerateCode();
                return(ConvertToBytes(content));
            }
        }
Пример #7
0
        private CodeCompileUnit GenerateCodeByRazor(string inputFileContent)
        {
            var projectPath         = Path.GetDirectoryName(GetProject().FullName);
            var projectRelativePath = InputFilePath.Substring(projectPath.Length);
            var virtualPath         = VirtualPathUtility.ToAppRelative("~" + projectRelativePath);

            var config = WebConfigurationManager.OpenMappedWebConfiguration(new WebConfigurationFileMap {
                VirtualDirectories = { { "/", new VirtualDirectoryMapping(projectPath, true) } }
            }, projectRelativePath);

            var sectGroup = new RazorWebSectionGroup
            {
                Host = (HostSection)config.GetSection(HostSection.SectionName) ??
                       new HostSection {
                    FactoryType = typeof(MvcWebRazorHostFactory).AssemblyQualifiedName
                },
                Pages = (RazorPagesSection)config.GetSection(RazorPagesSection.SectionName)
            };

            var host = projectRelativePath.IndexOf("app_code", StringComparison.InvariantCultureIgnoreCase) >= 0 ?
                       /* Helper file:  */ new WebCodeRazorHost(virtualPath, InputFilePath) :
                       /* Regular view: */ WebRazorHostFactory.CreateHostFromConfig(sectGroup, virtualPath, InputFilePath);

            host.DefaultNamespace        = FileNameSpace;
            host.DefaultDebugCompilation = string.Equals(GetVSProject().Project.ConfigurationManager.ActiveConfiguration.ConfigurationName, "debug", StringComparison.InvariantCultureIgnoreCase);
            host.DefaultClassName        = Path.GetFileNameWithoutExtension(InputFilePath).Replace('.', '_');

            var res = new RazorTemplateEngine(host).GenerateCode(new StringReader(inputFileContent), null, null, InputFilePath);

            foreach (RazorError error in res.ParserErrors)
            {
                GeneratorError(4, error.Message, (uint)error.Location.LineIndex + 1, (uint)error.Location.CharacterIndex + 1);
            }

            return(res.ParserErrors.Count > 0 ? null : res.GeneratedCode);
        }
        protected override byte[] GenerateCode(string inputFileContent)
        {
            var projectItem = GetProjectItem();

            var codeProvider = GetCodeProvider();

            var spans = Scanner.GetSpans(inputFileContent, true);

            var originalName = GetLastKnownFileName(projectItem);

            if (!originalName.Equals(projectItem.Name, StringComparison.InvariantCultureIgnoreCase))
            {
                RemoveOrphanedItem(projectItem, $"{originalName}.{codeProvider.FileExtension}");
            }

            if (spans.Any(a => a.Errors.Any()))
            {
                return(Encoding.UTF8.GetBytes("Error Generating Content"));
            }

            var content = SpansToContent.Convert(spans);


            var enumCode = content.GetEnumCode(codeProvider, FileNamespace);

            if (!string.IsNullOrWhiteSpace(enumCode))
            {
                CreateEnumFile(codeProvider, Encoding.UTF8.GetBytes(enumCode), projectItem);
            }
            else
            {
                foreach (ProjectItem item in projectItem.ProjectItems)
                {
                    if (item.Name.EndsWith(".cs"))
                    {
                        item.Delete();
                    }
                }
            }

            var solution = projectItem.ContainingProject.DTE.Solution;

            var relativePath = InputFilePath.Remove(0, Path.GetDirectoryName(solution.FullName)?.Length ?? 0);

            var sqlBytes = Encoding.UTF8.GetBytes(content.GetSqlCode(relativePath));

            if (string.IsNullOrWhiteSpace(content.CopySql))
            {
                return(sqlBytes);
            }

            var copyLocation = solution.FindProjectItem(content.CopySql);

            if (copyLocation == null)
            {
                GeneratorError(1, $"Could not find {content.CopySql} for copy operation", 0, 0);
                return(sqlBytes);
            }

            var targetPath = copyLocation.Properties.Item("FullPath").Value.ToString();

            if (!Directory.Exists(targetPath))
            {
                GeneratorError(1, $"{content.CopySql} is not a folder", 0, 0);
                return(sqlBytes);
            }

            if (!projectItem.Name.Equals(originalName, StringComparison.InvariantCultureIgnoreCase))
            {
                RemoveOrphanedItem(copyLocation, $"{originalName}.sql");
            }

            var copyFile = $"{targetPath}{projectItem.Name}.sql";

            if (WriteFile(copyFile, sqlBytes))
            {
                copyLocation.ProjectItems.AddFromFile(copyFile).Properties.Item("BuildAction").Value = "None";
            }

            return(sqlBytes);
        }
Пример #9
0
        /// <summary>
        /// Function that builds the contents of the generated file based on the contents of the input file
        /// </summary>
        /// <param name="inputFileContent">Content of the input file</param>
        /// <returns>Generated file as a byte array</returns>
        protected override byte[] GenerateCode(string inputFileContent)
        {
            var references = GetVSProject().References;
            //add reference to our buildprovider and virtualpathprovider
            var buildprovAssembly = typeof(CompiledVirtualPathProvider).Assembly;

            if (references.Find(buildprovAssembly.GetName().Name) == null)
            {
                references.Add(buildprovAssembly.Location);
            }

            // Get the root folder of the project
            var appRoot = Path.GetDirectoryName(GetProject().FullName);

            // Determine the project-relative path
            string projectRelativePath = InputFilePath.Substring(appRoot.Length);

            // Turn it into a virtual path by prepending ~ and fixing it up
            string virtualPath = VirtualPathUtility.ToAppRelative("~" + projectRelativePath);

            var vdm  = new VirtualDirectoryMapping(appRoot, true);
            var wcfm = new WebConfigurationFileMap();

            wcfm.VirtualDirectories.Add("/", vdm);

            var config = WebConfigurationManager.OpenMappedWebConfiguration(wcfm, projectRelativePath);
            //System.Configuration.ConfigurationManager.OpenExeConfiguration(configFile);

            var sectGroup = new RazorWebSectionGroup
            {
                Host = (HostSection)config.GetSection(HostSection.SectionName) ??
                       new HostSection {
                    FactoryType = typeof(MvcWebRazorHostFactory).AssemblyQualifiedName
                },
                Pages = (RazorPagesSection)config.GetSection(RazorPagesSection.SectionName)
            };

            // Create the same type of Razor host that's used to process Razor files in App_Code
            var host = IsHelper ?
                       new WebCodeRazorHost(virtualPath, InputFilePath) :
                       WebRazorHostFactory.CreateHostFromConfig(sectGroup, virtualPath, InputFilePath);

            // Set the namespace to be the same as what's used by default for regular .cs files
            host.DefaultNamespace = FileNameSpace;

            host.NamespaceImports.Remove("WebMatrix.Data");
            host.NamespaceImports.Remove("WebMatrix.WebData");

            var systemWebPages = config.GetSection("system.web/pages") as PagesSection;

            if (systemWebPages != null)
            {
                foreach (NamespaceInfo ns in systemWebPages.Namespaces)
                {
                    if (!host.NamespaceImports.Contains(ns.Namespace))
                    {
                        host.NamespaceImports.Add(ns.Namespace);
                    }
                }
            }

            var compilationSection = config.GetSection("system.web/compilation") as CompilationSection;

            if (compilationSection != null)
            {
                foreach (AssemblyInfo assembly in compilationSection.Assemblies)
                {
                    if (assembly.Assembly != "*" && references.Find(assembly.Assembly) == null)
                    {
                        references.Add(assembly.Assembly);
                    }
                }
            }

            // Create a Razor engine and pass it our host
            var engine = new RazorTemplateEngine(host);

            // Generate code
            GeneratorResults results = null;

            try {
                using (TextReader reader = new StringReader(inputFileContent)) {
                    results = engine.GenerateCode(reader, null, null, InputFilePath);
                }
            }
            catch (Exception e) {
                this.GeneratorError(4, e.ToString(), 1, 1);
                //Returning null signifies that generation has failed
                return(null);
            }

            // Output errors
            foreach (RazorError error in results.ParserErrors)
            {
                GeneratorError(4, error.Message, (uint)error.Location.LineIndex + 1, (uint)error.Location.CharacterIndex + 1);
            }

            CodeDomProvider provider = GetCodeProvider();

            try {
                if (this.CodeGeneratorProgress != null)
                {
                    //Report that we are 1/2 done
                    this.CodeGeneratorProgress.Progress(50, 100);
                }

                using (StringWriter writer = new StringWriter(new StringBuilder())) {
                    CodeGeneratorOptions options = new CodeGeneratorOptions();
                    options.BlankLinesBetweenMembers = false;
                    options.BracingStyle             = "C";

                    // Add a GeneratedCode attribute to the generated class
                    CodeCompileUnit     generatedCode = results.GeneratedCode;
                    var                 ns            = generatedCode.Namespaces[0];
                    CodeTypeDeclaration generatedType = ns.Types[0];
                    generatedType.CustomAttributes.Add(
                        new CodeAttributeDeclaration(
                            new CodeTypeReference(typeof(GeneratedCodeAttribute)),
                            new CodeAttributeArgument(new CodePrimitiveExpression("MvcRazorClassGenerator")),
                            new CodeAttributeArgument(new CodePrimitiveExpression("1.0"))));

                    if (!IsHelper)
                    {
                        generatedType.CustomAttributes.Add(
                            new CodeAttributeDeclaration(
                                new CodeTypeReference(typeof(PageVirtualPathAttribute)),
                                new CodeAttributeArgument(new CodePrimitiveExpression(virtualPath))));
                    }

                    //Generate the code
                    provider.GenerateCodeFromCompileUnit(generatedCode, writer, options);

                    if (this.CodeGeneratorProgress != null)
                    {
                        //Report that we are done
                        this.CodeGeneratorProgress.Progress(100, 100);
                    }
                    writer.Flush();

                    // Save as UTF8
                    Encoding enc = Encoding.UTF8;

                    //Get the preamble (byte-order mark) for our encoding
                    byte[] preamble       = enc.GetPreamble();
                    int    preambleLength = preamble.Length;

                    //Convert the writer contents to a byte array
                    byte[] body = enc.GetBytes(writer.ToString());

                    //Prepend the preamble to body (store result in resized preamble array)
                    Array.Resize <byte>(ref preamble, preambleLength + body.Length);
                    Array.Copy(body, 0, preamble, preambleLength, body.Length);

                    //Return the combined byte array
                    return(preamble);
                }
            }
            catch (Exception e) {
                this.GeneratorError(4, e.ToString(), 1, 1);
                //Returning null signifies that generation has failed
                return(null);
            }
        }
 public override int GetHashCode()
 {
     return(InputFilePath.GetHashCode());
 }
Пример #11
0
        protected override byte[] GenerateCode(string inputFileContent)
        {
            StringBuilder codes = new StringBuilder();

            System.Diagnostics.Trace.WriteLine("Start GenerateOnFile...");
            log.Clear();
            log.AppendLine("//Code Gen By " + System.Reflection.Assembly.GetCallingAssembly().FullName);
            log.AppendLine("//Start Run:");
            log.AppendLine("//CodeBase " + System.Reflection.Assembly.GetCallingAssembly().CodeBase);
            log.AppendLine("//wszInputFilePath:" + InputFilePath);
            log.AppendLine("//wszDefaultNamespace:" + FileNameSpace);

            if (Config == null)
            {
                try
                {
                    //插件搜索
                    BasePath = new FileInfo(System.Reflection.Assembly.GetCallingAssembly().CodeBase.Replace(@"file:///", "")).Directory.FullName;

                    if (File.Exists(BasePath + ConfigName))
                    {
                        Config = Serializable.Deserialize4File(typeof(Config), BasePath + ConfigName) as Config;
                    }
                }
                catch (Exception e)
                {
                    log.AppendLine(e.ToString());
                }
            }
            log.AppendLine("//BasePath:" + BasePath);
            System.Diagnostics.Trace.WriteLine(log.ToString());
            codes.AppendLine(log.ToString());

            log.Clear();
            if (Config == null)
            {
                Config = new Config();
            }

            if (Config.PlugPath == null)
            {
                System.Diagnostics.Trace.WriteLine("Run PlugManager...");

                try
                {
                    new PlugManager().Show();
                }
                catch
                {
                }
            }
            else
            {
                bool isMatch = false;

                try
                {
                    foreach (var config in Config.PlugConfigs)
                    {
                        if (InputFilePath.EndsWith(config.Exction))
                        {
                            var assembly = Assembly.Load(File.ReadAllBytes(Config.PlugPath + "\\" + config.DllName));
                            if (assembly != null)
                            {
                                var type = assembly.GetType(config.Type).BaseType;
                                if (type != null && type.Name == typeof(BasePlug).Name)
                                {
                                    var plug = Activator.CreateInstance(assembly.GetType(config.Type));
                                    if (plug != null)
                                    {
                                        log.AppendLine("//User Plug:" + config.DllName + " Type:" + config.Type);
                                        var method = plug.GetType().GetMethod("GenerateOnFile");
                                        if (method != null)
                                        {
                                            //plug.GenerateOnFile(codes, wszInputFilePath, bstrInputFileContents,
                                            //                    wszDefaultNamespace);
                                            method.Invoke(plug, new object[]
                                            {
                                                codes,
                                                InputFilePath,
                                                inputFileContent,
                                                FileNameSpace,
                                                Config.PlugPath + config.DllName
                                            });
                                            isMatch = true;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    isMatch = false;
                    MessageBox.Show(e.ToString());
                }
                if (!isMatch)
                {
                    System.Diagnostics.Trace.WriteLine("Run PlugManager...");

                    try
                    {
                        new PlugManager().Show();
                    }
                    catch
                    {
                    }
                }
            }
            codes.AppendLine(log.ToString());

            using (StringWriter writer = new StringWriter(new StringBuilder()))
            {
                if (this.CodeGeneratorProgress != null)
                {
                    //Report that we are done
                    this.CodeGeneratorProgress.Progress(100, 100);
                }
                writer.Write(codes.ToString());
                writer.Flush();


                //Get the Encoding used by the writer. We're getting the WindowsCodePage encoding,
                //which may not work with all languages
                Encoding enc = Encoding.GetEncoding(writer.Encoding.WindowsCodePage);

                //Get the preamble (byte-order mark) for our encoding
                byte[] preamble       = enc.GetPreamble();
                int    preambleLength = preamble.Length;

                //Convert the writer contents to a byte array
                byte[] body = enc.GetBytes(writer.ToString());

                //Prepend the preamble to body (store result in resized preamble array)
                Array.Resize <byte>(ref preamble, preambleLength + body.Length);
                Array.Copy(body, 0, preamble, preambleLength, body.Length);

                //Return the combined byte array
                return(preamble);
            }
        }
Пример #12
0
        protected override void Execute(CodeActivityContext context)
        {
            Result.Set(context, "Not Masked");
            string inputFilePath   = InputFilePath.Get(context);
            string outputDirPath   = OutputDirPath.Get(context);
            string maskingKeyWord  = MaskingKeyWord.Get(context);
            string occurrenceValue = Occurrence.Get(context);
            bool   maskOnlyKeyword = MaskOnlyKeyword.Get(context);

            if (!string.IsNullOrEmpty(inputFilePath) && !string.IsNullOrEmpty(outputDirPath) && !string.IsNullOrEmpty(maskingKeyWord) &&
                maskingKeyWord.IndexOf(" ") < 0 && !string.IsNullOrEmpty(occurrenceValue) && File.Exists(inputFilePath) &&
                Directory.Exists(outputDirPath))
            {
                string redactedPDFNameEscaped = Regex.Replace(Path.GetFileName(inputFilePath), "%", "%%");
                string redactedPDFPath        = $@"{outputDirPath}\{redactedPDFNameEscaped}";
                string jpgFilesDir            = ConvertPDFToJPGs(inputFilePath);
                if (maskOnlyKeyword)
                {
                    if (!string.IsNullOrEmpty(occurrenceValue) && occurrenceValue.Equals("ALL", StringComparison.OrdinalIgnoreCase))
                    {
                        int occurrence       = 0;
                        var redactedJPGFiles = RedactOnlyKeyword(jpgFilesDir, maskingKeyWord, occurrence, maskOnlyKeyword);
                        if (maskingSuccessfull)
                        {
                            ConvertJPGsToPDF(redactedJPGFiles, redactedPDFPath);
                            Result.Set(context, "Success");
                        }
                    }
                    else if (!string.IsNullOrEmpty(occurrenceValue))
                    {
                        if (IsDigitsOnly(occurrenceValue))
                        {
                            int occurrence       = Convert.ToInt32(occurrenceValue);
                            var redactedJPGFiles = RedactOnlyKeyword(jpgFilesDir, maskingKeyWord, occurrence, maskOnlyKeyword);
                            if (maskingSuccessfull)
                            {
                                ConvertJPGsToPDF(redactedJPGFiles, redactedPDFPath);
                                Result.Set(context, "Success");
                            }
                        }
                        else
                        {
                            throw new Exception("Occurrence should contain only digits.");
                        }
                    }
                }
                else if (!string.IsNullOrEmpty(occurrenceValue))
                {
                    if (IsDigitsOnly(occurrenceValue))
                    {
                        int occurrence       = Convert.ToInt32(occurrenceValue);
                        var redactedJPGFiles = RedactTextTillEnd(jpgFilesDir, maskingKeyWord, occurrence, maskOnlyKeyword);
                        if (maskingSuccessfull)
                        {
                            ConvertJPGsToPDF(redactedJPGFiles, redactedPDFPath);
                            Result.Set(context, "Success");
                        }
                    }
                    else
                    {
                        throw new Exception("Occurrence should contain only digits.");
                    }
                }
                Directory.Delete(jpgFilesDir, recursive: true);
            }
            else
            {
                if (!string.IsNullOrEmpty(inputFilePath) && File.Exists(inputFilePath))
                {
                    throw new Exception("Input File Path is not correct.");
                }
                else if (!string.IsNullOrEmpty(outputDirPath) && Directory.Exists(outputDirPath))
                {
                    throw new Exception("Directory Path is not correct.");
                }
                else if (!string.IsNullOrEmpty(maskingKeyWord) && maskingKeyWord.IndexOf(" ") < 0)
                {
                    throw new Exception("Masking Keyword is not correct.");
                }
                else if (!string.IsNullOrEmpty(occurrenceValue))
                {
                    throw new Exception("Occurrence Value should not be null.");
                }
            }
        }