part of streamy.runtime;

class DynamicEntity extends RawEntity {

  DynamicEntity() : super();

  DynamicEntity.fromMap(Map data) {
    data.forEach((key, value) {
      this[key] = value;
    });
  }

  noSuchMethod(Invocation invocation) {
    var memberName = MirrorSystem.getName(invocation.memberName);
    if (invocation.isGetter) {
      return this[memberName];
    } else if (invocation.isSetter) {
      // Setter member names have an '=' at the end, strip it.
      var key = memberName.substring(0, memberName.length - 1);
      this[key] = invocation.positionalArguments[0];
    } else {
      throw new ClosureInvocationException(memberName);
    }
  }

  Type get streamyType => DynamicEntity;
}
part of streamy.runtime;

class DynamicEntity extends RawEntity {

  DynamicEntity() : super();

  DynamicEntity.fromMap(Map data) {
    data.forEach((key, value) {
      this[key] = value;
    });
  }

  noSuchMethod(Invocation invocation) {
    var memberName = MirrorSystem.getName(invocation.memberName);
    if (invocation.isGetter) {
      return this[memberName];
    } else if (invocation.isSetter) {
      // Setter member names have an '=' at the end, strip it.
      var key = memberName.substring(0, memberName.length - 1);
      this[key] = invocation.positionalArguments[0];
    } else {
      // Perhaps the called was trying to call a nonexistent method,
      // or perhaps the caller was trying to invoke a data member as a
      // completion. Throw an appropriate error.
      if (contains(memberName)) {
        throw new ClosureInvocationException(memberName);
      } else {
        // The Invocation class and NoSuchMethodError have different ideas
        // about the type of the named arguments map.
        Map<String, dynamic> namedArgs = {};
        for (key in invocation.namedArguments.keys) {
          namedArgs[key.toString()] = invocation.namedArguments[key];
        }
        throw new NoSuchMethodError(this, memberName,
            invocation.positionalArguments, namedArgs);
      }
    }
  }

  Type get streamyType => DynamicEntity;
}

Throw NoSuchMethodError if the caller requests a nonexistent member
Throw NoSuchMethodError if the caller requests a nonexistent member

Angular--and potentially other callers--expect that when a method such
as containsKey is called on a DynamicEntity, that the object will throw
NoSuchMethodError. DynamicEntity, on the other hand, wants to ensure
that no one stashes a completion in a DynamicEntity and tries to call
it later. This patch accomodates both needs.
