Used by the IJsonResultsAdapter to provide information about the current node being processed.
Example #1
0
    public JsonNodeInfo VisitNode(JObject node, MappingContext mappingContext, NodeContext nodeContext) {
      var result = new JsonNodeInfo();
      var idProp = node.Property("id");
      var modelsProp = node.Property("models");
      if (idProp != null && modelsProp != null) {
        node.Add("modelLinks", modelsProp.Value);
        modelsProp.Value = new JArray();
        result.ServerTypeNameInfo = new TypeNameInfo("Make", "");
        return result;
      }

      var makeProp = node.Property("make");
      if (idProp != null && makeProp != null) {
        node.Add("makeLink", makeProp.Value);
        makeProp.Value = null;
        var catsProp = node.Property("categories");
        if (catsProp != null) {
          var styleProps = catsProp["Vehicle Style"];
          var styles = styleProps.Select(t => t.Value<String>()).ToAggregateString(", ");
          node.Add("vehicleStyles", new JValue(styles));
        }
        result.ServerTypeNameInfo = new TypeNameInfo("Model", "");
        return result;
      }
      return result;
      //// Model parser
      //else if (node.id && node.makeId) {
      //    // move 'node.make' link so 'make' can be null reference
      //    node.makeLink = node.make;
      //    node.make = null;

      //    // flatten styles and sizes as comma-separated strings
      //    var styles = node.categories && node.categories["Vehicle Style"];
      //    node.vehicleStyles = styles && styles.join(", ");
      //    var sizes = node.categories && node.categories["Vehicle Size"];
      //    node.vehicleSizes = sizes && sizes.join(", ");

      //    return { entityType: "Model" };
      //}
    }
 public JsonNodeInfo VisitNode(NodeContext nodeContext)
 {
     return(JsonResultsAdapter.VisitNode(nodeContext.Node, this, nodeContext));
 }
        private void ParseObject(NodeContext nodeContext, EntityAspect targetAspect)
        {
            // backingStore will be null if not allowed to overwrite the entity.
            var backingStore   = (targetAspect == null) ? null : targetAspect.BackingStore;
            var dict           = (IDictionary <String, JToken>)nodeContext.Node;
            var structuralType = nodeContext.StructuralType;
            // needs to be the current namingConvention
            var nc = _mappingContext.EntityManager.MetadataStore.NamingConvention;

            dict.ForEach(kvp => {
                var key  = nc.ServerPropertyNameToClient(kvp.Key, structuralType);
                var prop = structuralType.GetProperty(key);
                if (prop != null)
                {
                    if (prop.IsDataProperty)
                    {
                        if (backingStore != null)
                        {
                            var dp = (DataProperty)prop;
                            if (dp.IsComplexProperty)
                            {
                                var newCo     = (IComplexObject)kvp.Value.ToObject(dp.ClrType);
                                var co        = (IComplexObject)backingStore[key];
                                var coBacking = co.ComplexAspect.BackingStore;
                                newCo.ComplexAspect.BackingStore.ForEach(kvp2 => {
                                    coBacking[kvp2.Key] = kvp2.Value;
                                });
                            }
                            else
                            {
                                var val = kvp.Value;
                                if (val.Type == JTokenType.Null && dp.ClrType != typeof(String) && !TypeFns.IsNullableType(dp.ClrType))
                                {
                                    // this can only happen if the client is nonnullable but the server is nullable.
                                    backingStore[key] = dp.DefaultValue;
                                }
                                else if (dp.IsEnumType || (dp.DataType.ClrType == typeof(TimeSpan)))
                                {
                                    backingStore[key] = val.ToObject(dp.ClrType, _customSerializer);
                                }
                                else
                                {
                                    backingStore[key] = val.ToObject(dp.ClrType);
                                }
                            }
                        }
                    }
                    else
                    {
                        // prop is a ComplexObject
                        var np = (NavigationProperty)prop;

                        if (kvp.Value.HasValues)
                        {
                            NodeContext newContext;
                            if (np.IsScalar)
                            {
                                var nestedOb = (JObject)kvp.Value;
                                newContext   = new NodeContext()
                                {
                                    Node = nestedOb, ObjectType = prop.ClrType, StructuralProperty = np
                                };
                                var entity = (IEntity)CreateAndPopulate(newContext);
                                if (backingStore != null)
                                {
                                    backingStore[key] = entity;
                                }
                            }
                            else
                            {
                                var nestedArray = (JArray)kvp.Value;
                                var navSet      = (INavigationSet)TypeFns.CreateGenericInstance(typeof(NavigationSet <>), prop.ClrType);

                                nestedArray.Cast <JObject>().ForEach(jo => {
                                    newContext = new NodeContext()
                                    {
                                        Node = jo, ObjectType = prop.ClrType, StructuralProperty = np
                                    };
                                    var entity = (IEntity)CreateAndPopulate(newContext);
                                    navSet.Add(entity);
                                });
                                // add to existing nav set if there is one otherwise just set it.
                                object tmp;
                                if (backingStore.TryGetValue(key, out tmp))
                                {
                                    var backingNavSet = (INavigationSet)tmp;
                                    navSet.Cast <IEntity>().ForEach(e => backingNavSet.Add(e));
                                }
                                else
                                {
                                    navSet.NavigationProperty = np;
                                    navSet.ParentEntity       = targetAspect.Entity;
                                    backingStore[key]         = navSet;
                                }
                            }
                        }
                        else
                        {
                            // do nothing
                            //if (!np.IsScalar) {
                            //  return TypeFns.ConstructGenericInstance(typeof(NavigationSet<>), prop.ClrType);
                            //} else {
                            //  return null;
                            //}
                        }
                    }
                }
                else
                {
                    if (backingStore != null)
                    {
                        backingStore[key] = kvp.Value.ToObject <Object>();
                    }
                }
            });
        }
        protected virtual Object CreateAndPopulate(NodeContext nodeContext)
        {
            var node = nodeContext.Node;

            var nodeInfo = _mappingContext.VisitNode(nodeContext);

            if (nodeInfo.Ignore)
            {
                return(null);
            }

            node = nodeInfo.Node ?? node;

            if (nodeInfo.NodeRefId != null)
            {
                return(_mappingContext.RefMap[nodeInfo.NodeRefId]);
            }
            var        metadataStore = _mappingContext.MetadataStore;
            EntityType entityType;
            Type       objectType;

            if (nodeInfo.ServerTypeNameInfo != null)
            {
                var clientEntityTypeName = nodeInfo.ServerTypeNameInfo.ToClient(metadataStore).StructuralTypeName;
                entityType = metadataStore.GetEntityType(clientEntityTypeName);
                objectType = entityType.ClrType;
                if (!nodeContext.ObjectType.IsAssignableFrom(objectType))
                {
                    throw new Exception("Unable to convert returned type: " + objectType.Name + " into type: " +
                                        nodeContext.ObjectType.Name);
                }
                nodeContext.ObjectType = objectType;
            }
            else
            {
                objectType = nodeContext.ObjectType;
                entityType = metadataStore.GetEntityType(objectType);
            }

            // an entity type
            nodeContext.StructuralType = entityType;
            var keyValues = entityType.KeyProperties
                            .Select(p => node[p.NameOnServer].ToObject(p.ClrType))
                            .ToArray();
            var entityKey = EntityKey.Create(entityType, keyValues);
            var entity    = _mappingContext.EntityManager.GetEntityByKey(entityKey);

            if (entity == null)
            {
                entity = (IEntity)Activator.CreateInstance(objectType);
                entity.EntityAspect.EntityType = entityType;
            }
            // must be called before populate
            if (nodeInfo.NodeId != null)
            {
                _mappingContext.RefMap[nodeInfo.NodeId] = entity;
            }

            _mappingContext.Entities.Add(entity);
            return(PopulateEntity(nodeContext, entity));
        }
    public JsonNodeInfo VisitNode(JObject node, MappingContext mappingContext, NodeContext nodeContext) {
      var result = new JsonNodeInfo();

      JToken refToken;
      if (node.TryGetValue("$ref", out refToken)) {
        result.NodeRefId = refToken.Value<String>();
        return result;
      }

      JToken idToken;
      if (node.TryGetValue("$id", out idToken)) {
        result.NodeId = idToken.Value<String>();
      }

      JToken typeToken;
      if (node.TryGetValue("$type", out typeToken)) {
        var clrTypeName = typeToken.Value<String>();
        result.ServerTypeNameInfo = TypeNameInfo.FromClrTypeName(clrTypeName);
      }

      return result;
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
      if (reader.TokenType != JsonToken.Null) {
        // Load JObject from stream
        var node = JObject.Load(reader);

        var nodeContext = new NodeContext { Node = node, ObjectType = objectType };
        // Create target object based on JObject
        var target = CreateAndPopulate( nodeContext);
        return target;
      } else {
        return null;
      }
    }
 public JsonNodeInfo VisitNode(NodeContext nodeContext) {
   return JsonResultsAdapter.VisitNode(nodeContext.Node, this, nodeContext);
 }
 private void ParseObject(NodeContext nodeContext, EntityAspect targetAspect) {
   // backingStore will be null if not allowed to overwrite the entity.
   var backingStore = (targetAspect == null) ? null : targetAspect.BackingStore;
   var dict = (IDictionary<String, JToken>) nodeContext.Node;
   var structuralType = nodeContext.StructuralType;
   // needs to be the current namingConvention
   var nc = _mappingContext.EntityManager.MetadataStore.NamingConvention;
   dict.ForEach(kvp => {
     var key = nc.ServerPropertyNameToClient(kvp.Key, structuralType);
     var prop = structuralType.GetProperty(key);
     if (prop != null) {         
       if (prop.IsDataProperty) {
         if (backingStore != null) {
           var dp = (DataProperty)prop;
           if (dp.IsComplexProperty) {
             var newCo = (IComplexObject) kvp.Value.ToObject(dp.ClrType);
             var co = (IComplexObject)backingStore[key];
             var coBacking = co.ComplexAspect.BackingStore;
             newCo.ComplexAspect.BackingStore.ForEach(kvp2 => {
               coBacking[kvp2.Key] = kvp2.Value;
             });
           } else {
             var val = kvp.Value;
             if (val.Type == JTokenType.Null && dp.ClrType != typeof(String) && !TypeFns.IsNullableType(dp.ClrType)) {
               // this can only happen if the client is nonnullable but the server is nullable.
               backingStore[key] = dp.DefaultValue;
             } else if (dp.IsEnumType || (dp.DataType.ClrType == typeof (TimeSpan))) {
               backingStore[key] = val.ToObject(dp.ClrType, _customSerializer);
             } else {
               backingStore[key] = val.ToObject(dp.ClrType);
             }
           }
         }
       } else {
         // prop is a ComplexObject
         var np = (NavigationProperty)prop;
         
         if (kvp.Value.HasValues) {
           NodeContext newContext;
           if (np.IsScalar) {
             var nestedOb = (JObject)kvp.Value;
             newContext = new NodeContext() { Node = nestedOb, ObjectType = prop.ClrType, StructuralProperty = np}; 
             var entity = (IEntity)CreateAndPopulate(newContext);
             if (backingStore != null) backingStore[key] = entity;
           } else {
             var nestedArray = (JArray)kvp.Value;
             var navSet = (INavigationSet) TypeFns.CreateGenericInstance(typeof(NavigationSet<>), prop.ClrType);
             
             nestedArray.Cast<JObject>().ForEach(jo => {
               newContext = new NodeContext() { Node=jo, ObjectType = prop.ClrType, StructuralProperty = np};
               var entity = (IEntity)CreateAndPopulate(newContext);
               navSet.Add(entity);
             });
             // add to existing nav set if there is one otherwise just set it. 
             object tmp;
             if (backingStore.TryGetValue(key, out tmp)) {
               var backingNavSet = (INavigationSet) tmp;
               navSet.Cast<IEntity>().ForEach(e => backingNavSet.Add(e));
             } else {
               navSet.NavigationProperty = np;
               navSet.ParentEntity = targetAspect.Entity;
               backingStore[key] = navSet;
             }
           }
         } else {
           // do nothing
           //if (!np.IsScalar) {
           //  return TypeFns.ConstructGenericInstance(typeof(NavigationSet<>), prop.ClrType);
           //} else {
           //  return null;
           //}
         }
       }
     } else {
       if (backingStore != null) backingStore[key] = kvp.Value.ToObject<Object>();
     }
   });
   
 }
    protected virtual Object PopulateEntity(NodeContext nodeContext, IEntity entity) {
      
      var aspect = entity.EntityAspect;
      if (aspect.EntityManager == null) {
        // new to this entityManager
        ParseObject(nodeContext, aspect);
        aspect.Initialize();
        // TODO: This is a nit.  Wierd case where a save adds a new entity will show up with
        // a AttachOnQuery operation instead of AttachOnSave
        _mappingContext.EntityManager.AttachQueriedEntity(entity, (EntityType) nodeContext.StructuralType);
      } else if (_mappingContext.MergeStrategy == MergeStrategy.OverwriteChanges || aspect.EntityState == EntityState.Unchanged) {
        // overwrite existing entityManager
        ParseObject(nodeContext, aspect);
        aspect.Initialize();
        aspect.OnEntityChanged(_mappingContext.LoadingOperation == LoadingOperation.Query ? EntityAction.MergeOnQuery : EntityAction.MergeOnSave);
      } else {
        // preserveChanges handling - we still want to handle expands.
        ParseObject(nodeContext, null );
      }

      return entity;
    }
    protected virtual Object CreateAndPopulate(NodeContext nodeContext) {
      var node = nodeContext.Node;

      var nodeInfo = _mappingContext.VisitNode(nodeContext);
      if (nodeInfo.Ignore) return null;

      node = nodeInfo.Node ?? node;

      if (nodeInfo.NodeRefId != null) {
        return _mappingContext.RefMap[nodeInfo.NodeRefId];
      }
      var metadataStore = _mappingContext.MetadataStore;
      EntityType entityType;
      Type objectType;
      if (nodeInfo.ServerTypeNameInfo != null) {
        var clientEntityTypeName = nodeInfo.ServerTypeNameInfo.ToClient(metadataStore).StructuralTypeName;
        entityType = metadataStore.GetEntityType(clientEntityTypeName);
        objectType = entityType.ClrType;
        if (!nodeContext.ObjectType.IsAssignableFrom(objectType)) {
          throw new Exception("Unable to convert returned type: " + objectType.Name + " into type: " +
                              nodeContext.ObjectType.Name);
        }
        nodeContext.ObjectType = objectType;
      }
      else {
        objectType = nodeContext.ObjectType;
        entityType = metadataStore.GetEntityType(objectType);
      }

      // an entity type
      nodeContext.StructuralType = entityType;
      var keyValues = entityType.KeyProperties
        .Select(p => node[p.NameOnServer].ToObject(p.ClrType))
        .ToArray();
      var entityKey = EntityKey.Create(entityType, keyValues);
      var entity = _mappingContext.EntityManager.GetEntityByKey(entityKey);
      if (entity == null) {
        entity = (IEntity) Activator.CreateInstance(objectType);
        entity.EntityAspect.EntityType = entityType;
      }
      // must be called before populate
      if (nodeInfo.NodeId != null) {
        _mappingContext.RefMap[nodeInfo.NodeId] = entity;
      }

      _mappingContext.Entities.Add(entity);
      return PopulateEntity(nodeContext, entity);
    }