protected Relation(BlsPawn sourcePawn, string multiplexer, int minConnections, int maxConnections) { SourcePawn = sourcePawn; Multiplexer = multiplexer; MinConnections = minConnections; MaxConnections = maxConnections; }
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); }
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); }
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); }
public string GetStorageContainerNameForPawn(BlsPawn pawn) { return(_storageNamingEncoder.EncodePawnContainerName(pawn.GetType().Name)); }
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); }
/// <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) { }
public RelatesToOne(BlsPawn source, string multiplexer = "") : base(source, multiplexer, 0, 1) { }
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); }