Пример #1
0
        /// <summary>
        /// Parcours les relations et appelle les repository correspondant
        /// </summary>
        public void SaveRelation()
        {
            if (!this._informationRessource.HaveType)
            {
                return;
            }

            if (this._informationRessource.IsEnum)
            {
                return;
            }

            object idRessource = AttributeHandling.GetIdProperty(this._informationRessource.TypeRessource).GetValue(this._informationRessource.Ressource);

            // Parcours des relations
            foreach (Tuple <PropertyInfo, RelationshipJsonApiAttribute> relation in AttributeRelationsHandling.GetRelationshipProperties(this._informationRessource.TypeRessource))
            {
                //Instantiation de la classe RelationSavingEngine avec son type de ressource
                Type typeRessource = relation.Item1.PropertyType.IsGenericType ? relation.Item1.PropertyType.GetGenericArguments()[0] : relation.Item1.PropertyType;
                Type typeEngine    = typeof(RelationSavingEngine <>).MakeGenericType(typeRessource);
                Activator.CreateInstance(typeEngine, new object[] {
                    this._serviceProvider,
                    this._informationRessource,
                    relation.Item1,
                    relation.Item2,
                    idRessource
                });
            }
        }
Пример #2
0
        private static void FeedProperty(object model, PropertyInfo prop, int depth)
        {
            // Récupération du type de la proriété (soit son type direct, soit son type défini dans la propriété "Type" de l'annotation PropertyJsonApi
            Type typeprop = AttributeHandling.GetTypeProperty(prop);

            // Si on est autorisé en écriture (si ce n'est pas une readonly)
            if (prop.CanWrite)
            {
                // La liste ayant un traitement spécifique, on va vérifier qu'il s'agit d'une liste et récupérer immédiatement son type
                Type listType = null;
                if (prop.PropertyType.GetGenericArguments().Length > 0)
                {
                    listType = prop.PropertyType.GetGenericArguments()[0];
                }

                //Cas de la génération d'une propriété simple
                // /!\ les listes sont des types systèmes. Ainsi les List<Interface> auraient pue passerer dans ce test
                if (Utils.IsTypeSystem(typeprop) && (listType == null || !listType.IsInterface))
                {
                    prop.SetValue(model, Feed(typeprop, depth + 1));
                }

                // Si on traite une interface, une classe ou un liste d'interface, alors on passera par la génération de modèle
                else if (typeprop.IsInterface || typeprop.IsClass || (listType != null && listType.IsInterface))
                {
                    FeedPropertyObject(model, prop, depth);
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Execute on each request
        /// Convert Json Object in request body to the expected type in the controller action
        /// </summary>
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            if (AttributeHandling.IsIgnoreJsonApi(((ControllerActionDescriptor)context.ActionDescriptor).MethodInfo, Constants.WAY_READER))
            {
                return;
            }

            string parameter_name = context.ActionDescriptor.GetParameterNameJsonApi();
            object obj            = context.ActionArguments.FirstOrDefault(i => i.Key == parameter_name).Value;

            if (obj != null)
            {
                try
                {
                    JsonApiService service = context.HttpContext.RequestServices.GetRequiredService <JsonApiService>();

                    JsonApiReader jsonReader = new JsonApiReader(new StreamReader(context.HttpContext.Request.Body).ReadToEnd(), obj);
                    jsonReader.SetResolver(new ResolverData(context.HttpContext.RequestServices, service.Resolvers));
                    jsonReader.SetConstraintId(context.ActionArguments.FirstOrDefault(i => i.Key == context.ActionDescriptor.GetParameterNameIdArgument()).Value, context.HttpContext.Request.Method);

                    context.ActionArguments[parameter_name] = jsonReader.GetModel();
                }
                catch (JsonApiException ex)
                {
                    context.HttpContext.Response.StatusCode = Constants.ERROR_STATUT_JSONAPI;
                    context.Result = new ObjectResult(ex.Error.GetJsonErrors());
                }
            }

            base.OnActionExecuting(context);
        }
 public ImmutableOptions(DeclarationHandling declarationHandling, TextNodeHandling textNodeHandling, AttributeHandling attributeHandling, CommentHandling commentHandling, ProcessingInstructionHandling processingInstructionHandling)
 {
     DeclarationHandling           = declarationHandling;
     TextNodeHandling              = textNodeHandling;
     AttributeHandling             = attributeHandling;
     CommentHandling               = commentHandling;
     ProcessingInstructionHandling = processingInstructionHandling;
 }
Пример #5
0
        /// <summary>
        ///  Récupere la liste des champs donnés dans la Query String pour un type de modele
        ///  Si des "include" sont demandés, les champs clés des relations sont ajoutés également dans la liste des champs
        /// </summary>
        public override List <string> GetListeFields(Type type, string relationPath)
        {
            IEnumerable <PropertyInfo> relationshipProperties =
                AttributeRelationsHandling.GetRelationshipProperties(type)
                .Where(p => Utils.IsRelationInInclude(relationPath + "." + AttributeHandling.GetLabelProperty(p.Item1), this._includes))
                .Select(p => p.Item1);

            return(this.GetListeFieldsFromRelations(type, relationshipProperties));
        }
Пример #6
0
        protected PropertyInfo FindSecondaryForeignKeyProperty()
        {
            IEnumerable <PropertyInfo> idsProperties = AttributeHandling.GetIdsProperties(typeof(TRessource));

            //Si plus de 2 clés primaire, on ne peut pas définir instinctivement la seconde clé étrangere
            if (idsProperties.Count() > 2)
            {
                return(null);
            }

            return(idsProperties.FirstOrDefault(prop => prop != this.PrimaryForeigneKeyProperty));
        }
Пример #7
0
        private static bool IsSameType(PropertyInfo prop, Type outputType)
        {
            Type inType   = prop.PropertyType;
            Type typeprop = AttributeHandling.GetTypeProperty(prop);

            if (prop.PropertyType.GetGenericArguments().Length > 0)
            {
                inType   = prop.PropertyType.GetGenericArguments()[0];
                typeprop = AttributeHandling.GetTypeProperty(prop).GetGenericArguments()[0];
            }

            return((inType == outputType) || (typeprop == outputType));
        }
Пример #8
0
        /// <summary>
        /// Récupere la liste des champs donnés dans la Query String pour un type de modele
        /// </summary>
        /// <returns></returns>
        public virtual List <string> GetListeFields(Type type)
        {
            List <string> fields = this.GetListeFields(AttributeHandling.GetLabelProperty(type));

            if (fields != null)
            {
                //Récupere les vrais noms des propriétés
                List <PropertyInfo> fieldsModel = AttributeHandling.GetListeProperties(type, fields).ToList();
                fields = fieldsModel.Select(f => f.Name).ToList();
            }

            return(fields);
        }
Пример #9
0
        /// <summary>
        /// Récupere une liste d'identifiant qui sera injectée à la classe de criteres
        /// Dans le cas d'une relation ToOne, la liste d'identifiant contiendra la liste des clés étrangeres
        /// Dans le cas d'une relation ToMany, la liste d'identifiant contiendra la liste des identifiants des ressources parentes
        /// </summary>
        private object GetListeIdentifiant()
        {
            PropertyInfo propertyInfo = this._typeRelation == TypeRelation.One ?
                                        this._foreignKeyProperty :
                                        AttributeHandling.GetIdProperty(this._informationRessource.TypeRessource);

            Type   typeListe        = typeof(List <>);
            Type   typeListeGeneric = typeListe.MakeGenericType(propertyInfo.PropertyType);
            object listeIdentifiant = Activator.CreateInstance(typeListeGeneric);

            foreach (object ressource in this._informationRessource.RessourceEnum)
            {
                typeListeGeneric.GetMethod("Add").Invoke(listeIdentifiant, new object[] { propertyInfo.GetValue(ressource) });
            }

            return(listeIdentifiant);
        }
        private static void CompareAttributes(XElement a, XElement b, AttributeHandling attributeHandling)
        {
            var attributesA = a.Attributes();
            var attributesB = b.Attributes();

            switch (attributeHandling)
            {
            case AttributeHandling.Ignore:
                return;

            case AttributeHandling.IgnoreMissingInA:
                CompareSubSets(a, b);
                return;

            case AttributeHandling.IgnoreMissingInB:
                CompareSubSets(b, a);
                return;

            case AttributeHandling.IgnoreOrder:
                CompareSubSets(a, b);
                CompareSubSets(b, a);
                return;

            case AttributeHandling.Strict:
                if (attributesA.Count() != attributesB.Count())
                {
                    throw new UnequalityException(new UnequalityReason("The number of attributes differ.", a, b));
                }

                var aArray = attributesA.ToArray();
                var bArray = attributesB.ToArray();
                for (var i = 0; i < aArray.Length; i++)
                {
                    if (!AreEqual(aArray[i], bArray[i]))
                    {
                        throw new UnequalityException(new UnequalityReason($"Attributes at positition {i + 1} differ.", a, b));
                    }
                }

                return;

            default:
                throw new UnequalityException(new UnequalityReason("Unexpected"));
            }
        }
Пример #11
0
        /// <summary>
        /// Parcours les relations et effectue pour chacune d'elle une requete de récupération. Les résultats trouvés correspondant sont affectés au relations.
        /// </summary>
        /// <param name="depth">Niveau de profondeur de relation transmise récursivement</param>
        public void BuildRelation(int depth = 0, string baseRelationPath = null)
        {
            if (depth >= 5)
            {
                return;
            }

            if (!this._informationRessource.HaveType)
            {
                return;
            }

            if (baseRelationPath != null)
            {
                baseRelationPath += ".";
            }

            // Parcours des relations
            foreach (Tuple <PropertyInfo, RelationshipJsonApiAttribute> relation in AttributeRelationsHandling.GetRelationshipProperties(this._informationRessource.TypeRessource))
            {
                string relationPath = baseRelationPath + AttributeHandling.GetLabelProperty(relation.Item1);

                if (!this._queryService.IsInclude(relationPath))
                {
                    continue;
                }

                //Instantiation de la classe RelationsPropertyEngine avec son type de ressource
                Type typeEngine = typeof(RelationsPropertyEngine <>).MakeGenericType(relation.Item1.GetPropertyTypeSample());
                Activator.CreateInstance(typeEngine, new object[] {
                    this._serviceProvider,
                    this._queryService,
                    this._informationRessource,
                    relation.Item1,
                    relation.Item2,
                    relationPath,
                    depth
                });
            }
        }
Пример #12
0
        public void Apply(ControllerModel controller)
        {
            if (controller.ControllerType.IsGenericType)
            {
                // Le parametre généric de la ressource est en premiere position
                Type primaryRessourceType = controller.ControllerType.GetPrimaryRessourceType();

                // Route à appliquer au controller
                string route;

                // Cas d'un Controlleur simple
                if (!controller.ControllerType.IsControllerRelation())
                {
                    ControllerJsonApiAttribute controllerAttribute = primaryRessourceType.GetCustomAttribute <ControllerJsonApiAttribute>();
                    route = controllerAttribute.Route;

                    // Cas d'un Controlleur de relation
                }
                else
                {
                    Type secondaryRessourceType = controller.ControllerType.GetSecondaryRessourceType();

                    ControllerJsonApiAttribute controllerAttribute = secondaryRessourceType.GetCustomAttribute <ControllerJsonApiAttribute>();

                    PropertyInfo propertyRelation = secondaryRessourceType.GetProperties().FirstOrDefault(p => p.GetPropertyTypeSample() == primaryRessourceType);

                    if (controllerAttribute == null || propertyRelation == null)
                    {
                        throw new NotImplementedException();
                    }

                    route = controllerAttribute.Route + "/{id}/" + AttributeHandling.GetLabelProperty(propertyRelation);
                }

                controller.Selectors.Clear();
                controller.Selectors.Add(new SelectorModel {
                    AttributeRouteModel = new AttributeRouteModel(new RouteAttribute(route))
                });
            }
        }
Пример #13
0
        private static void FeedPropertyObject(object modelToBind, PropertyInfo relationship, int depth)
        {
            // Récupération du type de la propriété
            Type typeRelationship = AttributeHandling.GetTypeProperty(relationship);
            // Génération d'une instance de ce type
            object tempObj = Activator.CreateInstance(typeRelationship);

            // Génération d'une liste de modèle
            if (Utils.IsEnum(tempObj))
            {
                //--------Cas particulier------//
                //Type spécifié
                Type sendedType = typeRelationship.GetGenericArguments()[0];
                //Type attendu
                Type waitingType = relationship.PropertyType.GetGenericArguments()[0];
                //Instanciation particulière lorsque le type attendu dans le BO est une List<Interface>
                if (waitingType.GetTypeInfo().IsInterface)
                {
                    tempObj = Activator.CreateInstance(typeof(List <>).MakeGenericType(waitingType));
                }
                //---------------------------//

                BindList(sendedType, tempObj, depth);
            }
            // Génération d'un modèle simple
            else
            {
                BindModel(typeRelationship, tempObj, depth);
            }

            try
            {
                relationship.SetValue(modelToBind, tempObj);
            }
            catch (Exception)
            {
                //On ne bloque pas
            }
        }
Пример #14
0
        public RelationsPropertyEngine(
            IServiceProvider serviceProvider,
            IQueryService queryService,
            InformationRessource informationRessource,
            PropertyInfo propertyRelation,
            RelationshipJsonApiAttribute relationshipJApiAttribute,
            string _relationPath,
            int depth)
        {
            this._serviceProvider      = serviceProvider;
            this._queryService         = queryService;
            this._informationRessource = informationRessource;
            this._relationProperty     = propertyRelation;
            this._relationAttribute    = relationshipJApiAttribute;
            this._depth        = depth;
            this._relationPath = _relationPath;

            (PropertyInfo foreignKeyProperty, ForeignKeyJsonApiAttribute foreignKeyAttribute) =
                AttributeRelationsHandling.FindForeignKeyPropertyAndAttribute(this._informationRessource.TypeRessource, this._relationProperty.Name);

            if (foreignKeyProperty == null && foreignKeyAttribute == null)
            {
                throw new JsonApiArchitectureException($"ForeignKeyJsonApi manquant pour {this._relationProperty.Name} dans {this._informationRessource.TypeRessource.Name}, ajouter[ForeignKeyJsonApi (RelationName = nameof({this._relationProperty.Name}))]");
            }

            this._identifiantRelationProperty = AttributeHandling.GetIdProperty(typeof(T));

            if (this._identifiantRelationProperty == null)
            {
                throw new JsonApiArchitectureException($"Ajouter [IdJsonApi] sur {typeof(T).Name}");
            }

            this._foreignKeyProperty  = foreignKeyProperty;
            this._foreignKeyAttribute = foreignKeyAttribute;
            this._typeRelation        = this._relationAttribute is HasManyJsonApiAttribute ? TypeRelation.Many : TypeRelation.One;

            this.GetRelations();
        }
Пример #15
0
        /// <summary>
        /// Execute after each action
        /// Convert return type to jsonAPI format
        /// </summary>
        /// <param name="context"></param>
        public override void OnActionExecuted(ActionExecutedContext context)
        {
            if (AttributeHandling.IsIgnoreJsonApi(((ControllerActionDescriptor)context.ActionDescriptor).MethodInfo, Constants.WAY_PARSER))
            {
                return;
            }

            JsonApiService service = context.HttpContext.RequestServices.GetRequiredService <JsonApiService>();

            if (service.Error != null && service.Error.HasErrors())
            {
                context.HttpContext.Response.StatusCode = Constants.ERROR_STATUT_JSONAPI;
                context.Result = new ObjectResult(service.Error.GetJsonErrors());

                return;
            }

            if (context.Result is ObjectResult)
            {
                object result = ((ObjectResult)context.Result).Value;

                //If result is already JObject, return it without transform
                if (result?.GetType() == typeof(Newtonsoft.Json.Linq.JObject))
                {
                    return;
                }

                //Transform result to JsonAPI format
                JsonApiParser jsonAPIParser = service.Parser;
                jsonAPIParser.SetResolver(new ResolverData(context.HttpContext.RequestServices, service.Resolvers));
                jsonAPIParser.SetModel(result);
                jsonAPIParser.SetOptionsWithQuery(context.HttpContext.Request.Query);

                ((ObjectResult)context.Result).Value = jsonAPIParser.GetJson();
            }

            base.OnActionExecuted(context);
        }
Пример #16
0
        public virtual async Task <IActionResult> UpdateRessource(int id, [IdArgumentJsonApi] int idRelation, TRessource ressource)
        {
            new RelationsEngine(this.HttpContext.RequestServices, this._queryService, ressource).SaveRelation();

            try {
                AssignIdsInRessource(ressource, id, idRelation, out PropertyInfo secondaryForeigneKeyProperty);

                int idTemp = await this._repository.UpdateAsync(ressource);

                if (AttributeHandling.GetIdsProperties(typeof(TRessource)).Count() == 1)
                {
                    idRelation = idTemp;
                }
                else
                {
                    idRelation = int.Parse(secondaryForeigneKeyProperty.GetValue(ressource).ToString());
                }
            } catch (NotImplementedException) {
                return(NotFound());
            }

            return(await this.GetRessource(id, idRelation));
        }
Пример #17
0
        private T GetJsonApi <T>(JToken source) where T : new()
        {
            var model = new T();

            if (source == null)
            {
                return(model);
            }

            try {
                var type    = new JProperty("type", AttributeHandling.GetLabelProperty(new T().GetType()));
                var attr    = new JProperty("attributes", source);
                var jobject = new JObject {
                    type,
                    attr
                };

                return((T) new JsonApiReader(jobject.ToString(), model).GetModel(true));
            } catch (JsonApiException ex) {
                ex.Error.GetErrors().ForEach(e => this._jsonapi.Error.Create(e));

                throw new ArgumentException($"Query invalid|Element in query string is not in expected format");
            }
        }
Пример #18
0
 /// <summary>
 /// Définit si un type de modele est présent dans le parametre "include" de la Query String
 /// </summary>
 public bool IsInclude <T>() => this.IsInclude(AttributeHandling.GetLabelProperty(typeof(T)));
Пример #19
0
        /// <summary>
        /// Récuperer l'instance de la classe de critéres à utiliser pour le datasource
        /// </summary>
        /// <returns></returns>
        private object GetCriteres()
        {
            Type       typeCriteres = this._foreignKeyAttribute.Criteres ?? AttributeRelationsHandling.GetCriteresType(typeof(T));
            MethodInfo filterMethod = this._queryService.GetType().GetMethod(nameof(IQueryService.FilterOnInclude)).MakeGenericMethod(typeCriteres);
            object     criteres     = filterMethod.Invoke(this._queryService, new object[] { AttributeHandling.GetLabelProperty(this._relationProperty) });

            if (this._foreignKeyAttribute.Property == null)
            {
                if (this._typeRelation == TypeRelation.Many)
                {
                    (criteres as ICriteresBase).ListeId = this.GetListeIdentifiantMany().ConvertListObjectToListInt();
                }
                else
                {
                    (criteres as ICriteresBase).ListeId = this.GetListeIdentifiant().ConvertListObjectToListInt();
                }

                (criteres as ICriteresBase).SkipTake = null;
            }
            else
            {
                typeCriteres.GetProperty(this._foreignKeyAttribute.Property).SetValue(criteres, this.GetListeIdentifiant());
            }

            return(criteres);
        }
Пример #20
0
        private void UpdateWithRepository(MethodInfo updateMethod, object repoInstance, object relationValue)
        {
            // int idRelation = (updateMethod.Invoke(repoInstance, new object[] { relationValue }) as Task<int>).GetAwaiter().GetResult();

            this._foreignKeyProperty.SetValue(this._informationRessource.Ressource, AttributeHandling.GetIdProperty(typeof(T)).GetValue(relationValue));
        }