Exemplo n.º 1
0
        protected override CommandResult ExecuteDetailed(GetTargetsCommandArgs args, ChangeObservable observable)
        {
            IEnumerable <Exception> exceptions = Enumerable.Empty <Exception>();
            TargetsCommandResult    commandResult;

            if (args.All)
            {
                commandResult = new TargetsCommandResult(sdkRepository.GetAllTargets()
                                                         .Select(t => new TargetResult(t.Name, t.Version,
                                                                                       t.LongVersion,
                                                                                       t.ShortVersion))
                                                         .OrderBy(t => t.Name).ThenByDescending(t => t.Version));
            }
            else
            {
                ExecutionContext.WriteWarning("This command is deprecated. Use 'get project-information' instead.", false);

                ProjectEntity project          = ProjectEntity.Decorate(entityFactory.Create(Guid.NewGuid().ToByteString(), args).Root);
                TargetsResult targetsResult    = targetParser.Targets(project, false);
                Target[]      availableTargets = sdkRepository.GetAllTargets().ToArray();
                commandResult = new TargetsCommandResult(targetsResult.ValidTargets
                                                         .Select(t => new TargetResult(t.Name, t.Version,
                                                                                       t.LongVersion,
                                                                                       t.ShortVersion,
                                                                                       availableTargets.Any(at => t.Name == at.Name && at.LongVersion == t.LongVersion)))
                                                         .OrderBy(t => t.Name).ThenByDescending(t => t.Version));
                exceptions = targetsResult.Errors;
            }

            return(new CommandResult(0, commandResult, exceptions));
        }
Exemplo n.º 2
0
        protected override CommandResult ExecuteDetailed(GetSdksCommandArgs args, ChangeObservable observable)
        {
            IEnumerable <SdkPath>   sdkPaths   = Enumerable.Empty <SdkPath>();
            IEnumerable <Exception> exceptions = Enumerable.Empty <Exception>();

            if (args.All)
            {
                sdkPaths = sdkRepository.GetAllTargets()
                           .GroupBy(target => sdkRepository.GetSdk(target).Root.FullName)
                           .Select(group => new SdkPath(group.Key, group.Select(target => new TargetResult(target.Name,
                                                                                                           target.Version,
                                                                                                           target.LongVersion,
                                                                                                           target.ShortVersion))));
            }
            else
            {
                ProjectEntity project       = ProjectEntity.Decorate(entityFactory.Create(Guid.NewGuid().ToByteString(), args).Root);
                TargetsResult targetsResult = targetParser.Targets(project);
                sdkPaths = targetsResult.ValidTargets
                           .GroupBy(target => sdkRepository.GetSdk(target).Root.FullName)
                           .Select(group => new SdkPath(group.Key, group.Select(target => new TargetResult(target.Name,
                                                                                                           target.Version,
                                                                                                           target.LongVersion,
                                                                                                           target.ShortVersion))));
                exceptions = targetsResult.Errors;
            }
            return(new CommandResult(0, new SdksCommandResult(sdkPaths)));
        }
Exemplo n.º 3
0
        protected override int Execute(SetTargetsCommandArgs args, ChangeObservable observable)
        {
            ProjectEntity project    = ProjectEntity.Decorate(entityFactory.Create(Guid.NewGuid().ToByteString(), args).Root);
            FileEntity    fileEntity = FileEntity.Decorate(project);

            if (!project.Settings.IsPersistent)
            {
                throw new TargetNotSettableForProjectException();
            }

            if (args.Add)
            {
                Target result = targetParser.AddTarget(project, args.Name, args.Version);
                userInterface.WriteInformation($"Successfully added target {result.Name} {result.LongVersion} to project {fileEntity.Directory.FullName}.");
            }
            else if (args.Remove)
            {
                Target result = targetParser.RemoveTarget(project, args.Name, args.Version);
                userInterface.WriteInformation($"Successfully removed target {result.Name} {result.LongVersion} from project {fileEntity.Directory.FullName}.");
            }
            else
            {
                throw new SetTargetsOptionMissingException();
            }

            return(0);
        }
Exemplo n.º 4
0
        protected override int Execute(UpdateTargetsCommandArgs args, ChangeObservable observable)
        {
            ProjectEntity project = ProjectEntity.Decorate(entityFactory.Create(Guid.NewGuid().ToByteString(), args).Root);

            targetParser.UpdateTargets(project, args.Downgrade);
            return(0);
        }
        public void Execute(Entity dataModel, ChangeObservable observable)
        {
            ProjectEntity project = ProjectEntity.Decorate(dataModel.Root);

            IEnumerable <Entity> targets = project.Targets.ToArray();

            if (!targets.Any())
            {
                throw new FormattableException("Please use --target to specify for which targets the library shall be generated.");
            }

            foreach (Entity target in targets)
            {
                VirtualDirectory deployRoot      = DeployEntity.Decorate(target).DeployDirectory;
                VirtualDirectory deployDirectory = deployRoot.Directory("lib", project.Name);
                BuildEntity      buildEntity     = BuildEntity.Decorate(target);
                if (!buildEntity.HasBuildSystem)
                {
                    TargetEntity targetEntity = TargetEntity.Decorate(target);
                    executionContext.WriteWarning(new CMakeBuildSystemNotFoundException(targetEntity.FullName, buildEntity.BuildType).Message);
                    return;
                }

                foreach (string externalLibrary in buildEntity.BuildSystem.ExternalLibraries)
                {
                    VirtualFile newFile = fileSystem.GetFile(externalLibrary).CopyTo(deployDirectory);
                    executionContext.Observable.OnNext(new Change(() => newFile.Delete(), $"Copied {externalLibrary} to {newFile.FullName}."));
                }
            }
        }
Exemplo n.º 6
0
        protected override CommandResult ExecuteDetailed(GetIncludePathsCommandArgs args, ChangeObservable observable)
        {
            ExecutionContext.WriteWarning("This command is deprecated. Use 'get project-information' instead.", false);

            ProjectEntity        project       = ProjectEntity.Decorate(entityFactory.Create(Guid.NewGuid().ToByteString(), args).Root);
            TargetsResult        targetsResult = targetParser.Targets(project);
            IEnumerable <string> paths         = targetsResult.ValidTargets
                                                 .Select(sdkRepository.GetSdk)
                                                 .Where(sdk => sdk != null)
                                                 .Distinct()
                                                 .SelectMany(sdk => sdk.IncludePaths);

            return(new CommandResult(0, new IncludePathsCommandResult(paths.Select(p => new Path(p))),
                                     targetsResult.Errors));
        }
Exemplo n.º 7
0
        private metaDataTemplate FindFieldTemplate(string name, Entity owner)
        {
            IEnumerable <metaDataTemplate> possibleTemplates =
                templateRepository.FieldTemplates.Where(t => t.name.Equals(name, StringComparison.OrdinalIgnoreCase) &&
                                                        FirmwareVersionIsSupported(t.supportedFirmwareVersions));
            metaDataTemplate fieldTemplate = NewestTemplate(possibleTemplates);

            return(fieldTemplate);

            bool FirmwareVersionIsSupported(string supportedFirmwareVersion)
            {
                if (supportedFirmwareVersion == null)
                {
                    return(true);
                }
                ProjectEntity project   = ProjectEntity.Decorate(owner.IsRoot() ? owner : owner.Root);
                Version       minTarget = project.Targets.Min(t => TargetEntity.Decorate(t).Version);

                if (minTarget == null)
                {
                    return(true);
                }

                NuGetVersion targetVersion = new NuGetVersion(minTarget);

                if (VersionRange.TryParse(supportedFirmwareVersion, out VersionRange supportedVersion))
                {
                    return(supportedVersion.Satisfies(targetVersion));
                }

                return(true);
            }

            metaDataTemplate NewestTemplate(IEnumerable <metaDataTemplate> templates)
            {
                IEnumerable <metaDataTemplate> templatesWithVersion = templates.Where(t => t.supportedFirmwareVersions != null);

                if (!templatesWithVersion.Any())
                {
                    return(templates.FirstOrDefault());
                }

                return(templatesWithVersion.Where(template => template.supportedFirmwareVersions.Equals(
                                                      templatesWithVersion.Max(t => t.supportedFirmwareVersions), StringComparison.OrdinalIgnoreCase))
                       .FirstOrDefault());
            }
        }
Exemplo n.º 8
0
        public int BuildLibraryForProject(Entity project, ChangeObservable observable,
                                          string metaFilesDirectory, string libraryLocation, string outputDirectory,
                                          Guid libraryGuid, IEnumerable <string> targets,
                                          IEnumerable <string> externalLibraries, string buildType)
        {
            userInterface.WriteInformation("Starting library generation...");

            ProjectEntity projectEntity = ProjectEntity.Decorate(project);
            IEnumerable <(Target, string)> targetsSet;

            if (!targets.Any())
            {
                TargetsResult ts = targetParser.Targets(projectEntity, false);
                if (!ts.ValidTargets.Any())
                {
                    throw new FormattableException
                              ("Please use --target to specify for which targets the library shall be generated.");
                }
                else
                {
                    HashSet <(Target, string)> targetsHashSet = new HashSet <(Target, string)>();
                    foreach (Target target in ts.ValidTargets)
                    {
                        targetsHashSet.Add((target, null));
                    }
                    targetsSet = targetsHashSet;
                }
            }
            else
            {
                targetsSet = targetParser.GetSpecificTargets(targets, false);
            }

            Dictionary <Target, IEnumerable <VirtualFile> > externalLibs =
                ExternalLibrariesParser.ParseExternalLibraries(externalLibraries, targetParser,
                                                               fileSystem, targetsSet.Select(t => t.Item1));

            int result = libraryBuilderExecuter.Execute(projectEntity, metaFilesDirectory, libraryLocation,
                                                        outputDirectory, observable, userInterface, libraryGuid, targetsSet, externalLibs, buildType);

            if (result == 0)
            {
                userInterface.WriteInformation("Successfully generated library!");
            }
            return(result);
        }
Exemplo n.º 9
0
        public void Execute(Entity dataModel, ChangeObservable observable)
        {
            ProjectEntity project = ProjectEntity.Decorate(dataModel.Root);

            if (!project.Settings.IsPersistent)
            {
                try
                {
                    ICodeModel codeModel = dataModel.Root.Value <ICodeModel>();
                    if (codeModel != null)
                    {
                        VirtualEntry acfFile = codeModel.SourceDirectories
                                               .SelectMany(directory => directory.Entries)
                                               .Where(entry => entry.Name.EndsWith(Constants.AcfConfigExtension, StringComparison.OrdinalIgnoreCase))
                                               .FirstOrDefault();
                        if (acfFile != null)
                        {
                            using (Stream xmlStream = (acfFile as VirtualFile).OpenRead())
                                using (XmlReader reader = XmlReader.Create(xmlStream))
                                {
                                    while (reader.Read())
                                    {
                                        if (reader.MoveToContent() == XmlNodeType.Element && reader.Name == "Component")
                                        {
                                            string componenttype = reader.GetAttribute("type");
                                            if (componenttype.Contains("::"))
                                            {
                                                throw new OldAcfConfigException();
                                            }
                                        }
                                    }
                                }
                        }
                    }
                }
                catch (XmlException)
                {
                    executionContext.WriteWarning("From version 2021.6 on the component type attribute inside the .acf.config file" +
                                                  " must use the namespace separator '.' instead of '::'!");
                }
            }
        }
Exemplo n.º 10
0
        protected override CommandResult ExecuteDetailed(GetCompilerSpecificationsCommandArgs args, ChangeObservable observable)
        {
            ProjectEntity project       = ProjectEntity.Decorate(entityFactory.Create(Guid.NewGuid().ToByteString(), args).Root);
            TargetsResult targetsResult = targetParser.Targets(project);
            IEnumerable <CompilerInformation> compilers = targetsResult.ValidTargets
                                                          .Select(sdkRepository.GetSdk)
                                                          .Where(sdk => sdk != null)
                                                          .Distinct()
                                                          .Select(sdk => sdk.CompilerInformation);

            return(new CommandResult(0,
                                     new CompilerSpecificationCommandResult(
                                         compilers.Select(c => new CompilerSpecificationResult(c.CompilerPath,
                                                                                               "cpp",
                                                                                               c.Sysroot,
                                                                                               c.Flags,
                                                                                               c.IncludePaths.Select(p => new Path(p)),
                                                                                               c.Makros.Select(m => new CompilerMacroResult(m.Name, m.Value))))),
                                     targetsResult.Errors));
        }
Exemplo n.º 11
0
        protected override CommandResult ExecuteDetailed(GetSdksCommandArgs args, ChangeObservable observable)
        {
            string[] sdks;
            IEnumerable <Exception> exceptions = Enumerable.Empty <Exception>();

            if (args.All)
            {
                sdks = sdkRepository.Sdks.Select(s => s.Root.FullName).ToArray();
            }
            else
            {
                ProjectEntity project       = ProjectEntity.Decorate(entityFactory.Create(Guid.NewGuid().ToByteString(), args).Root);
                TargetsResult targetsResult = targetParser.Targets(project);
                sdks = targetsResult.ValidTargets.Select(sdkRepository.GetSdk).Distinct()
                       .Select(s => s.Root.FullName).ToArray();

                exceptions = targetsResult.Errors;
            }

            return(new CommandResult(0, new SdksCommandResult(sdks.Select(s => new Path(s))), exceptions));
        }
Exemplo n.º 12
0
        public void DeployFiles(Entity dataModel)
        {
            IEnumerable <Entity> deployableEntities = dataModel.Root.Hierarchy();
            ProjectEntity        project            = ProjectEntity.Decorate(dataModel.Root);

            // get targets to deploy for
            IEnumerable <Target> targets = null;

            CommandEntity command = CommandEntity.Decorate(dataModel);

            if (command.IsCommandArgumentSpecified(Constants.TargetArgumentName))
            {
                IEnumerable <string> rawTargets = command.GetMultiValueArgument(Constants.TargetArgumentName);

                if (rawTargets.Any())
                {
                    targets = targetParser.GetSpecificTargets(rawTargets, false).Select(t => t.Item1);
                }
                else
                {
                    targets = targetParser.Targets(project, false).ValidTargets;
                }
            }
            else
            {
                targets = targetParser.Targets(project, false).ValidTargets;
            }
            if (!targets.Any())
            {
                throw new NoTargetSpecifiedException();
            }


            foreach (Entity deployableEntity in deployableEntities)
            {
                DeployFilesFromTemplate(deployableEntity);
            }

            if (command.IsCommandArgumentSpecified(Constants.FilesArgumentName))
            {
                IEnumerable <string> files = command.GetMultiValueArgument(Constants.FilesArgumentName);

                foreach (string file in files)
                {
                    DeployFileFromArgument(file);
                }
            }

            void DeployFileFromArgument(string file)
            {
                Match match = FilesDecoder.Match(file);

                if (!match.Success)
                {
                    throw new FormattableException($"The input {file} could not be parsed. Expected pattern is <fileLocation>|<destination>[|<target>]");
                }

                string from      = match.Groups["from"].Value;
                string to        = match.Groups["destination"].Value;
                string rawTarget = match.Groups["target"].Value;

                VirtualDirectory baseDirectory     = null;
                string           relativePath      = null;
                bool             recreateStructure = false;

                string[] path          = fileSystem.GetPath(from);
                int      firstWildCard = path.TakeWhile(p => !p.Contains('*') && !p.Contains('?')).Count();

                if (firstWildCard != path.Length)
                {
                    baseDirectory     = fileSystem.GetDirectory(Path.Combine(path.Take(firstWildCard).ToArray()), project.Path, false);
                    relativePath      = Path.Combine(path.Skip(firstWildCard).ToArray());
                    recreateStructure = true;
                }

                if (recreateStructure)
                {
                    IEnumerable <VirtualFile> deployFiles = baseDirectory.Files(relativePath, true).ToArray();
                    if (!deployFiles.Any())
                    {
                        throw new DeployFileNotFoundException(@from);
                    }
                    foreach (VirtualFile deployFile in deployFiles)
                    {
                        string structure       = Path.GetDirectoryName(deployFile.GetRelativePath(baseDirectory));
                        string fileDestination = string.IsNullOrEmpty(structure) ? to : Path.Combine(to, structure);
                        DeployFile(deployFile.FullName, fileDestination);
                    }
                }
                else if (fileSystem.FileExists(from, project.Path))
                {
                    DeployFile(from, to);
                }
                else
                {
                    throw new DeployFileNotFoundException(@from);
                }

                void DeployFile(string sourceFile, string destinationDirectory)
                {
                    if (!string.IsNullOrEmpty(rawTarget))
                    {
                        DeployFileForRawTarget(rawTarget, sourceFile, destinationDirectory);
                    }
                    else
                    {
                        foreach (Target target in targets)
                        {
                            DeployFileForTarget(target, sourceFile, destinationDirectory);
                        }
                    }
                }

                void DeployFileForRawTarget(string target, string sourceFile, string destinationDirectory)
                {
                    Target parsedTarget = targetParser.ParseTarget(target, null, targets);

                    DeployFileForTarget(parsedTarget, sourceFile, destinationDirectory);
                }

                void DeployFileForTarget(Target target, string sourceFile, string destinationDirectory)
                {
                    VirtualFile fileToCopy = fileSystem.GetFile(sourceFile, project.Path);
                    VirtualFile copiedFile = fileSystem.GetDirectory(destinationDirectory, GetOutputDirectory(target).FullName).File(fileToCopy.Name);

                    using (Stream source = fileToCopy.OpenRead(true))
                        using (Stream destination = copiedFile.OpenWrite())
                        {
                            destination.SetLength(0);
                            source.CopyTo(destination);

                            executionContext.WriteVerbose($"Deployed file {fileToCopy.FullName} to {copiedFile.FullName}.");
                        }
                }
            }

            void DeployFilesFromTemplate(Entity deployableEntity)
            {
                TemplateDescription template = deployableEntity.Template();

                if (template == null)
                {
                    return;
                }

                foreach (templateFile file in template.File)
                {
                    if (!file.deployPathSpecified)
                    {
                        continue;
                    }

                    VirtualFile deployableFile = GetFile(file, dataModel.Root.Path, false, out string path);

                    DeployFile(file, deployableFile, path);
                }

                foreach (templateGeneratedFile generatedFile in template.GeneratedFile ?? Enumerable.Empty <templateGeneratedFile>())
                {
                    if (!generatedFile.deployPathSpecified)
                    {
                        continue;
                    }

                    VirtualFile deployableFile = GetFile(generatedFile, dataModel.Root.Path, true, out string path);

                    DeployFile(generatedFile, deployableFile, path);
                }

                VirtualFile GetDestination(templateFile file, Target target, string name)
                {
                    string basePath = GetOutputDirectory(target).FullName;
                    string path     = resolver.Resolve(file.deployPath ?? string.Empty, deployableEntity);

                    VirtualFile destination = fileSystem.GetFile(Path.Combine(path, name), basePath);

                    return(destination);
                }

                void DeployFile(templateFile file, VirtualFile deployableFile, string filePath)
                {
                    if (deployableFile == null)
                    {
                        executionContext.WriteVerbose($"Could not find file {filePath} in {dataModel.Root.Path}, the file will not be deployed.");
                        return;
                    }
                    foreach (Target target in targets)
                    {
                        VirtualFile destination = GetDestination(file, target, deployableFile.Name);

                        using (Stream source = deployableFile.OpenRead(true))
                            using (Stream dest = destination.OpenWrite())
                            {
                                dest.SetLength(0);
                                source.CopyTo(dest);
                            }

                        executionContext.WriteVerbose($"Deployed file {deployableFile.FullName} to {destination.FullName}.");
                    }
                }

                VirtualFile GetFile(templateFile file, string basePath, bool isGeneratedFile, out string realFilePath)
                {
                    string path = resolver.Resolve(file.path ?? string.Empty, deployableEntity);
                    string name = resolver.Resolve(file.name, deployableEntity);

                    if (isGeneratedFile && file is templateGeneratedFile generatedFile)
                    {
                        realFilePath = Path.Combine(path, name);
                        if (!Path.IsPathRooted(realFilePath))
                        {
                            realFilePath = Path.Combine(Constants.IntermediateFolderName, generatedFile.generator?.ToLowerInvariant() ?? string.Empty, realFilePath);
                        }
                    }
                    else
                    {
                        realFilePath = Path.Combine(path, name);
                    }

                    VirtualFile destination = fileSystem.FileExists(realFilePath, basePath)
                                                  ? fileSystem.GetFile(realFilePath, basePath)
                                                  : null;

                    return(destination);
                }
            }

            VirtualDirectory GetOutputDirectory(Target target)
            {
                string buildTypeFolder = command.IsCommandArgumentSpecified(Constants.BuildTypeArgumentName)
                                             ? FormatBuildType(command.GetSingleValueArgument(Constants.BuildTypeArgumentName))
                                             : Constants.ReleaseFolderName;
                string basePath = project.Path;

                if (!command.IsCommandArgumentSpecified(Constants.OutputArgumentName))
                {
                    return(fileSystem.GetDirectory(Path.Combine(basePath, Constants.LibraryFolderName, target.GetFullName().Replace(',', '_'),
                                                                buildTypeFolder)));
                }

                basePath = fileSystem.GetDirectory(command.GetSingleValueArgument(Constants.OutputArgumentName), basePath).FullName;
                basePath = Path.Combine(basePath, target.GetFullName().Replace(',', '_'), buildTypeFolder);

                return(fileSystem.GetDirectory(basePath));

                string FormatBuildType(string buildType)
                {
                    if (string.IsNullOrEmpty(buildType))
                    {
                        return(Constants.ReleaseFolderName);
                    }

                    return(buildType.Substring(0, 1).ToUpperInvariant() +
                           buildType.Substring(1).ToLowerInvariant());
                }
            }
        }
        //TODO Patch libmeta here
        public int Execute(Entity dataModel)
        {
            ProjectEntity        project           = ProjectEntity.Decorate(dataModel.Root);
            CodeEntity           projectCodeEntity = CodeEntity.Decorate(project);
            string               projectName       = projectCodeEntity.Namespace;
            IEnumerable <Entity> targets           = project.Targets.ToArray();

            if (!targets.Any())
            {
                throw new FormattableException("Please use --target to specify for which targets the library shall be generated.");
            }
            Dictionary <Entity, VirtualFile> projectLibraries = targets.ToDictionary(t => t, FindLibrary);
            List <string>      externalLibraries = new List <string>();
            List <VirtualFile> deletableFiles    = new List <VirtualFile>();

            foreach (Entity target in targets)
            {
                CopyExternalLibrariesToOutputDirectory(target, projectLibraries,
                                                       out IEnumerable <string> libraries,
                                                       out IEnumerable <VirtualFile> toBeDeleted);
                externalLibraries.AddRange(libraries);
                deletableFiles.AddRange(toBeDeleted);
            }
            CheckMetaFiles(targets.First());

            string commandOptionsFile = GenerateCommandOptions(project, projectLibraries, projectName);
            int    result             = ExecuteLibraryBuilderWithCommandOptions(commandOptionsFile, project);

            foreach (VirtualFile deletable in deletableFiles)
            {
                deletable.Delete();
            }

            return(result);

            VirtualFile FindLibrary(Entity target)
            {
                VirtualDirectory deployDirectory = DeployEntity.Decorate(target).DeployDirectory;

                string libFile = deployDirectory.Files("*.so", true)
                                 .OrderByDescending(f => f.Name.Equals($"lib{projectName}.so", StringComparison.OrdinalIgnoreCase))
                                 .ThenByDescending(f => f.LastWriteTime)
                                 .FirstOrDefault()
                                 ?.FullName;

                if (string.IsNullOrEmpty(libFile))
                {
                    throw new LibraryNotFoundException(deployDirectory.FullName);
                }

                VirtualFile file = fileSystem.GetFile(libFile);

                return(file);
            }

            void CheckMetaFiles(Entity target)
            {
                TemplateEntity   projectTemplateEntity = TemplateEntity.Decorate(project);
                VirtualDirectory deployDirectory       = DeployEntity.Decorate(target).DeployDirectory;

                if (!fileSystem.FileExists(Path.Combine(deployDirectory.FullName, $"{projectName}.libmeta")))
                {
                    throw new MetaLibraryNotFoundException(deployDirectory.FullName);
                }

                PatchLibmeta(fileSystem.GetFile(Path.Combine(deployDirectory.FullName, $"{projectName}.libmeta")));
                IEnumerable <VirtualFile> metaFiles = deployDirectory.Files(searchRecursive: true);

                IEnumerable <Entity> componentsWithoutMetaFile = projectTemplateEntity.EntityHierarchy
                                                                 .Where(e => e.Type.Equals("component", StringComparison.OrdinalIgnoreCase))
                                                                 .Where(c => !metaFiles.Any(f => f.Name.Equals($"{c.Name}.{Constants.CompmetaExtension}",
                                                                                                               StringComparison.Ordinal)))
                                                                 .ToArray();

                if (componentsWithoutMetaFile.Any())
                {
                    throw new MetaFileNotFoundException(deployDirectory.FullName, $"{componentsWithoutMetaFile.First().Name}.{Constants.CompmetaExtension}");
                }

                IEnumerable <Entity> programsWithoutMetaFile = projectTemplateEntity.EntityHierarchy
                                                               .Where(e => e.Type.Equals("program", StringComparison.OrdinalIgnoreCase))
                                                               .Where(p => !metaFiles.Any(f => f.Name.Equals($"{p.Name}.{Constants.ProgmetaExtension}",
                                                                                                             StringComparison.Ordinal)))
                                                               .ToArray();

                if (programsWithoutMetaFile.Any())
                {
                    throw new MetaFileNotFoundException(deployDirectory.FullName, $"{programsWithoutMetaFile.First().Name}.{Constants.ProgmetaExtension}");
                }
            }

            void PatchLibmeta(VirtualFile libmetaFile)
            {
                if (!externalLibraries.Any())
                {
                    return;
                }
                XmlSerializer             serializer = new XmlSerializer(typeof(MetaConfigurationDocument));
                MetaConfigurationDocument document;

                try
                {
                    using (Stream fileStream = libmetaFile.OpenRead())
                        using (XmlReader reader = XmlReader.Create(fileStream))
                        {
                            document = (MetaConfigurationDocument)serializer.Deserialize(reader);
                        }
                }
                catch (XmlException e)
                {
                    executionContext.WriteWarning($"Cannot parse libmeta file. Cannot patch dependencies. {e.Message}");
                    return;
                }

                document.schemaVersion = "4.0";
                LibraryDefinition    definition   = (LibraryDefinition)document.Item;
                IEnumerable <string> dependencies = externalLibraries.Select(Path.GetFileName)
                                                    .Concat(definition.Dependencies?.Select(d => d.path) ??
                                                            Enumerable.Empty <string>());

                definition.Dependencies = dependencies.Select(d => new DependencyDefinition {
                    path = d
                }).ToArray();

                using (Stream fileStream = libmetaFile.OpenWrite())
                    using (XmlWriter writer = XmlWriter.Create(fileStream, new XmlWriterSettings
                    {
                        Indent = true
                    }))
                    {
                        serializer.Serialize(writer, document);
                    }
            }
        }
        public override Entity Resolve(Entity owner, string key, bool fallback = false)
        {
            TemplateEntity ownerTemplateEntity = TemplateEntity.Decorate(owner);

            if (key == EntityKeys.FieldArpDataTypeKey && owner.Type == EntityKeys.FormatKey)
            {
                return(ResolveArpDataType());
            }
            if (key == EntityKeys.TypeMetaDataFormatKey && owner.Type == EntityKeys.FormatKey)
            {
                return(ResolveTypeMetaDataFormat());
            }
            if (key == EntityKeys.ExpandHiddenTypesFormatKey)
            {
                return(ExpandHiddenTypes());
            }
            if (key == EntityKeys.FilterHiddenTypesFormatKey)
            {
                return(FilterHiddenTypes());
            }
            if (key == EntityKeys.IsFieldKey)
            {
                return(owner.Create(key, CodeEntity.Decorate(owner).AsField != null));
            }
            if (key == EntityKeys.IsTypeKey)
            {
                return(owner.Create(key, CodeEntity.Decorate(owner).AsType != null));
            }
            if (key == EntityKeys.BigDataProjectKey)
            {
                return(GetBigDataProjectEntity());
            }
            if (key == EntityKeys.NormalProjectKey)
            {
                return(GetNormalProjectEntity());
            }


            ISymbol symbol = owner.Value <ISymbol>();

            if (symbol != null)
            {
                Entity result = owner.PropertyValueEntity(key, symbol);
                if (result != null)
                {
                    return(result);
                }

                throw new ContentProviderException(key, owner);
            }

            if (key == EntityKeys.BaseDirectoryKey && HasBaseDirectory(owner, out string baseDirectory))
            {
                return(owner.Create(key, baseDirectory));
            }

            IType type = owner.Value <IType>();

            if (type != null)
            {
                return(ResolveType());
            }

            IField field = owner.Value <IField>();

            if (field != null)
            {
                return(ResolveField());
            }

            IDataType dataType = owner.Value <IDataType>();

            if (dataType != null)
            {
                return(ResolveDataType());
            }

            ICodeModel codeModel = owner.Value <ICodeModel>();

            if (codeModel != null)
            {
                return(ResolveCodeModel());
            }
            throw new ContentProviderException(key, owner);

            IEnumerable <CodeEntity> GetPortEnums()
            {
                return(GetAllPorts().Concat(GetPortStructures().SelectMany(p => p.Fields))
                       .Select(f => f.ResolvedType)
                       .Where(t => t.AsEnum != null)
                       .Distinct());
            }

            IEnumerable <CodeEntity> GetAllPorts()
            {
                bool IsPort(CodeEntity fieldEntity)
                {
                    return(fieldEntity.AsField != null &&
                           fieldEntity.AsField.HasAttributeWithoutValue(EntityKeys.PortAttributeKey));
                }

                return(TemplateEntity.Decorate(owner).EntityHierarchy
                       .Select(CodeEntity.Decorate)
                       .SelectMany(c => c.Fields)
                       .Where(IsPort));
            }

            IEnumerable <CodeEntity> GetPortStructures()
            {
                HashSet <CodeEntity> structures = new HashSet <CodeEntity>(GetAllPorts()
                                                                           .Select(f => f.ResolvedType)
                                                                           .Where(t => t.AsType != null &&
                                                                                  t.AsEnum == null),
                                                                           new FullNameCodeEntityComparer());

                HashSet <CodeEntity> visited = new HashSet <CodeEntity>(new FullNameCodeEntityComparer());

                while (structures.Except(visited).Any())
                {
                    foreach (CodeEntity structure in structures.Except(visited).ToArray())
                    {
                        foreach (CodeEntity structureField in structure.Fields)
                        {
                            CodeEntity structureDataType = structureField.ResolvedType;
                            if (structureDataType.AsType != null && structureDataType.AsEnum == null)
                            {
                                structures.Add(structureDataType);
                            }
                        }

                        visited.Add(structure);
                    }
                }

                return(structures);
            }

            Entity FilterHiddenTypes()
            {
                IEnumerable <IType> types = owner.Select(CodeEntity.Decorate)
                                            .Where(c => !c.IsHidden())
                                            .Select(c => c.AsType)
                                            .ToArray();
                string name = owner.FirstOrDefault()?.Name ?? string.Empty;

                return(owner.Create(key, types.Select(t => owner.Create(name, t.FullName, t))));
            }

            Entity ExpandHiddenTypes()
            {
                IEnumerable <CodeEntity> dataSourceFields = owner.Select(CodeEntity.Decorate);

                dataSourceFields = ExpandHiddenStructureFields(dataSourceFields);
                string name = owner.FirstOrDefault()?.Name ?? string.Empty;

                return(owner.Create(key, dataSourceFields.Select(e => e.AsField)
                                    .Select(f => owner.Create(name, f.Name, f))));

                IEnumerable <CodeEntity> ExpandHiddenStructureFields(IEnumerable <CodeEntity> fields)
                {
                    foreach (CodeEntity hiddenField in fields)
                    {
                        CodeEntity hiddenType = hiddenField.ResolvedType;
                        if (hiddenType == null || !hiddenType.IsHidden())
                        {
                            yield return(hiddenField);

                            continue;
                        }

                        foreach (CodeEntity hiddenTypeField in ExpandHiddenStructureFields(hiddenType.Fields))
                        {
                            yield return(hiddenTypeField);
                        }
                    }
                }
            }

            T ChooseMetaDataTemplate <T>(IEnumerable <(T template, string name, string context)> templates)
            {
                return(templates.OrderByDescending(t => ContextComplexity(t.context ?? string.Empty))
                       .FirstOrDefault(Matches)
                       .template);

                bool Matches((T template, string name, string context) template)
                {
                    if (!key.Equals(template.name, StringComparison.OrdinalIgnoreCase))
                    {
                        return(false);
                    }

                    if (string.IsNullOrEmpty(template.context))
                    {
                        return(true);
                    }
                    string[] contextPath = template.context.Split(new [] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries)
                                           .Reverse().ToArray();
                    Entity current = owner;

                    foreach (string part in contextPath)
                    {
                        current = current?.Owner;
                        if (current?[$"is{part}"].Value <bool>() != true)
                        {
                            return(false);
                        }
                    }

                    return(true);
                }

                int ContextComplexity(string context)
                {
                    return(context.Count(c => c == '/' || c == '\\'));
                }
            }

            Entity ResolveType()
            {
                switch (key)
                {
                case EntityKeys.PathKey:
                {
                    return(owner.Create(key, type.GetFile(owner).Parent.FullName));
                }

                case EntityKeys.FieldsKey:
                {
                    return(owner.Create(key, type.Fields.Select(f => owner.Create(key.Singular(), f.Name, f))));
                }

                case EntityKeys.FileKey:
                {
                    VirtualFile file = owner.Root.Value <ICodeModel>()
                                       .Types[type];
                    return(owner.Create(key, file.Name, file));
                }

                case EntityKeys.BaseTypeKey:
                {
                    IDataType baseType = type.BaseTypes.FirstOrDefault();
                    return(owner.Create(key, baseType));
                }

                default:
                {
                    if (TryResolveTypeTemplate(out Entity result))
                    {
                        return(result);
                    }

                    if (TryResolveProperty(out result))
                    {
                        return(result);
                    }

                    if (TryResolveFields(out result))
                    {
                        return(result);
                    }

                    if (TryResolveRelationship(out result))
                    {
                        return(result);
                    }

                    throw new ContentProviderException(key, owner);
                }
                }

                bool TryResolveTypeTemplate(out Entity result)
                {
                    Templates.Type.metaDataTemplate typeMetaDataTemplate = ChooseMetaDataTemplate(templateRepository.TypeTemplates
                                                                                                  .Select(t => (t, t.name, t.context)));
                    if (typeMetaDataTemplate != null)
                    {
                        result = GetTypeTemplateEntity(typeMetaDataTemplate);
                        return(true);
                    }

                    result = null;
                    return(false);

                    Entity GetTypeTemplateEntity(Templates.Type.metaDataTemplate metaDataTemplate)
                    {
                        if (!metaDataTemplate.hasvalue)
                        {
                            bool hasAttribute = type.HasAttributeWithoutValue(metaDataTemplate.name);
                            return(owner.Create(key, new Func <string>(hasAttribute.ToString), hasAttribute));
                        }
                        (string[] values, CodePosition position) = GetTypeTemplateValue();
                        IEnumerable <string> formattedValues = VerifyValues().ToArray();

                        return(metaDataTemplate.multiplicity == Templates.Type.multiplicity.OneOrMore
                                   ? owner.Create(key, formattedValues.Select(v => owner.Create(key.Singular(), v)))
                                   : owner.Create(key, formattedValues.First()));

                        IEnumerable <string> VerifyValues()
                        {
                            return(values.Select(VerifyValue));

                            string VerifyValue(string arg)
                            {
                                (bool success, string message, string newValue) = metaDataTemplate.ValueRestriction.Verify(arg);
                                if (!success)
                                {
                                    owner.AddCodeException(new FieldAttributeRestrictionException(metaDataTemplate.name, arg, message, position, type.GetFile(owner)));
                                }

                                return(newValue);
                            }
                        }

                        (string[], CodePosition) GetTypeTemplateValue()
                        {
                            IAttribute attribute = type.Attributes.LastOrDefault(a => a.Name.Equals(metaDataTemplate.name,
                                                                                                    StringComparison.OrdinalIgnoreCase));
                            string value = attribute?.Values.FirstOrDefault() ??
                                           resolver.Resolve(metaDataTemplate.defaultvalue, owner);

                            return(metaDataTemplate.multiplicity == Templates.Type.multiplicity.OneOrMore
                                        ? value.Split(new[] { metaDataTemplate.split }, StringSplitOptions.RemoveEmptyEntries)
                                        : new[] { value },
                                   attribute?.Position ?? new CodePosition(0, 0));
                        }
                    }
                }

                bool TryResolveProperty(out Entity result)
                {
                    result = owner.PropertyValueEntity(key, type);
                    return(result != null);
                }

                bool TryResolveFields(out Entity result)
                {
                    metaDataTemplate metaDataTemplate = templateRepository.FieldTemplates
                                                        .FirstOrDefault(t => t.name.Plural().Equals(key,
                                                                                                    StringComparison
                                                                                                    .OrdinalIgnoreCase));

                    if (metaDataTemplate != null)
                    {
                        IEnumerable <IField> fields = type.Fields
                                                      .Where(f => f.Attributes
                                                             .Any(a => a.Name
                                                                  .Equals(metaDataTemplate.name,
                                                                          StringComparison.OrdinalIgnoreCase)));
                        result = owner.Create(key, fields.Select(f => owner.Create(metaDataTemplate.name, f.Name, f)));
                        return(true);
                    }

                    result = null;
                    return(false);
                }

                bool TryResolveRelationship(out Entity result)
                {
                    templateRelationship[] relationships = owner.Template().Relationship;
                    templateRelationship   relationship  = relationships?.FirstOrDefault(r => r.name.Equals(key, StringComparison.OrdinalIgnoreCase))
                                                           ?? relationships?.FirstOrDefault(r => r.name.Equals(key.Singular(), StringComparison.OrdinalIgnoreCase));
                    TemplateDescription relationshipDescription = relationship != null?templateRepository.Template(relationship.type) : null;

                    if (relationshipDescription != null)
                    {
                        IEnumerable <string> names = type.Attributes
                                                     .Where(a => a.Name.Equals(relationship.name,
                                                                               StringComparison.OrdinalIgnoreCase))
                                                     .SelectMany(a => a.Values);
                        result = relationship.GetRelationship(relationshipDescription, owner, names.ToArray());
                        return(true);
                    }

                    result = null;
                    return(false);
                }
            }

            Entity ResolveField()
            {
                switch (key)
                {
                case EntityKeys.FieldNameKey:
                {
                    return(owner.Create(key, field.Name));
                }

                case EntityKeys.DataTypeKey:
                {
                    IDataType fieldDataType = GetRealFieldDataType();
                    return(owner.Create(key, fieldDataType.Name, fieldDataType));
                }

                case EntityKeys.ResolvedTypeKey:
                {
                    ICodeModel model         = owner.Root.Value <ICodeModel>();
                    IDataType  fieldDataType = field.DataType;
                    IType      realType      = fieldDataType.PotentialFullNames
                                               .Select(model.Type)
                                               .FirstOrDefault(t => t != null);
                    return(owner.Create(key, realType?.Name, realType));
                }

                case EntityKeys.MultiplicityKey:
                {
                    return(owner.Create(key, field.Multiplicity.Select(m => owner.Create(key, new Func <string>(m.ToString), m))));
                }

                default:
                {
                    metaDataTemplate metaDataTemplate = templateRepository.FieldTemplates
                                                        .FirstOrDefault(t => t.name.Equals(key,
                                                                                           StringComparison.OrdinalIgnoreCase));
                    if (metaDataTemplate != null)
                    {
                        return(GetFieldTemplateEntity(metaDataTemplate));
                    }
                    throw new ContentProviderException(key, owner);
                }
                }

                IDataType GetRealFieldDataType()
                {
                    ICodeModel rootCodeModel = owner.Root.Value <ICodeModel>();
                    IEnum      @enum         = field.DataType.PotentialFullNames.Select(n => rootCodeModel.GetEnum(n)).FirstOrDefault(e => e != null);

                    if (@enum != null)
                    {
                        (IDataType enumBaseType, _) = GetEnumBaseType(@enum);
                        return(enumBaseType);
                    }

                    return(field.DataType);
                }

                Entity GetFieldTemplateEntity(metaDataTemplate metaDataTemplate)
                {
                    if (!metaDataTemplate.hasvalue)
                    {
                        bool hasAttribute = field.HasAttributeWithoutValue(metaDataTemplate.name);
                        return(owner.Create(key, new Func <string>(hasAttribute.ToString), hasAttribute));
                    }
                    (string[] values, CodePosition position) = GetFieldTemplateValue();
                    IEnumerable <string> formattedValues = VerifyValues().ToArray();

                    return(metaDataTemplate.multiplicity == multiplicity.OneOrMore
                               ? owner.Create(key, formattedValues.Select(v => owner.Create(key.Singular(), v)))
                               : owner.Create(key, formattedValues.First()));

                    IEnumerable <string> VerifyValues()
                    {
                        return(values.Select(VerifyValue));

                        string VerifyValue(string arg)
                        {
                            (bool success, string message, string newValue) = metaDataTemplate.ValueRestriction.Verify(arg);
                            if (!success)
                            {
                                owner.AddCodeException(new FieldAttributeRestrictionException(metaDataTemplate.name, arg, message, position, field.GetFile(owner)));
                            }

                            return(newValue);
                        }
                    }

                    (string[], CodePosition) GetFieldTemplateValue()
                    {
                        IAttribute attribute = field.Attributes.LastOrDefault(a => a.Name.Equals(metaDataTemplate.name,
                                                                                                 StringComparison.OrdinalIgnoreCase));
                        string value = string.IsNullOrEmpty(attribute?.Values.FirstOrDefault())
                                           ? resolver.Resolve(metaDataTemplate.defaultvalue, owner)
                                           : attribute.Values.First();

                        return(metaDataTemplate.multiplicity == multiplicity.OneOrMore
                                    ? value.Split(new[] { metaDataTemplate.split }, StringSplitOptions.RemoveEmptyEntries)
                                    : new[] { value },
                               attribute?.Position ?? new CodePosition(0, 0));
                    }
                }
            }

            Entity ResolveCodeModel()
            {
                switch (key)
                {
                case EntityKeys.PortStructsKey:
                {
                    return(owner.Create(key, GetPortStructures().Select(c => c.Base)));
                }

                case EntityKeys.PortEnumsKey:
                {
                    return(owner.Create(key, GetPortEnums().Select(c => c.Base)));
                }

                case EntityKeys.NamespaceKey:
                {
                    bool prior206Target = CheckProjectTargets();
                    IEnumerable <string> relevantTypes = TemplateEntity.Decorate(owner).EntityHierarchy
                                                         .Select(CodeEntity.Decorate)
                                                         .Where(c => !c.IsRoot())
                                                         .Select(c => c.FullName);
                    string ns = prior206Target
                                        ? codeModel.RootNamespaceForOldTarget(
                        relevantTypes.ToArray(), GetPortStructures().Concat(GetPortEnums())
                        .Select(c => c.FullName)
                        .ToArray())
                                        : codeModel.RootNamespace(relevantTypes.ToArray());
                    if (string.IsNullOrEmpty(ns))
                    {
                        ns = owner.Name;
                    }

                    return(owner.Create(key, ns));
                }

                default:
                    throw new ContentProviderException(key, owner);
                }

                bool CheckProjectTargets()
                {
                    IEnumerable <TargetEntity> targets = ProjectEntity.Decorate(owner).Targets.Select(t => TargetEntity.Decorate(t));

                    return(targets.Any(t => t.Version < new Version(20, 6)));
                }
            }

            Entity ResolveDataType()
            {
                switch (key)
                {
                case EntityKeys.NameKey:
                    return(owner.Create(key, dataType.Name));

                case EntityKeys.FullNameKey:
                    string fullName = GetDataTypeFullName();
                    return(owner.Create(key, fullName));

                default:
                    throw new ContentProviderException(key, owner);
                }

                string GetDataTypeFullName()
                {
                    ICodeModel rootCodeModel = owner.Root.Value <ICodeModel>();

                    return(dataType.PotentialFullNames.FirstOrDefault(fn => rootCodeModel.Type(fn) != null)
                           ?? dataType.Name);
                }
            }

            Entity ResolveTypeMetaDataFormat()
            {
                IEntityBase dataSource         = ownerTemplateEntity.FormatOrigin;
                IDataType   dataSourceDataType = dataSource.HasValue <IDataType>()
                                                   ? dataSource.Value <IDataType>()
                                                   : dataSource.Value <IField>().DataType;

                ICodeModel rootCodeModel = dataSource.Root.Value <ICodeModel>();
                string     dataTypeName  = string.Empty;

                if (dataSourceDataType != null)
                {
                    dataTypeName = dataSourceDataType.PotentialFullNames
                                   .Select(n => rootCodeModel.Type(n))
                                   .FirstOrDefault(t => t != null)
                                   ?.Name
                                   ?? datatypeConversion.Convert(dataSourceDataType);
                }

                return(owner.Create(key, dataTypeName));
            }

            Entity ResolveArpDataType()
            {
                IEntityBase dataSource      = ownerTemplateEntity.FormatOrigin;
                IField      dataSourceField = dataSource.Value <IField>();

                if (dataSourceField == null)
                {
                    throw new FormatTargetMismatchException("arpDataType", "field|port", dataSource.Type);
                }

                ICodeModel rootCodeModel = dataSource.Root.Value <ICodeModel>();
                bool       isStruct      = dataSourceField.DataType.PotentialFullNames.Any(n => rootCodeModel.GetClass(n) != null || rootCodeModel.GetStructure(n) != null);
                IEnum      @enum         = dataSourceField.DataType.PotentialFullNames.Select(n => rootCodeModel.GetEnum(n)).FirstOrDefault(e => e != null);
                bool       isArray       = dataSourceField.Multiplicity.Any();
                string     arpName       = "DataType::" + GetArpDataType(dataSourceField.DataType.Name);

                return(owner.Create(key, arpName));

                string GetArpDataType(string dataTypeName)
                {
                    string postfix = isArray ? " | DataType::Array" : string.Empty;

                    if (isStruct)
                    {
                        return("Struct" + postfix);
                    }

                    if (@enum != null)
                    {
                        (IDataType enumBaseType, string formattedBaseType) = GetEnumBaseType(@enum);

                        return($"Enum | DataType::{formattedBaseType}" + postfix);
                    }

                    (bool success, string value) = FormatDataType(dataTypeName);

                    if (!success)
                    {
                        throw new UnknownDataTypeException(value);
                    }

                    return(value + postfix);
                }
            }

            (bool success, string value) FormatDataType(string unformattedValue)
            {
                if (unformattedValue.Contains('<'))
                {
                    unformattedValue = unformattedValue.Substring(0, unformattedValue.IndexOf('<'));
                }

                string result      = owner.Create("temporaryCtnFormatContainer", unformattedValue).Format()["knownDataTypes"].Value <string>();
                Match  unkownMatch = UnkownDataTypeRegex.Match(result);

                if (unkownMatch.Success)
                {
                    return(false, unkownMatch.Groups["dataType"].Value);
                }

                return(true, result);
            }

            (IDataType, string) GetEnumBaseType(IEnum @enum)
            {
                IDataType enumDataType = @enum.BaseTypes.FirstOrDefault();
                string    enumBaseType = enumDataType?.Name;

                if (string.IsNullOrEmpty(enumBaseType))
                {
                    throw new MissingEnumDataTypeException(@enum);
                }

                (bool formatted, string formattedBaseType) = FormatDataType(enumBaseType);
                if (!formatted)
                {
                    throw new UnkownEnumDataTypeException(formattedBaseType, @enum);
                }

                return(enumDataType, formattedBaseType);
            }

            Entity GetBigDataProjectEntity()
            {
                if (HasMoreThan1000Fields())
                {
                    return(owner.Create(key, "true", true));
                }
                return(owner.Create(key, "false", false));
            }

            Entity GetNormalProjectEntity()
            {
                if (HasMoreThan1000Fields())
                {
                    return(owner.Create(key, "false", false));
                }
                return(owner.Create(key, "true", true));
            }

            bool HasMoreThan1000Fields()
            {
                ICodeModel model = owner.Value <ICodeModel>();

                if (model == null ||
                    GetAllPorts().Concat(GetPortStructures().SelectMany(s => s.Fields)).Count() <= 1000)
                {
                    return(false);
                }
                return(true);
            }
        }