/// <summary>
        /// Manual database locking is used here in order to avoid deadlocks (may depend on usage of READ_COMMITTED_SNAPSHOT),
        /// see integration test AddUnregisteredPrincipalsParallel.
        /// </summary>
        /// <remarks>
        /// Note that lock resource name is case-sensitive in SQL Server.
        /// </remarks>
        private CustomLockInfo CreteCustomLock(string userName)
        {
            string key = $"AuthorizationDataLoader.{userName}";

            key = CsUtility.LimitWithHash(key, 255); // SQL Server limits key length to 255.

            try
            {
                _sqlExecuter.ExecuteSql(
                    $@"DECLARE @lockResult int;
                    EXEC @lockResult = sp_getapplock {SqlUtility.QuoteText(key)}, 'Exclusive';
                    IF @lockResult < 0
                    BEGIN
                        RAISERROR('AuthorizationDataLoader lock.', 16, 10);
                        ROLLBACK;
                        RETURN;
                    END");
                return(new CustomLockInfo(key));
            }
            catch (FrameworkException ex) when(ex.Message.TrimEnd().EndsWith("AuthorizationDataLoader lock."))
            {
                throw new UserException(
                          "Cannot initialize the new user, because the user record is locked by another command that is still running.",
                          ex);
            }
        }
        public void GenerateCode(IConceptInfo conceptInfo, ICodeBuilder codeBuilder)
        {
            var info = (UniqueReferenceInfo)conceptInfo;

            if (DslUtility.IsQueryable(info.Extension) && DslUtility.IsQueryable(info.Base))
            {
                DataStructureQueryableCodeGenerator.AddNavigationPropertyWithBackingField(codeBuilder, info.Extension,
                                                                                          csPropertyName: "Base",
                                                                                          propertyType: "Common.Queryable." + info.Base.Module.Name + "_" + info.Base.Name,
                                                                                          additionalSetterCode: "ID = value != null ? value.ID : Guid.Empty;");
                DataStructureQueryableCodeGenerator.AddNavigationPropertyWithBackingField(codeBuilder, info.Base,
                                                                                          csPropertyName: info.ExtensionPropertyName(),
                                                                                          propertyType: "Common.Queryable." + info.Extension.Module.Name + "_" + info.Extension.Name,
                                                                                          additionalSetterCode: null);
            }

            if (UniqueReferenceDatabaseDefinition.IsSupported(info) &&
                info.Extension is IOrmDataStructure &&
                info.Base is IWritableOrmDataStructure)
            {
                var    ormDataStructure          = (IOrmDataStructure)info.Extension;
                string systemMessage             = $"DataStructure:{info.Extension.FullName},Property:ID,Referenced:{info.Base.FullName}";
                string onDeleteInterpretSqlError = @"if (interpretedException is Rhetos.UserException && Rhetos.Utilities.MsSqlUtility.IsReferenceErrorOnDelete(interpretedException, "
                                                   + CsUtility.QuotedString(ormDataStructure.GetOrmSchema() + "." + ormDataStructure.GetOrmDatabaseObject()) + @", "
                                                   + CsUtility.QuotedString("ID") + @", "
                                                   + CsUtility.QuotedString(UniqueReferenceDatabaseDefinition.GetConstraintName(info)) + @"))
                        ((Rhetos.UserException)interpretedException).SystemMessage = " + CsUtility.QuotedString(systemMessage) + @";
                    ";
                codeBuilder.InsertCode(onDeleteInterpretSqlError, WritableOrmDataStructureCodeGenerator.OnDatabaseErrorTag, info.Base);
            }
        }
Example #3
0
 /// <summary>
 /// Returns plugins that are registered for the given interface, sorted by dependencies (MefPovider.DependsOn).
 /// </summary>
 internal static IEnumerable <PluginInfo> FindPlugins(ContainerBuilder builder, Type pluginInterface)
 {
     lock (_pluginsLock)
     {
         if (_pluginsByExport == null)
         {
             var assemblies = ListAssemblies();
             try
             {
                 _pluginsByExport = LoadPlugins(assemblies);
             }
             catch (Exception ex)
             {
                 string typeLoadReport = CsUtility.ReportTypeLoadException(ex, "Cannot load plugins.", assemblies);
                 if (typeLoadReport != null)
                 {
                     throw new FrameworkException(typeLoadReport, ex);
                 }
                 else
                 {
                     ExceptionsUtility.Rethrow(ex);
                 }
             }
         }
         return(_pluginsByExport.Get(pluginInterface.FullName));
     }
 }
Example #4
0
 private static string ImplementationCodeSnippet(RegExMatchInfo info)
 {
     return(string.Format(@"[RegularExpression({0}, ErrorMessage = {1})]
 ",
                          CsUtility.QuotedString(info.RegularExpression),
                          CsUtility.QuotedString(info.ErrorMessage)));
 }
Example #5
0
        /// <summary>
        /// Case-insensitive comparison.
        /// </summary>
        public static void AssertContains(string text, IEnumerable <string> patterns, string message = null, string errorContext = null)
        {
            CsUtility.Materialize(ref patterns);
            if (patterns.Any(string.IsNullOrEmpty))
            {
                throw new ArgumentException("Given list of patterns contains an empty string.");
            }

            Console.WriteLine("[AssertContains] Text: '" + text + "'.");

            foreach (var pattern in patterns)
            {
                Console.Write("[AssertContains] Looking for pattern '" + pattern + "'.");

                if (text.ToLower().Contains(pattern.ToLower()))
                {
                    Console.WriteLine(" Found.");
                }
                else
                {
                    Console.WriteLine(" Not found.");
                    Console.WriteLine(errorContext);
                    Assert.Fail("Text should contain pattern '" + pattern + "'."
                                + (string.IsNullOrEmpty(message) ? " " + message : "")
                                + " " + "The text is '" + text.Limit(200, true) + "'.");
                }
            }
        }
#pragma warning disable S1172 // Unused method parameters should be removed
        // Parameter "IConfiguration configuration" is not used here in default configuration,
        // but is allowed as an option for custom configuration implementations.
        private void DefaultContainerConfiguration(IConfiguration configuration, ContainerBuilder builder, List <Action <ContainerBuilder> > customActions)
        {
            builder.AddRhetosRuntime();
            builder.AddRhetosPluginModules();

            CsUtility.InvokeAll(builder, customActions);
        }
        private IConfiguration BuildConfiguration()
        {
            var configurationBuilder = new ConfigurationBuilder(_builderLogProvider);

            CsUtility.InvokeAll(configurationBuilder, _configureConfigurationActions);
            return(configurationBuilder.Build());
        }
        public void GetShortTypeName()
        {
            var types = new[]
            {
                typeof(int),
                typeof(string),
                typeof(InnerClass),
                typeof(List <int>),
                typeof(List <string>),
                typeof(List <InnerClass>),
                typeof(int[]),
                typeof(string[]),
                typeof(InnerClass[]),
                typeof(Dictionary <List <InnerClass[]>, InnerClass>),
            };

            var results = types.Select(t => CsUtility.GetShortTypeName(t)).ToList();

            string expected =
                @"Int32
String
InnerClass
List`1<Int32>
List`1<String>
List`1<InnerClass>
Int32[]
String[]
InnerClass[]
Dictionary`2<List`1<InnerClass[]>, InnerClass>";

            TestUtility.AssertAreEqualByLine(expected, string.Join("\r\n", results));
        }
Example #9
0
        public void GenerateCode(IConceptInfo conceptInfo, ICodeBuilder codeBuilder)
        {
            var info = (QueryInfo)conceptInfo;

            codeBuilder.InsertCode($"new KeyValuePair<string, Type>({CsUtility.QuotedString(info.Parameter)}, typeof({info.Parameter})),{Environment.NewLine}            ",
                                   RepositoryHelper.ReadParameterTypesTag, info.DataStructure);
        }
        public IEnumerable <IConceptInfo> CreateNewConcepts(ChangesOnReferencedInfo conceptInfo, IDslModel existingConcepts)
        {
            var reference = DslUtility.GetPropertyByPath(conceptInfo.Computation, conceptInfo.ReferencePath, existingConcepts).Value;

            if (!(reference is ReferencePropertyInfo))
            {
                throw new DslSyntaxException(conceptInfo, $"The given path '{conceptInfo.ReferencePath}' should end with a reference property, instead of the {reference.GetUserDescription()}.");
            }
            var referenced = ((ReferencePropertyInfo)reference).Referenced;

            var computationDependencies = new List <Tuple <DataStructureInfo, string> >();

            if (referenced is IWritableOrmDataStructure)
            {
                computationDependencies.Add(Tuple.Create(referenced, "item => item.ID"));
            }
            else if (referenced is PolymorphicInfo)
            {
                AddPolymorphicImplementations(computationDependencies, (PolymorphicInfo)referenced, existingConcepts, conceptInfo);
            }

            string referencePathWithGuid = ChangeReferenceToGuid(conceptInfo.ReferencePath);

            return(computationDependencies.Select(dep =>
                                                  new ChangesOnChangedItemsInfo
            {
                Computation = conceptInfo.Computation,
                DependsOn = dep.Item1,
                FilterType = "FilterCriteria",
                FilterFormula = $@"changedItems => new FilterCriteria({CsUtility.QuotedString(referencePathWithGuid)}, ""In"","
                                + $" _domRepository.Common.FilterId.CreateQueryableFilterIds(changedItems.Select({dep.Item2})))"
            }));
        }
Example #11
0
        /// <summary>
        /// Clears the roles' authorization data from the cache: RoleRoles, RolePermissions and Role (full list).
        /// </summary>
        public void ClearCacheRoles(IEnumerable <Guid> roleIds)
        {
            CsUtility.Materialize(ref roleIds);
            _logger.Trace(() => "ClearCacheRoles: " + string.Join(", ", roleIds) + ".");

            var deleteKeys =
                roleIds.Distinct()
                .Select(roleId => "AuthorizationDataCache.RoleRoles." + roleId.ToString())
                .Concat(roleIds.Select(roleId => "AuthorizationDataCache.RolePermissions." + roleId.ToString()))
                .Concat(new[] { "AuthorizationDataCache.Roles" });

            var cache = MemoryCache.Default;

            foreach (string key in deleteKeys)
            {
                cache.Remove(key);
            }

            var systemRoles = (IDictionary <SystemRole, Guid>)cache.Get("AuthorizationDataCache.SystemRoles");

            if (systemRoles != null && systemRoles.Values.Intersect(roleIds).Any())
            {
                _logger.Trace(() => "ClearCacheRoles: SystemRoles.");
                cache.Remove("AuthorizationDataCache.SystemRoles");
            }
        }
Example #12
0
        public static void Save(IEnumerable <InstalledPackage> packages)
        {
            CsUtility.Materialize(ref packages);
            string serialized = JsonConvert.SerializeObject(packages, _serializerSettings);

            File.WriteAllText(GetPackagesFilePath(), serialized, Encoding.UTF8);
        }
Example #13
0
        /// <summary>
        /// The function may return permissions for more claims than required.
        /// </summary>
        public IEnumerable <PrincipalPermissionInfo> GetPrincipalPermissions(IPrincipal principal, IEnumerable <Guid> claimIds = null)
        {
            CsUtility.Materialize(ref claimIds);
            if (claimIds != null && !claimIds.Any())
            {
                return(Enumerable.Empty <PrincipalPermissionInfo>());
            }

            var query = _principalPermissionRepository.Query()
                        .Where(principalPermission => principalPermission.IsAuthorized != null &&
                               principalPermission.PrincipalID == principal.ID);

            if (claimIds != null && claimIds.Count() < _sqlFilterItemsLimit)
            {
                query = query.Where(principalPermission => claimIds.Contains(principalPermission.ClaimID.Value));
            }

            return(query.Select(principalPermission => new PrincipalPermissionInfo
            {
                ID = principalPermission.ID,
                PrincipalID = principalPermission.PrincipalID.Value,
                ClaimID = principalPermission.ClaimID.Value,
                IsAuthorized = principalPermission.IsAuthorized.Value,
            })
                   .ToList());
        }
Example #14
0
        /// <summary>
        /// The function may return permissions for more claims than required.
        /// </summary>
        public IEnumerable <RolePermissionInfo> GetRolePermissions(IEnumerable <Guid> roleIds, IEnumerable <Guid> claimIds = null)
        {
            CsUtility.Materialize(ref roleIds);
            CsUtility.Materialize(ref claimIds);
            if (!roleIds.Any() || (claimIds != null && !claimIds.Any()))
            {
                return(Enumerable.Empty <RolePermissionInfo>());
            }

            var query = _rolePermissionRepository.Query()
                        .Where(rolePermission => rolePermission.IsAuthorized != null &&
                               roleIds.Contains(rolePermission.RoleID.Value));

            if (claimIds != null && claimIds.Count() < _sqlFilterItemsLimit)
            {
                query = query.Where(rolePermission => claimIds.Contains(rolePermission.ClaimID.Value));
            }

            return(query.Select(rolePermission => new RolePermissionInfo
            {
                ID = rolePermission.ID,
                RoleID = rolePermission.RoleID.Value,
                ClaimID = rolePermission.ClaimID.Value,
                IsAuthorized = rolePermission.IsAuthorized.Value,
            })
                   .ToList());
        }
Example #15
0
        public IEnumerable <TPlugin> GetImplementations(Type implements)
        {
            var typeHierarchy      = CsUtility.GetClassHierarchy(implements);
            var allImplementations = typeHierarchy.SelectMany(type => PreSort(_pluginsByImplementation.Value[type]));

            return(_cache.SortedByMetadataDependsOnAndRemoveSuppressed(implements, allImplementations));
        }
Example #16
0
        public IEnumerable <IConceptInfo> CreateNewConcepts(IEnumerable <IConceptInfo> existingConcepts)
        {
            var itemFilter = new ItemFilterInfo
            {
                Expression = String.Format("item => item.{0} != null && item.{1} != null && item.{0} > item.{1}", PropertyFrom.Name, PropertyTo.Name),
                FilterName = PropertyFrom.Name + "_" + PropertyTo.Name + "_RangeFilter",
                Source     = PropertyFrom.DataStructure
            };
            var invalidData = new InvalidDataInfo
            {
                Source       = PropertyFrom.DataStructure,
                FilterType   = itemFilter.FilterName,
                ErrorMessage = "Value of {0} has to be less than or equal to {1}."
            };
            var messageParameters = new InvalidDataMessageParametersConstantInfo
            {
                InvalidData       = invalidData,
                MessageParameters = CsUtility.QuotedString(PropertyFrom.Name) + ", " + CsUtility.QuotedString(PropertyTo.Name)
            };
            var invalidProperty = new InvalidDataMarkProperty2Info
            {
                InvalidData  = invalidData,
                MarkProperty = PropertyFrom
            };

            return(new IConceptInfo[] { itemFilter, invalidData, messageParameters, invalidProperty });
        }
Example #17
0
        private static string CheckLockedPropertySnippet(LockPropertyInfo info)
        {
            string propertyName = info.Source.Name;

            if (info.Source is ReferencePropertyInfo)
            {
                propertyName += "ID";
            }

            return(string.Format(
                       @"if (updatedNew.Count() > 0 || deletedIds.Count() > 0)
            {{
                {0}[] changedItems = updated.Zip(updatedNew, (i, j) => ({4})
                    ? i : null).Where(x => x != null).ToArray();

                if (changedItems != null && changedItems.Length > 0)
                {{
                    var lockedItems = _domRepository.{0}.Filter(this.Query(changedItems.Select(item => item.ID)), new {1}());
                    if (lockedItems.Count() > 0)
                        throw new Rhetos.UserException({2}, ""DataStructure:{0},ID:"" + lockedItems.First().ID.ToString() + "",Property:{3}"");
                }}
            }}
            ",
                       info.Source.DataStructure.GetKeyProperties(),
                       info.FilterType,
                       CsUtility.QuotedString(info.Title),
                       propertyName,
                       CompareValuePropertySnippet(propertyName)));
        }
        public void GenerateCode(IConceptInfo conceptInfo, ICodeBuilder codeBuilder)
        {
            var info = (RegisteredInterfaceImplementationInfo)conceptInfo;

            var interfaceType = Type.GetType(info.InterfaceAssemblyQualifiedName);

            if (interfaceType == null)
            {
                throw new DslSyntaxException(conceptInfo, "Could not find type '" + info.InterfaceAssemblyQualifiedName + "'.");
            }

            // TODO: Remove IQueryableRepository registration.  IQueryableRepository should be cast from repository object in Rhetos.Dom.DefaultConcepts.GenericRepositories class.
            string registerRepository = string.Format(
                @"builder.RegisterType<{0}._Helper.{1}_Repository>().As<IQueryableRepository<{2}>>().InstancePerLifetimeScope();
            ",
                info.DataStructure.Module.Name,
                info.DataStructure.Name,
                interfaceType.FullName);

            codeBuilder.InsertCode(registerRepository, ModuleCodeGenerator.CommonAutofacConfigurationMembersTag);

            string registerImplementationName = string.Format(
                @"{{ typeof({0}), {1} }},
            ",
                interfaceType.FullName,
                CsUtility.QuotedString(
                    info.DataStructure.Module.Name
                    + "." + info.DataStructure.Name));

            codeBuilder.InsertCode(registerImplementationName, ModuleCodeGenerator.RegisteredInterfaceImplementationNameTag);
        }
        private static IEnumerable <IConceptInfo> InitializeNonparsablePropertiesRecursive(IAlternativeInitializationConcept alternativeInitializationConcept, HashSet <string> alreadyCreated, int depth, ILogger traceLogger)
        {
            if (depth > 10)
            {
                throw new DslSyntaxException(alternativeInitializationConcept, "Macro concept references cannot be resolved.");
            }

            List <IConceptInfo> result = new List <IConceptInfo>();

            IEnumerable <IConceptInfo> createdConcepts;

            alternativeInitializationConcept.InitializeNonparsableProperties(out createdConcepts);
            CsUtility.Materialize(ref createdConcepts);

            if (createdConcepts != null && createdConcepts.Count() > 0)
            {
                traceLogger.Trace(() => alternativeInitializationConcept.GetShortDescription() + " generated on alternative initialization: "
                                  + string.Join(", ", createdConcepts.Select(c => c.GetShortDescription())) + ".");

                result.AddRange(createdConcepts);
                foreach (var concept in createdConcepts.OfType <IAlternativeInitializationConcept>())
                {
                    if (!alreadyCreated.Contains(concept.GetFullDescription()))
                    {
                        alreadyCreated.Add(concept.GetFullDescription());
                        result.AddRange(InitializeNonparsablePropertiesRecursive(concept, alreadyCreated, depth + 1, traceLogger));
                    }
                }
            }

            return(result);
        }
Example #20
0
        public IEnumerable <IConceptInfo> CreateNewConcepts(IEnumerable <IConceptInfo> existingConcepts)
        {
            string filterName = "SystemRequired" + Property.Name;

            var filter = new ItemFilterInfo
            {
                Source     = Property.DataStructure,
                FilterName = filterName,
                Expression = "item => item." + Property.Name + " == null"
            };
            var invalidData = new InvalidDataInfo
            {
                Source       = Property.DataStructure,
                FilterType   = filterName,
                ErrorMessage = "System required property {0} is not set."
            };
            var messageParameters = new InvalidDataMessageParametersConstantInfo
            {
                InvalidData       = invalidData,
                MessageParameters = CsUtility.QuotedString(Property.GetUserDescription())
            };
            var invalidProperty = new InvalidDataMarkProperty2Info
            {
                InvalidData  = invalidData,
                MarkProperty = Property
            };

            return(new IConceptInfo[] { filter, invalidData, messageParameters, invalidProperty });
        }
Example #21
0
        public IEnumerable <IConceptInfo> CreateNewConcepts(IEnumerable <IConceptInfo> existingConcepts)
        {
            var itemFilter = new ItemFilterInfo
            {
                Expression = String.Format("item => !String.IsNullOrEmpty(item.{0}) && item.{0}.Length > {1}", Property.Name, Length),
                FilterName = Property.Name + "_MaxLengthFilter",
                Source     = Property.DataStructure
            };
            var invalidData = new InvalidDataInfo
            {
                Source       = Property.DataStructure,
                FilterType   = itemFilter.FilterName,
                ErrorMessage = "Maximum allowed length of {0} is {1} characters."
            };
            var messageParameters = new InvalidDataMessageParametersConstantInfo
            {
                InvalidData       = invalidData,
                MessageParameters = CsUtility.QuotedString(Property.Name) + ", " + Length
            };
            var invalidProperty = new InvalidDataMarkProperty2Info
            {
                InvalidData  = invalidData,
                MarkProperty = Property
            };

            return(new IConceptInfo[] { itemFilter, invalidData, messageParameters, invalidProperty });
        }
Example #22
0
        public IEnumerable <IConceptInfo> CreateNewConcepts(IEnumerable <IConceptInfo> existingConcepts)
        {
            var filterParameter = new ParameterInfo
            {
                Module = Property.DataStructure.Module,
                Name   = Property.Name + "_RegExMatchFilter",
            };

            string filterExpression = string.Format(@"(source, repository, parameter) =>
                {{
                    var items = source.Where(item => !string.IsNullOrEmpty(item.{0})).Select(item => new {{ item.ID, item.{0} }}).ToList();
                    var regex = new System.Text.RegularExpressions.Regex({1});
                    var invalidItemIds = items.Where(item => !regex.IsMatch(item.{0})).Select(item => item.ID).ToList();
                    return Filter(source, invalidItemIds);
                }}",
                                                    Property.Name,
                                                    CsUtility.QuotedString("^" + RegularExpression + "$"));

            var itemFilterRegExMatchProperty = new ComposableFilterByInfo
            {
                Expression = filterExpression,
                Parameter  = filterParameter.Module.Name + "." + filterParameter.Name,
                Source     = Property.DataStructure
            };

            var invalidDataRegExMatchProperty = new InvalidDataMarkPropertyInfo
            {
                DependedProperty = Property,
                FilterType       = itemFilterRegExMatchProperty.Parameter,
                ErrorMessage     = ErrorMessage,
                Source           = Property.DataStructure
            };

            return(new IConceptInfo[] { filterParameter, itemFilterRegExMatchProperty, invalidDataRegExMatchProperty });
        }
Example #23
0
        /// <summary>
        /// Returns after-deploy scripts, ordered by natural sort of file paths inside each package.
        /// </summary>
        private List <Script> GetScripts(InstalledPackage package)
        {
            string afterDeployFolder = Path.GetFullPath(Path.Combine(package.Folder, "AfterDeploy"));

            if (!Directory.Exists(afterDeployFolder))
            {
                return new List <Script> {
                }
            }
            ;

            var files = Directory.GetFiles(afterDeployFolder, "*.*", SearchOption.AllDirectories)
                        .OrderBy(path => CsUtility.GetNaturalSortString(path).Replace(@"\", @" \"));

            const string expectedExtension = ".sql";
            var          badFile           = files.FirstOrDefault(file => Path.GetExtension(file).ToLower() != expectedExtension);

            if (badFile != null)
            {
                throw new FrameworkException("After-deploy script '" + badFile + "' does not have the expected extension '" + expectedExtension + "'.");
            }

            return(files.Select(path => new Script
            {
                Package = package,
                Path = path,
                Name = GetSimpleName(path, afterDeployFolder)
            })
                   .ToList());
        }
Example #24
0
 private void LogConcepts(StringBuilder report, string reportName, IEnumerable <IConceptInfo> concepts, bool first = false)
 {
     CsUtility.Materialize(ref concepts);
     if (concepts != null && concepts.Any())
     {
         report.Append(first ? "" : "\r\n").Append(reportName).Append(": ").Append(string.Join(", ", concepts.Select(c => c.GetShortDescription())) + ".");
     }
 }
 public void Indent()
 {
     Assert.AreEqual("", CsUtility.Indent("", 0));
     Assert.AreEqual(" a", CsUtility.Indent("a", 1));
     Assert.AreEqual("  a", CsUtility.Indent("a", 2));
     Assert.AreEqual("  a\r\n  b", CsUtility.Indent("a\r\nb", 2));
     Assert.AreEqual("  a\r\n  b", CsUtility.Indent("a\nb", 2));
 }
        public void GenerateCode(IConceptInfo conceptInfo, ICodeBuilder codeBuilder)
        {
            var info = (InvalidDataErrorMetadataInfo)conceptInfo;

            codeBuilder.InsertCode(
                $"metadata[{CsUtility.QuotedString(info.Key)}] = {CsUtility.QuotedString(info.Value)};\r\n            ",
                InvalidDataCodeGenerator.ErrorMetadataTag, info.InvalidData);
        }
 protected static string AddFilterSnippet(ApplyFilterOnClientReadInfo info)
 {
     return(string.Format(
                @"{{ {0}, {1} }},
     ",
                CsUtility.QuotedString(info.DataStructure.GetKeyProperties()),
                CsUtility.QuotedString(info.FilterName)));
 }
Example #28
0
 private void LogConcepts(StringBuilder report, string reportName, IEnumerable <IConceptInfo> concepts)
 {
     CsUtility.Materialize(ref concepts);
     if (concepts != null && concepts.Count() > 0)
     {
         report.Append("\r\n  " + reportName + ": " + string.Join(", ", concepts.Select(c => c.GetShortDescription())) + ".");
     }
 }
Example #29
0
        public void GenerateCode(IConceptInfo conceptInfo, ICodeBuilder codeBuilder)
        {
            var info = (RowPermissionsInheritExtensionWriteInfo)conceptInfo;

            codeBuilder.InsertCode(
                ", " + CsUtility.QuotedString(info.Extends.ExtensionPropertyName()),
                RowPermissionsInheritWriteCodeGenerator.ExtensionReferenceTag,
                info.InheritWrite);
        }
Example #30
0
        public void NaturalSortTest_NonNumeric()
        {
            var tests = new[] { "", " ", "  ", "a", ".", "-" };

            foreach (var test in tests)
            {
                Assert.AreEqual(test, CsUtility.GetNaturalSortString(test));
            }
        }