Skip to content

Commit 0a072b5

Browse files
committed
Improve type bindings for unknown classes in jphp extensions.
1 parent 14f9397 commit 0a072b5

File tree

5 files changed

+173
-54
lines changed

5 files changed

+173
-54
lines changed

jphp-runtime/src/php/runtime/memory/support/MemoryOperation.java

Lines changed: 3 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -110,28 +110,7 @@ public static MemoryOperation get(final Class<?> type, Type genericTypes, boolea
110110
}
111111

112112
if (Enum.class.isAssignableFrom(type)) {
113-
return new MemoryOperation() {
114-
@Override
115-
public Class<?>[] getOperationClasses() {
116-
return new Class<?>[]{Enum.class};
117-
}
118-
119-
@Override
120-
@SuppressWarnings("unchecked")
121-
public Object convert(Environment env, TraceInfo trace, Memory arg) throws Throwable {
122-
return arg.isNull() ? null : Enum.valueOf((Class<? extends Enum>) type, arg.toString());
123-
}
124-
125-
@Override
126-
public Memory unconvert(Environment env, TraceInfo trace, Object arg) throws Throwable {
127-
return arg == null ? Memory.NULL : StringMemory.valueOf(((Enum) arg).name());
128-
}
129-
130-
@Override
131-
public void applyTypeHinting(ParameterEntity parameter) {
132-
parameter.setTypeEnum((Class<? extends Enum>) type);
133-
}
134-
};
113+
return new EnumMemoryOperation((Class<? extends Enum>) type);
135114
}
136115

137116
final Class<? extends BaseWrapper> wrapperClass = wrappers.get(type);
@@ -197,36 +176,7 @@ public void applyTypeHinting(ParameterEntity parameter) {
197176
}
198177
};
199178
} else if (IObject.class.isAssignableFrom(type)) {
200-
return new MemoryOperation() {
201-
@Override
202-
public Class<?>[] getOperationClasses() {
203-
return new Class<?>[]{IObject.class};
204-
}
205-
206-
@Override
207-
@SuppressWarnings("unchecked")
208-
public Object convert(Environment env, TraceInfo trace, Memory arg) throws Throwable {
209-
if (arg.isNull()) {
210-
return null;
211-
}
212-
213-
return arg.toObject((Class<? extends IObject>) type);
214-
}
215-
216-
@Override
217-
public Memory unconvert(Environment env, TraceInfo trace, Object arg) throws Throwable {
218-
if (arg == null) {
219-
return Memory.NULL;
220-
}
221-
222-
return ObjectMemory.valueOf((IObject) arg);
223-
}
224-
225-
@Override
226-
public void applyTypeHinting(ParameterEntity parameter) {
227-
parameter.setType(ReflectionUtils.getClassName(type));
228-
}
229-
};
179+
return new IObjectMemoryOperation((Class<? extends IObject>) type);
230180
} else {
231181
Class<?> superType = type.getSuperclass();
232182

@@ -238,7 +188,7 @@ public void applyTypeHinting(ParameterEntity parameter) {
238188
}
239189

240190
if (operation == null) {
241-
return null;
191+
return null; //new BeanMemoryOperation(type);
242192
}
243193

244194
if (genericTypes instanceof ParameterizedType) {
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package php.runtime.memory.support.operation;
2+
3+
import php.runtime.Memory;
4+
import php.runtime.common.HintType;
5+
import php.runtime.env.Environment;
6+
import php.runtime.env.TraceInfo;
7+
import php.runtime.memory.ArrayMemory;
8+
import php.runtime.memory.support.MemoryOperation;
9+
import php.runtime.reflection.ParameterEntity;
10+
import php.runtime.reflection.support.TypeChecker;
11+
12+
import java.util.HashMap;
13+
import java.util.Map;
14+
import java.util.concurrent.ConcurrentHashMap;
15+
16+
public class BeanMemoryOperation extends MemoryOperation {
17+
private final Class<?> beanClass;
18+
private final Class<?>[] operationClasses;
19+
20+
protected static final Map<Class<?>, BeanMemoryOperation> instances = new ConcurrentHashMap<>();
21+
22+
public static boolean isLikeBean(Class<?> aClass) {
23+
return ArrayMemory.isLikeBean(aClass);
24+
}
25+
26+
public static BeanMemoryOperation of(Class<?> beanClass, Class<?>... aliasBeanClasses) {
27+
if (aliasBeanClasses == null || aliasBeanClasses.length == 0) {
28+
return instances.computeIfAbsent(beanClass, aClass -> new BeanMemoryOperation(aClass));
29+
} else {
30+
return new BeanMemoryOperation(beanClass, aliasBeanClasses);
31+
}
32+
}
33+
34+
protected BeanMemoryOperation(Class<?> beanClass, Class<?>... aliasBeanClasses) {
35+
this.beanClass = beanClass;
36+
37+
if (!isLikeBean(beanClass)) {
38+
throw new IllegalArgumentException(beanClass + " cannot be bean class");
39+
}
40+
41+
operationClasses = new Class[1 + (aliasBeanClasses == null ? 0 : aliasBeanClasses.length)];
42+
operationClasses[0] = beanClass;
43+
44+
if (aliasBeanClasses != null) {
45+
System.arraycopy(aliasBeanClasses, 0, operationClasses, 1, aliasBeanClasses.length);
46+
}
47+
}
48+
49+
@Override
50+
public Class<?>[] getOperationClasses() {
51+
return operationClasses;
52+
}
53+
54+
@Override
55+
public Object convert(Environment env, TraceInfo trace, Memory arg) throws Throwable {
56+
if (arg.isNull()) {
57+
return null;
58+
}
59+
60+
return ((ArrayMemory) arg).toBean(env, trace, beanClass);
61+
}
62+
63+
@Override
64+
public Memory unconvert(Environment env, TraceInfo trace, Object arg) throws Throwable {
65+
return ArrayMemory.ofNullableBean(env, trace, arg);
66+
}
67+
68+
@Override
69+
public void applyTypeHinting(ParameterEntity parameter) {
70+
parameter.setTypeChecker(TypeChecker.of(HintType.ARRAY));
71+
}
72+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package php.runtime.memory.support.operation;
2+
3+
import php.runtime.Memory;
4+
import php.runtime.env.Environment;
5+
import php.runtime.env.TraceInfo;
6+
import php.runtime.memory.StringMemory;
7+
import php.runtime.memory.support.MemoryOperation;
8+
import php.runtime.reflection.ParameterEntity;
9+
10+
public class EnumMemoryOperation extends MemoryOperation {
11+
private Class<? extends Enum> enumClass;
12+
13+
public EnumMemoryOperation(Class<? extends Enum> enumClass) {
14+
this.enumClass = enumClass;
15+
}
16+
17+
@Override
18+
public Class<?>[] getOperationClasses() {
19+
return new Class[] { enumClass };
20+
}
21+
22+
@Override
23+
@SuppressWarnings("unchecked")
24+
public Object convert(Environment env, TraceInfo trace, Memory arg) throws Throwable {
25+
return arg.isNull() ? null : Enum.valueOf(enumClass, arg.toString());
26+
}
27+
28+
@Override
29+
public Memory unconvert(Environment env, TraceInfo trace, Object arg) throws Throwable {
30+
return arg == null ? Memory.NULL : StringMemory.valueOf(((Enum) arg).name());
31+
}
32+
33+
@Override
34+
public void applyTypeHinting(ParameterEntity parameter) {
35+
parameter.setTypeEnum(enumClass);
36+
}
37+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package php.runtime.memory.support.operation;
2+
3+
import php.runtime.Memory;
4+
import php.runtime.env.Environment;
5+
import php.runtime.env.TraceInfo;
6+
import php.runtime.lang.IObject;
7+
import php.runtime.memory.ObjectMemory;
8+
import php.runtime.memory.support.MemoryOperation;
9+
import php.runtime.reflection.ParameterEntity;
10+
import php.runtime.reflection.support.ReflectionUtils;
11+
12+
public class IObjectMemoryOperation extends MemoryOperation {
13+
private Class<? extends IObject> type;
14+
15+
public IObjectMemoryOperation(Class<? extends IObject> type) {
16+
this.type = type;
17+
}
18+
19+
@Override
20+
public Class<?>[] getOperationClasses() {
21+
return new Class<?>[]{ type };
22+
}
23+
24+
@Override
25+
@SuppressWarnings("unchecked")
26+
public Object convert(Environment env, TraceInfo trace, Memory arg) throws Throwable {
27+
if (arg.isNull()) {
28+
return null;
29+
}
30+
31+
return arg.toObject((Class<? extends IObject>) type);
32+
}
33+
34+
@Override
35+
public Memory unconvert(Environment env, TraceInfo trace, Object arg) throws Throwable {
36+
if (arg == null) {
37+
return Memory.NULL;
38+
}
39+
40+
return ObjectMemory.valueOf((IObject) arg);
41+
}
42+
43+
@Override
44+
public void applyTypeHinting(ParameterEntity parameter) {
45+
parameter.setType(ReflectionUtils.getClassName(type));
46+
}
47+
}

jphp-runtime/src/php/runtime/reflection/CompileMethodEntity.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import php.runtime.lang.IObject;
1717
import php.runtime.memory.support.MemoryOperation;
1818
import php.runtime.memory.support.MemoryUtils;
19+
import php.runtime.memory.support.operation.BeanMemoryOperation;
1920
import php.runtime.reflection.support.ReflectionUtils;
2021

2122
import java.lang.annotation.Annotation;
@@ -350,6 +351,10 @@ public void setParameters(ParameterEntity[] parameters) {
350351
returnOperation = unknownTypeFetcher.call(resultType, null);
351352
}
352353

354+
if (returnOperation == null && BeanMemoryOperation.isLikeBean(resultType)) {
355+
returnOperation = BeanMemoryOperation.of(resultType);
356+
}
357+
353358
if (returnOperation == null) {
354359
throw new CriticalException("Unsupported type for binding - " + resultType + " in " + method.getDeclaringClass().getName() + "." + method.getName());
355360
}
@@ -401,7 +406,15 @@ public Object convert(Environment env, TraceInfo trace, Memory arg) throws Throw
401406
}
402407
}
403408

404-
throw new CriticalException("Unsupported type for binding - " + parameterType);
409+
if (BeanMemoryOperation.isLikeBean(parameterType)) {
410+
op = BeanMemoryOperation.of(parameterType);
411+
argumentOperations[i] = op;
412+
if (k <= parameters.length - 1) {
413+
op.applyTypeHinting(parameters[k]);
414+
}
415+
} else {
416+
throw new CriticalException("Unsupported type for binding - " + parameterType);
417+
}
405418
}
406419
}
407420
}

0 commit comments

Comments
 (0)