calabash-android 0.4.0.pre6 → 0.4.0.pre7
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/calabash-android +7 -0
- data/bin/calabash-android-build.rb +1 -1
- data/bin/calabash-android-console.rb +1 -1
- data/bin/calabash-android-run.rb +1 -1
- data/calabash-android.gemspec +1 -0
- data/irbrc +2 -0
- data/lib/calabash-android/helpers.rb +4 -2
- data/lib/calabash-android/lib/TestServer.apk +0 -0
- data/lib/calabash-android/operations.rb +31 -22
- data/lib/calabash-android/version.rb +1 -1
- data/test-server/instrumentation-backend/.classpath +0 -1
- data/test-server/instrumentation-backend/antlr/UIQuery.g +11 -2
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/Command.java +4 -3
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/FranklyResult.java +95 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/Result.java +7 -1
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/HttpServer.java +15 -23
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/location/FakeGPSLocation.java +13 -10
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/CalabashChromeClient.java +136 -36
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/DumpBodyHtml.java +38 -18
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/DumpHtml.java +38 -16
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/EnterTextByCssSelector.java +94 -66
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/ExecuteAsyncJavascript.java +55 -33
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/ExecuteJavascript.java +54 -31
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/JavaScriptOperation.java +44 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/PressByCssSelector.java +52 -27
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/QueryHelper.java +39 -32
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/ScrollTo.java +56 -41
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/SetPropertyByCssSelector.java +50 -25
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/SetText.java +19 -22
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/CompletedFuture.java +40 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/InvocationOperation.java +201 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/Operation.java +7 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/PropertyOperation.java +56 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/Query.java +144 -72
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/UIQuery.tokens +15 -12
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/UIQueryResultVoid.java +22 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ViewMapper.java +38 -11
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/antlr/UIQueryLexer.java +226 -109
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/antlr/UIQueryParser.java +237 -84
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/PartialFutureList.java +100 -0
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryAST.java +1 -1
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryASTClassName.java +26 -22
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryASTWith.java +170 -102
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryEvaluator.java +54 -155
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryUtils.java +97 -2
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/query/ast/UIQueryVisibility.java +32 -0
- metadata +27 -5
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/Query.java +0 -24
- data/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/webview/Touch.java +0 -44
- data/test-server/instrumentation-backend/tests/sh/calaba/instrumentationbackend/query/tests/UIQueryTest.java +0 -134
@@ -1,7 +1,6 @@
|
|
1
1
|
package sh.calaba.instrumentationbackend.actions.webview;
|
2
2
|
|
3
3
|
|
4
|
-
import java.util.HashMap;
|
5
4
|
import java.util.List;
|
6
5
|
import java.util.Map;
|
7
6
|
|
@@ -9,60 +8,76 @@ import sh.calaba.instrumentationbackend.InstrumentationBackend;
|
|
9
8
|
import sh.calaba.instrumentationbackend.Result;
|
10
9
|
import sh.calaba.instrumentationbackend.actions.Action;
|
11
10
|
import sh.calaba.instrumentationbackend.actions.Actions;
|
12
|
-
import sh.calaba.org.codehaus.jackson.map.ObjectMapper;
|
13
|
-
import sh.calaba.org.codehaus.jackson.type.TypeReference;
|
14
11
|
import android.test.TouchUtils;
|
15
12
|
import android.webkit.WebView;
|
16
13
|
|
17
14
|
|
18
15
|
public class ScrollTo implements Action {
|
19
|
-
|
20
|
-
|
16
|
+
|
17
|
+
@Override
|
21
18
|
public Result execute(String... args) {
|
22
19
|
//TODO: Should do horizontal scrolling if needed
|
23
|
-
String
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
}
|
36
|
-
}
|
37
|
-
|
38
|
-
return new Result(true, "");
|
20
|
+
final String uiQuery = "webView " + args[0] + ":'"+ args[1] + "'";
|
21
|
+
|
22
|
+
CalabashChromeClient calabashChromeClient = CalabashChromeClient.findAndPrepareWebViews().get(0);
|
23
|
+
WebView webView = calabashChromeClient.getWebView();
|
24
|
+
|
25
|
+
scrollToTop(webView);
|
26
|
+
|
27
|
+
while (keepScrolling(uiQuery, webView)) {
|
28
|
+
TouchUtils.dragQuarterScreenUp(Actions.parentTestCase, InstrumentationBackend.solo.getCurrentActivity());
|
29
|
+
}
|
30
|
+
|
31
|
+
return new Result(isVisible(uiQuery, webView), "");
|
39
32
|
}
|
40
33
|
|
34
|
+
private void scrollToTop(final WebView webView) {
|
35
|
+
InstrumentationBackend.instrumentation.runOnMainSync(new Runnable() {
|
36
|
+
@Override
|
37
|
+
public void run() {
|
38
|
+
webView.scrollTo(0, 0);
|
39
|
+
}
|
40
|
+
});
|
41
|
+
}
|
41
42
|
|
43
|
+
private boolean keepScrolling(String uiQuery, WebView webView) {
|
44
|
+
int centerY = getCenterY(uiQuery, webView);
|
45
|
+
System.out.println("Keep scrolling centerY: "+ centerY);
|
42
46
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
if (p.isEmpty()) {
|
48
|
-
throw new RuntimeException("No element found");
|
49
|
-
}
|
50
|
-
System.out.println(p);
|
51
|
-
final Map<String, Object> firstRect = QueryHelper.findFirstVisibleRectangle(p);
|
52
|
-
return firstRect;
|
53
|
-
} catch (Exception e) {
|
54
|
-
throw new RuntimeException(e);
|
55
|
-
}
|
47
|
+
int[] location = new int[2];
|
48
|
+
webView.getLocationOnScreen(location);
|
49
|
+
int top = location[1];
|
50
|
+
int bottom = top + webView.getHeight();
|
56
51
|
|
57
|
-
|
52
|
+
System.out.println("isVisible top: "+ top);
|
53
|
+
System.out.println("isVisible bottom: "+ bottom);
|
54
|
+
|
55
|
+
return centerY > bottom;
|
56
|
+
}
|
57
|
+
|
58
|
+
private boolean isVisible(String uiQuery, WebView webView) {
|
59
|
+
int centerY = getCenterY(uiQuery, webView);
|
60
|
+
System.out.println("isVisible centerY: "+ centerY);
|
61
|
+
|
62
|
+
int[] location = new int[2];
|
63
|
+
webView.getLocationOnScreen(location);
|
64
|
+
int top = location[1];
|
65
|
+
int bottom = top + webView.getHeight();
|
66
|
+
System.out.println("isVisible top: "+ top);
|
67
|
+
System.out.println("isVisible bottom: "+ bottom);
|
68
|
+
|
69
|
+
return top < centerY && centerY < bottom;
|
70
|
+
}
|
58
71
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
72
|
+
@SuppressWarnings({ "rawtypes", "unchecked" })
|
73
|
+
private int getCenterY(String uiQuery, WebView webView) {
|
74
|
+
List queryResult = new sh.calaba.instrumentationbackend.query.Query(uiQuery).executeQuery();
|
75
|
+
if (queryResult.isEmpty()) {
|
76
|
+
throw new RuntimeException("Query found no elements");
|
77
|
+
}
|
78
|
+
final Map<String, Object> firstVisibleRectangle = QueryHelper.findFirstVisibleRectangle(queryResult);
|
64
79
|
|
65
|
-
|
80
|
+
return Math.round((Float)firstVisibleRectangle.get("center_y"));
|
66
81
|
}
|
67
82
|
|
68
83
|
@Override
|
@@ -1,42 +1,67 @@
|
|
1
1
|
package sh.calaba.instrumentationbackend.actions.webview;
|
2
2
|
|
3
3
|
|
4
|
-
import
|
4
|
+
import java.util.ArrayList;
|
5
|
+
import java.util.List;
|
6
|
+
import java.util.concurrent.Callable;
|
7
|
+
|
5
8
|
import sh.calaba.instrumentationbackend.Result;
|
6
|
-
import sh.calaba.instrumentationbackend.TestHelpers;
|
7
9
|
import sh.calaba.instrumentationbackend.actions.Action;
|
10
|
+
import sh.calaba.instrumentationbackend.actions.webview.CalabashChromeClient.WebFuture;
|
11
|
+
import sh.calaba.instrumentationbackend.query.ast.UIQueryUtils;
|
8
12
|
import android.webkit.WebView;
|
9
13
|
|
10
14
|
|
11
15
|
public class SetPropertyByCssSelector implements Action {
|
12
16
|
|
13
|
-
@
|
17
|
+
@SuppressWarnings({ "unchecked", "rawtypes" })
|
18
|
+
@Override
|
14
19
|
public Result execute(String... args) {
|
15
|
-
String cssSelector = args[0];
|
16
|
-
String propertyName = args[1];
|
17
|
-
String value = args[2];
|
18
|
-
|
19
|
-
|
20
|
-
WebView webView = ccc.getWebView();
|
20
|
+
final String cssSelector = args[0];
|
21
|
+
final String propertyName = args[1];
|
22
|
+
final String value = args[2];
|
23
|
+
|
24
|
+
List<WebFuture> webResults = (List<WebFuture>) UIQueryUtils.evaluateSyncInMainThread(new Callable() {
|
21
25
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
26
|
+
public Object call() throws Exception {
|
27
|
+
|
28
|
+
List<WebFuture> webResults = new ArrayList();
|
29
|
+
for (CalabashChromeClient ccc : CalabashChromeClient.findAndPrepareWebViews()) {
|
30
|
+
WebView webView = ccc.getWebView();
|
31
|
+
|
32
|
+
final String assignment = "document.querySelector(\"" + cssSelector + "\")." + propertyName + " = " + value + ";";
|
33
|
+
System.out.println(assignment);
|
34
|
+
webView.loadUrl("javascript:(function() {" +
|
35
|
+
assignment +
|
36
|
+
"prompt('calabash:true');" +
|
37
|
+
"})()");
|
38
|
+
webResults.add(ccc.getResult());
|
39
|
+
}
|
35
40
|
|
36
|
-
|
37
|
-
|
41
|
+
return webResults;
|
42
|
+
|
43
|
+
}
|
44
|
+
});
|
45
|
+
|
46
|
+
List<String> allResults = new ArrayList<String>(webResults.size());
|
47
|
+
boolean success = false;
|
48
|
+
for (WebFuture f : webResults) {
|
49
|
+
String result = f.getAsString();
|
50
|
+
allResults.add(result);
|
51
|
+
if ("true".equals(result)) {
|
52
|
+
success = true;
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
if (allResults.size() == 0) {
|
57
|
+
return new Result(false, "No WebView found");
|
58
|
+
}
|
59
|
+
else {
|
60
|
+
return new Result(success, allResults);
|
61
|
+
}
|
62
|
+
}
|
38
63
|
|
39
|
-
|
64
|
+
@Override
|
40
65
|
public String key() {
|
41
66
|
return "set_property_by_css_selector";
|
42
67
|
}
|
@@ -1,14 +1,12 @@
|
|
1
1
|
package sh.calaba.instrumentationbackend.actions.webview;
|
2
2
|
|
3
3
|
|
4
|
-
import java.util.HashMap;
|
5
4
|
import java.util.List;
|
6
5
|
import java.util.Map;
|
7
6
|
|
8
7
|
import sh.calaba.instrumentationbackend.Result;
|
9
8
|
import sh.calaba.instrumentationbackend.actions.Action;
|
10
|
-
import sh.calaba.
|
11
|
-
import sh.calaba.org.codehaus.jackson.type.TypeReference;
|
9
|
+
import sh.calaba.instrumentationbackend.actions.webview.CalabashChromeClient.WebFuture;
|
12
10
|
|
13
11
|
|
14
12
|
public class SetText implements Action {
|
@@ -18,26 +16,25 @@ public class SetText implements Action {
|
|
18
16
|
* args[1]: xpath or css selector
|
19
17
|
* args[2]: text to enter into the first selected element
|
20
18
|
*/
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
throw new RuntimeException("No element found");
|
29
|
-
}
|
30
|
-
Map<String, Object> firstElement = QueryHelper.findFirstVisibleElement(p);
|
31
|
-
//TODO: Hack! Should be serialized instead of removed
|
32
|
-
firstElement.remove("class");
|
33
|
-
firstElement.remove("html");
|
34
|
-
String firstElementJson = QueryHelper.toJsonString(firstElement);
|
35
|
-
|
36
|
-
String result = QueryHelper.executeJavascriptInWebview("set_text.js", firstElementJson, args[2]);
|
37
|
-
return new Result(true, result);
|
38
|
-
} catch (Exception e) {
|
39
|
-
throw new RuntimeException(e);
|
19
|
+
@SuppressWarnings({ "rawtypes", "unchecked"})
|
20
|
+
@Override
|
21
|
+
public Result execute(final String... args) {
|
22
|
+
final String uiQuery = "webView " + args[0] + ":'"+ args[1] + "'";
|
23
|
+
List queryResult = new sh.calaba.instrumentationbackend.query.Query(uiQuery).executeQuery();
|
24
|
+
if (queryResult.isEmpty()) {
|
25
|
+
throw new RuntimeException("No element found");
|
40
26
|
}
|
27
|
+
Map<String, Object> firstElement = QueryHelper.findFirstVisibleElement(queryResult);
|
28
|
+
//TODO: Hack! Should be serialized instead of removed
|
29
|
+
CalabashChromeClient client = CalabashChromeClient.findAndPrepareWebViews().get(0);
|
30
|
+
firstElement.remove("class");
|
31
|
+
firstElement.remove("webView");
|
32
|
+
firstElement.remove("html");
|
33
|
+
String firstElementJson = QueryHelper.toJsonString(firstElement);
|
34
|
+
|
35
|
+
WebFuture result = QueryHelper.executeAsyncJavascriptInWebviews(client.getWebView(),"set_text.js", firstElementJson, args[2]);
|
36
|
+
|
37
|
+
return new Result(true,result.getAsString());
|
41
38
|
}
|
42
39
|
|
43
40
|
@Override
|
@@ -0,0 +1,40 @@
|
|
1
|
+
package sh.calaba.instrumentationbackend.query;
|
2
|
+
|
3
|
+
import java.util.concurrent.ExecutionException;
|
4
|
+
import java.util.concurrent.Future;
|
5
|
+
import java.util.concurrent.TimeUnit;
|
6
|
+
import java.util.concurrent.TimeoutException;
|
7
|
+
|
8
|
+
public class CompletedFuture<T> implements Future<T> {
|
9
|
+
private final T result;
|
10
|
+
|
11
|
+
public CompletedFuture(final T result) {
|
12
|
+
this.result = result;
|
13
|
+
}
|
14
|
+
|
15
|
+
@Override
|
16
|
+
public boolean cancel(final boolean b) {
|
17
|
+
return false;
|
18
|
+
}
|
19
|
+
|
20
|
+
@Override
|
21
|
+
public boolean isCancelled() {
|
22
|
+
return false;
|
23
|
+
}
|
24
|
+
|
25
|
+
@Override
|
26
|
+
public boolean isDone() {
|
27
|
+
return true;
|
28
|
+
}
|
29
|
+
|
30
|
+
@Override
|
31
|
+
public T get() throws InterruptedException, ExecutionException {
|
32
|
+
return this.result;
|
33
|
+
}
|
34
|
+
|
35
|
+
@Override
|
36
|
+
public T get(long timeout, TimeUnit unit) throws InterruptedException,
|
37
|
+
ExecutionException, TimeoutException {
|
38
|
+
return get();
|
39
|
+
}
|
40
|
+
}
|
@@ -0,0 +1,201 @@
|
|
1
|
+
package sh.calaba.instrumentationbackend.query;
|
2
|
+
|
3
|
+
import java.lang.reflect.Method;
|
4
|
+
import java.util.List;
|
5
|
+
import java.util.concurrent.atomic.AtomicReference;
|
6
|
+
|
7
|
+
import sh.calaba.instrumentationbackend.InstrumentationBackend;
|
8
|
+
|
9
|
+
public class InvocationOperation implements Operation {
|
10
|
+
|
11
|
+
private final String methodName;
|
12
|
+
@SuppressWarnings("rawtypes")
|
13
|
+
private final List arguments;
|
14
|
+
private final Class<?>[] classes;
|
15
|
+
private final Class<?>[] classesWithCharseq;
|
16
|
+
|
17
|
+
@SuppressWarnings("rawtypes")
|
18
|
+
public InvocationOperation(String methodName, List arguments) {
|
19
|
+
this.methodName = methodName;
|
20
|
+
this.arguments = arguments;
|
21
|
+
this.classes = extractArgumentTypes(false);
|
22
|
+
this.classesWithCharseq = extractArgumentTypes(true);
|
23
|
+
}
|
24
|
+
|
25
|
+
@SuppressWarnings("rawtypes")
|
26
|
+
@Override
|
27
|
+
public Object apply(final Object o) throws Exception {
|
28
|
+
final AtomicReference ref = new AtomicReference();
|
29
|
+
final AtomicReference<Exception> refEx = new AtomicReference<Exception>();
|
30
|
+
|
31
|
+
InstrumentationBackend.instrumentation.runOnMainSync(new Runnable() {
|
32
|
+
|
33
|
+
@SuppressWarnings("unchecked")
|
34
|
+
@Override
|
35
|
+
public void run() {
|
36
|
+
try {
|
37
|
+
Method method = o.getClass().getMethod(InvocationOperation.this.methodName, InvocationOperation.this.classes);
|
38
|
+
method.setAccessible(true);
|
39
|
+
try {
|
40
|
+
Object result;
|
41
|
+
if( method.getReturnType().equals(Void.TYPE)){
|
42
|
+
invokeMethod(o, method);
|
43
|
+
result = "<VOID>";
|
44
|
+
}
|
45
|
+
else {
|
46
|
+
result = invokeMethod(o, method);
|
47
|
+
}
|
48
|
+
ref.set(result);
|
49
|
+
return;
|
50
|
+
} catch (Exception e) {
|
51
|
+
refEx.set(e);
|
52
|
+
return;
|
53
|
+
}
|
54
|
+
} catch (NoSuchMethodException e) {
|
55
|
+
try {
|
56
|
+
Method method = o.getClass().getMethod(InvocationOperation.this.methodName, InvocationOperation.this.classesWithCharseq);
|
57
|
+
method.setAccessible(true);
|
58
|
+
try {
|
59
|
+
Object result;
|
60
|
+
if( method.getReturnType().equals(Void.TYPE)){
|
61
|
+
invokeMethod(o, method);
|
62
|
+
result = "<VOID>";
|
63
|
+
}
|
64
|
+
else {
|
65
|
+
result = invokeMethod(o, method);
|
66
|
+
}
|
67
|
+
ref.set(result);
|
68
|
+
return;
|
69
|
+
} catch (Exception ee) {
|
70
|
+
refEx.set(e);
|
71
|
+
return;
|
72
|
+
}
|
73
|
+
} catch (NoSuchMethodException ee) {
|
74
|
+
System.out.println("Method not found with correct argument types. Trying to type convert.");
|
75
|
+
}
|
76
|
+
}
|
77
|
+
//Warning: Slow path
|
78
|
+
Method[] methods = o.getClass().getMethods();
|
79
|
+
for (Method m : methods) {
|
80
|
+
if (m.getName().equals(InvocationOperation.this.methodName)) {
|
81
|
+
Class<?>[] parameterTypes = m.getParameterTypes();
|
82
|
+
if (parameterTypes.length == InvocationOperation.this.classes.length && areArgumentsConvertibleTo(parameterTypes)) {
|
83
|
+
try {
|
84
|
+
Object result;
|
85
|
+
if( m.getReturnType().equals(Void.TYPE)){
|
86
|
+
invokeMethod(o, m);
|
87
|
+
result = "<VOID>";
|
88
|
+
}
|
89
|
+
else {
|
90
|
+
result = invokeMethod(o, m);
|
91
|
+
}
|
92
|
+
ref.set(result);
|
93
|
+
return;
|
94
|
+
} catch (Exception e) {
|
95
|
+
refEx.set(e);
|
96
|
+
return;
|
97
|
+
}
|
98
|
+
|
99
|
+
}
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
}
|
104
|
+
|
105
|
+
});
|
106
|
+
|
107
|
+
if (refEx.get() != null) {
|
108
|
+
throw refEx.get();
|
109
|
+
}
|
110
|
+
return ref.get();
|
111
|
+
}
|
112
|
+
|
113
|
+
@SuppressWarnings("rawtypes")
|
114
|
+
private Class[] extractArgumentTypes(boolean convertStringCharSeq) {
|
115
|
+
Class[] types = new Class[arguments.size()];
|
116
|
+
for (int i=0;i<arguments.size(); i++) {
|
117
|
+
Object o = arguments.get(i);
|
118
|
+
if (o != null) {
|
119
|
+
Class<?> c = o.getClass();
|
120
|
+
if (convertStringCharSeq && c.equals(String.class)) {
|
121
|
+
c = CharSequence.class;//Android API specific optimization
|
122
|
+
}
|
123
|
+
types[i] = c;
|
124
|
+
}
|
125
|
+
else {
|
126
|
+
types[i] = null;
|
127
|
+
}
|
128
|
+
}
|
129
|
+
return types;
|
130
|
+
}
|
131
|
+
|
132
|
+
//parameterType.length == this.classes.length
|
133
|
+
//Note: right now we don't do any clever mapping, we
|
134
|
+
//only use Java's sub type relation: isAssigableFrom
|
135
|
+
private boolean areArgumentsConvertibleTo(Class<?>[] parameterTypes) {
|
136
|
+
for (int i=0; i < parameterTypes.length; i++) {
|
137
|
+
Class<?> typei = parameterTypes[i];
|
138
|
+
if (this.classes[i] == null) {
|
139
|
+
if (typei.isPrimitive()) {
|
140
|
+
//Can't pass null as primitive
|
141
|
+
return false;
|
142
|
+
}
|
143
|
+
continue; //can always pass null (unless primitive)
|
144
|
+
}
|
145
|
+
if (!typei.isAssignableFrom(this.classes[i])) {
|
146
|
+
return false;
|
147
|
+
}
|
148
|
+
}
|
149
|
+
return true;
|
150
|
+
}
|
151
|
+
|
152
|
+
private Object invokeMethod(Object o, Method m) throws Exception {
|
153
|
+
List<?> a = this.arguments;
|
154
|
+
int size = a.size();
|
155
|
+
switch(size) {
|
156
|
+
case 0:
|
157
|
+
return m.invoke(o);
|
158
|
+
case 1:
|
159
|
+
return m.invoke(o,a.get(0));
|
160
|
+
case 2:
|
161
|
+
return m.invoke(o,a.get(0),a.get(1));
|
162
|
+
case 3:
|
163
|
+
return m.invoke(o,a.get(0),a.get(1),a.get(2));
|
164
|
+
case 4:
|
165
|
+
return m.invoke(o,a.get(0),a.get(1),a.get(2),a.get(3));
|
166
|
+
case 5:
|
167
|
+
return m.invoke(o,a.get(0),a.get(1),a.get(2),a.get(3),a.get(4));
|
168
|
+
case 6:
|
169
|
+
return m.invoke(o,a.get(0),a.get(1),a.get(2),a.get(3),a.get(4),a.get(5));
|
170
|
+
case 7:
|
171
|
+
return m.invoke(o,a.get(0),a.get(1),a.get(2),a.get(3),a.get(4),a.get(5),a.get(6));
|
172
|
+
case 8:
|
173
|
+
return m.invoke(o,a.get(0),a.get(1),a.get(2),a.get(3),a.get(4),a.get(5),a.get(6),a.get(7));
|
174
|
+
case 9:
|
175
|
+
return m.invoke(o,a.get(0),a.get(1),a.get(2),a.get(3),a.get(4),a.get(5),a.get(6),a.get(7),a.get(8));
|
176
|
+
case 10:
|
177
|
+
return m.invoke(o,a.get(0),a.get(1),a.get(2),a.get(3),a.get(4),a.get(5),a.get(6),a.get(7),a.get(8),a.get(9));
|
178
|
+
case 11:
|
179
|
+
return m.invoke(o,a.get(0),a.get(1),a.get(2),a.get(3),a.get(4),a.get(5),a.get(6),a.get(7),a.get(8),a.get(9),a.get(10));
|
180
|
+
case 12:
|
181
|
+
return m.invoke(o,a.get(0),a.get(1),a.get(2),a.get(3),a.get(4),a.get(5),a.get(6),a.get(7),a.get(8),a.get(9),a.get(10),a.get(11));
|
182
|
+
case 13:
|
183
|
+
return m.invoke(o,a.get(0),a.get(1),a.get(2),a.get(3),a.get(4),a.get(5),a.get(6),a.get(7),a.get(8),a.get(9),a.get(10),a.get(11),a.get(12));
|
184
|
+
case 14:
|
185
|
+
return m.invoke(o,a.get(0),a.get(1),a.get(2),a.get(3),a.get(4),a.get(5),a.get(6),a.get(7),a.get(8),a.get(9),a.get(10),a.get(11),a.get(12),a.get(13));
|
186
|
+
case 15:
|
187
|
+
return m.invoke(o,a.get(0),a.get(1),a.get(2),a.get(3),a.get(4),a.get(5),a.get(6),a.get(7),a.get(8),a.get(9),a.get(10),a.get(11),a.get(12),a.get(13),a.get(14));
|
188
|
+
case 16:
|
189
|
+
return m.invoke(o,a.get(0),a.get(1),a.get(2),a.get(3),a.get(4),a.get(5),a.get(6),a.get(7),a.get(8),a.get(9),a.get(10),a.get(11),a.get(12),a.get(13),a.get(14),a.get(15));
|
190
|
+
}
|
191
|
+
throw new UnsupportedOperationException("Method with more than 16 arguments are not supported");
|
192
|
+
|
193
|
+
}
|
194
|
+
|
195
|
+
|
196
|
+
@Override
|
197
|
+
public String getName() {
|
198
|
+
return "InvocationOp["+this.methodName+", arguments = " + this.arguments + "]";
|
199
|
+
}
|
200
|
+
|
201
|
+
}
|