예제 #1
0
        private Lazy <IRelationMetadata> CreateRecursor(RelationMetadata metadata)
        {
            if (metadata.HasFlag(RelationMetadataFlags.Item))
            {
                IRelationMetadata recursiveParent = this.GetRecursiveParent(metadata);

                if (recursiveParent != null)
                {
                    string recursivePath = metadata.Notation.Path(recursiveParent.Identity.Name, metadata.Parent.Identity.Name);
                    string otherPath     = metadata.Notation.Combine(metadata.Identity.Name, recursivePath);

                    MetadataIdentity otherId = metadata.Identity.Push(recursivePath);

                    return(new Lazy <IRelationMetadata>(() => this.GetMetadata(metadata.Schema, otherId)));
                }
            }
            else if (metadata.Owner.Recursor != null)
            {
                IRelationContract contract = this.GetContract(metadata);

                if (contract != null && metadata.Owner.Type.Equals(contract.ItemType))
                {
                    return(new Lazy <IRelationMetadata>(() => metadata.Owner));
                }
            }

            return(null);
        }
예제 #2
0
        private RelationMetadata CreateItem(RelationMetadata parent)
        {
            if (parent.Owner.HasFlag(RelationMetadataFlags.Recursive))
            {
                MemberInfo parentMember = parent.Owner.Parent?.Member;
                MemberInfo thisMember   = parent.Member;

                if (parentMember != null && parentMember.Equals(thisMember))
                {
                    return(null);
                }
            }

            IRelationContract contract = this.GetContract(parent);

            if (contract == null)
            {
                return(null);
            }

            MetadataIdentity itemId   = parent.Identity.Push(contract.ItemName ?? "Item");
            RelationMetadata metadata = new RelationMetadata(parent.Schema, itemId)
            {
                Parent     = parent,
                Type       = contract.ItemType,
                Flags      = RelationMetadataFlags.Item,
                ReadIndex  = contract.ReadIndex,
                WriteIndex = contract.WriteIndex,
                Depth      = parent.Depth + 1,
            };

            metadata.Owner       = metadata;
            metadata.Item        = this.CreateItem(metadata);
            metadata.Properties  = this.CreateLazy(() => this.CreateProperties(metadata));
            metadata.Annotations = this.CreateAnnotations(metadata).ToList();

            if (contract.ReadIndex != null)
            {
                metadata.Flags |= RelationMetadataFlags.Readable;
            }

            if (contract.WriteIndex != null)
            {
                metadata.Flags |= RelationMetadataFlags.Writable;
            }

            if (metadata.Item != null)
            {
                metadata.Flags |= RelationMetadataFlags.List;
            }

            return(metadata);
        }
예제 #3
0
        private RelationMetadata CreateProperty(RelationMetadata parent, MemberInfo memberInfo)
        {
            MetadataIdentity propertyId = parent.Identity.Push(memberInfo.Name);

            RelationMetadata metadata = new RelationMetadata(parent.Schema, propertyId)
            {
                Type   = this.GetMemberType(memberInfo),
                Parent = parent,
                Member = memberInfo,
                Owner  = parent.Owner,
                Flags  = RelationMetadataFlags.Property,
                Depth  = parent.Depth,
            };

            metadata.Item        = this.CreateItem(metadata);
            metadata.Properties  = this.CreateLazy(() => this.CreateProperties(metadata));
            metadata.Annotations = this.CreateAnnotations(metadata).ToList();

            if (metadata.Item != null)
            {
                metadata.Flags |= RelationMetadataFlags.List;
            }

            if (memberInfo is PropertyInfo pi)
            {
                if (pi.CanRead)
                {
                    metadata.Flags |= RelationMetadataFlags.Readable;
                }

                if (pi.CanWrite)
                {
                    metadata.Flags |= RelationMetadataFlags.Writable;
                }
            }
            else if (memberInfo is FieldInfo)
            {
                metadata.Flags |= RelationMetadataFlags.Readable | RelationMetadataFlags.Writable;
            }

            parent.Schema.AddMetadata <IRelationMetadata>(metadata);

            if (metadata.Item != null)
            {
                parent.Schema.AddMetadata <IRelationMetadata>(metadata.Item);
            }

            this.AddRecursors(metadata);

            return(metadata);
        }
예제 #4
0
        private Schema CreateSchema(Type modelType)
        {
            Schema newSchema = new Schema(this, modelType);

            foreach (IMetadataBuilder builder in this)
            {
                MetadataIdentity       newIdentity = new MetadataIdentity(newSchema, this.Notation.Model());
                MetadataBuilderContext context     = new MetadataBuilderContext(newIdentity, newSchema);

                builder.Initialize(context);
            }

            return(newSchema);
        }
        private RelationMetadata CreateItem(IMetadataBuilderContext context, RelationMetadata parent)
        {
            IRelationListContract contract = this.GetListContract(parent);

            if (contract == null)
            {
                return(null);
            }

            MetadataIdentity itemId = parent.Identity.Child(contract.ItemName ?? "Item");

            RelationMetadata metadata = new RelationMetadata(itemId)
            {
                Parent     = parent,
                Type       = contract.ItemType,
                Flags      = RelationMetadataFlags.Item | RelationMetadataFlags.Property,
                ReadIndex  = contract.ReadIndex,
                WriteIndex = contract.WriteIndex,
            };

            metadata.MemberOf    = metadata;
            metadata.Item        = this.CreateItem(context, metadata);
            metadata.Properties  = this.CreateLazy(() => this.CreateProperties(context, metadata));
            metadata.Annotations = this.CreateAnnotations(metadata).ToList();

            if (this.IsMetadataRecursive(metadata))
            {
                metadata.Flags |= RelationMetadataFlags.Recursive;
            }

            if (contract.ReadIndex != null)
            {
                metadata.Flags |= RelationMetadataFlags.Readable;
            }

            if (contract.WriteIndex != null)
            {
                metadata.Flags |= RelationMetadataFlags.Writable;
            }

            if (metadata.Item != null)
            {
                metadata.Flags |= RelationMetadataFlags.List;
            }

            context.AddMetadata <IRelationMetadata>(metadata);

            return(metadata);
        }
        private RelationMetadata CreateProperty(IMetadataBuilderContext context, RelationMetadata parent, MemberInfo memberInfo)
        {
            MetadataIdentity attributeId = parent.Identity.Child(memberInfo.Name);

            RelationMetadata metadata = new RelationMetadata(attributeId)
            {
                Type     = this.GetMemberType(memberInfo),
                Parent   = parent,
                Member   = memberInfo,
                MemberOf = parent.MemberOf,
                Flags    = RelationMetadataFlags.Property,
            };

            metadata.Item        = this.CreateItem(context, metadata);
            metadata.Properties  = this.CreateLazy(() => this.CreateProperties(context, metadata));
            metadata.Annotations = this.CreateAnnotations(metadata).ToList();

            if (metadata.Item != null)
            {
                metadata.Flags |= RelationMetadataFlags.List;
            }

            if (this.IsMetadataRecursive(metadata))
            {
                metadata.Flags |= RelationMetadataFlags.Recursive;
            }

            if (memberInfo is PropertyInfo pi)
            {
                if (pi.CanRead)
                {
                    metadata.Flags |= RelationMetadataFlags.Readable;
                }

                if (pi.CanWrite)
                {
                    metadata.Flags |= RelationMetadataFlags.Writable;
                }
            }
            else if (memberInfo is FieldInfo)
            {
                metadata.Flags |= RelationMetadataFlags.Readable | RelationMetadataFlags.Writable;
            }

            context.AddMetadata <IRelationMetadata>(metadata);

            return(metadata);
        }
        private IRelationMetadata GetMetadata(IMetadataBuilderContext context, MetadataIdentity identity)
        {
            MetadataIdentity  parentIdentity = identity.Parent();
            IRelationMetadata parent         = context.GetMetadata <IRelationMetadata>(parentIdentity.Name) ?? this.GetMetadata(context, parentIdentity);

            if (parent == null)
            {
                return(null);
            }
            else if (parent.Item != null && parent.Item.Identity.Equals(identity))
            {
                return(parent.Item);
            }

            return(parent.Properties.FirstOrDefault(m => m.Identity.Equals(identity)));
        }
예제 #8
0
        internal IRelationMetadata GetMetadata(Schema schema, MetadataIdentity identity)
        {
            MetadataIdentity  parentIdentity = identity.Pop();
            IRelationMetadata parent         = schema.GetCachedMetadata <IRelationMetadata>(parentIdentity.Name) ?? this.GetMetadata(schema, parentIdentity);

            if (parent == null)
            {
                return(null);
            }
            else if (parent.Item != null && parent.Item.Identity.Equals(identity))
            {
                return(parent.Item);
            }

            return(parent.Properties.FirstOrDefault(m => m.Identity.Equals(identity)));
        }
예제 #9
0
        public static MetadataNotFoundException FromMetadata <TMetadata>(MetadataIdentity identity, string message = null, Exception innerException = null)
            where TMetadata : IMetadata
        {
            string fullMessage;

            if (identity != null)
            {
                fullMessage = $"Metadata of type '{typeof(TMetadata).GetSanitizedName()}' not found for property '{identity.Name}' in schema '{identity.Schema.Model.GetSanitizedFullName()}'.";
            }
            else
            {
                fullMessage = $"Metadata of type '{typeof(TMetadata).GetSanitizedName()}' not found.";
            }

            if (message != null || innerException?.Message != null)
            {
                fullMessage += $" {message}";
            }

            return(new MetadataNotFoundException(fullMessage, innerException));
        }
예제 #10
0
        public TMetadata Lookup <TMetadata>(string name)
            where TMetadata : IMetadata
        {
            MetadataKey          key  = this.CreateKey <TMetadata>(name);
            ReaderWriterLockSlim slim = this.GetLock <TMetadata>();

            try
            {
                slim.EnterReadLock();

                if (this.entries.TryGetValue(key, out object value))
                {
                    return((TMetadata)value);
                }
            }
            catch (LockRecursionException ex)
            {
                throw MetadataBuilderException.NoRecursion <TMetadata>(name, ex);
            }
            finally
            {
                if (slim.IsReadLockHeld)
                {
                    slim.ExitReadLock();
                }
            }


            slim.EnterWriteLock();

            try
            {
                MetadataIdentity  identity = new MetadataIdentity(this, name);
                IRelationMetadata relation = this.GetCachedMetadata <IRelationMetadata>(name) ?? this.Store.RelationBuilder.GetMetadata(this, identity);

                if (relation == null)
                {
                    return(default);
예제 #11
0
        internal void Initialize(Schema schema, Type modelType)
        {
            MetadataIdentity identity = new MetadataIdentity(schema);
            RelationMetadata metadata = new RelationMetadata(schema, identity)
            {
                Flags = RelationMetadataFlags.Model | RelationMetadataFlags.Readable,
                Type  = modelType,
            };

            metadata.Owner      = metadata;
            metadata.Properties = this.CreateLazy(() => this.CreateProperties(metadata));
            metadata.Depth      = 0;

            metadata.Annotations = this.CreateAnnotations(metadata).ToList();
            metadata.Item        = this.CreateItem(metadata);

            if (metadata.Item != null)
            {
                metadata.Flags |= RelationMetadataFlags.List;
            }

            schema.AddMetadata <IRelationMetadata>(metadata);
        }
예제 #12
0
 public static MetadataKey FromIdentity <TMetadata>(MetadataIdentity identity) => new MetadataKey(typeof(TMetadata), identity.Name, identity.Schema.Notation.Comparer);
예제 #13
0
 public RelationMetadata(MetadataIdentity identity)
 {
     this.Identity = identity ?? throw new ArgumentNullException(nameof(identity));
 }
예제 #14
0
 public MetadataBuilderContext(MetadataIdentity identity, Schema schema)
 {
     this.Identity = identity ?? throw new ArgumentNullException(nameof(identity));
     this.Schema   = schema ?? throw new ArgumentNullException(nameof(schema));
 }
예제 #15
0
 public RelationMetadata(Schema schema, MetadataIdentity identity)
 {
     this.Schema   = schema ?? throw new ArgumentNullException(nameof(identity));
     this.Notation = schema.Notation;
     this.Identity = identity ?? throw new ArgumentNullException(nameof(identity));
 }