Esempio n. 1
0
        static CodeBlock WriteNode(
            CompilerContext compilerContext,
            CodeGenerationContext codeGenContext,
            NodeProperty[] existingNodeProperties = null)
        {
            var resourceUri = codeGenContext.UriGenerator.Invoke(codeGenContext.ResourceInstance);

            var nodeProperties =
                new List <NodeProperty>(existingNodeProperties ?? Enumerable.Empty <NodeProperty>());

            nodeProperties.AddRange(
                GetNodeProperties(compilerContext, codeGenContext,
                                  resourceUri));

            IEnumerable <AnyExpression> render()
            {
                if (compilerContext.Resource.Hydra().Collection.IsCollection&&
                    !compilerContext.Resource.Hydra().Collection.IsHydraCollectionType)
                {
                    var collectionItemType  = compilerContext.Resource.Hydra().Collection.ItemType;
                    var hydraCollectionType = HydraTypes.Collection.MakeGenericType(collectionItemType);
                    var collectionCtor      =
                        hydraCollectionType.GetConstructor(new[]
                                                           { typeof(IEnumerable <>).MakeGenericType(collectionItemType), typeof(string) });

                    if (collectionCtor == null)
                    {
                        throw new InvalidOperationException(
                                  $"Could not generate new HydraCollection<{collectionItemType.Name}>(IEnumerable<{collectionItemType.Name}>, string>()");
                    }

                    var collectionWrapper = Expression.Variable(hydraCollectionType, "hydraCollectionType");

                    yield return(collectionWrapper);

                    var instantiateCollection = Expression.Assign(
                        collectionWrapper,
                        Expression.New(collectionCtor, codeGenContext.ResourceInstance,
                                       Expression.Constant(compilerContext.Resource.Hydra().Collection.ManagesRdfTypeName)));
                    yield return(instantiateCollection);

                    var hydraCollectionModel = compilerContext.MetaModel.GetResourceModel(hydraCollectionType);

                    var hydraCollectionProperties = GetNodeProperties(
                        compilerContext.Push(hydraCollectionModel),
                        codeGenContext.Push(collectionWrapper), resourceUri).ToList();

                    var nodeTypeNode = nodeProperties.FirstOrDefault(x => x.Name == "@type");

                    if (nodeTypeNode != null && compilerContext.Resource.Hydra().Collection.IsFrameworkCollection)
                    {
                        nodeProperties.Clear();
                        nodeProperties.AddRange(hydraCollectionProperties);
                    }
                    else
                    {
                        hydraCollectionProperties.RemoveAll(n => n.Name == "@type");
                        nodeProperties.AddRange(hydraCollectionProperties);
                    }
                }

                if (nodeProperties.Any())
                {
                    yield return(WriteNodeProperties(codeGenContext, nodeProperties));
                }
            }

            return(new CodeBlock(render()));
        }
Esempio n. 2
0
        static NodeProperty CreateNodeProperty(
            CompilerContext compilerContext,
            CodeGenerationContext codeGenContext,
            ResourceProperty property)
        {
            Expression resource = codeGenContext.ResourceInstance;

            if (codeGenContext.ResourceInstance != resource)
            {
                throw new InvalidOperationException("yo backtrack");
            }

            var pi = property.Member;

            // var propertyValue;
            Debug.Assert(pi.DeclaringType != null, "pi.DeclaringType != null");
            var propertyValue = Expression.Variable(pi.PropertyType, $"val{pi.DeclaringType.Name}{pi.Name}");

            // propertyValue = resource.Property;
            var propertyValueAssignment = Expression.Assign(propertyValue, Expression.MakeMemberAccess(resource, pi));

            var preamble = new InlineCode(new Expression[] { propertyValue, propertyValueAssignment });

            if (compilerContext.MetaModel.TryGetResourceModel(pi.PropertyType, out var propertyResourceModel))
            {
                var jsonPropertyName = property.Name;
                return(new NodeProperty(jsonPropertyName)
                {
                    Preamble = preamble,
                    Code = new InlineCode(new[]
                    {
                        codeGenContext.JsonWriter.WritePropertyName(jsonPropertyName),
                        codeGenContext.JsonWriter.WriteBeginObject(),
                        WriteNode(
                            compilerContext.Push(propertyResourceModel),
                            codeGenContext.Push(propertyValue)),
                        codeGenContext.JsonWriter.WriteEndObject()
                    }),
                    Conditional = Expression.NotEqual(propertyValue, Expression.Default(pi.PropertyType))
                });
            }

            var itemTypes = (from i in pi.PropertyType.GetInterfaces()
                             .Concat(pi.PropertyType.IsInterface ? new[] { pi.PropertyType } : Array.Empty <Type>())
                             where i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable <>)
                             let itemType = i.GetGenericArguments()[0]
                                            where itemType != typeof(object)
                                            select itemType).ToList();

            // not an iri node itself, but is it a list of nodes?
            var itemResourceRegistrations = (
                from itemType in itemTypes
                let resourceModels = compilerContext.MetaModel.ResourceRegistrations.Where(r =>
                                                                                           r.ResourceType != null && itemType.IsAssignableFrom(r.ResourceType)).ToList()
                                     where resourceModels.Any()
                                     orderby resourceModels.Count() descending
                                     select
                                     (
                    itemType,
                    (from possible in resourceModels
                     orderby possible.ResourceType.GetInheritanceDistance(itemType)
                     select possible).ToList()
                                     )).ToList <(Type itemType, List <ResourceModel> models)>();

            if (itemResourceRegistrations.Any())
            {
                return(CreateNodePropertyAsList(compilerContext, codeGenContext, property, itemResourceRegistrations,
                                                propertyValue, preamble));
            }

            // not a list of iri or blank nodes
            var propValue = CreateNodePropertyValue(codeGenContext, property, resource);

            propValue.Preamble    = preamble;
            propValue.Conditional = Expression.NotEqual(propertyValue, Expression.Default(pi.PropertyType));
            return(propValue);

            // it's a list of nodes
        }