Skip to content

Commit

Permalink
model effects
Browse files Browse the repository at this point in the history
  • Loading branch information
huanghaiyang committed Dec 22, 2019
1 parent 837c5a5 commit 8f4d813
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 17 deletions.
8 changes: 7 additions & 1 deletion lib/src/annotation/SideEffectModel.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import 'dart:mirrors';

String SIDE_EFFECT_MODEL_NAME = "sideEffectModel";

typedef EffectFunction = InstanceMirror Function(InstanceMirror transformedReflectee);

@pragma('vm:entry-point')
class SideEffectModel {
final Function func;

final List<EffectFunction> effects;

@pragma('vm:entry-point')
const SideEffectModel(this.func);
const SideEffectModel(this.func, {this.effects});
}
1 change: 1 addition & 0 deletions lib/src/delegate/ApplicationHttpServerDelegate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import 'package:Q/src/delegate/ApplicationLifecycleDelegate.dart';
import 'package:Q/src/delegate/HttpRequestLifecycleDelegate.dart';
import 'package:Q/src/helpers/ApplicationHelper.dart';
import 'package:Q/src/helpers/AsyncHelper.dart';
import 'package:Q/src/helpers/ResponseHelper.dart';
import 'package:Q/src/helpers/RouterHelper.dart';
import 'package:Q/src/interceptor/HttpRequestInterceptorState.dart';
import 'package:Q/src/request/RequestTimeout.dart';
Expand Down
2 changes: 1 addition & 1 deletion lib/src/helpers/ResponseHelper.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'dart:io';

class ResponseHelper {
static void addCorsHeaders(HttpResponse response) {
static void addCorsHeaders(HttpResponse response) async {
response.headers.add('Access-Control-Allow-Origin', '*');
response.headers.add('Access-Control-Allow-Methods', 'POST, OPTIONS, HEAD');
response.headers.add('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
Expand Down
54 changes: 44 additions & 10 deletions lib/src/helpers/reflect/ClassTransformer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ import 'package:Q/Q.dart';
import 'package:Q/src/exception/RequiredAnnotationNotFoundException.dart';
import 'package:Q/src/exception/RequiredInitialValueMustBeProvidedException.dart';
import 'package:Q/src/utils/SymbolUtil.dart';
import 'package:curie/curie.dart';

class ClassTransformer {
static final String FUNC_FIELD = 'func';

static dynamic fromMap(Map data, Type clazz) {
static final String EFFECT_FIELDS = 'effects';

static dynamic fromMap(Map data, Type clazz) async {
ClassMirror classMirror = reflectClass(clazz);
InstanceMirror instanceMirror = classMirror.newInstance(Symbol.empty, []);
InstanceMirror sideEffectModelMirror = classMirror.metadata.firstWhere((InstanceMirror instanceMirror) {
Expand All @@ -18,12 +21,35 @@ class ClassTransformer {
InstanceMirror func = sideEffectModelMirror.getField(Symbol(FUNC_FIELD));
if (func != null) {
FunctionTypeMirror functionTypeMirror = func.type;
List<Future> futures = List();
functionTypeMirror.parameters.forEach((ParameterMirror parameterMirror) {
instanceMirror.setField(parameterMirror.simpleName, reflectParameterValue(data, parameterMirror, instanceMirror));
futures.add(() async {
instanceMirror.setField(parameterMirror.simpleName, await reflectParameterValue(data, parameterMirror, instanceMirror));
return true;
}());
});
await Future.wait(futures);
} else {
throw RequiredFieldNotFoundException(name: FUNC_FIELD);
}
InstanceMirror effectsMirror = sideEffectModelMirror.getField(Symbol(EFFECT_FIELDS));
if (effectsMirror != null) {
List<EffectFunction> effects = effectsMirror.reflectee;
if (effects != null) {
effects = List.from(effects);
if (effects != null) {
if (effects.isNotEmpty) {
EffectFunction firstEffect = effects[0];
effects[0] = (dynamic value) {
InstanceMirror effectResult = Function.apply(firstEffect, [instanceMirror]);
return effectResult;
};
InstanceMirror result = await waterfall(effects);
return result.reflectee;
}
}
}
}
} else {
InstanceMirror modelAnnotationMirror = classMirror.metadata.firstWhere((InstanceMirror instanceMirror) {
return instanceMirror.type == reflectClass(Model);
Expand All @@ -40,14 +66,15 @@ class ClassTransformer {
}
}
}

return instanceMirror.reflectee;
}

static dynamic reflectParameterValue(Map data, ParameterMirror parameterMirror, InstanceMirror instanceMirror) {
static dynamic reflectParameterValue(Map data, ParameterMirror parameterMirror, InstanceMirror instanceMirror) async {
if (!instanceMirror.type.declarations.containsKey(parameterMirror.simpleName)) {
throw SideEffectModelReflectFunctionParameterNotMatchClassFieldException(name: SymbolUtil.toChars(parameterMirror.simpleName));
}
for (String key in data.keys) {
await for (String key in Stream.fromIterable(List.from(data.keys))) {
if (SymbolUtil.toChars(parameterMirror.simpleName) == key) {
dynamic value = data[key];
Type parameterType = parameterMirror.type.reflectedType;
Expand All @@ -60,22 +87,29 @@ class ClassTransformer {
throw RequiredInitialValueMustBeProvidedException(name: key);
}
if (parameterClassMirror == reflectClass(List)) {
List.from(value).forEach((dynamic val) {
initialValue.add(fromMap(val, subType));
List<Future> futures = List();
List.from(value).forEach((dynamic val) async {
futures.add(() async {
return await fromMap(val, subType);
}());
});
initialValue.addAll(await Future.wait(futures));
return initialValue;
} else if (parameterClassMirror == reflectClass(Set)) {
Set.from(value).forEach((dynamic val) {
initialValue.add(fromMap(val, subType));
List<Future> futures = List();
Set.from(value).forEach((dynamic val) async {
futures.add(() async {
return await fromMap(val, subType);
}());
});
return initialValue;
initialValue.addAll(await Future.wait(futures));
}
} else {
return ReflectHelper.reflectCollection(parameterMirror.type.reflectedType, subType, value);
}
}
if (hasModel(parameterMirror.type.reflectedType)) {
return fromMap(value, reflectClass(SideEffectModel).reflectedType);
return await fromMap(value, reflectClass(SideEffectModel).reflectedType);
}
return ReflectHelper.reflectParameterValue(parameterType, value.toString());
}
Expand Down
2 changes: 1 addition & 1 deletion lib/src/interceptor/HttpPrefetchInterceptor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class HttpPrefetchInterceptor implements AbstractInterceptor {
Future<bool> preHandle(HttpRequest req, HttpResponse res, InterceptorContext interceptorContext) async {
if (req.method.toUpperCase() == 'OPTIONS' &&
Application.getApplicationContext().configuration.httpRequestConfigure.prefetchStrategy == PrefetchStrategy.ALLOW) {
ResponseHelper.addCorsHeaders(res);
await ResponseHelper.addCorsHeaders(res);
res.write('');
return false;
}
Expand Down
14 changes: 10 additions & 4 deletions test/ClassTransformer_test.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import 'dart:mirrors';

import 'package:Q/Q.dart';
import 'package:Q/src/helpers/reflect/ClassTransformer.dart';
import 'package:test/test.dart';

void createPerson(String name, int id, int age, List<Person> friends, {List<String> nicknames, List<Person> girlFriends}) {}

InstanceMirror delegatePerson(InstanceMirror value) {
return value;
}

//@Model({'name': String, 'int': int, 'age': num, 'friends': List, 'nicknames': List})
@SideEffectModel(createPerson)
@SideEffectModel(createPerson, effects: [delegatePerson])
class Person {
int id;
String name;
num age;
List<Person> friends = List();
List<String> nicknames = List();
List<Person> girlFriends = List();
List friends = List();
List nicknames = List();
List girlFriends = List();

Person();

Expand Down

0 comments on commit 8f4d813

Please # to comment.