Exemple #1
0
        public void SetMemberValue(IConceptInfo conceptInfo, object value)
        {
            PropertyInfo pi;
            FieldInfo    fi;

            if ((pi = MemberInfo as PropertyInfo) != null)
            {
                try
                {
                    pi.SetValue(conceptInfo, value, null);
                }
                catch (ArgumentException ae)
                {
                    throw new FrameworkException(
                              string.Format(CultureInfo.InvariantCulture,
                                            "Unable to convert property {0} in concept {1} from type {2} to type {3}",
                                            pi.Name,
                                            conceptInfo.GetType().FullName,
                                            pi.PropertyType.FullName,
                                            value != null ? value.GetType().FullName : "unknown"),
                              ae);
                }
            }
            else if ((fi = MemberInfo as FieldInfo) != null)
            {
                try
                {
                    fi.SetValue(conceptInfo, value);
                }
                catch (ArgumentException ae)
                {
                    throw new FrameworkException(
                              string.Format(CultureInfo.InvariantCulture,
                                            "Unable to convert property {0} in concept {1} from type {2} to type {3}",
                                            pi.Name,
                                            conceptInfo.GetType().FullName,
                                            pi.PropertyType.FullName,
                                            value != null ? value.GetType().FullName : "unknown"),
                              ae);
                }
            }
            else
            {
                throw new FrameworkException(
                          string.Format(CultureInfo.InvariantCulture,
                                        "Unexpected member type {0} for member {1}.",
                                        MemberInfo.MemberType,
                                        MemberInfo.Name));
            }
        }
Exemple #2
0
        private bool ConteptsValueEqualOrBase(IConceptInfo newConcept, IConceptInfo existingConcept)
        {
            if (object.ReferenceEquals(newConcept, existingConcept))
            {
                return(true);
            }
            else if (newConcept.GetKey() != existingConcept.GetKey())
            {
                return(false);
            }
            else if (!newConcept.GetType().IsInstanceOfType(existingConcept))
            {
                return(false);
            }
            else
            {
                var newConceptMemebers = ConceptMembers.Get(newConcept);
                foreach (ConceptMember member in newConceptMemebers)
                {
                    if (member.IsKey)
                    {
                        continue;
                    }

                    if (!IsConceptMemberEqual(newConcept, existingConcept, member))
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
Exemple #3
0
        private ValueOrError <IConceptInfo> ParseMembers(ITokenReader tokenReader, IConceptInfo lastConcept, bool readingAReference)
        {
            IConceptInfo conceptInfo = (IConceptInfo)Activator.CreateInstance(ConceptInfoType);
            bool         firstMember = true;
            bool         lastPropertyWasInlineParent = false;
            bool         lastConceptUsed             = false;

            var listOfMembers = readingAReference ? Members.Where(m => m.IsKey) : Members.Where(m => m.IsParsable);

            foreach (ConceptMember member in listOfMembers)
            {
                var valueOrError = ReadMemberValue(member, tokenReader, lastConcept, firstMember, ref lastPropertyWasInlineParent, ref lastConceptUsed, readingAReference);

                if (valueOrError.IsError)
                {
                    return(ValueOrError <IConceptInfo> .CreateError(string.Format(CultureInfo.InvariantCulture,
                                                                                  "Cannot read the value of {0} in {1}. {2}",
                                                                                  member.Name, ConceptInfoType.Name, valueOrError.Error)));
                }

                member.SetMemberValue(conceptInfo, valueOrError.Value);
                firstMember = false;
            }

            if (!lastConceptUsed && lastConcept != null)
            {
                return(ValueOrError <IConceptInfo> .CreateError(string.Format(
                                                                    "This concept cannot be enclosed within {0}. Trying to read {1}.",
                                                                    lastConcept.GetType().Name, ConceptInfoType.Name)));
            }

            return(ValueOrError <IConceptInfo> .CreateValue(conceptInfo));
        }
        private void OnMemberRead(ITokenReader iTokenReader, IConceptInfo conceptInfo, ConceptMember conceptMember, ValueOrError <object> valueOrError)
        {
            // have we reached a new keyword after target pos? if so, prevent further member parsing
            if (result.NextKeywordToken != null)
            {
                return;
            }

            var tokenReader = (TokenReader)iTokenReader;

            if (tokenReader.PositionInTokenList <= 0 || lastTokenBeforeTarget == null)
            {
                return;
            }

            var conceptType   = conceptInfo.GetType();
            var lastTokenRead = result.Tokens[tokenReader.PositionInTokenList - 1];

            // track last tokens/members parsed before or at target
            if (lastTokenRead.PositionInDslScript <= lastTokenBeforeTarget.PositionInDslScript && !valueOrError.IsError)
            {
                result.LastTokenParsed[conceptType]       = lastTokenRead;
                result.LastMemberReadAttempt[conceptType] = conceptMember;
            }

            // we are interested in those concepts whose member parsing stops at or after target position
            if (lastTokenRead.PositionInDslScript >= lastTokenBeforeTarget.PositionInDslScript && !result.ActiveConceptValidTypes.Contains(conceptType))
            {
                result.ActiveConceptValidTypes.Add(conceptType);
            }
        }
Exemple #5
0
        private static string GetPropertyName <T>(Expression <Func <T, object> > referenceProperty, IConceptInfo checkValueType)
        {
            var memberExpression = referenceProperty.Body as MemberExpression;

            if (memberExpression == null)
            {
                throw new FrameworkException("Invalid FindByReference method argument: referenceProperty. The argument should be a lambda expression selecting a property of the class "
                                             + typeof(T).Name + ". For example: \"conceptInfo => conceptInfo.SomeProperty\".");
            }

            var property = memberExpression.Member as PropertyInfo;

            if (property == null || memberExpression.Expression.NodeType != ExpressionType.Parameter)
            {
                throw new FrameworkException("Invalid FindByReference method argument: referenceProperty. The argument should be a lambda expression selecting a property of the class "
                                             + typeof(T).Name + ". For example: \"conceptInfo => conceptInfo.SomeProperty\".");
            }

            if (!typeof(IConceptInfo).IsAssignableFrom(property.PropertyType))
            {
                throw new FrameworkException("Invalid FindByReference method argument: referenceProperty. The selected property should be of type that implements IConceptInfo."
                                             + " Property '" + property.Name + "' is of type '" + property.PropertyType.Name + "'.");
            }

            if (!property.PropertyType.IsAssignableFrom(checkValueType.GetType()))
            {
                throw new FrameworkException("Invalid FindByReference method arguments: The selected property " + property.Name
                                             + " type '" + property.PropertyType.Name
                                             + "' does not match the given referenced concept '" + checkValueType.GetUserDescription() + "'.");
            }

            return(property.Name);
        }
        /// <summary>
        /// Use only for generating an error details. Returns the concept's description ignoring possible null reference errors.
        /// </summary>
        public static string GetErrorDescription(this IConceptInfo ci)
        {
            if (ci == null)
            {
                return("<null>");
            }
            var report = new StringBuilder();

            report.Append(ci.GetType().FullName);
            foreach (var member in ConceptMembers.Get(ci))
            {
                report.Append(" " + member.Name + "=");
                var memberValue = member.GetValue(ci);
                try
                {
                    if (memberValue == null)
                    {
                        report.Append("<null>");
                    }
                    else if (member.IsConceptInfo)
                    {
                        AppendMembers(report, (IConceptInfo)memberValue, SerializationOptions.KeyMembers, exceptionOnNullMember: false);
                    }
                    else
                    {
                        report.Append(memberValue.ToString());
                    }
                }
                catch (Exception ex)
                {
                    report.Append("<" + ex.GetType().Name + ">");
                }
            }
            return(report.ToString());
        }
Exemple #7
0
        private static void ValidateNewConceptSameAsExisting(IConceptInfo newConcept, IConceptInfo existingConcept)
        {
            if (newConcept == existingConcept)
            {
                return;
            }

            if (newConcept.GetFullDescription() == existingConcept.GetFullDescription())
            {
                return;
            }

            // The new concept is allowed to be a simple version (base class) of the existing concept, even if it is not the same.
            // This will allow some macro concepts to create simplified new concept that will be ignored if more specific version is already implemented.
            // Note: Unfortunately this logic should not simply be reversed to also ignore old concept if the new concept is a derivation of the old one,
            // because other macros might have already used the old concept to generate a different business logic.
            if (newConcept.GetType().IsAssignableFrom(existingConcept.GetType()) &&
                newConcept.GetFullDescription() == existingConcept.GetFullDescriptionAsBaseConcept(newConcept.GetType()))
            {
                return;
            }

            throw new DslSyntaxException(
                      "Concept with same key is described twice with different values."
                      + "\r\nValue 1: " + existingConcept.GetFullDescription()
                      + "\r\nValue 2: " + newConcept.GetFullDescription()
                      + "\r\nSame key: " + newConcept.GetKey());
        }
        private static List<MethodInfo> GetPluginMethods(IConceptMacro conceptMacro, IConceptInfo conceptInfo)
        {
            var methods = conceptMacro.GetType().GetInterfaces()
                    .Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IConceptMacro<>)
                        && i.GetGenericArguments().Single().IsAssignableFrom(conceptInfo.GetType()))
                    .Select(i => i.GetMethod("CreateNewConcepts"))
                    .ToList();

            if (methods.Count == 0)
                throw new FrameworkException(string.Format(
                    "Plugin {0} does not implement generic interface {1} that accepts argument {2}.",
                    conceptMacro.GetType().FullName,
                    typeof(IConceptMacro<>).FullName,
                    conceptInfo.GetType().FullName));

            return methods;
        }
Exemple #9
0
        /// <summary>
        /// Returns a string that fully describes the concept instance.
        /// The string contains concept's type name and all concept's properties.
        /// </summary>
        public static string GetFullDescription(this IConceptInfo ci)
        {
            StringBuilder desc = new StringBuilder(200);

            desc.Append(ci.GetType().FullName);
            desc.Append(' ');
            AppendMembers(desc, ci, SerializationOptions.AllMembers);
            return(desc.ToString());
        }
        public static string GetShortDescription(this IConceptInfo ci)
        {
            StringBuilder desc = new StringBuilder(100);

            desc.Append(ci.GetType().Name);
            desc.Append(" ");
            AppendMembers(desc, ci, SerializationOptions.KeyMembers);
            return(desc.ToString());
        }
        private static Type BaseConceptInfoType(IConceptInfo ci)
        {
            Type t = ci.GetType();

            while (typeof(IConceptInfo).IsAssignableFrom(t.BaseType) && t.BaseType.IsClass)
            {
                t = t.BaseType;
            }
            return(t);
        }
        public static Type BaseConceptInfoType(this IConceptInfo ci)
        {
            Type t = ci.GetType();

            while (typeof(IConceptInfo).IsAssignableFrom(t.BaseType))
            {
                t = t.BaseType;
            }
            return(t);
        }
Exemple #13
0
        private static List <MethodInfo> GetPluginMethods(IConceptDataMigration dataMigrationScript, IConceptInfo conceptInfo)
        {
            var methods = dataMigrationScript.GetType().GetInterfaces()
                          .Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IConceptDataMigration <>) &&
                                 i.GetGenericArguments().Single().IsAssignableFrom(conceptInfo.GetType()))
                          .Select(i => i.GetMethod("GenerateCode"))
                          .ToList();

            if (methods.Count == 0)
            {
                throw new FrameworkException(string.Format(
                                                 "Plugin {0} does not implement generic interface {1} that accepts argument {2}.",
                                                 dataMigrationScript.GetType().FullName,
                                                 typeof(IConceptDataMigration <>).FullName,
                                                 conceptInfo.GetType().FullName));
            }

            return(methods);
        }
 public NewConceptApplication(IConceptInfo conceptInfo, IConceptDatabaseDefinition conceptImplementation)
 {
     Id = Guid.Empty;
     ConceptInfo = conceptInfo;
     ConceptInfoTypeName = conceptInfo.GetType().AssemblyQualifiedName;
     ConceptInfoKey = conceptInfo.GetKey();
     ConceptImplementation = conceptImplementation;
     ConceptImplementationType = conceptImplementation.GetType();
     ConceptImplementationTypeName = ConceptImplementationType.AssemblyQualifiedName;
     ConceptImplementationVersion = GetVersionFromAttribute(ConceptImplementationType);
 }
 public NewConceptApplication(IConceptInfo conceptInfo, IConceptDatabaseDefinition conceptImplementation)
 {
     Id                            = Guid.Empty;
     ConceptInfo                   = conceptInfo;
     ConceptInfoTypeName           = conceptInfo.GetType().AssemblyQualifiedName;
     ConceptInfoKey                = conceptInfo.GetKey();
     ConceptImplementation         = conceptImplementation;
     ConceptImplementationType     = conceptImplementation.GetType();
     ConceptImplementationTypeName = ConceptImplementationType.AssemblyQualifiedName;
     ConceptImplementationVersion  = GetVersionFromAttribute(ConceptImplementationType);
 }
        /// <summary>
        /// Returns a string that describes the concept instance cast as a base concept.
        /// The string contains base concept's type name and the base concept's properties.
        /// </summary>
        public static string GetFullDescriptionAsBaseConcept(this IConceptInfo ci, Type baseConceptType)
        {
            if (!baseConceptType.IsAssignableFrom(ci.GetType()))
            {
                throw new FrameworkException($"{baseConceptType} is not assignable from {ci.GetUserDescription()}.");
            }
            StringBuilder desc = new StringBuilder(200);

            desc.Append(baseConceptType.FullName);
            desc.Append(" ");
            AppendMembers(desc, ci, SerializationOptions.AllMembers, false, baseConceptType);
            return(desc.ToString());
        }
        private static void AppendMember(StringBuilder text, IConceptInfo ci, ConceptMember member, bool exceptionOnNullMember)
        {
            object memberValue = member.GetValue(ci);

            if (memberValue == null)
            {
                if (exceptionOnNullMember)
                {
                    throw new DslSyntaxException(ci, string.Format(
                                                     "{0}'s property {1} is null. Info: {2}.",
                                                     ci.GetType().Name, member.Name, ci.GetErrorDescription()));
                }
                else
                {
                    text.Append("<null>");
                }
            }
            else if (member.IsConceptInfo)
            {
                IConceptInfo value = (IConceptInfo)member.GetValue(ci);
                if (member.ValueType == typeof(IConceptInfo))
                {
                    text.Append(BaseConceptInfoType(value).Name).Append(":");
                }
                AppendMembers(text, value, SerializationOptions.KeyMembers, exceptionOnNullMember);
            }
            else if (member.ValueType == typeof(string))
            {
                text.Append(SafeDelimit(member.GetValue(ci).ToString()));
            }
            else
            {
                throw new FrameworkException(string.Format(
                                                 "IConceptInfo member {0} of type {1} in {2} is not supported.",
                                                 member.Name, member.ValueType.Name, ci.GetType().Name));
            }
        }
Exemple #18
0
        public void Add(IConceptInfo concept)
        {
            Type conceptType = concept.GetType();

            _subtypes.Add(conceptType);

            foreach (ConceptMember member in ConceptMembers.Get(concept))
            {
                if (member.IsConceptInfo)
                {
                    string referencedConceptKey = ((IConceptInfo)member.GetValue(concept)).GetKey();
                    _conceptsIndex.Add(referencedConceptKey, conceptType, member.Name, concept);
                }
            }
        }
Exemple #19
0
        private string ReportPreviousConcept(IConceptInfo conceptInfo)
        {
            var sb = new StringBuilder();

            if (conceptInfo != null)
            {
                sb.AppendFormat("Previous concept: {0}", conceptInfo.GetUserDescription()).AppendLine();
                var properties = conceptInfo.GetType().GetProperties().ToList();
                properties.ForEach(it =>
                                   sb.AppendFormat("Property {0} ({1}) = {2}",
                                                   it.Name,
                                                   it.PropertyType.Name,
                                                   it.GetValue(conceptInfo, null) ?? "<null>")
                                   .AppendLine());
            }
            return(sb.ToString());
        }
Exemple #20
0
        // The new concept is allowed to be a simple version (base class) of the existing concept, even if it is not the same.
        // This will allow some macro concepts to create simplified new concept that will be ignored if more specific version is already implemented.
        // Note: Unfortunately this logic should not simply be reversed to also ignore old concept if the new concept is a derivation of the old one,
        // because other macros might have already used the old concept to generate a different business logic.
        private void ValidateNewConceptSameAsExisting(IConceptInfo newConcept, IConceptInfo existingConcept)
        {
            _validateDuplicateStopwatch.Start();

            if (newConcept != existingConcept &&
                newConcept.GetFullDescription() != existingConcept.GetFullDescription() &&
                !(newConcept.GetType().IsAssignableFrom(existingConcept.GetType()) &&
                  newConcept.GetFullDescription() == existingConcept.GetFullDescriptionAsBaseConcept(newConcept.GetType())))
            {
                throw new DslSyntaxException(
                          "Concept with same key is described twice with different values."
                          + "\r\nValue 1: " + existingConcept.GetFullDescription()
                          + "\r\nValue 2: " + newConcept.GetFullDescription()
                          + "\r\nSame key: " + newConcept.GetKey());
            }

            _validateDuplicateStopwatch.Stop();
        }
Exemple #21
0
        public static ConceptSyntaxNode CreateConceptSyntaxNode(this DslSyntax dslSyntax, IConceptInfo ci)
        {
            var conceptInfoType = ci.GetType();
            var node            = new ConceptSyntaxNode(dslSyntax.GetConceptType(conceptInfoType));
            var members         = ConceptMembers.Get(conceptInfoType);

            if (node.Parameters.Length != members.Length)
            {
                throw new InvalidOperationException(
                          $"{nameof(ConceptSyntaxNode)} parameters count ({node.Parameters.Length})" +
                          $" does not match {nameof(ConceptMembers)} count ({members.Length}).");
            }

            for (int m = 0; m < members.Length; m++)
            {
                object value = members[m].GetValue(ci);

                node.Parameters[m] = value;

                if (value == null)
                {
                    node.Parameters[m] = null;
                }
                else if (value is string)
                {
                    node.Parameters[m] = value;
                }
                else if (value is IConceptInfo referencedConceptInfo)
                {
                    var referencedNode = CreateConceptSyntaxNode(dslSyntax, referencedConceptInfo);
                    node.Parameters[m] = referencedNode;
                }
                else
                {
                    var valueType = value?.GetType().Name ?? "null";
                    throw new ArgumentException($"Value type {valueType} is not expected in '{ci.GetUserDescription()}', parameter {members[m].Name}.");
                }
            }

            return(node);
        }
Exemple #22
0
 private static ConceptApplication NewConceptApplication(
     IConceptInfo conceptInfo,
     IConceptDatabaseDefinition conceptImplementation,
     Guid Id,
     string CreateQuery,
     ConceptApplication[] DependsOn,
     int OldCreationOrder)
 {
     return(new ConceptApplication
     {
         //ConceptInfo = conceptInfo,
         ConceptInfoTypeName = conceptInfo.GetType().AssemblyQualifiedName,
         ConceptInfoKey = conceptInfo.GetKey(),
         //ConceptImplementation = conceptImplementation,
         //ConceptImplementationType = conceptImplementation.GetType(),
         ConceptImplementationTypeName = conceptImplementation.GetType().AssemblyQualifiedName,
         //ConceptImplementationVersion = GetVersionFromAttribute(conceptImplementation.GetType()),
         Id = Id,
         CreateQuery = CreateQuery,
         DependsOn = DependsOn,
         OldCreationOrder = OldCreationOrder
     });
 }
Exemple #23
0
        private static void AppendMembers(StringBuilder text, IConceptInfo ci, SerializationOptions serializationOptions, bool exceptionOnNullMember = false, Type asBaseConceptType = null)
        {
            IEnumerable<ConceptMember> members = ConceptMembers.Get(asBaseConceptType ?? ci.GetType());
            if (serializationOptions == SerializationOptions.KeyMembers)
                members = members.Where(member => member.IsKey);

            bool firstMember = true;
            foreach (ConceptMember member in members)
            {
                string separator = member.IsKey ? "." : " ";
                if (!firstMember)
                    text.Append(separator);
                firstMember = false;

                AppendMember(text, ci, member, exceptionOnNullMember);
            }
        }
Exemple #24
0
 private static Type BaseConceptInfoType(IConceptInfo ci)
 {
     Type t = ci.GetType();
     while (typeof(IConceptInfo).IsAssignableFrom(t.BaseType) && t.BaseType.IsClass)
         t = t.BaseType;
     return t;
 }
Exemple #25
0
        private ValueOrError <IConceptInfo> ParseMembers(ITokenReader tokenReader, IConceptInfo useLastConcept, bool readingAReference, ref bool parsedFirstReferenceElement)
        {
            IConceptInfo conceptInfo = (IConceptInfo)Activator.CreateInstance(ConceptInfoType);
            bool         firstMember = true;

            var listOfMembers = readingAReference ? Members.Where(m => m.IsKey) : Members.Where(m => m.IsParsable);

            var parentProperty = listOfMembers.LastOrDefault(member => member.IsParentNested)
                                 ?? (listOfMembers.First().IsConceptInfo ? listOfMembers.First() : null);

            if (useLastConcept != null && parentProperty == null)
            {
                return(ValueOrError <IConceptInfo> .CreateError($"This concept cannot be nested within {useLastConcept.GetType().Name}. Trying to read {ConceptInfoType.Name}."));
            }

            foreach (ConceptMember member in listOfMembers)
            {
                if (!readingAReference)
                {
                    parsedFirstReferenceElement = false; // Reset a reference elements group, that should separated by dot.
                }
                var valueOrError = ReadMemberValue(member, tokenReader, member == parentProperty ? useLastConcept : null, firstMember, ref parsedFirstReferenceElement, readingAReference);

                if (valueOrError.IsError)
                {
                    return(ValueOrError <IConceptInfo> .CreateError(string.Format(CultureInfo.InvariantCulture,
                                                                                  "Cannot read the value of {0} in {1}. {2}",
                                                                                  member.Name, ConceptInfoType.Name, valueOrError.Error)));
                }

                member.SetMemberValue(conceptInfo, valueOrError.Value);
                firstMember = false;
            }

            return(ValueOrError <IConceptInfo> .CreateValue(conceptInfo));
        }
Exemple #26
0
 private static void AppendMember(StringBuilder text, IConceptInfo ci, ConceptMember member, bool exceptionOnNullMember)
 {
     object memberValue = member.GetValue(ci);
     if (memberValue == null)
         if (exceptionOnNullMember)
             throw new DslSyntaxException(ci, string.Format(
                 "{0}'s property {1} is null. Info: {2}.",
                 ci.GetType().Name, member.Name, ci.GetErrorDescription()));
         else
             text.Append("<null>");
     else if (member.IsConceptInfo)
     {
         IConceptInfo value = (IConceptInfo)member.GetValue(ci);
         if (member.ValueType == typeof(IConceptInfo))
             text.Append(BaseConceptInfoType(value).Name).Append(":");
         AppendMembers(text, value, SerializationOptions.KeyMembers, exceptionOnNullMember);
     }
     else if (member.ValueType == typeof(string))
         text.Append(SafeDelimit(member.GetValue(ci).ToString()));
     else
         throw new FrameworkException(string.Format(
             "IConceptInfo member {0} of type {1} in {2} is not supported.",
             member.Name, member.ValueType.Name, ci.GetType().Name));
 }
Exemple #27
0
        // Check if the data structure already contains a specific row permissions filter that is not rule-based. Such filter is not compatible with RowPermissionsPluginableFiltersInfo.
        private void CheckForIncompatibleSpecificRowPermissionsFilter(IDslModel existingConcepts, IConceptInfo newRowPermissionsFilter, RowPermissionsPluginableFiltersInfo conceptInfo)
        {
            IConceptInfo oldRowPermissions = existingConcepts.FindByKey(newRowPermissionsFilter.GetKey());

            if (oldRowPermissions == null)
            {
                return;
            }

            string filterName;
            string newFilterExpression;
            string oldFilterExpression = null;

            if (newRowPermissionsFilter is RowPermissionsReadInfo newReadFilter)
            {
                filterName          = RowPermissionsReadInfo.FilterName;
                newFilterExpression = newReadFilter.SimplifiedExpression;
                if (oldRowPermissions is RowPermissionsReadInfo oldReadFilter)
                {
                    oldFilterExpression = oldReadFilter.SimplifiedExpression;
                }
            }
            else if (newRowPermissionsFilter is RowPermissionsWriteInfo newWriteFilter)
            {
                filterName          = RowPermissionsWriteInfo.FilterName;
                newFilterExpression = newWriteFilter.SimplifiedExpression;
                if (oldRowPermissions is RowPermissionsWriteInfo oldWriteFilter)
                {
                    oldFilterExpression = oldWriteFilter.SimplifiedExpression;
                }
            }
            else
            {
                throw new InvalidOperationException($"Unexpected {nameof(newRowPermissionsFilter)} type '{newRowPermissionsFilter.GetType()}'.");
            }

            if (oldFilterExpression == null || oldFilterExpression != newFilterExpression)
            {
                throw new DslSyntaxException(conceptInfo, "Cannot use row permissions rules or row permissions inheritance on "
                                             + conceptInfo.DataStructure.GetUserDescription() + " because it already contains a specific row permissions filter ("
                                             + filterName + ")."
                                             + " Use RowPermissions concept instead of the specific filter, to create rules-based row permissions.");
            }
        }
Exemple #28
0
        private ValueOrError<IConceptInfo> ParseMembers(ITokenReader tokenReader, IConceptInfo lastConcept, bool readingAReference)
        {
            IConceptInfo conceptInfo = (IConceptInfo)Activator.CreateInstance(ConceptInfoType);
            bool firstMember = true;
            bool lastPropertyWasInlineParent = false;
            bool lastConceptUsed = false;

            var listOfMembers = readingAReference ? Members.Where(m => m.IsKey) : Members.Where(m => m.IsParsable);
            foreach (ConceptMember member in listOfMembers)
            {
                var valueOrError = ReadMemberValue(member, tokenReader, lastConcept, firstMember, ref lastPropertyWasInlineParent, ref lastConceptUsed, readingAReference);

                if (valueOrError.IsError)
                    return ValueOrError<IConceptInfo>.CreateError(string.Format(CultureInfo.InvariantCulture,
                        "Cannot read the value of {0} in {1}. {2}",
                        member.Name, ConceptInfoType.Name, valueOrError.Error));

                member.SetMemberValue(conceptInfo, valueOrError.Value);
                firstMember = false;
            }

            if (!lastConceptUsed && lastConcept != null)
                return ValueOrError<IConceptInfo>.CreateError(string.Format(
                    "This concept cannot be enclosed within {0}. Trying to read {1}.",
                    lastConcept.GetType().Name, ConceptInfoType.Name));

            return ValueOrError<IConceptInfo>.CreateValue(conceptInfo);
        }
Exemple #29
0
 public static ConceptMember[] Get(IConceptInfo conceptInfo)
 {
     return(Get(conceptInfo.GetType(), new Lazy <IConceptInfo>(() => conceptInfo)));
 }
Exemple #30
0
 public static ConceptMember[] Get(IConceptInfo conceptInfo)
 {
     return Get(conceptInfo.GetType(), new Lazy<IConceptInfo>(() => conceptInfo));
 }
        private static void AppendMembers(StringBuilder text, IConceptInfo ci, SerializationOptions serializationOptions, bool exceptionOnNullMember = false, Type asBaseConceptType = null)
        {
            IEnumerable <ConceptMember> members = ConceptMembers.Get(asBaseConceptType ?? ci.GetType());

            if (serializationOptions == SerializationOptions.KeyMembers)
            {
                members = members.Where(member => member.IsKey);
            }

            bool firstMember = true;

            foreach (ConceptMember member in members)
            {
                string separator = member.IsKey ? "." : " ";
                if (!firstMember)
                {
                    text.Append(separator);
                }
                firstMember = false;

                AppendMember(text, ci, member, exceptionOnNullMember);
            }
        }
Exemple #32
0
        private ValueOrError <object> ReadMemberValue(ConceptMember member, ITokenReader tokenReader, IConceptInfo useLastConcept,
                                                      bool firstMember, ref bool parsedFirstReferenceElement, bool readingAReference)
        {
            try
            {
                if (member.IsStringType)
                {
                    if (useLastConcept != null)
                    {
                        return(ValueOrError <object> .CreateError($"This concept cannot be nested within {useLastConcept.GetType().Name}. Trying to read {ConceptInfoType.Name}."));
                    }

                    if (readingAReference && parsedFirstReferenceElement)
                    {
                        if (!tokenReader.TryRead("."))
                        {
                            return(ValueOrError <object> .CreateError(string.Format(
                                                                          "Parent property and the following key value ({0}) must be separated with a dot. Expected \".\"",
                                                                          member.Name)));
                        }
                    }

                    parsedFirstReferenceElement = true;

                    // Legacy syntax:
                    if (!readingAReference && member.IsKey && member.IsStringType && !firstMember)
                    {
                        if (tokenReader.TryRead("."))
                        {
                            AddWarning($"Obsolete syntax: Remove '.' from {Keyword} statement. {((TokenReader)tokenReader).ReportPosition()}.");
                        }
                    }

                    return(tokenReader.ReadText().ChangeType <object>());
                }

                if (member.ValueType == typeof(IConceptInfo))
                {
                    if (useLastConcept != null)
                    {
                        return((object)useLastConcept);
                    }
                    else
                    {
                        return(ValueOrError <object> .CreateError($"Member of type IConceptInfo can only be nested within" +
                                                                  $" the referenced parent concept. It must be a first member or marked with {nameof(ConceptParentAttribute)}."));
                    }
                }

                if (useLastConcept != null && member.ValueType.IsInstanceOfType(useLastConcept))
                {
                    return((object)useLastConcept);
                }

                if (member.IsConceptInfo && firstMember && !readingAReference && Members.Count(m => m.IsParsable) == 1)
                {
                    // This validation is not necessary for consistent parsing. It is enforced simply to avoid ambiguity for future concept overloads
                    // when parsing similar concepts such as "Logging { AllProperties; }", "History { AllProperties; }" and "Persisted { AllProperties; }".
                    var parentMembers = ConceptMembers.Get(member.ValueType).Where(m => m.IsParsable).ToArray();
                    if (parentMembers.Count() == 1 && parentMembers.Single().IsConceptInfo)
                    {
                        return(ValueOrError.CreateError($"{ConceptInfoHelper.GetKeywordOrTypeName(ConceptInfoType)} must be nested" +
                                                        $" within the referenced parent concept {ConceptInfoHelper.GetKeywordOrTypeName(member.ValueType)}." +
                                                        $" A single-reference concept that references another single-reference concept must always be used with nested syntax to avoid ambiguity."));
                    }
                }

                if (member.IsConceptInfo)
                {
                    if (firstMember && member.ValueType == ConceptInfoType)
                    {
                        return(ValueOrError.CreateError(string.Format(
                                                            "Recursive concept {0} cannot be used as a root because its parent property ({1}) must reference another concept. Use a non-recursive concept for the root and a derivation of the root concept with additional parent property as a recursive concept.",
                                                            ConceptInfoHelper.GetKeywordOrTypeName(ConceptInfoType), member.Name)));
                    }

                    GenericParser subParser = new GenericParser(member.ValueType, "");
                    return(subParser.ParseMembers(tokenReader, useLastConcept, true, ref parsedFirstReferenceElement).ChangeType <object>());
                }

                return(ValueOrError.CreateError(string.Format(
                                                    "GenericParser does not support members of type \"{0}\". Try using string or implementation of IConceptInfo.",
                                                    member.ValueType.Name)));
            }
            catch (DslSyntaxException ex)
            {
                return(ValueOrError <object> .CreateError(ex.Message));
            }
        }
Exemple #33
0
 public void Add(IConceptInfo concept)
 {
     _conceptsByType.Add(concept.GetType(), concept);
 }
 public static string GetKeywordOrTypeName(this IConceptInfo ci)
 {
     return(ci.GetKeyword() ?? ci.GetType().Name);
 }
 /// <summary>
 /// Return value is null if IConceptInfo implementations does not have ConceptKeyword attribute. Such classes are usually used as a base class for other concepts.
 /// </summary>
 public static string GetKeyword(this IConceptInfo ci)
 {
     return(GetKeyword(ci.GetType()));
 }
Exemple #36
0
 public static Type BaseConceptInfoType(this IConceptInfo ci)
 {
     return(BaseConceptInfoType(ci.GetType()));
 }
Exemple #37
0
        public void SetMemberValue(IConceptInfo conceptInfo, object value)
        {
            PropertyInfo pi;
            FieldInfo fi;

            if ((pi = MemberInfo as PropertyInfo) != null)
                try
                {
                    pi.SetValue(conceptInfo, value, null);
                }
                catch (ArgumentException ae)
                {
                    throw new FrameworkException(
                        string.Format(CultureInfo.InvariantCulture,
                            "Unable to convert property {0} in concept {1} from type {2} to type {3}",
                                pi.Name,
                                conceptInfo.GetType().FullName,
                                pi.PropertyType.FullName,
                                value != null ? value.GetType().FullName : "unknown"),
                        ae);
                }
            else if ((fi = MemberInfo as FieldInfo) != null)
                try
                {
                    fi.SetValue(conceptInfo, value);
                }
                catch (ArgumentException ae)
                {
                    throw new FrameworkException(
                        string.Format(CultureInfo.InvariantCulture,
                            "Unable to convert property {0} in concept {1} from type {2} to type {3}",
                                pi.Name,
                                conceptInfo.GetType().FullName,
                                pi.PropertyType.FullName,
                                value != null ? value.GetType().FullName : "unknown"),
                        ae);
                }
            else
                throw new FrameworkException(
                    string.Format(CultureInfo.InvariantCulture,
                        "Unexpected member type {0} for member {1}.",
                            MemberInfo.MemberType,
                            MemberInfo.Name));
        }
Exemple #38
0
 protected string ReportErrorContext(IConceptInfo conceptInfo, int index)
 {
     var sb = new StringBuilder();
     sb.AppendLine(_dslSource.ReportError(index));
     if (conceptInfo != null)
     {
         sb.AppendFormat("Previous concept: {0}", conceptInfo.GetUserDescription()).AppendLine();
         var properties = conceptInfo.GetType().GetProperties().ToList();
         properties.ForEach(it =>
             sb.AppendFormat("Property {0} ({1}) = {2}",
                 it.Name,
                 it.PropertyType.Name,
                 it.GetValue(conceptInfo, null) ?? "<null>")
                 .AppendLine());
     }
     return sb.ToString();
 }
Exemple #39
0
 public static ConceptMember[] Get(IConceptInfo conceptInfo)
 {
     return(Get(conceptInfo.GetType(), conceptInfo));
 }