Example #1
0
        internal static Metadata Make(MetadataLevel level, AccessRights rights)
        {
            var domain          = rights?.Keys ?? RESTarConfig.Resources;
            var entityResources = domain
                                  .OfType <IEntityResource>()
                                  .Where(r => r.IsGlobal)
                                  .OrderBy(r => r.Name)
                                  .ToList();
            var terminalResources = domain
                                    .OfType <ITerminalResource>()
                                    .ToList();

            if (level == MetadataLevel.OnlyResources)
            {
                return new Metadata
                       {
                           CurrentAccessScope = new Dictionary <IResource, Method[]>(rights ?? AccessRights.Root),
                           EntityResources    = entityResources.ToArray(),
                           TerminalResources  = terminalResources.ToArray()
                       }
            }
            ;

            var checkedTypes = new HashSet <Type>();

            void parseType(Type type)
            {
                switch (type)
                {
                case var _ when type.IsEnum:
                    checkedTypes.Add(type);
                    break;

                case var _ when type.IsNullable(out var baseType):
                    parseType(baseType);

                    break;

                case var _ when type.ImplementsGenericInterface(typeof(IEnumerable <>), out var param) && param.Any():
                    if (param[0].ImplementsGenericInterface(typeof(IEnumerable <>)))
                    {
                        break;
                    }
                    parseType(param[0]);

                    break;

                case var _ when type.IsGenericType && type.GetGenericTypeDefinition() == typeof(KeyValuePair <,>):
                case var _ when IsPrimitive(type):
                case var _ when type == typeof(object):
                    break;

                case var _ when checkedTypes.Add(type):
                    type.GetFields(BindingFlags.Public | BindingFlags.Instance)
                    .Where(p => !p.RESTarIgnored())
                    .Select(p => p.FieldType)
                    .ForEach(parseType);

                    type.GetDeclaredProperties().Values
                    .Where(p => !p.Hidden)
                    .Select(p => p.Type)
                    .ForEach(parseType);
                    break;
                }
            }

            var entityTypes   = entityResources.Select(r => r.Type).ToList();
            var terminalTypes = terminalResources.Select(r => r.Type).ToList();

            entityTypes.ForEach(parseType);
            checkedTypes.ExceptWith(entityTypes);
            terminalTypes.ForEach(parseType);
            checkedTypes.ExceptWith(terminalTypes);

            return(new Metadata
            {
                CurrentAccessScope = new Dictionary <IResource, Method[]>(rights ?? AccessRights.Root),
                EntityResources = entityResources.ToArray(),
                TerminalResources = terminalResources.ToArray(),
                EntityResourceTypes = new ReadOnlyDictionary <Type, Member[]>(entityTypes.ToDictionary(t => t, type =>
                                                                                                       type.GetDeclaredProperties().Values.Cast <Member>().ToArray())),
                PeripheralTypes = new ReadOnlyDictionary <Type, Member[]>(checkedTypes.ToDictionary(t => t, type =>
                {
                    var props = type.GetDeclaredProperties().Values;
                    var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance)
                                 .Where(p => !p.RESTarIgnored())
                                 .Select(f => new Field(f));
                    return props.Union <Member>(fields).ToArray();
                }))
            });
        }
Example #2
0
 /// <summary>
 /// Generates metadata according to a given metadata level
 /// </summary>
 public static Metadata Get(MetadataLevel level) => Make(level, null);