예제 #1
0
 protected Relation(BlsPawn sourcePawn, string multiplexer, int minConnections, int maxConnections)
 {
     SourcePawn     = sourcePawn;
     Multiplexer    = multiplexer;
     MinConnections = minConnections;
     MaxConnections = maxConnections;
 }
예제 #2
0
        public void ResolveContainerMetadataFromPawnSubClass(BlsPawn pawn)
        {
            BlGraphContainer container = new BlGraphContainer
            {
                Properties           = new List <BlContainerProp>(),
                BlContainerName      = pawn.GetType().Name,
                StorageContainerName = _storageNamingEncoder.EncodePawnContainerName(pawn.GetType().Name)
            };

            container = ResolveContainerProps(container, pawn);
            _compiledCollections.Add(container);
        }
예제 #3
0
        internal void Connect(BlsPawn source, BlsPawn target, string relation)
        {
            if (ToRemove.Contains(source) || ToRemove.Contains(target))
            {
                throw new InvalidOperationException("you are trying to work with a pawn which has been deleted.");
            }

            var con = new Connection {
                From = source, To = target, RelationName = relation
            };

            ToConnect.Add(con);
            ToDisconnect.Remove(con);
        }
예제 #4
0
        private LoseNode ConvertToLoseNode(BlsPawn pawn)
        {
            var node = new LoseNode
            {
                Name = pawn.GetType().Name, ConnectionPoints = new List <LoseEnd>()
            };

            List <PropertyInfo> properties = pawn.GetType().GetProperties().ToList();

            foreach (PropertyInfo property in properties)
            {
                var propType = property.PropertyType;
                if (propType.BaseType != null &&
                    propType.BaseType.Name == typeof(Relation <>).Name &&
                    propType.IsGenericType &&
                    propType.GenericTypeArguments.Length == 1)
                {
                    Type   relatedType = propType.GenericTypeArguments[0];
                    object obj         = pawn.GetType().GetProperty(property.Name)?.GetValue(pawn, null);

                    if (obj != null)
                    {
                        Type objectType = obj.GetType().BaseType;
                        if (objectType != null)
                        {
                            var mxProp  = objectType.GetProperty("Multiplexer");
                            var minProp = objectType.GetProperty("MinConnections");
                            var maxProp = objectType.GetProperty("MaxConnections");
                            if (mxProp != null)
                            {
                                var min = minProp != null?minProp.GetValue(obj) : 0;

                                var max = maxProp != null?maxProp.GetValue(obj) : int.MaxValue;

                                string mxName = mxProp.GetValue(obj).ToString();
                                var    end    = new LoseEnd
                                {
                                    ToName = relatedType.Name, Multiplexer = mxName, MinConnections = (int)min, MaxConnections = (int)max
                                };
                                node.ConnectionPoints.Add(end);
                            }
                        }
                    }
                }
            }

            return(node);
        }
예제 #5
0
 public string GetStorageContainerNameForPawn(BlsPawn pawn)
 {
     return(_storageNamingEncoder.EncodePawnContainerName(pawn.GetType().Name));
 }
예제 #6
0
        private BlGraphContainer ResolveContainerProps(BlGraphContainer container, BlsPawn pawn)
        {
            var softDeleteFlagUsed = false;

            List <PropertyInfo> properties = pawn.GetType().GetProperties().ToList();

            foreach (PropertyInfo property in properties)
            {
                Type propType = property.PropertyType;

                if (BlUtils.IsEnumerableType(propType) && propType != typeof(string))
                {
                    throw new DisallowedPawnPropertyError(
                              $"Collection properties are not allowed in pawns: {property.Name} of {pawn.GetType().Name}");
                }

                Attribute[] attributes = property.GetCustomAttributes().ToArray();

                var blProp = new BlContainerProp();
                if (property.CanRead && property.CanWrite)
                {
                    container.Properties.Add(blProp);

                    blProp.Name     = property.Name;
                    blProp.PropType = propType;

                    if (attributes.Any())
                    {
                        foreach (Attribute attribute in attributes)
                        {
                            if (attribute is UsedForSoftDeletes)
                            {
                                if (blProp.PropType != typeof(bool))
                                {
                                    throw new InvalidPropertyTypeForSoftDelete($"Only boolean type is allowed for the soft delete flag. You are trying to apply it to the property {blProp.Name}, which is of type {blProp.PropType}");
                                }
                                if (softDeleteFlagUsed)
                                {
                                    throw new DuplicateSoftDeletionFlagError(
                                              $"Attempting to declare second soft deletion flag in pawn {blProp.Name}. Only one soft deletion property is allowed per pawn");
                                }

                                blProp.IsSoftDeleteProp = true;
                                softDeleteFlagUsed      = true;
                            }

                            if (attribute is FullTextSearchable)
                            {
                                if (blProp.PropType != typeof(string))
                                {
                                    throw new InvalidFullTextSearchAttributeError(
                                              $"Attempting to apply a full text search attribute to a non-string property {blProp.Name} of {container.BlContainerName}");
                                }

                                blProp.IsSearchable = true;
                            }

                            if (attribute is StringLengthRestriction sRes)
                            {
                                if (blProp.PropType != typeof(string))
                                {
                                    throw new InvalidRestrictiveAttributeError(
                                              $"Attempting to apply a string attribute to a non-string property {blProp.Name} of {container.BlContainerName}");
                                }

                                blProp.MinChar = sRes.MinCharacters;
                                blProp.MaxChar = sRes.MaxCharacters == 0 ? int.MaxValue : sRes.MaxCharacters;
                            }

                            if (attribute is NumberRestriction nRes)
                            {
                                if (!BlUtils.IsNumericType(blProp.PropType))
                                {
                                    throw new InvalidRestrictiveAttributeError(
                                              $"Attempting to apply a numeric attribute to a non-number property {blProp.Name} of {container.BlContainerName}");
                                }

                                blProp.MinValue = nRes.Minimum;
                                blProp.MaxValue = Math.Abs(nRes.Maximum) < 0.000001 ? float.MaxValue : nRes.Maximum;
                            }

                            if (attribute is DateRestriction dRes)
                            {
                                if (blProp.PropType != typeof(DateTime))
                                {
                                    throw new InvalidRestrictiveAttributeError(
                                              $"Attempting to apply a date restriction attribute to a non-date property {blProp.Name} of {container.BlContainerName}");
                                }

                                DateTime earliestValue;
                                DateTime latestValue;

                                if (string.IsNullOrEmpty(dRes.Earliest))
                                {
                                    earliestValue = DateTime.MinValue;
                                }
                                else
                                {
                                    var parsed = DateTime.TryParse(dRes.Earliest, out earliestValue);
                                    if (!parsed)
                                    {
                                        throw new InvalidRestrictiveAttributeError(
                                                  $"Date restriction attribute is not in correct format: {blProp.Name} of {container.BlContainerName}");
                                    }
                                }

                                if (string.IsNullOrEmpty(dRes.Latest))
                                {
                                    latestValue = DateTime.MaxValue;
                                }
                                else
                                {
                                    var parsed = DateTime.TryParse(dRes.Latest, out latestValue);
                                    if (!parsed)
                                    {
                                        throw new InvalidRestrictiveAttributeError(
                                                  $"Date restriction attribute is not in correct format: {blProp.Name} of {container.BlContainerName}");
                                    }
                                }

                                blProp.EarliestDate = earliestValue;
                                blProp.LatestDate   = latestValue;
                            }
                        }
                    }
                }
            }

            return(container);
        }
예제 #7
0
 /// <summary>
 /// Create a new one-to-many relation
 /// </summary>
 /// <param name="source">Source pawn</param>
 /// <param name="multiplexer">A string used to specify a unique relation in case more than one relation exists
 /// for one particular of pawn</param>
 /// <param name="min">Minimum allowed number of connected pawn objects; defaults to 0</param>
 /// <param name="max">Maximum allowed number of connected pawn objects; defaults to <see cref="int.MaxValue"/></param>
 public RelatesToMany(BlsPawn source, string multiplexer = "", int min = 0, int max = int.MaxValue)
     : base(source, multiplexer, min, max)
 {
 }
예제 #8
0
 public RelatesToOne(BlsPawn source, string multiplexer = "") : base(source, multiplexer, 0, 1)
 {
 }
예제 #9
0
        internal BlBinaryExpression ApplySoftDeleteFilterIfApplicable(bool includeDeleted, BlBinaryExpression filter, BlsPawn pawn)
        {
            string           containerName  = Graph.GetStorageContainerNameForPawn(pawn);
            BlGraphContainer container      = Graph.CompiledCollections.FirstOrDefault(c => c.StorageContainerName == containerName);
            BlContainerProp  softDeleteProp = container?.Properties.FirstOrDefault(prop => prop.IsSoftDeleteProp);

            if (softDeleteProp == null)
            {
                return(filter);
            }

            var softDeleteClause = new BlBinaryExpression
            {
                PropName = softDeleteProp.Name, Operator = BlOperator.Eq, Value = includeDeleted
            };

            if (filter == null)
            {
                return(softDeleteClause);
            }

            var newRoot = new BlBinaryExpression
            {
                Left = filter, Operator = BlOperator.And, Right = softDeleteClause
            };

            return(newRoot);
        }