From 73478f0b1f972bc302155bef7655e1dcdf9ceb79 Mon Sep 17 00:00:00 2001 From: lh <1209405678@qq.com> Date: Fri, 24 Nov 2017 09:50:00 +0800 Subject: [PATCH] init --- .gitignore | 9 + .idea/compiler.xml | 22 + .idea/copyright/profiles_settings.xml | 3 + .idea/gradle.xml | 19 + .idea/misc.xml | 46 ++ .idea/modules.xml | 10 + .idea/runConfigurations.xml | 12 + app/.gitignore | 1 + app/build.gradle | 43 ++ app/proguard-rules.pro | 25 + .../qhclh/ytzh/ExampleInstrumentedTest.java | 26 + app/src/main/AndroidManifest.xml | 29 + app/src/main/assets/litepal.xml | 9 + .../com/qhclh/ytzh/base/BaseActivity.java | 99 ++++ .../com/qhclh/ytzh/configs/ConfigBase.java | 31 + .../com/qhclh/ytzh/configs/ConfigUtil.java | 29 + .../com/qhclh/ytzh/configs/LastLoginInfo.java | 32 + .../qhclh/ytzh/configs/LoginUserConfig.java | 31 + .../com/qhclh/ytzh/configs/ServerConfig.java | 93 +++ .../com/qhclh/ytzh/home/MainActivity.java | 43 ++ .../com/qhclh/ytzh/home/MyApplication.java | 61 ++ .../main/java/com/qhclh/ytzh/home/RpcUrl.java | 11 + .../ytzh/interfaces/OnPromptListener.java | 7 + .../com/qhclh/ytzh/splash/SplashActivity.java | 66 +++ .../com/qhclh/ytzh/tasks/CallableTask.java | 115 ++++ .../com/qhclh/ytzh/tasks/ViewOnClickTask.java | 39 ++ .../qhclh/ytzh/utils/ActivityCollector.java | 36 ++ .../com/qhclh/ytzh/utils/DateTimeUtil.java | 72 +++ .../java/com/qhclh/ytzh/utils/DialogUtil.java | 189 ++++++ .../java/com/qhclh/ytzh/utils/StringUtil.java | 30 + app/src/main/res/anim/anim_in_left.xml | 9 + app/src/main/res/anim/anim_in_right.xml | 9 + app/src/main/res/anim/anim_out_left.xml | 9 + app/src/main/res/anim/anim_out_right.xml | 9 + app/src/main/res/drawable-xhdpi/back.png | Bin 0 -> 225392 bytes app/src/main/res/layout/act_main.xml | 12 + app/src/main/res/layout/act_splash.xml | 9 + app/src/main/res/layout/include_line.xml | 6 + app/src/main/res/layout/include_tab_bar.xml | 45 ++ app/src/main/res/layout/include_tool_bar.xml | 17 + app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3418 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 4208 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2206 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2555 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4842 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 6114 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 7718 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 10056 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 10486 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 14696 bytes app/src/main/res/values/colors.xml | 24 + app/src/main/res/values/dimens.xml | 174 ++++++ app/src/main/res/values/strings.xml | 3 + app/src/main/res/values/styles.xml | 54 ++ .../java/com/qhclh/ytzh/ExampleUnitTest.java | 17 + build.gradle | 23 + gradle.properties | 17 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 53636 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 160 +++++ gradlew.bat | 90 +++ jsonrpc/.gitignore | 1 + jsonrpc/build.gradle | 27 + jsonrpc/proguard-rules.pro | 17 + .../org/forks/jsonrpc/ApplicationTest.java | 13 + jsonrpc/src/main/AndroidManifest.xml | 11 + .../java/org/forks/jsonrpc/DFDataTable.java | 38 ++ .../main/java/org/forks/jsonrpc/Helper.java | 76 +++ .../org/forks/jsonrpc/HttpJsonRpcClient.java | 84 +++ .../InvalidPropertyValueException.java | 23 + .../java/org/forks/jsonrpc/IterHelper.java | 69 +++ .../java/org/forks/jsonrpc/JsonRpcClient.java | 93 +++ .../org/forks/jsonrpc/JsonRpcException.java | 51 ++ .../java/org/forks/jsonrpc/JsonRpcResult.java | 179 ++++++ .../jsonrpc/JsonRpcRuntimeException.java | 22 + .../main/java/org/forks/jsonrpc/ManyList.java | 199 +++++++ .../java/org/forks/jsonrpc/NamedValue.java | 66 +++ .../org/forks/jsonrpc/NamedValueMeta.java | 84 +++ .../jsonrpc/NoSuchRpcPropertyException.java | 22 + .../java/org/forks/jsonrpc/RpcFacade.java | 269 +++++++++ .../java/org/forks/jsonrpc/RpcObject.java | 386 ++++++++++++ .../java/org/forks/jsonrpc/RpcObjectMeta.java | 75 +++ .../org/forks/jsonrpc/RpcPropertyMeta.java | 61 ++ .../main/java/org/forks/jsonrpc/RpcType.java | 5 + .../java/org/forks/jsonrpc/RpcTypeParser.java | 557 ++++++++++++++++++ jsonrpc/src/main/res/values/strings.xml | 3 + .../org/forks/jsonrpc/ExampleUnitTest.java | 15 + settings.gradle | 1 + 88 files changed, 4378 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/compiler.xml create mode 100644 .idea/copyright/profiles_settings.xml create mode 100644 .idea/gradle.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/runConfigurations.xml create mode 100644 app/.gitignore create mode 100644 app/build.gradle create mode 100644 app/proguard-rules.pro create mode 100644 app/src/androidTest/java/com/qhclh/ytzh/ExampleInstrumentedTest.java create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/assets/litepal.xml create mode 100644 app/src/main/java/com/qhclh/ytzh/base/BaseActivity.java create mode 100644 app/src/main/java/com/qhclh/ytzh/configs/ConfigBase.java create mode 100644 app/src/main/java/com/qhclh/ytzh/configs/ConfigUtil.java create mode 100644 app/src/main/java/com/qhclh/ytzh/configs/LastLoginInfo.java create mode 100644 app/src/main/java/com/qhclh/ytzh/configs/LoginUserConfig.java create mode 100644 app/src/main/java/com/qhclh/ytzh/configs/ServerConfig.java create mode 100644 app/src/main/java/com/qhclh/ytzh/home/MainActivity.java create mode 100644 app/src/main/java/com/qhclh/ytzh/home/MyApplication.java create mode 100644 app/src/main/java/com/qhclh/ytzh/home/RpcUrl.java create mode 100644 app/src/main/java/com/qhclh/ytzh/interfaces/OnPromptListener.java create mode 100644 app/src/main/java/com/qhclh/ytzh/splash/SplashActivity.java create mode 100644 app/src/main/java/com/qhclh/ytzh/tasks/CallableTask.java create mode 100644 app/src/main/java/com/qhclh/ytzh/tasks/ViewOnClickTask.java create mode 100644 app/src/main/java/com/qhclh/ytzh/utils/ActivityCollector.java create mode 100644 app/src/main/java/com/qhclh/ytzh/utils/DateTimeUtil.java create mode 100644 app/src/main/java/com/qhclh/ytzh/utils/DialogUtil.java create mode 100644 app/src/main/java/com/qhclh/ytzh/utils/StringUtil.java create mode 100644 app/src/main/res/anim/anim_in_left.xml create mode 100644 app/src/main/res/anim/anim_in_right.xml create mode 100644 app/src/main/res/anim/anim_out_left.xml create mode 100644 app/src/main/res/anim/anim_out_right.xml create mode 100644 app/src/main/res/drawable-xhdpi/back.png create mode 100644 app/src/main/res/layout/act_main.xml create mode 100644 app/src/main/res/layout/act_splash.xml create mode 100644 app/src/main/res/layout/include_line.xml create mode 100644 app/src/main/res/layout/include_tab_bar.xml create mode 100644 app/src/main/res/layout/include_tool_bar.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/dimens.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/styles.xml create mode 100644 app/src/test/java/com/qhclh/ytzh/ExampleUnitTest.java create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 jsonrpc/.gitignore create mode 100644 jsonrpc/build.gradle create mode 100644 jsonrpc/proguard-rules.pro create mode 100644 jsonrpc/src/androidTest/java/org/forks/jsonrpc/ApplicationTest.java create mode 100644 jsonrpc/src/main/AndroidManifest.xml create mode 100644 jsonrpc/src/main/java/org/forks/jsonrpc/DFDataTable.java create mode 100644 jsonrpc/src/main/java/org/forks/jsonrpc/Helper.java create mode 100644 jsonrpc/src/main/java/org/forks/jsonrpc/HttpJsonRpcClient.java create mode 100644 jsonrpc/src/main/java/org/forks/jsonrpc/InvalidPropertyValueException.java create mode 100644 jsonrpc/src/main/java/org/forks/jsonrpc/IterHelper.java create mode 100644 jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcClient.java create mode 100644 jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcException.java create mode 100644 jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcResult.java create mode 100644 jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcRuntimeException.java create mode 100644 jsonrpc/src/main/java/org/forks/jsonrpc/ManyList.java create mode 100644 jsonrpc/src/main/java/org/forks/jsonrpc/NamedValue.java create mode 100644 jsonrpc/src/main/java/org/forks/jsonrpc/NamedValueMeta.java create mode 100644 jsonrpc/src/main/java/org/forks/jsonrpc/NoSuchRpcPropertyException.java create mode 100644 jsonrpc/src/main/java/org/forks/jsonrpc/RpcFacade.java create mode 100644 jsonrpc/src/main/java/org/forks/jsonrpc/RpcObject.java create mode 100644 jsonrpc/src/main/java/org/forks/jsonrpc/RpcObjectMeta.java create mode 100644 jsonrpc/src/main/java/org/forks/jsonrpc/RpcPropertyMeta.java create mode 100644 jsonrpc/src/main/java/org/forks/jsonrpc/RpcType.java create mode 100644 jsonrpc/src/main/java/org/forks/jsonrpc/RpcTypeParser.java create mode 100644 jsonrpc/src/main/res/values/strings.xml create mode 100644 jsonrpc/src/test/java/org/forks/jsonrpc/ExampleUnitTest.java create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..39fb081 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures +.externalNativeBuild diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..96cc43e --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..e7bedf3 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..ec344a3 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..54207cd --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..1024777 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..75a08a9 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,43 @@ +apply plugin: 'com.android.application' +apply plugin: 'android-apt' + +android { + compileSdkVersion 26 + buildToolsVersion "26.0.0" + defaultConfig { + applicationId "com.qhclh.ytzh" + minSdkVersion 15 + targetSdkVersion 26 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + compile fileTree(include: ['*.jar'], dir: 'libs') + androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { + exclude group: 'com.android.support', module: 'support-annotations' + }) + compile 'com.android.support:appcompat-v7:26.+' + testCompile 'junit:junit:4.12' + compile 'com.jakewharton:butterknife:8.4.0' + apt 'com.jakewharton:butterknife-compiler:8.4.0' + compile 'com.github.bumptech.glide:glide:3.7.0' + compile 'com.android.support:support-v4:26.0.0-alpha1' + compile 'com.android.support:design:26.0.0-alpha1' + compile 'org.greenrobot:eventbus:3.0.0' + compile 'com.umeng.analytics:analytics:latest.integration' + compile 'pub.devrel:easypermissions:0.2.1' + compile 'com.google.code.gson:gson:2.8.1' + compile 'org.litepal.android:core:1.3.0' + compile 'com.journeyapps:zxing-android-embedded:3.5.0' + compile 'com.google.zxing:core:3.3.0' + compile project(':jsonrpc') +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..2f7a964 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,25 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in F:\SDK/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/androidTest/java/com/qhclh/ytzh/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/qhclh/ytzh/ExampleInstrumentedTest.java new file mode 100644 index 0000000..198dcdb --- /dev/null +++ b/app/src/androidTest/java/com/qhclh/ytzh/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.qhclh.ytzh; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumentation test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() throws Exception { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("com.qhclh.ytzh", appContext.getPackageName()); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..cbd9572 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/assets/litepal.xml b/app/src/main/assets/litepal.xml new file mode 100644 index 0000000..8590a8f --- /dev/null +++ b/app/src/main/assets/litepal.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/qhclh/ytzh/base/BaseActivity.java b/app/src/main/java/com/qhclh/ytzh/base/BaseActivity.java new file mode 100644 index 0000000..a9638be --- /dev/null +++ b/app/src/main/java/com/qhclh/ytzh/base/BaseActivity.java @@ -0,0 +1,99 @@ +package com.qhclh.ytzh.base; + +import android.os.Bundle; +import android.support.annotation.IdRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.app.ActionBar; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + + +import com.qhclh.ytzh.R; +import com.qhclh.ytzh.utils.ActivityCollector; +import com.umeng.analytics.MobclickAgent; + +import butterknife.ButterKnife; + + +/** + * Created by 青花瓷 on 2017/7/19. + */ + +public abstract class BaseActivity extends AppCompatActivity { + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(setLayoutId()); + ButterKnife.bind(this); + ActivityCollector.addActivity(this); + initView(); + initData(); + initOper(); + } + + protected abstract int setLayoutId(); + protected abstract void initView(); + protected abstract void initData(); + protected abstract void initOper(); + ///< toolbar设置 + public void initToolbar(Toolbar toolbar, String title, View.OnClickListener listener) { + if (toolbar == null) { + return; + } + TextView tvTitle = findById(toolbar, R.id.tv_toolbar_title); + if (tvTitle != null) { + tvTitle.setText(title == null ? "" : title); + } + setSupportActionBar(toolbar); + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setDisplayShowTitleEnabled(false); + } + if (listener != null) { + toolbar.setNavigationIcon(R.drawable.back); + toolbar.setNavigationOnClickListener(listener); + } + } + + @Override + protected void onResume() { + super.onResume(); + try { + MobclickAgent.onResume(this); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + protected void onPause() { + super.onPause(); + try { + MobclickAgent.onPause(this); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + @Override + protected void onDestroy() { + super.onDestroy(); + ActivityCollector.removeActivity(this); + } + + public void finishAll(){ActivityCollector.finishAll();} + + public void showToast(String str) { + Toast.makeText(this, str, Toast.LENGTH_SHORT).show(); + } + + protected T findById(@NonNull View view, @IdRes int resId) { + return ButterKnife.findById(view, resId); + } +} diff --git a/app/src/main/java/com/qhclh/ytzh/configs/ConfigBase.java b/app/src/main/java/com/qhclh/ytzh/configs/ConfigBase.java new file mode 100644 index 0000000..c872861 --- /dev/null +++ b/app/src/main/java/com/qhclh/ytzh/configs/ConfigBase.java @@ -0,0 +1,31 @@ +package com.qhclh.ytzh.configs; + +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; + +import com.qhclh.ytzh.utils.StringUtil; + + +public abstract class ConfigBase { + String mName; + Context mContext; + + public ConfigBase(Context context, String name) { + mName = name; + mContext = context; + } + + public SharedPreferences getStore() { + if (StringUtil.IsNullOrEmpty(mName)) { + return PreferenceManager.getDefaultSharedPreferences(mContext); + } else { + return mContext.getSharedPreferences(mName, Context.MODE_PRIVATE); + } + } + + public abstract void GetValues(SharedPreferences store); + + public abstract void SetValues(SharedPreferences.Editor store); + +} diff --git a/app/src/main/java/com/qhclh/ytzh/configs/ConfigUtil.java b/app/src/main/java/com/qhclh/ytzh/configs/ConfigUtil.java new file mode 100644 index 0000000..b0f6cec --- /dev/null +++ b/app/src/main/java/com/qhclh/ytzh/configs/ConfigUtil.java @@ -0,0 +1,29 @@ +package com.qhclh.ytzh.configs; + +import android.content.Context; +import android.content.SharedPreferences; + + +public class ConfigUtil { + public static void Fill(T config) { + SharedPreferences store = config.getStore(); + config.GetValues(store); + } + + public static void Save(T config) { + SharedPreferences store = config.getStore(); + SharedPreferences.Editor editor = store.edit(); + editor.clear(); + config.SetValues(editor); + editor.commit(); + } + + public static String getServerUri(Context context) { + ServerConfig config = new ServerConfig(context); + Fill(config); + return config.getServerUri(); + } + + +} + diff --git a/app/src/main/java/com/qhclh/ytzh/configs/LastLoginInfo.java b/app/src/main/java/com/qhclh/ytzh/configs/LastLoginInfo.java new file mode 100644 index 0000000..eadb74f --- /dev/null +++ b/app/src/main/java/com/qhclh/ytzh/configs/LastLoginInfo.java @@ -0,0 +1,32 @@ +package com.qhclh.ytzh.configs; + +import android.content.Context; +import android.content.SharedPreferences; + + +public class LastLoginInfo extends ConfigBase { + + public LastLoginInfo(Context context) { + super(context, "LastLoginUserInfo"); + // TODO Auto-generated constructor stub + } + + @Override + public void GetValues(SharedPreferences store) { + Username = store.getString("Username", ""); + Password = store.getString("Password", ""); + CurrentTimeMillis = store.getLong("CurrentTimeMillis", 0); + } + + @Override + public void SetValues(SharedPreferences.Editor store) { + store.putString("Username", Username); + store.putString("Password", Password); + store.putLong("CurrentTimeMillis", System.currentTimeMillis()); + } + + public String Username; + public String Password; + public long CurrentTimeMillis; + +} diff --git a/app/src/main/java/com/qhclh/ytzh/configs/LoginUserConfig.java b/app/src/main/java/com/qhclh/ytzh/configs/LoginUserConfig.java new file mode 100644 index 0000000..37ada9f --- /dev/null +++ b/app/src/main/java/com/qhclh/ytzh/configs/LoginUserConfig.java @@ -0,0 +1,31 @@ +package com.qhclh.ytzh.configs; + +import android.content.Context; +import android.content.SharedPreferences; + + +public class LoginUserConfig extends ConfigBase { + + public LoginUserConfig(Context context) { + super(context, "LoginUserConfig"); + } + + @Override + public void GetValues(SharedPreferences store) { + Username = store.getString("Username", ""); + Password = store.getString("Password", ""); + DisplayName = store.getString("DisplayName", ""); + } + + @Override + public void SetValues(SharedPreferences.Editor store) { + store.putString("Username", Username); + store.putString("Password", Password); + store.putString("DisplayName", DisplayName); + } + + public String Username; + public String Password; + public String DisplayName; + +} diff --git a/app/src/main/java/com/qhclh/ytzh/configs/ServerConfig.java b/app/src/main/java/com/qhclh/ytzh/configs/ServerConfig.java new file mode 100644 index 0000000..05e9ee4 --- /dev/null +++ b/app/src/main/java/com/qhclh/ytzh/configs/ServerConfig.java @@ -0,0 +1,93 @@ +package com.qhclh.ytzh.configs; + +import android.content.Context; +import android.content.SharedPreferences; + +import org.forks.jsonrpc.RpcFacade; + + +public class ServerConfig extends ConfigBase { + + String JPUSH_TAG_KEY="jpushtagkey"; + String SYSTEMSET_ENABLE_SCAN="systemset_enable_scan"; + String ENABLE_Catogray="systemset_enable_catogray"; + String ENABLE_MoneyTipe="systemset_enable_moneytipe"; + String ENABLE_StoreGoods="systemset_enable_storegoods"; + + public ServerConfig(Context context) { + super(context, ""); + } + + @Override + public void GetValues(SharedPreferences store) { + mServerUri = store.getString(RpcFacade.SERVER_URI_PREFKEY, ""); + mTag = store.getString(JPUSH_TAG_KEY, ""); + mEnableGoodsScan = store.getBoolean(SYSTEMSET_ENABLE_SCAN,false); + mEnableGoodsCatogray = store.getBoolean(ENABLE_Catogray,false); + mEnablMoneyTipe = store.getBoolean(ENABLE_MoneyTipe,false); + mEnablStoreGoods = store.getBoolean(ENABLE_StoreGoods,false); + + } + + @Override + public void SetValues(SharedPreferences.Editor store) { + store.putString(RpcFacade.SERVER_URI_PREFKEY, getServerUri()); + store.putString(JPUSH_TAG_KEY, getTag()); + store.putBoolean(SYSTEMSET_ENABLE_SCAN,getEnableGoodsScan()); + store.putBoolean(ENABLE_Catogray,getEnableGoodsCatogray()); + store.putBoolean(ENABLE_MoneyTipe,getEnableMoneyTipe()); + store.putBoolean(ENABLE_StoreGoods,getEnableStoreGoods()); + } + + private String mServerUri; + private String mTag; + + public String getServerUri() { + return mServerUri; + } + + public void setServerUri(String value) { + mServerUri = value; + } + + + public String getTag() { + return mTag; + } + + public void setTag(String value) { + mTag = value; + } + + private boolean mEnableGoodsScan; + public boolean getEnableGoodsScan() { + return mEnableGoodsScan; + } + public void setEnableGoodsScang(boolean value) { + mEnableGoodsScan = value; + } + + private boolean mEnableGoodsCatogray; + public boolean getEnableGoodsCatogray() { + return mEnableGoodsCatogray; + } + public void setEnableGoodsCatogray(boolean value) { + mEnableGoodsCatogray = value; + } + + private boolean mEnablMoneyTipe; + public boolean getEnableMoneyTipe() { + return mEnablMoneyTipe; + } + public void setEnableMoneyTipe(boolean value) { + mEnablMoneyTipe = value; + } + + private boolean mEnablStoreGoods; + public boolean getEnableStoreGoods() { + return mEnablStoreGoods; + } + public void setEnableStoreGoods(boolean value) { + mEnablStoreGoods = value; + } +} diff --git a/app/src/main/java/com/qhclh/ytzh/home/MainActivity.java b/app/src/main/java/com/qhclh/ytzh/home/MainActivity.java new file mode 100644 index 0000000..2b7d37f --- /dev/null +++ b/app/src/main/java/com/qhclh/ytzh/home/MainActivity.java @@ -0,0 +1,43 @@ +package com.qhclh.ytzh.home; + +import android.support.v7.widget.Toolbar; +import android.view.View; +import android.widget.TextView; + +import com.qhclh.ytzh.R; +import com.qhclh.ytzh.base.BaseActivity; + +import butterknife.BindView; + +public class MainActivity extends BaseActivity { + @BindView(R.id.textaaa) + TextView textView; + + @BindView(R.id.toolbar) + Toolbar mToolbar; + + @Override + protected int setLayoutId() { + return R.layout.act_main; + } + + @Override + protected void initView() { + initToolbar(mToolbar, "aaaaa", new View.OnClickListener() { + @Override + public void onClick(View view) { + finish(); + } + }); + } + + @Override + protected void initData() { + textView.setText("aaaaaaaaaaa"); + } + + @Override + protected void initOper() { + + } +} diff --git a/app/src/main/java/com/qhclh/ytzh/home/MyApplication.java b/app/src/main/java/com/qhclh/ytzh/home/MyApplication.java new file mode 100644 index 0000000..9e4fbb8 --- /dev/null +++ b/app/src/main/java/com/qhclh/ytzh/home/MyApplication.java @@ -0,0 +1,61 @@ +package com.qhclh.ytzh.home; + +import android.app.Activity; + +import com.qhclh.ytzh.configs.ConfigUtil; +import com.qhclh.ytzh.configs.LastLoginInfo; +import com.qhclh.ytzh.configs.ServerConfig; + +import org.forks.jsonrpc.RpcFacade; +import org.litepal.LitePalApplication; + +import java.util.LinkedList; +import java.util.List; + +/** + * Created by 青花瓷 on 2017/11/23. + */ + +public class MyApplication extends LitePalApplication { + + private final String NAME ="ytzh"; + static LastLoginInfo mLoginInfo; + private static MyApplication instance; + String url= RpcUrl.BaseAppUrl; + ServerConfig config; + + private List activityList = new LinkedList(); + + public static MyApplication getInstance(){ + if (null == instance) { + instance = new MyApplication(); + } + return instance; + } + @Override + public void onCreate() { + super.onCreate(); + + mLoginInfo = new LastLoginInfo(this); + ConfigUtil.Fill(mLoginInfo); + + ///< 先暂时必须设置URL + config = new ServerConfig(this); + config.setServerUri(url); + ConfigUtil.Save(config); + + RpcFacade.init(this.getApplicationContext(),NAME); + } + + public void exit() { + for (Activity activity : activityList) { + activity.finish(); + } + System.exit(0); + } + + public static void ClearLogin() { + mLoginInfo.Username = ""; + ConfigUtil.Save(mLoginInfo); + } +} diff --git a/app/src/main/java/com/qhclh/ytzh/home/RpcUrl.java b/app/src/main/java/com/qhclh/ytzh/home/RpcUrl.java new file mode 100644 index 0000000..ef3b534 --- /dev/null +++ b/app/src/main/java/com/qhclh/ytzh/home/RpcUrl.java @@ -0,0 +1,11 @@ +package com.qhclh.ytzh.home; + +public class RpcUrl { + + ///< 域名开发 +// public static String BaseAppUrl = "http://192.168.1.9/MarketPlace/"; + ///< 正式服务器地址 + public static String BaseAppUrl = "http://47.93.175.172/Marketplace/"; + ///< 外网测试 +// public static String BaseAppUrl = "http://111.198.52.49:81/MarketPlace/"; +} diff --git a/app/src/main/java/com/qhclh/ytzh/interfaces/OnPromptListener.java b/app/src/main/java/com/qhclh/ytzh/interfaces/OnPromptListener.java new file mode 100644 index 0000000..109aac2 --- /dev/null +++ b/app/src/main/java/com/qhclh/ytzh/interfaces/OnPromptListener.java @@ -0,0 +1,7 @@ +package com.qhclh.ytzh.interfaces; + + +public interface OnPromptListener { + public void OnPrompt(String prompt); + +} diff --git a/app/src/main/java/com/qhclh/ytzh/splash/SplashActivity.java b/app/src/main/java/com/qhclh/ytzh/splash/SplashActivity.java new file mode 100644 index 0000000..6850548 --- /dev/null +++ b/app/src/main/java/com/qhclh/ytzh/splash/SplashActivity.java @@ -0,0 +1,66 @@ +package com.qhclh.ytzh.splash; + +import android.content.Intent; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.widget.LinearLayout; + +import com.qhclh.ytzh.R; +import com.qhclh.ytzh.base.BaseActivity; +import com.qhclh.ytzh.home.MainActivity; + +import butterknife.BindView; + +/** + * Created by 青花瓷 on 2017/11/23. + */ + +public class SplashActivity extends BaseActivity { + @BindView(R.id.ll_splash) + LinearLayout ll_splash; + + @Override + protected int setLayoutId() { + return R.layout.act_splash; + } + + @Override + protected void initView() { + + } + + @Override + protected void initData() { + + } + + @Override + protected void initOper() { + + //渐变展示启动屏 + AlphaAnimation aa = new AlphaAnimation(0.3f, 1.0f); + aa.setDuration(2000); + ll_splash.startAnimation(aa); + aa.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationEnd(Animation arg0) { + redirectTo(); + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + + @Override + public void onAnimationStart(Animation animation) { + } + + }); + + } + + private void redirectTo() { + startActivity(new Intent(this, MainActivity.class)); + finish(); + } +} diff --git a/app/src/main/java/com/qhclh/ytzh/tasks/CallableTask.java b/app/src/main/java/com/qhclh/ytzh/tasks/CallableTask.java new file mode 100644 index 0000000..687c922 --- /dev/null +++ b/app/src/main/java/com/qhclh/ytzh/tasks/CallableTask.java @@ -0,0 +1,115 @@ +package com.qhclh.ytzh.tasks; + +import android.app.ProgressDialog; +import android.content.Context; +import android.os.AsyncTask; +import android.util.Log; + + +import com.qhclh.ytzh.utils.DialogUtil; + +import java.util.concurrent.Callable; + +public abstract class CallableTask implements Callable { + final String tag = "CallableTask"; + + Boolean mIsRunning = false; + + protected abstract void successUI(); + + void failUI(Exception e) { + Log.e(tag, e.getMessage(), e); + if(e.getMessage().contains("Unauthorized")) + { + return; + } + if(e.getMessage().contains("Socket")) + { + return; + } + if(e.getMessage().contains("cannot")) + { + return; + } + + DialogUtil.AutoHiddenAlert(mContext,e.getMessage()); +// DialogUtil.Alert(mContext, e.getMessage()); + } + + Context mContext; + ProgressDialog mDialog; + String mMessage; + + public CallableTask(Context context, String message) { + mContext = context; + mMessage = message; + } + + public final void execute() { + if (mIsRunning) { + Log.w(tag, "任务重复执行"); + return; + } + new Task().execute(); + } + + class Task extends AsyncTask { + Exception mException; + + @Override + protected Void doInBackground(Void... params) { + try { + mIsRunning = true; + call(); + } catch (Exception ex) { + mException = ex; + cancel(false); + } + return null; + } + + @Override + protected void onCancelled() { + super.onCancelled(); + endExecute(); + failUI(mException); + } + + @Override + protected void onPostExecute(Void result) { + super.onPostExecute(result); + endExecute(); + successUI(); + } + + + public void endExecute() { +// if (mDialog != null && isValidContext(mContext) && mDialog.isShowing()) { + if (mDialog != null) { + mDialog.dismiss(); + } + mIsRunning = false; + + } + + @Override + protected void onPreExecute() { + super.onPreExecute(); +// if (isValidContext(mContext)) { + mDialog = ProgressDialog.show(mContext, "请稍等", mMessage, true); +// } + } + + } + +// private boolean isValidContext (Context c){ +// Activity a = (Activity)c; +// if (a.isDestroyed() || a.isFinishing()){ +// return false; +// }else{ +// return true; +// } +// } + + +} diff --git a/app/src/main/java/com/qhclh/ytzh/tasks/ViewOnClickTask.java b/app/src/main/java/com/qhclh/ytzh/tasks/ViewOnClickTask.java new file mode 100644 index 0000000..855c10c --- /dev/null +++ b/app/src/main/java/com/qhclh/ytzh/tasks/ViewOnClickTask.java @@ -0,0 +1,39 @@ +package com.qhclh.ytzh.tasks; + +import android.content.Context; +import android.content.DialogInterface; +import android.view.View; + +import com.qhclh.ytzh.utils.DialogUtil; +import com.qhclh.ytzh.utils.StringUtil; + + +public abstract class ViewOnClickTask extends CallableTask implements + View.OnClickListener { + + private String mPrompt; + + public ViewOnClickTask(Context context, String message) { + super(context, message); + } + + public void setPrompt(String prompt) { + mPrompt = prompt; + } + + public void onClick(View v) { + + if (!StringUtil.IsNullOrEmpty(mPrompt)) { + DialogUtil.Confirm(v.getContext(), mPrompt, "确定", "取消", + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + ViewOnClickTask.this.execute(); + } + }); + } else { + super.execute(); + } + + } + +} diff --git a/app/src/main/java/com/qhclh/ytzh/utils/ActivityCollector.java b/app/src/main/java/com/qhclh/ytzh/utils/ActivityCollector.java new file mode 100644 index 0000000..7446e66 --- /dev/null +++ b/app/src/main/java/com/qhclh/ytzh/utils/ActivityCollector.java @@ -0,0 +1,36 @@ +package com.qhclh.ytzh.utils; + +import android.app.Activity; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by jiangxk on 2016/11/29. + */ + +public class ActivityCollector { + private ActivityCollector() { + + } + + private static List sActivityList = new ArrayList<>(); + + public static void addActivity(Activity activity) { + if (!sActivityList.contains(activity)) { + sActivityList.add(activity); + } + } + + public static void removeActivity(Activity activity) { + sActivityList.remove(activity); + } + + public static void finishAll() { + for (Activity activity : sActivityList) { + if (!activity.isFinishing()) { + activity.finish(); + } + } + } +} diff --git a/app/src/main/java/com/qhclh/ytzh/utils/DateTimeUtil.java b/app/src/main/java/com/qhclh/ytzh/utils/DateTimeUtil.java new file mode 100644 index 0000000..c5cf18e --- /dev/null +++ b/app/src/main/java/com/qhclh/ytzh/utils/DateTimeUtil.java @@ -0,0 +1,72 @@ +package com.qhclh.ytzh.utils; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; + + +public final class DateTimeUtil { + static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + + static SimpleDateFormat dateFormatDetail = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + + public static Date ParseDate(String dateStr) throws ParseException { + return dateFormat.parse(dateStr); + } + public static Date ParseDateDetail(String dateStr) throws ParseException { + return dateFormatDetail.parse(dateStr); + } + + public static Date SafeParseDate(String dateStr) { + try { + if (StringUtil.IsNullOrEmpty(dateStr)) { + return new Date(); + } + return ParseDate(dateStr); + } catch (ParseException e) { + return new Date(); + } + } + + + public static Date SafeParseDateDetail(String dateStr) { + try { + if (StringUtil.IsNullOrEmpty(dateStr)) { + return new Date(); + } + return ParseDateDetail(dateStr); + } catch (ParseException e) { + return new Date(); + } + } + + public static Calendar SafeParseCalendar(String dateStr) { + Calendar calendar = Calendar.getInstance(Locale.getDefault()); + calendar.setTime(SafeParseDate(dateStr)); + return calendar; + } + + public static String FormatDate(Calendar calendar) { + return dateFormat.format(calendar.getTime()); + } + + public static String FormatDate(Date date) { + if (date == null) { + return ""; + } + return dateFormat.format(date); + } + public static String FormatDateDetail(Date date) { + if (date == null) { + return ""; + } + return dateFormatDetail.format(date); + } + + public static Date RemoveTime(Date time) { + return SafeParseDate(FormatDate(time)); + } + +} diff --git a/app/src/main/java/com/qhclh/ytzh/utils/DialogUtil.java b/app/src/main/java/com/qhclh/ytzh/utils/DialogUtil.java new file mode 100644 index 0000000..cdd3ea0 --- /dev/null +++ b/app/src/main/java/com/qhclh/ytzh/utils/DialogUtil.java @@ -0,0 +1,189 @@ +package com.qhclh.ytzh.utils; + +import android.app.Activity; +import android.app.DatePickerDialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Handler; +import android.support.v7.app.AlertDialog; +import android.view.View; +import android.widget.DatePicker; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + + +import com.qhclh.ytzh.interfaces.OnPromptListener; + +import java.util.Calendar; +import java.util.Date; +import java.util.concurrent.Callable; + + +public class DialogUtil { + abstract static class ProgressDialogHelper { + Context mContext; + String mMessage; + Callable mRunnable; + Handler mHandler = new Handler(); + + Callable mCallableAfterSuccess; + + public void setCallableAfterSuccess(Callable callable) { + mCallableAfterSuccess = callable; + } + + public ProgressDialogHelper(Context context, String message, + Callable runnable) { + this.mContext = context; + this.mMessage = message; + this.mRunnable = runnable; + } + + ProgressDialog mDialog; + + public void Start() { + mDialog = ProgressDialog.show(mContext, "请稍等", mMessage, true); + Thread thread = new Thread() { + @Override + public void run() { + try { + mRunnable.call(); + } catch (Exception ex) { + ex.printStackTrace(); + Runnable runnable = new Runnable() { + + public void run() { + DialogUtil.Alert(mContext, mMessage); + + } + + String mMessage; + + public Runnable setMessage(String message) { + mMessage = message; + return this; + } + + }.setMessage(ex.getMessage()); + mHandler.post(runnable); + } finally { + mDialog.dismiss(); + } + } + + }; + thread.start(); + } + } + + public static void Progress(Context context, String message, + Callable callable) { + new ProgressDialogHelper(context, message, callable) { + }.Start(); + } + + public static void Progress(Context context, String message, + Callable callable, Callable callableAfterSuccess) { + ProgressDialogHelper helper = new ProgressDialogHelper(context, + message, callable) { + }; + + helper.Start(); + + } + + public static void Alert(Context context, String message) { + new AlertDialog.Builder(context).setMessage(message) + .setPositiveButton("确定", null).show(); + } + + public static void AlertAndFinish(final Activity activity, String message) { + new AlertDialog.Builder(activity).setMessage(message) + .setPositiveButton("确定", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + activity.finish(); + } + + }).show(); + } + + public static void Alert(View view, String message) { + Alert(view.getContext(), message); + } + + public static void AutoHiddenAlert(Context context, String message) { + Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); + } + + public static void AutoHiddenAlert(View view, String message) { + AutoHiddenAlert(view.getContext(), message); + } + + public interface SetDate { + void setDate(Date date); + } + + public static void AddSelectDateDialog(TextView arg0, + final SetDate onsetdate) { + arg0.setOnClickListener(new View.OnClickListener() { + + public void onClick(final View view) { + final TextView textView = (TextView) view; + DatePickerDialog.OnDateSetListener onDateSetListener = new DatePickerDialog.OnDateSetListener() { + + public void onDateSet(DatePicker datePicker, int year, + int month, int day) { + Calendar calendar = Calendar.getInstance(); + calendar.set(year, month, day); + textView.setText(DateTimeUtil.FormatDate(calendar)); + onsetdate.setDate(calendar.getTime()); + } + + }; + + String dateStr = textView.getText().toString(); + Calendar calendar = DateTimeUtil.SafeParseCalendar(dateStr); + + new DatePickerDialog(view.getContext(), onDateSetListener, + calendar.get(Calendar.YEAR), calendar + .get(Calendar.MONTH), calendar + .get(Calendar.DAY_OF_MONTH)).show(); + } + + }); + } + + public static void Prompt(Context context, String title, String message, + String inputValue, int inputType, final OnPromptListener onprompt) { + final EditText input = new EditText(context); + input.setText(inputValue); + input.setInputType(inputType); + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(title).setMessage(message).setView(input) + .setPositiveButton("确定", new DialogInterface.OnClickListener() { + + public void onClick(DialogInterface arg0, int arg1) { + String prompt = input.getText().toString(); + onprompt.OnPrompt(prompt); + } + }) + .setNegativeButton("取消", new DialogInterface.OnClickListener() { + + public void onClick(DialogInterface dialog, int which) { + + } + }).show(); + + } + + public static void Confirm(Context context, String title, + String trueString, String falseString, + DialogInterface.OnClickListener onConfirm) { + new AlertDialog.Builder(context).setTitle(title) + .setPositiveButton(trueString, onConfirm) + .setNegativeButton(falseString, null).show(); + } + +} diff --git a/app/src/main/java/com/qhclh/ytzh/utils/StringUtil.java b/app/src/main/java/com/qhclh/ytzh/utils/StringUtil.java new file mode 100644 index 0000000..af88171 --- /dev/null +++ b/app/src/main/java/com/qhclh/ytzh/utils/StringUtil.java @@ -0,0 +1,30 @@ +package com.qhclh.ytzh.utils; + +import android.content.Context; + +import java.math.BigDecimal; + +public class StringUtil { + public static Boolean IsNullOrEmpty(String s) { + return s == null || s.length() == 0; + } + + public String GetResource(Context context, int resId) { + return context.getString(resId); + } + + public static String ToString(Object object) { + if (object == null) { + return ""; + } + return String.format("%s", object); + } + + public static BigDecimal ParseMoney(String strValue) { + if (IsNullOrEmpty(strValue)) { + return null; + } + return BigDecimal.valueOf(Double.valueOf(strValue)); + } + +} diff --git a/app/src/main/res/anim/anim_in_left.xml b/app/src/main/res/anim/anim_in_left.xml new file mode 100644 index 0000000..958fdf9 --- /dev/null +++ b/app/src/main/res/anim/anim_in_left.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_in_right.xml b/app/src/main/res/anim/anim_in_right.xml new file mode 100644 index 0000000..8d1ca6b --- /dev/null +++ b/app/src/main/res/anim/anim_in_right.xml @@ -0,0 +1,9 @@ + + + + diff --git a/app/src/main/res/anim/anim_out_left.xml b/app/src/main/res/anim/anim_out_left.xml new file mode 100644 index 0000000..2ba701e --- /dev/null +++ b/app/src/main/res/anim/anim_out_left.xml @@ -0,0 +1,9 @@ + + + + diff --git a/app/src/main/res/anim/anim_out_right.xml b/app/src/main/res/anim/anim_out_right.xml new file mode 100644 index 0000000..e462ded --- /dev/null +++ b/app/src/main/res/anim/anim_out_right.xml @@ -0,0 +1,9 @@ + + + + diff --git a/app/src/main/res/drawable-xhdpi/back.png b/app/src/main/res/drawable-xhdpi/back.png new file mode 100644 index 0000000000000000000000000000000000000000..cae70d1b8f1a8e2098a724ed64493e84a20a13ff GIT binary patch literal 225392 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 S?m=|`0000 + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/act_splash.xml b/app/src/main/res/layout/act_splash.xml new file mode 100644 index 0000000..acaa945 --- /dev/null +++ b/app/src/main/res/layout/act_splash.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_line.xml b/app/src/main/res/layout/include_line.xml new file mode 100644 index 0000000..645cb3f --- /dev/null +++ b/app/src/main/res/layout/include_line.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_tab_bar.xml b/app/src/main/res/layout/include_tab_bar.xml new file mode 100644 index 0000000..e4b9dfb --- /dev/null +++ b/app/src/main/res/layout/include_tab_bar.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/include_tool_bar.xml b/app/src/main/res/layout/include_tool_bar.xml new file mode 100644 index 0000000..313814b --- /dev/null +++ b/app/src/main/res/layout/include_tool_bar.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..cde69bcccec65160d92116f20ffce4fce0b5245c GIT binary patch literal 3418 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..efc028a636dd690a51db5a525cf781a5a7daba68 GIT binary patch literal 2555 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..3af2608a4492ef9ae63a77ec3305aedda89594cb GIT binary patch literal 6114 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..324e72cdd7480cb983fa1bcc7ce686e51ef87fe7 GIT binary patch literal 7718 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..9bec2e623103ac9713b00cad8502a057c1efda61 GIT binary patch literal 10056 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 ek+^GN3bv-?^>(QkVinb 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 + + + #E3383B + + #E3383B + + #E3383B + + + #999999 + #EEEEEE + #E3383B + #E6E3383B + #eeee4242 + #ffffff + #000000 + #767c82 + #282828 + #00000000 + #a3a3a3 + + + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..86b6c8d --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,174 @@ + + + 16dp + 16dp + + + 6sp + 10sp + 12sp + 14sp + 16sp + 18sp + 20sp + 22sp + 24sp + 26sp + 30sp + 32sp + 34sp + 38sp + 48sp + + 0dp + 0.1dp + 0.2dp + 0.4dp + 0.5dp + 1dp + 2dp + 3dp + 5dp + 6dp + 7dp + 8dp + 10dp + 11dp + 12dp + 13dp + 14dp + 15dp + 16dp + 18dp + 20dp + 22dp + 24dp + 25dp + 26dp + 28dp + 30dp + 32dp + 34dp + 35dp + 36dp + 38dp + 40dp + 42dp + 44dp + 46dp + 48dp + 50dp + 52dp + 53dp + 54dp + 55dp + 56dp + 59dp + 60dp + 62dp + 64dp + 65dp + 66dp + 68dp + 69dp + 70dp + 72dp + 74dp + 75dp + 78dp + 80dp + 82dp + 84dp + 85dp + 86dp + 88dp + 90dp + 94dp + 95dp + 96dp + 98dp + 100dp + 102dp + 103dp + 105dp + 106dp + 108dp + 110dp + 112dp + 114dp + 117dp + 120dp + 122dp + 124dp + 129dp + 130dp + 138dp + 150dp + 154dp + 156dp + 157dp + 158dp + 172dp + 175dp + 176dp + 180dp + 188dp + 200dp + 207dp + 218dp + 220dp + 230dp + 240dp + 250dp + 252dp + 274dp + 275dp + 280dp + 300dp + 350dp + + 1px + 8px + 20px + + @dimen/text_size_12 + 24dp + 24dp + 8dp + + + + 50dp + + + 50dp + 22dp + + + + + 65dp + + + 50dp + + + 38dp + + + 15dp + + + 16dp + + + 60dp + + + 57dp + + + 15dip + 20dip + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..459caa0 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Ytzh + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..9678078 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/test/java/com/qhclh/ytzh/ExampleUnitTest.java b/app/src/test/java/com/qhclh/ytzh/ExampleUnitTest.java new file mode 100644 index 0000000..1e0680d --- /dev/null +++ b/app/src/test/java/com/qhclh/ytzh/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.qhclh.ytzh; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() throws Exception { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..3fb806a --- /dev/null +++ b/build.gradle @@ -0,0 +1,23 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.2' + classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + jcenter() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..aac7c9b --- /dev/null +++ b/gradle.properties @@ -0,0 +1,17 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..13372aef5e24af05341d49695ee84e5f9b594659 GIT binary patch literal 53636 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ⅅ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 H-+%o-(+5aQ literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..b5f2530 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Thu Nov 23 10:54:26 CST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..9d82f78 --- /dev/null +++ b/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/jsonrpc/.gitignore b/jsonrpc/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/jsonrpc/.gitignore @@ -0,0 +1 @@ +/build diff --git a/jsonrpc/build.gradle b/jsonrpc/build.gradle new file mode 100644 index 0000000..d1a24d1 --- /dev/null +++ b/jsonrpc/build.gradle @@ -0,0 +1,27 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion 23 + buildToolsVersion '25.0.0' + defaultConfig { + minSdkVersion 15 + targetSdkVersion 23 + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + productFlavors { + } +} + +dependencies { + compile fileTree(include: ['*.jar'], dir: 'libs') + testCompile 'junit:junit:4.12' + compile 'com.android.support:appcompat-v7:23.3.0' + compile 'org.jbundle.util.osgi.wrapped:org.jbundle.util.osgi.wrapped.org.apache.http.client:4.1.2' +} diff --git a/jsonrpc/proguard-rules.pro b/jsonrpc/proguard-rules.pro new file mode 100644 index 0000000..45dc58a --- /dev/null +++ b/jsonrpc/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /opt/android-sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/jsonrpc/src/androidTest/java/org/forks/jsonrpc/ApplicationTest.java b/jsonrpc/src/androidTest/java/org/forks/jsonrpc/ApplicationTest.java new file mode 100644 index 0000000..5e36ac6 --- /dev/null +++ b/jsonrpc/src/androidTest/java/org/forks/jsonrpc/ApplicationTest.java @@ -0,0 +1,13 @@ +package org.forks.jsonrpc; + +import android.app.Application; +import android.test.ApplicationTestCase; + +/** + * Testing Fundamentals + */ +public class ApplicationTest extends ApplicationTestCase { + public ApplicationTest() { + super(Application.class); + } +} \ No newline at end of file diff --git a/jsonrpc/src/main/AndroidManifest.xml b/jsonrpc/src/main/AndroidManifest.xml new file mode 100644 index 0000000..b553aa1 --- /dev/null +++ b/jsonrpc/src/main/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/jsonrpc/src/main/java/org/forks/jsonrpc/DFDataTable.java b/jsonrpc/src/main/java/org/forks/jsonrpc/DFDataTable.java new file mode 100644 index 0000000..1d9147b --- /dev/null +++ b/jsonrpc/src/main/java/org/forks/jsonrpc/DFDataTable.java @@ -0,0 +1,38 @@ +package org.forks.jsonrpc; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public final class DFDataTable { + private Map mColumns; + private List mRows; + private RpcObject mSumRow; + + DFDataTable() { + this(new HashMap(), + new ArrayList(), null); + } + + DFDataTable(Map columns, List rows, + RpcObject sumRow) { + super(); + mColumns = columns; + mRows = rows; + mSumRow = sumRow; + } + + public Map getColumns() { + return mColumns; + } + + public List getRows() { + return mRows; + } + + public RpcObject getSumRow() { + return mSumRow; + } + +} diff --git a/jsonrpc/src/main/java/org/forks/jsonrpc/Helper.java b/jsonrpc/src/main/java/org/forks/jsonrpc/Helper.java new file mode 100644 index 0000000..fefb104 --- /dev/null +++ b/jsonrpc/src/main/java/org/forks/jsonrpc/Helper.java @@ -0,0 +1,76 @@ +package org.forks.jsonrpc; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONTokener; + +final class Helper { + static String getString(JSONObject obj, String name) + throws JsonRpcException { + try { + return obj.getString(name); + } catch (JSONException e) { + throw new JsonRpcException(e); + } + } + + static int getInt(JSONObject obj, String name) throws JsonRpcException { + try { + return obj.getInt(name); + } catch (JSONException e) { + throw new JsonRpcException(e); + } + } + + static JSONObject parseJsonObject(String json) throws JsonRpcException { + try { + return (JSONObject) new JSONTokener(json).nextValue(); + } catch (JSONException e) { + throw new JsonRpcException(e); + } + } + + static JSONArray getJsonArray(JSONObject obj, String name) + throws JsonRpcException { + try { + return obj.getJSONArray(name); + } catch (JSONException e) { + throw new JsonRpcException(e); + } + } + + public static JSONArray getJsonArray(JSONArray array, int i) + throws JsonRpcException { + try { + return array.getJSONArray(i); + } catch (JSONException e) { + throw new JsonRpcException(e); + } + } + + static JSONObject getJsonObject(JSONArray arr, int idx) + throws JsonRpcException { + try { + return arr.getJSONObject(idx); + } catch (JSONException e) { + throw new JsonRpcException(e); + } + } + + static Object get(JSONObject obj, String name) throws JsonRpcException { + try { + return obj.get(name); + } catch (JSONException e) { + throw new JsonRpcException(e); + } + } + + public static Object get(JSONArray array, int idx) throws JsonRpcException { + try { + return array.get(idx); + } catch (JSONException e) { + throw new JsonRpcException(e); + } + } +} diff --git a/jsonrpc/src/main/java/org/forks/jsonrpc/HttpJsonRpcClient.java b/jsonrpc/src/main/java/org/forks/jsonrpc/HttpJsonRpcClient.java new file mode 100644 index 0000000..f92dc5a --- /dev/null +++ b/jsonrpc/src/main/java/org/forks/jsonrpc/HttpJsonRpcClient.java @@ -0,0 +1,84 @@ +package org.forks.jsonrpc; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpVersion; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.CookieStore; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.BasicCookieStore; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.params.BasicHttpParams; +import org.apache.http.params.HttpConnectionParams; +import org.apache.http.params.HttpParams; +import org.apache.http.params.HttpProtocolParams; +import org.apache.http.util.EntityUtils; + +public final class HttpJsonRpcClient extends JsonRpcClient { + + private final String mRequestUri; + final static CookieStore sCookieStore = new BasicCookieStore(); + private static DefaultHttpClient sHttpClient; + private static String sAppName = "[android] "; + + static { + HttpParams params = new BasicHttpParams(); + HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); + HttpConnectionParams.setSoTimeout(params, 45 * 1000); + sHttpClient = new DefaultHttpClient(params); + sHttpClient.setCookieStore(sCookieStore); + } + + public HttpJsonRpcClient(String requestUri, String method) { + super(method); + mRequestUri = requestUri; + } + + @Override + protected String doRequest(String json) throws JsonRpcException { + HttpPost request = new HttpPost(mRequestUri); + request.setEntity(newStringEntity(json)); + request.setHeader("User-Agent", sAppName); + HttpResponse response = getResponse(request); + return getResponseString(response); + } + + static void sSetClientAppName(String appName) { + sAppName = "[android] " + appName; + } + + private static String getResponseString(HttpResponse response) + throws JsonRpcException { + HttpEntity back = response.getEntity(); + try { + return EntityUtils.toString(back); + } catch (IOException e) { + throw new JsonRpcException(e); + } + } + + private static StringEntity newStringEntity(String json) + throws JsonRpcException { + try { + return new StringEntity(json, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new JsonRpcException(e); + } + } + + private static HttpResponse getResponse(HttpPost request) + throws JsonRpcException { + try { + return sHttpClient.execute(request); + } catch (ClientProtocolException e) { + throw new JsonRpcException(e); + } catch (IOException e) { + throw new JsonRpcException(e); + } + } + +} diff --git a/jsonrpc/src/main/java/org/forks/jsonrpc/InvalidPropertyValueException.java b/jsonrpc/src/main/java/org/forks/jsonrpc/InvalidPropertyValueException.java new file mode 100644 index 0000000..08b5911 --- /dev/null +++ b/jsonrpc/src/main/java/org/forks/jsonrpc/InvalidPropertyValueException.java @@ -0,0 +1,23 @@ +package org.forks.jsonrpc; + +@SuppressWarnings("serial") +public final class InvalidPropertyValueException extends + JsonRpcRuntimeException { + + public InvalidPropertyValueException() { + } + + public InvalidPropertyValueException(String detailMessage) { + super(detailMessage); + } + + public InvalidPropertyValueException(Throwable throwable) { + super(throwable); + } + + public InvalidPropertyValueException(String detailMessage, + Throwable throwable) { + super(detailMessage, throwable); + } + +} diff --git a/jsonrpc/src/main/java/org/forks/jsonrpc/IterHelper.java b/jsonrpc/src/main/java/org/forks/jsonrpc/IterHelper.java new file mode 100644 index 0000000..fa07168 --- /dev/null +++ b/jsonrpc/src/main/java/org/forks/jsonrpc/IterHelper.java @@ -0,0 +1,69 @@ +package org.forks.jsonrpc; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.NoSuchElementException; + +final class IterHelper { + private IterHelper() { + } + + public static ArrayList toList(Iterable iter) { + ArrayList result = new ArrayList(); + for (T item : iter) { + result.add(item); + } + return result; + } + + public static ArrayList toList(T... items) { + ArrayList result = new ArrayList(items.length); + for (T item : items) { + result.add(item); + } + return result; + } + + public static int count(Iterable iter) { + int result = 0; + for (@SuppressWarnings("unused") + T item : iter) { + result++; + } + return result; + } + + public static Iterable skip(final int n, final Iterable iter) { + return new Iterable() { + + public Iterator iterator() { + + return new Iterator() { + + Iterator mIter = iter.iterator(); + { + try { + for (int i = 0; i < n; i++) { + mIter.next(); + } + } catch (NoSuchElementException e) { + } + } + + public boolean hasNext() { + return mIter.hasNext(); + } + + public T next() { + return mIter.next(); + } + + public void remove() { + mIter.remove(); + } + }; + } + }; + } + +} diff --git a/jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcClient.java b/jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcClient.java new file mode 100644 index 0000000..0504579 --- /dev/null +++ b/jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcClient.java @@ -0,0 +1,93 @@ +package org.forks.jsonrpc; + +import org.json.JSONException; +import org.json.JSONObject; + +import android.util.Log; + +public abstract class JsonRpcClient { + private final String mMethod; + private final static String LOG_TAG = "JsonRpcClient"; + private long requestTime; + + protected JsonRpcClient(String method) { + mMethod = method; + } + + public final JsonRpcResult call(Object... args) throws JsonRpcException { + try { + JSONObject req = newRequest(args); + JSONObject res = request(req); + checkResponseId(req, res); + checkError(res); + return new JsonRpcResult(res.get("result")); + } catch (JSONException e) { + Log.w(LOG_TAG, "", e); + throw new JsonRpcException(e); + } + catch (JsonRpcException e){ + throw e; + } + catch (Exception e){ + throw new JsonRpcException(JsonRpcException.NETWORK_ERROR_CODE,e.getMessage()); + } + } + + private static void checkResponseId(JSONObject req, JSONObject res) + throws JSONException, JsonRpcException { + int reqId = req.getInt("id"); + int resId = res.getInt("id"); + if (reqId != resId) { + throw new JsonRpcException(String.format( + "response id (%d) does not match to request id (%d)", + reqId, resId)); + } + } + + private static void checkError(JSONObject res) throws JSONException, + JsonRpcException { + JSONObject err = res.optJSONObject("error"); + if (err != null) { + int code = err.getInt("code"); + String msg = err.getString("message"); + String trace = err.optString("detail"); + throw new JsonRpcException(code, msg, trace); + } + } + + private JSONObject request(JSONObject req) throws JsonRpcException { + String json = req.toString(); + log_request(json); + String jsonBack = doRequest(json); + log_response(jsonBack); + return Helper.parseJsonObject(jsonBack); + } + + private void log_response(String jsonBack) { + long duration = System.currentTimeMillis() - requestTime; + Log.i(LOG_TAG, String.format("get response using %d ms, response: %s", + duration, jsonBack)); + } + + private void log_request(String reqJson) { + requestTime = System.currentTimeMillis(); + Log.v(LOG_TAG, "start request: " + reqJson); + } + + protected abstract String doRequest(String json) throws JsonRpcException; + + private JSONObject newRequest(Object[] args) throws JSONException { + Object params = RpcTypeParser.toJson(args); + return newRequest(params); + } + + private static int mIdSeed; + + private JSONObject newRequest(Object params) throws JSONException { + JSONObject result = new JSONObject(); + result.put("id", mIdSeed++); + result.put("method", mMethod); + result.put("params", params); + return result; + } +} diff --git a/jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcException.java b/jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcException.java new file mode 100644 index 0000000..7643922 --- /dev/null +++ b/jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcException.java @@ -0,0 +1,51 @@ +package org.forks.jsonrpc; + +public final class JsonRpcException extends Exception { + public boolean isNetworkError(){ + return mCode == NETWORK_ERROR_CODE; + } + static int NETWORK_ERROR_CODE = -1; + + private static final long serialVersionUID = -3409287525569584913L; + private int mCode = 0; + private String mTrace; + + public JsonRpcException() { + super(); + } + + public JsonRpcException(String message, Throwable throwable) { + super(message, throwable); + } + + public JsonRpcException(String message) { + super(message); + } + + public JsonRpcException(Throwable throwable) { + super(throwable); + } + + public JsonRpcException(int code, String message) { + this(code, message, null); + } + + public JsonRpcException(int code, String message, String trace) { + super(message); + mCode = code; + mTrace = trace; + } + + public int getCode() { + return mCode; + } + + public boolean is5xxError() { + return mCode >= 500 && mCode < 600; + } + + public String getDetailMessage() { + return mTrace; + } + +} diff --git a/jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcResult.java b/jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcResult.java new file mode 100644 index 0000000..47a4d00 --- /dev/null +++ b/jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcResult.java @@ -0,0 +1,179 @@ +package org.forks.jsonrpc; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import org.json.JSONObject; + +public final class JsonRpcResult { + private final Object mResult; + + JsonRpcResult(Object result) { + super(); + mResult = result; + } + + public Object getRaw() { + return mResult; + } + + public Integer getInt() { + return (Integer) RpcTypeParser.sInt.fromJson(mResult); + } + + public String getString() { + return (String) RpcTypeParser.sString.fromJson(mResult); + } + + public Short getShort() { + return (Short) RpcTypeParser.sShort.fromJson(mResult); + } + + public Long getLong() { + return (Long) RpcTypeParser.sLong.fromJson(mResult); + } + + public Short getByte() { + return (Short) RpcTypeParser.sByte.fromJson(mResult); + } + + public Double getDouble() { + return (Double) RpcTypeParser.sDouble.fromJson(mResult); + } + + public Boolean getBoolean() { + return (Boolean) RpcTypeParser.sBoolean.fromJson(mResult); + } + + public BigDecimal getDecimal() { + return (BigDecimal) RpcTypeParser.sDecimal.fromJson(mResult); + } + + public BigDecimal getMoney() { + return getDecimal(); + } + + public boolean isNull() { + return mResult == JSONObject.NULL; + } + + public Date getDate() { + return (Date) RpcTypeParser.sDate.fromJson(mResult); + } + + public RpcObject getRpcObject(String objPath) throws JsonRpcException { + return (RpcObject) RpcTypeParser.fromJson(mResult, objPath); + } + + public DFDataTable getTable() { + return (DFDataTable) RpcTypeParser.sTable.fromJson(mResult); + } + + public ManyList getManyList(String objPath) throws JsonRpcException { + return getByType("onetomany(" + objPath + ")"); + } + + public List getIntList() throws JsonRpcException { + return getByType("[int]"); + } + + public List getShortList() throws JsonRpcException { + return getByType("[short]"); + } + + public List getByteList() throws JsonRpcException { + return getByType("[byte]"); + } + + public List getLongList() throws JsonRpcException { + return getByType("[long]"); + } + + public List getBooleanList() throws JsonRpcException { + return getByType("[bool]"); + } + + public List getDoubleList() throws JsonRpcException { + return getByType("[double]"); + } + + public List getStringList() throws JsonRpcException { + return getByType("[str]"); + } + + public List getDateList() throws JsonRpcException { + return getByType("[datetime]"); + } + + public List getDecimalList() throws JsonRpcException { + return getByType("[decimal]"); + } + + public List getMoneyList() throws JsonRpcException { + return getByType("[money]"); + } + + public List getRpcObjectList(String objPath) + throws JsonRpcException { + return getByType("[" + objPath + "]"); + } + + public Map getIntMap() throws JsonRpcException { + return getByType("{str:int}"); + } + + public Map getByteMap() throws JsonRpcException { + return getByType("{str:byte}"); + } + + public Map getShortMap() throws JsonRpcException { + return getByType("{str:short}"); + } + + public Map getLongMap() throws JsonRpcException { + return getByType("{str:long}"); + } + + public Map getBooleanMap() throws JsonRpcException { + return getByType("{str:bool}"); + } + + public Map getDoubleMap() throws JsonRpcException { + return getByType("{str:double}"); + } + + public Map getStringMap() throws JsonRpcException { + return getByType("{str:str}"); + } + + public Map getDateMap() throws JsonRpcException { + return getByType("{str:datetime}"); + } + + public Map getDecimalMap() throws JsonRpcException { + return getByType("{str:decimal}"); + } + + public Map getMoneyMap() throws JsonRpcException { + return getByType("{str:money}"); + } + + public Map getRpcObjectMap(String objPath) + throws JsonRpcException { + return getByType("{str:" + objPath + "}"); + } + + private T getByType(String rpcType) throws JsonRpcException { + RpcType type = RpcTypeParser.parse(rpcType); + return (T) type.fromJson(mResult); + } + + JSONObject getJsonObject() { + if (isNull()) { + return null; + } + return (JSONObject) mResult; + } +} diff --git a/jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcRuntimeException.java b/jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcRuntimeException.java new file mode 100644 index 0000000..541673b --- /dev/null +++ b/jsonrpc/src/main/java/org/forks/jsonrpc/JsonRpcRuntimeException.java @@ -0,0 +1,22 @@ +package org.forks.jsonrpc; + +public class JsonRpcRuntimeException extends RuntimeException { + + private static final long serialVersionUID = 4017156582402768366L; + + public JsonRpcRuntimeException() { + } + + public JsonRpcRuntimeException(String detailMessage) { + super(detailMessage); + } + + public JsonRpcRuntimeException(Throwable throwable) { + super(throwable); + } + + public JsonRpcRuntimeException(String detailMessage, Throwable throwable) { + super(detailMessage, throwable); + } + +} diff --git a/jsonrpc/src/main/java/org/forks/jsonrpc/ManyList.java b/jsonrpc/src/main/java/org/forks/jsonrpc/ManyList.java new file mode 100644 index 0000000..6863741 --- /dev/null +++ b/jsonrpc/src/main/java/org/forks/jsonrpc/ManyList.java @@ -0,0 +1,199 @@ +package org.forks.jsonrpc; + +import java.util.ArrayList; +import java.util.Collection; + +import android.util.Pair; + +import org.json.JSONException; +import org.json.JSONObject; + +@SuppressWarnings("serial") +public final class ManyList extends ArrayList { + private final RpcObjectMeta mItemMeta; + private final ArrayList mNewItems = new ArrayList(); + private final ArrayList mDeletedItems = new ArrayList(); + + public ManyList(RpcObjectMeta itemMeta) { + mItemMeta = itemMeta; + } + + public static ManyList create(String itemObjectPath) + throws JsonRpcException { + return new ManyList(RpcObjectMeta.get(itemObjectPath)); + } + + @Override + public void add(int index, RpcObject object) { + checkMetaType(object); + addNew(object); + super.add(index, object); + } + + @Override + public boolean add(RpcObject object) { + checkMetaType(object); + addNew(object); + return super.add(object); + } + + @Override + public boolean addAll(Collection collection) { + checkMetaTypes(collection); + addNewObjects(collection); + return super.addAll(collection); + } + + @Override + public boolean addAll(int location, + Collection collection) { + checkMetaTypes(collection); + addNewObjects(collection); + return super.addAll(location, collection); + } + + @Override + public void clear() { + for (RpcObject item : this) { + addDeleted(item); + } + super.clear(); + } + + @Override + public RpcObject remove(int index) { + RpcObject result = super.remove(index); + addDeleted(result); + return result; + } + + @Override + protected void removeRange(int fromIndex, int toIndex) { + for (int i = fromIndex; i < toIndex; i++) { + addDeleted(get(i)); + } + super.removeRange(fromIndex, toIndex); + } + + @Override + public boolean removeAll(Collection collection) { + // it is too complex to test modify track, and rarely used + throw new UnsupportedOperationException(); + } + + @Override + public boolean retainAll(Collection collection) { + // it is too complex to test modify track, and rarely used + throw new UnsupportedOperationException(); + } + + @Override + public RpcObject set(int index, RpcObject object) { + RpcObject result = super.set(index, object); + addDeleted(result); + addNew(object); + return result; + } + + private void addNewObjects(Collection collection) { + for (RpcObject item : collection) { + addNew(item); + } + } + + private void addNew(RpcObject object) { + if (!mDeletedItems.remove(object)) { + mNewItems.add(object); + } + } + + private void addDeleted(RpcObject object) { + if (!mNewItems.remove(object)) { + mDeletedItems.add(object); + } + } + + JSONObject toJson() throws JSONException { + JSONObject result = new JSONObject(); + Pair, Collection> changedUnChanged = getChangedUnChangedItems(); + putArrayField(result, "_data", changedUnChanged.second); + putArrayField(result, "_new", getNewItems()); + putArrayField(result, "_deleted", getDeletedItems()); + putArrayField(result, "_modified", changedUnChanged.first); + + return result; + } + + private static void putArrayField(JSONObject result, String fieldName, + Collection list) throws JSONException { + if (!list.isEmpty()) { + result.put(fieldName, RpcTypeParser.toJson(list)); + } + } + + private void checkMetaTypes(Collection collection) { + if (!RpcFacade.sDebug) { + return; + } + + for (RpcObject rpcObject : collection) { + checkMetaType(rpcObject); + } + } + + private void checkMetaType(RpcObject object) { + if (!RpcFacade.sDebug) { + return; + } + + RpcObjectMeta objMeta = object.getMeta(); + if (objMeta != mItemMeta) { + throwMetaMisMatchError(objMeta); + } + } + + private void throwMetaMisMatchError(RpcObjectMeta objMeta) { + String msg = "RpcObject %s can not add to %s ManyList"; + msg = String.format(msg, objMeta.getName(), mItemMeta.getName()); + throw new IllegalArgumentException(msg); + } + + Collection getNewItems() { + return mNewItems; + } + + Collection getDeletedItems() { + return mDeletedItems; + } + + Pair, Collection> + getChangedUnChangedItems() { + ArrayList changed = new ArrayList(); + ArrayList unchanged = new ArrayList(); + + for (RpcObject item : this) { + if (!isNewObject(item)) { + if (!item.isModified()) { + unchanged.add(item); + } else { + changed.add(item); + } + } + } + + return new Pair, Collection>(changed, + unchanged); + } + + void acceptChanges() { + mNewItems.clear(); + mDeletedItems.clear(); + for (RpcObject obj : this) { + obj.acceptChanges(); + } + } + + private boolean isNewObject(RpcObject item) { + return mNewItems.contains(item); + } +} diff --git a/jsonrpc/src/main/java/org/forks/jsonrpc/NamedValue.java b/jsonrpc/src/main/java/org/forks/jsonrpc/NamedValue.java new file mode 100644 index 0000000..123ce44 --- /dev/null +++ b/jsonrpc/src/main/java/org/forks/jsonrpc/NamedValue.java @@ -0,0 +1,66 @@ +package org.forks.jsonrpc; + +import java.util.HashMap; + +import android.util.SparseArray; + +public final class NamedValue { + + private final short mValue; + private final String mName; + + private NamedValue(short value, String name) { + super(); + mValue = value; + mName = name; + } + + public short getValue() { + return mValue; + } + + public String getName() { + return mName; + } + + @Override + public String toString() { + return getName(); + } + + private static final HashMap> sInstancePool = new HashMap>(); + + public static synchronized NamedValue create(String idtype, short val) { + SparseArray array = sInstancePool.get(idtype); + if (array == null) { + array = createArray(idtype); + sInstancePool.put(idtype, array); + } + NamedValue result = array.get(val); + if (result == null) { + result = new NamedValue(val, Short.toString(val)); + array.put(val, result); + } + return result; + } + + private static SparseArray createArray(String idtype) { + try { + SparseArray pairs = NamedValueMeta.get(idtype); + SparseArray result = new SparseArray( + pairs.size()); + for (int i = 0; i < pairs.size(); i++) { + int key = pairs.keyAt(i); + NamedValue v = new NamedValue((short) key, pairs.valueAt(i)); + result.append(key, v); + } + return result; + } catch (JsonRpcException e) { + throw new JsonRpcRuntimeException(e); + } + } + + static void reset() { + sInstancePool.clear(); + } +} diff --git a/jsonrpc/src/main/java/org/forks/jsonrpc/NamedValueMeta.java b/jsonrpc/src/main/java/org/forks/jsonrpc/NamedValueMeta.java new file mode 100644 index 0000000..f3bdb22 --- /dev/null +++ b/jsonrpc/src/main/java/org/forks/jsonrpc/NamedValueMeta.java @@ -0,0 +1,84 @@ +package org.forks.jsonrpc; + +import java.util.HashMap; +import java.util.List; + +import android.util.SparseArray; + +import static org.forks.jsonrpc.RpcFacade.toFullErtPathByPrefixedErt; + +public final class NamedValueMeta { + private static final String NAMED_VALUE_PAIR = "/sbin/NamedValuePair"; + private static final String METHOD = "/sbin/NamedValue/GetDefinition"; + private static final HashMap> sCache = new HashMap>(); + + public static final class Pair { + public final int Value; + public final String Name; + + Pair(int value, String name) { + super(); + Value = value; + Name = name; + } + } + + public static final SparseArray get(String idType) + throws JsonRpcException { + synchronized (sCache) { + SparseArray result = sCache.get(idType); + if (result != null) { + return result; + } + } + + SparseArray result = doGet(idType); + synchronized (sCache) { + sCache.put(idType, result); + } + return result; + } + + private static SparseArray doGet(String idType) + throws JsonRpcException { + String methodPath = toFullErtPathByPrefixedErt(idType, METHOD); + String rpcPath = toFullErtPathByPrefixedErt(idType, NAMED_VALUE_PAIR); + + JsonRpcResult res = RpcFacade.rpcCall(methodPath, idType); + List pairs = res.getRpcObjectList(rpcPath); + return toNamedValueMap(pairs); + } + + private static SparseArray toNamedValueMap(List pairs) { + SparseArray result = new SparseArray(pairs.size()); + for (RpcObject pair : pairs) { + Integer key = pair.getInt("Value"); + String value = pair.getString("Name"); + result.put(key, value); + } + return result; + } + + static void reset() { + sCache.clear(); + } + + static void register(String idType, SparseArray names) { + sCache.put(idType, names); + } + + public static String toName(Short val, String namedValueType) + throws JsonRpcException { + if (val == null) { + return ""; + } + String idType = RpcTypeParser.getNamedValueTidType(namedValueType); + SparseArray names = get(idType); + String result = names.get(val); + if (result == null) { + result = val.toString(); + } + return result; + } + +} diff --git a/jsonrpc/src/main/java/org/forks/jsonrpc/NoSuchRpcPropertyException.java b/jsonrpc/src/main/java/org/forks/jsonrpc/NoSuchRpcPropertyException.java new file mode 100644 index 0000000..1de5a31 --- /dev/null +++ b/jsonrpc/src/main/java/org/forks/jsonrpc/NoSuchRpcPropertyException.java @@ -0,0 +1,22 @@ +package org.forks.jsonrpc; + +@SuppressWarnings("serial") +public final class NoSuchRpcPropertyException extends JsonRpcRuntimeException { + + NoSuchRpcPropertyException() { + super(); + } + + NoSuchRpcPropertyException(String detailMessage, Throwable throwable) { + super(detailMessage, throwable); + } + + NoSuchRpcPropertyException(String detailMessage) { + super(detailMessage); + } + + NoSuchRpcPropertyException(Throwable throwable) { + super(throwable); + } + +} diff --git a/jsonrpc/src/main/java/org/forks/jsonrpc/RpcFacade.java b/jsonrpc/src/main/java/org/forks/jsonrpc/RpcFacade.java new file mode 100644 index 0000000..d35cc88 --- /dev/null +++ b/jsonrpc/src/main/java/org/forks/jsonrpc/RpcFacade.java @@ -0,0 +1,269 @@ +package org.forks.jsonrpc; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.os.Build; +import android.os.Handler; +import android.preference.PreferenceManager; +import android.util.Log; +import android.webkit.CookieManager; +import android.webkit.CookieSyncManager; +import android.webkit.WebView; + +import org.apache.http.cookie.Cookie; + +public final class RpcFacade { + private static final PreferenceMonitor PREFERENCE_MONITOR = new PreferenceMonitor(); + public static final String SERVER_URI_PREFKEY = "ServerUri"; + private static final String DEBUG_PREFKEY = "Debug"; + private static final String TAG = "RpcFacade"; + private static final String REST_URI = ""; + private static String sRestUri = REST_URI; + private static Context sContext; + private static String sUsername = ""; + private static String sPasswd; + private static final String LOGOUT_METHOD = "/MainSystem/MainSystem/Auth/Logout"; + private static final String LOGIN_METHOD = "/MainSystem/MainSystem/Auth/Login"; + static boolean sDebug = true; + + // keep reference + @SuppressWarnings("unused") + private static KeepSession sKeepSession; + + private RpcFacade() { + } + + public static void syncCookie(WebView webView){ + CookieSyncManager.createInstance(webView.getContext()); + + CookieManager cookieManager = CookieManager.getInstance(); + cookieManager.setAcceptCookie(true); + cookieManager.removeAllCookie(); + for(Cookie cookie:HttpJsonRpcClient.sCookieStore.getCookies()){ + if(cookie.getName().equals("EasyAuth")) { + String cookieString = cookie.getName() + "=" + cookie.getValue() + "; path=" + cookie.getPath(); + cookieManager.setCookie(RpcFacade.getServerUri(), cookieString); + } + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + cookieManager.flush(); + } + + CookieSyncManager.getInstance().sync(); + + } + + public static void init(Context context, String appName) { + Context appContext = context.getApplicationContext(); + if (sContext == null) { + Log.v(TAG, "init RpcFacade, appname: " + appName); + sContext = appContext; + sKeepSession = new KeepSession(); + HttpJsonRpcClient.sSetClientAppName(appName); + initPreference(); + } else if (sContext != appContext) { + Log.v(TAG, "invalid reinit RpcFacade"); + String message = "RpcFacade is inited, can not init again"; + throw new JsonRpcRuntimeException(message); + } + } + + public static void setServerUri(String uri){ + SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(sContext); + SharedPreferences.Editor editor = prefs.edit(); + editor.putString(SERVER_URI_PREFKEY,uri); + editor.commit(); + } + + + public static boolean isInited() { + return sContext != null; + } + + private static void initPreference() { + Log.d(TAG, + "restore settings from preference, monitor preference change"); + SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(sContext); + restoreDebugFromPref(prefs); + restoreServerUriFromPref(prefs); + + // OnSharedPreferenceChangeListener is a weeked event, + // we must keep the event listener instance ourself + prefs.registerOnSharedPreferenceChangeListener(PREFERENCE_MONITOR); + } + + public static JsonRpcResult rpcCall(String method, Object... args) + throws JsonRpcException { + try { + return doRpcCall(method, args); + } catch (JsonRpcException e) { + if (e.getCode() == 401 && isLogedIn()) { + autoLogin(); + return doRpcCall(method, args); + } + throw e; + } + } + + public static String getUsername() { + return sUsername; + } + + public static void login(String user, String passwd) + throws JsonRpcException { + Log.i(TAG, "Start login: " + user); + callLogin(user, passwd); + sUsername = user; + sPasswd = passwd; + } + + public static void restoreLogined(String username,String password){ + sUsername = username; + sPasswd = password; + } + + public static void logout() { + try { + if (isLogedIn()) { + Log.i(TAG, "logout user: " + sUsername); + sUsername = ""; + doRpcCall(LOGOUT_METHOD); + } + } catch (JsonRpcException e) { + } + } + + private static void autoLogin() throws JsonRpcException { + String user = sUsername; + String pwd = sPasswd; + if (user.length() > 0) { + callLogin(user, pwd); + } + } + + private static JsonRpcResult doRpcCall(String method, Object... args) + throws JsonRpcException { + JsonRpcClient client = new HttpJsonRpcClient(getRestUri(method), method); + return client.call(args); + } + + private static void callLogin(String user, String passwd) + throws JsonRpcException { + doRpcCall(LOGIN_METHOD, user, passwd); + } + + private static String getRestUri(String method) { + StringBuilder sb = new StringBuilder(); + appendServerUri(sb); + + String subSystem = getSystem(method); + if (!IsMainSystem(subSystem)) { + appendSubSystem(sb, subSystem); + } + + sb.append("Rest.aspx"); + return sb.toString(); + } + + private static boolean IsMainSystem(String subSystem) { + return subSystem.equals("MainSystem"); + } + + private static void appendSubSystem(StringBuilder sb, String subSystem) { + sb.append("O/"); + sb.append(subSystem); + sb.append('/'); + } + + private static void appendServerUri(StringBuilder sb) { + String serverUri = getServerUri(); + if (serverUri.charAt(serverUri.length() - 1) != '/') { + sb.append('/'); + } + sb.append(serverUri); + } + + public static String getServerUri() { + return sRestUri; + } + + static String getSystem(String method) { + int endIdx = method.indexOf('/', 1); + return method.substring(1, endIdx); + } + + public static String toFullErtPathByPrefixedErt(String objPath, + String subMethodPath) { + String subSystem = getSystem(objPath); + return "/" + subSystem + subMethodPath; + } + + public static boolean isLogedIn() { + return sUsername.length() > 0; + } + + private static void restoreServerUriFromPref(SharedPreferences pref) { + sRestUri = pref.getString(SERVER_URI_PREFKEY, REST_URI); + Log.d(TAG, "get serverUri from preference: " + sRestUri); + } + + private static void restoreDebugFromPref(SharedPreferences pref) { + sDebug = pref.getBoolean(DEBUG_PREFKEY, true); + Log.d(TAG, "get debug mode from preference: " + sDebug); + } + + private static class KeepSession implements Runnable { + private static Handler handler; + + public KeepSession() { + if (handler != null) { + throw new RuntimeException("More than one instance?"); + } + handler = new Handler(); + startAgain(); + } + + public void run() { + if (isLogedIn()) { + Log.i(TAG, "connecting to server to maintain session"); + try { + heartBeat(); + } catch (Exception e) { + Log.w(TAG, e.toString()); + } + } else { + Log.i(TAG, "no need to connect server, not logged in"); + } + startAgain(); + } + + private static void heartBeat() throws JsonRpcException { + // use auto login, because the cell phone maybe just awake after + // sleep, and server is kick the user out because of not activity + // in 2 minutes. + rpcCall("/MainSystem/MainSystem/Auth/Ping"); + } + + private void startAgain() { + handler.postDelayed(this, 60 * 1000); + } + } + + private static final class PreferenceMonitor implements + OnSharedPreferenceChangeListener { + + public void onSharedPreferenceChanged( + SharedPreferences sharedPreferences, String key) { + Log.d(TAG, "preference changed, key: " + key); + if (key.equals(DEBUG_PREFKEY)) { + restoreDebugFromPref(sharedPreferences); + } else if (key.equals(SERVER_URI_PREFKEY)) { + restoreServerUriFromPref(sharedPreferences); + } + } + + } +} diff --git a/jsonrpc/src/main/java/org/forks/jsonrpc/RpcObject.java b/jsonrpc/src/main/java/org/forks/jsonrpc/RpcObject.java new file mode 100644 index 0000000..4c5e8d5 --- /dev/null +++ b/jsonrpc/src/main/java/org/forks/jsonrpc/RpcObject.java @@ -0,0 +1,386 @@ +package org.forks.jsonrpc; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +@SuppressWarnings("serial") +public final class RpcObject extends HashMap { + private final RpcObjectMeta mMeta; + private HashMap mBackup; + + RpcObject(RpcObjectMeta meta) throws JsonRpcException { + super(); + + mMeta = meta; + initValueStore(mMeta.getProps()); + acceptChanges(); + } + + public final static RpcObject create(String objPath) + throws JsonRpcException { + return new RpcObject(RpcObjectMeta.get(objPath)); + } + + public RpcObjectMeta getMeta() { + return mMeta; + } + + public Short getByte(String propName) { + return (Short) get(propName, RpcTypeParser.BYTE); + } + + public void setByte(String propName, Short value) { + set(propName, value, RpcTypeParser.BYTE); + } + + public Integer getInt(String propName) { + return (Integer) get(propName, RpcTypeParser.INT); + } + + public void setInt(String propName, Integer value) { + set(propName, value, RpcTypeParser.INT); + } + + public Short getShort(String propName) { + return (Short) get(propName, RpcTypeParser.SHORT); + } + + public void setShort(String propName, Short value) { + set(propName, value, RpcTypeParser.SHORT); + } + + public Long getLong(String propName) { + return (Long) get(propName, RpcTypeParser.LONG); + } + + public void setLong(String propName, Long value) { + set(propName, value, RpcTypeParser.LONG); + } + + public Double getDouble(String propName) { + return (Double) get(propName, RpcTypeParser.DOUBLE); + } + + public void setDouble(String propName, Double value) { + set(propName, value, RpcTypeParser.DOUBLE); + } + + public BigDecimal getDecimal(String propName) { + return (BigDecimal) get(propName, RpcTypeParser.DECIMAL); + } + + public void setDecimal(String propName, BigDecimal value) { + set(propName, value, RpcTypeParser.DECIMAL); + } + + public BigDecimal getMoney(String propName) { + return (BigDecimal) get(propName, RpcTypeParser.MONEY); + } + + public void setMoney(String propName, BigDecimal value) { + set(propName, value, RpcTypeParser.MONEY); + } + + public Date getDate(String propName) { + return (Date) get(propName, RpcTypeParser.DATE); + } + + public void setDate(String propName, Date value) { + set(propName, value, RpcTypeParser.DATE); + } + + public String getString(String propName) { + return (String) get(propName, RpcTypeParser.STRING); + } + + public String getGuid(String propName){ + return (String)get(propName,RpcTypeParser.GUID); + } + + public void setString(String propName, String value) { + set(propName, value, RpcTypeParser.STRING); + } + + public Integer getLookupValue(String propName) { + return (Integer) get(propName, RpcTypeParser.LOOKUPVALUE); + } + + public void setLookupValue(String propName, Integer value) { + set(propName, value, RpcTypeParser.LOOKUPVALUE); + } + + public NamedValue getNamedValue(String propName) { + checkNamedValueProp(propName); + return (NamedValue) get(propName); + } + + public void setNamedValue(String propName, Short value) { + NamedValue val = toNamedValue(propName, value); + setNamedValue(propName, val); + } + + private NamedValue toNamedValue(String propName, Short value) { + if (value == null) { + return null; + } + RpcPropertyMeta prop = getPropertyMeta(propName); + String idtype = RpcTypeParser.getNamedValueTidType(prop.getType()); + return NamedValue.create(idtype, value); + } + + public void setNamedValue(String propName, NamedValue value) { + checkNamedValueProp(propName); + put(propName, value); + } + + public Long getEntityKey(String propName) { + return (Long) get(propName, RpcTypeParser.ENTITYKEY); + } + + public void setEntityKey(String propName, Long value) { + set(propName, value, RpcTypeParser.ENTITYKEY); + } + + private void initValueStore(Map props) + throws JsonRpcException { + for (RpcPropertyMeta prop : props.values()) { + put(prop.getName(), createDefaultValue(prop)); + } + } + + private static Object createDefaultValue(RpcPropertyMeta prop) + throws JsonRpcException { + if (RpcTypeParser.isManyList(prop.getType())) { + return createManyList(prop); + } else if (RpcTypeParser.isList(prop.getType())) { + return new ArrayList(); + } else if (RpcTypeParser.isMap(prop.getType())) { + return new HashMap(); + } + return prop.getDefaultValue(); + } + + private static ManyList createManyList(RpcPropertyMeta prop) + throws JsonRpcException { + return ManyList + .create(RpcTypeParser.getManyListItemType(prop.getType())); + } + + private void set(String propName, Object value, String type) { + isPropDefined(propName, type); + put(propName, value); + } + + private Object get(String propName, String type) { + isPropDefined(propName, type); + return get(propName); + } + + private void isPropDefined(String propName, String type) { + if (RpcFacade.sDebug) { + RpcPropertyMeta prop = getPropertyMeta(propName); + checkPropertyType(type, prop); + } + } + + private RpcPropertyMeta getPropertyMeta(String propName) { + RpcPropertyMeta prop = mMeta.getProps().get(propName); + if (prop == null) { + throw new NoSuchRpcPropertyException(propName); + } + return prop; + } + + public Boolean getBoolean(String propName) { + return (Boolean) get(propName, RpcTypeParser.BOOL); + } + + public void setBoolean(String propName, Boolean value) { + set(propName, value, RpcTypeParser.BOOL); + } + + public ManyList getManyList(String propName) { + if (RpcFacade.sDebug) { + checkManyListProp(propName); + } + return (ManyList) get(propName); + } + + public List getList(String propName) { + if (RpcFacade.sDebug) { + checkListProp(propName); + } + return (List) get(propName); + } + + public Map getMap(String propName) { + if (RpcFacade.sDebug) { + checkMapProp(propName); + } + return (Map) get(propName); + } + + public RpcObject getRpcObject(String propName) throws JsonRpcException { + checkRpcObjectType(propName, null); + return (RpcObject) get(propName); + } + + public void setRpcObject(String propName, RpcObject value) + throws JsonRpcException { + checkRpcObjectType(propName, value); + put(propName, value); + } + + private void checkPropertyType(String type, RpcPropertyMeta prop) { + if (!prop.getType().equals(type)) { + String msg = String.format( + "Type: %s, prop: %s, prop type: %s, access type: %s", + mMeta.getName(), prop.getName(), prop.getType(), type); + throw new InvalidPropertyValueException(msg); + } + } + + private void checkListProp(String propName) { + RpcPropertyMeta propMeta = getPropertyMeta(propName); + if (!RpcTypeParser.isList(propMeta.getType())) { + String pattern = "Property '%s' is '%s', not List"; + String message = String.format(pattern, propName, + propMeta.getType()); + throw new InvalidPropertyValueException(message); + } + } + + private void checkMapProp(String propName) { + RpcPropertyMeta propMeta = getPropertyMeta(propName); + if (!RpcTypeParser.isMap(propMeta.getType())) { + String pattern = "Property '%s' is '%s', not Map"; + String message = String.format(pattern, propName, + propMeta.getType()); + throw new InvalidPropertyValueException(message); + } + } + + private void checkManyListProp(String propName) { + RpcPropertyMeta propMeta = getPropertyMeta(propName); + if (!RpcTypeParser.isManyList(propMeta.getType())) { + String pattern = "Property '%s' is '%s', not ManyList"; + String message = String.format(pattern, propName, + propMeta.getType()); + throw new InvalidPropertyValueException(message); + } + } + + private void checkRpcObjectType(String propName, RpcObject value) + throws JsonRpcException { + if (!RpcFacade.sDebug) { + return; + } + + RpcPropertyMeta prop = getPropertyMeta(propName); + String propPath = prop.getType(); + if (!RpcTypeParser.isRpcObject(propPath)) { + String pattern = "Property '%s' is '%s', not rpc object"; + String message = String.format(pattern, propName, propPath); + throw new InvalidPropertyValueException(message); + } + + RpcObjectMeta propMeta = RpcObjectMeta.get(propPath); + if (value != null && propMeta != value.mMeta) { + String pattern = "Property '%s' only accept object '%s'"; + String message = String.format(pattern, propName, propPath); + throw new InvalidPropertyValueException(message); + } + } + + private void checkNamedValueProp(String propName) { + RpcPropertyMeta prop = getPropertyMeta(propName); + if (!RpcTypeParser.isNamedValue(prop.getType())) { + String msg = String.format( + "Type: %s, prop: %s, prop type: %s, is not namedvalue", + mMeta.getName(), prop.getName(), prop.getType()); + throw new InvalidPropertyValueException(msg); + } + } + + static RpcObject create(RpcObjectMeta meta, JSONArray tableRow) + throws JsonRpcException { + RpcObject result = new RpcObject(meta); + + // must be LinkedHashMap<> because we rely on the value order + LinkedHashMap props = (LinkedHashMap) meta + .getProps(); + int i = 0; + for (RpcPropertyMeta prop : props.values()) { + String name = prop.getName(); + Object value = Helper.get(tableRow, i); + if (value != null) { + value = RpcTypeParser.fromJson(value, prop.getType()); + } + result.put(name, value); + i++; + } + + result.acceptChanges(); + return result; + } + + JSONObject toJson() throws JSONException { + JSONObject result = new JSONObject(); + for (Entry entry : entrySet()) { + RpcPropertyMeta prop = mMeta.getProps().get(entry.getKey()); + Object value = entry.getValue(); + if (!equalToDefaultValue(prop, value)) { + value = RpcTypeParser.toJson(value); + result.put(entry.getKey(), value); + } + } + return result; + } + + void acceptChanges() { + mBackup = new HashMap(this); + for (RpcPropertyMeta prop : mMeta.getProps().values()) { + if (RpcTypeParser.isManyList(prop.getType())) { + getManyList(prop.getName()).acceptChanges(); + } + } + } + + boolean isModified() { + return !super.equals(mBackup); + } + + @Override + public boolean equals(Object object) { + return object == this; + } + + @Override + public int hashCode() { + return super.hashCode(); + } + + private static boolean equalToDefaultValue(RpcPropertyMeta prop, + Object value) { + Object defaultValue = prop.getDefaultValue(); + if (defaultValue == value) { + return true; + } + + if (defaultValue != null) { + return defaultValue.equals(value); + } + + return false; + } + +} diff --git a/jsonrpc/src/main/java/org/forks/jsonrpc/RpcObjectMeta.java b/jsonrpc/src/main/java/org/forks/jsonrpc/RpcObjectMeta.java new file mode 100644 index 0000000..1722eda --- /dev/null +++ b/jsonrpc/src/main/java/org/forks/jsonrpc/RpcObjectMeta.java @@ -0,0 +1,75 @@ +package org.forks.jsonrpc; + +import java.util.HashMap; +import java.util.Map; + +import org.json.JSONArray; +import org.json.JSONObject; + +import static org.forks.jsonrpc.Helper.*; +import static org.forks.jsonrpc.RpcFacade.rpcCall; + +public final class RpcObjectMeta { + private final String mName; + private final Map mProps; + + public RpcObjectMeta(String name, Map props) { + super(); + mName = name; + mProps = props; + } + + public String getName() { + return mName; + } + + public Map getProps() { + return mProps; + } + + public static RpcObjectMeta parse(JSONObject jsonObj) + throws JsonRpcException { + String name = getString(jsonObj, "name"); + JSONArray propsJson = getJsonArray(jsonObj, "props"); + Map props = RpcPropertyMeta.parse(propsJson); + return new RpcObjectMeta(name, props); + } + + private static Map sCache = new HashMap(); + + public static RpcObjectMeta get(String objPath) throws JsonRpcException { + RpcObjectMeta result; + synchronized (sCache) { + result = sCache.get(objPath); + if (result != null) { + return result; + } + } + + result = getFromServer(objPath); + synchronized (sCache) { + sCache.put(objPath, result); + } + + return result; + } + + private static RpcObjectMeta getFromServer(String objPath) + throws JsonRpcException { + String getMethod = "/sbin/ObjectMeta/Get"; + String method = RpcFacade.toFullErtPathByPrefixedErt(objPath, getMethod); + JsonRpcResult result = rpcCall(method, objPath); + return parse(result.getJsonObject()); + } + + // only used in unit test + static void registerMeta(String objPath, RpcObjectMeta meta) { + if (sCache.put(objPath, meta) != null) { + throw new JsonRpcRuntimeException(objPath); + } + } + + static void reset() { + sCache.clear(); + } +} diff --git a/jsonrpc/src/main/java/org/forks/jsonrpc/RpcPropertyMeta.java b/jsonrpc/src/main/java/org/forks/jsonrpc/RpcPropertyMeta.java new file mode 100644 index 0000000..f110905 --- /dev/null +++ b/jsonrpc/src/main/java/org/forks/jsonrpc/RpcPropertyMeta.java @@ -0,0 +1,61 @@ +package org.forks.jsonrpc; + +import java.util.HashMap; +import java.util.Map; + +import org.json.JSONArray; +import org.json.JSONObject; + +import static org.forks.jsonrpc.Helper.*; + +public final class RpcPropertyMeta { + private final String mName; + private final String mType; + private final Object mDefaultValue; + + public RpcPropertyMeta(String name, String type, Object defaultValue) { + super(); + mName = name; + mType = type; + mDefaultValue = defaultValue; + } + + public String getName() { + return mName; + } + + public String getType() { + return mType; + } + + public Object getDefaultValue() { + return mDefaultValue; + } + + static Map parse(JSONArray arr) + throws JsonRpcException { + Map result = new HashMap( + arr.length()); + return parse(result, arr); + } + + static Map parse( + Map result, JSONArray arr) + throws JsonRpcException { + for (int i = 0; i < arr.length(); i++) { + JSONObject item = getJsonObject(arr, i); + RpcPropertyMeta prop = parse(item); + result.put(prop.getName(), prop); + } + return result; + } + + private static RpcPropertyMeta parse(JSONObject json) + throws JsonRpcException { + String name = getString(json, "name"); + String type = getString(json, "type"); + Object defaultValue = json.opt("defaultvalue"); + defaultValue = RpcTypeParser.fromJson(defaultValue, type); + return new RpcPropertyMeta(name, type, defaultValue); + } +} diff --git a/jsonrpc/src/main/java/org/forks/jsonrpc/RpcType.java b/jsonrpc/src/main/java/org/forks/jsonrpc/RpcType.java new file mode 100644 index 0000000..f72a193 --- /dev/null +++ b/jsonrpc/src/main/java/org/forks/jsonrpc/RpcType.java @@ -0,0 +1,5 @@ +package org.forks.jsonrpc; + +interface RpcType { + Object fromJson(Object jsonValue); +} diff --git a/jsonrpc/src/main/java/org/forks/jsonrpc/RpcTypeParser.java b/jsonrpc/src/main/java/org/forks/jsonrpc/RpcTypeParser.java new file mode 100644 index 0000000..47bef1f --- /dev/null +++ b/jsonrpc/src/main/java/org/forks/jsonrpc/RpcTypeParser.java @@ -0,0 +1,557 @@ +package org.forks.jsonrpc; + +import static org.forks.jsonrpc.Helper.getJsonObject; + +import java.lang.reflect.Array; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +public final class RpcTypeParser { + static final String BYTE = "byte"; + static final String SHORT = "short"; + static final String INT = "int"; + static final String LONG = "long"; + static final String BOOL = "bool"; + static final String DOUBLE = "double"; + static final String SINGLE = "single"; + static final String DECIMAL = "decimal"; + static final String DATE = "datetime"; + static final String STRING = "str"; + static final String GUID = "guid"; + static final String BIN = "bin"; + static final String MONEY = "money"; + static final String LOOKUPVALUE = "lookup"; + static final String ENTITYKEY = "entitykey"; + static final String TABLE = "table"; + + public static boolean isManyList(String rpcType) { + return rpcType.startsWith("onetomany(") && rpcType.endsWith(")"); + } + + public static String getManyListItemType(String rpcType) { + return rpcType.substring("onetomany(".length(), rpcType.indexOf(')')); + } + + public static boolean isList(String rpcType) { + return startWith(rpcType, '['); + } + + public static boolean isMap(String rpcType) { + return startWith(rpcType, '{'); + } + + public static boolean isRpcObject(String rpcType) { + return startWith(rpcType, '/'); + } + + public static boolean isNamedValue(String rpcType) { + return rpcType.startsWith("namedvalue(") && rpcType.endsWith(")"); + } + + public static String getNamedValueTidType(String rpcType) { + return rpcType.substring("namedvalue(".length(), rpcType.length() - 1); + } + + private static boolean startWith(String s, char ch) { + return s.length() != 0 && s.charAt(0) == ch; + } + + public static String getMapValueType(String rpcType) { + int start = rpcType.indexOf(':'); + return rpcType.substring(start + 1, rpcType.length() - 1); + } + + public static String getListItemType(String rpcType) { + return rpcType.substring(1, rpcType.length() - 1); + } + + public static Object fromJson(Object jsonValue, String rpcType) + throws JsonRpcException { + if (isNull(jsonValue)) { + return null; + } + + RpcType type = parse(rpcType); + return type.fromJson(jsonValue); + } + + public static Object toJson(Object value) throws JSONException { + if (value == null) { + return JSONObject.NULL; + } else if (value instanceof Date) { + return dateToJson((Date) value); + } else if (value instanceof RpcObject) { + return ((RpcObject) value).toJson(); + } else if (value instanceof ManyList) { + return ((ManyList) value).toJson(); + } else if (value instanceof List) { + return listToJson((List) value); + } else if (value.getClass().isArray()) { + return arrayToJson(value); + } else if (value instanceof Map) { + return mapToJson((Map) value); + } else if (value instanceof NamedValue) { + return namedValueToJson((NamedValue) value); + } else { + return value; + } + } + + private static Object namedValueToJson(NamedValue value) { + return value.getValue(); + } + + private static Object mapToJson(Map map) throws JSONException { + JSONObject result = new JSONObject(); + for (Entry entry : map.entrySet()) { + Object value = entry.getValue(); + value = toJson(value); + result.put((String) entry.getKey(), value); + } + return result; + } + + private static Object listToJson(List coll) throws JSONException { + JSONArray result = new JSONArray(); + for (Object item : coll) { + item = toJson(item); + result.put(item); + } + return result; + } + + private static Object arrayToJson(Object array) throws JSONException { + JSONArray result = new JSONArray(); + int len = Array.getLength(array); + for (int i = 0; i < len; i++) { + Object item = Array.get(array, i); + item = toJson(item); + result.put(item); + } + return result; + } + + private static Object dateToJson(Date val) { + return String.format("/Date(%tQ+0800)/", val); + } + + synchronized static final RpcType parse(String rpcType) + throws JsonRpcException { + RpcType result = sRpcTypeCache.get(rpcType); + if (result == null) { + result = doParse(rpcType); + sRpcTypeCache.put(rpcType, result); + } + return result; + } + + static final boolean isNull(Object jsonObj) { + return jsonObj == null || jsonObj == JSONObject.NULL; + } + + private static final Map sRpcTypeCache = new HashMap(); + + private static RpcType doParse(String rpcType) throws JsonRpcException { + if (rpcType.equals(BOOL)) { + return sBoolean; + } else if (rpcType.equals(BYTE)) { + return sByte; + } else if (rpcType.equals(SHORT)) { + return sShort; + } else if (rpcType.equals(INT)) { + return sInt; + } else if (rpcType.equals(LONG)) { + return sLong; + } else if (rpcType.equals(SINGLE)) { + return sDouble; + } else if (rpcType.equals(DOUBLE)) { + return sDouble; + } else if (rpcType.equals(STRING)) { + return sString; + } else if(rpcType.equals(GUID)){ + return sString; + } else if (rpcType.equals(BIN)){ + return sString; + } + else if (rpcType.equals(DECIMAL)) { + return sDecimal; + } else if (rpcType.equals(DATE)) { + return sDate; + } else if (rpcType.equals(MONEY)) { + return sDecimal; + } else if (rpcType.equals(LOOKUPVALUE)) { + return sInt; + } else if (isNamedValue(rpcType)) { + return new RpcTypeNullWrap(new NamedValueRpcType(rpcType)); + } else if (rpcType.equals(ENTITYKEY)) { + return sLong; + } else if (isList(rpcType)) { + return new RpcTypeNullWrap(new ListRpcType(rpcType)); + } else if (isRpcObject(rpcType)) { + RpcObjectMeta meta = RpcObjectMeta.get(rpcType); + return new RpcTypeNullWrap(new RpcObjectRpcType(meta)); + } else if (isMap(rpcType)) { + return new RpcTypeNullWrap(new MapRpcType(rpcType)); + } else if (isManyList(rpcType)) { + return new RpcTypeNullWrap(new ManyListRpcType(rpcType)); + } else if (rpcType.equals(TABLE)) { + return sTable; + } else { + throw new JsonRpcException("Unknown rpc type '" + rpcType + "'"); + } + } + + private static final RpcType sDirect = new RpcTypeNullWrap( + new DirectRpcType()); + static final RpcType sInt = sDirect; + static final RpcType sBoolean = sDirect; + static final RpcType sShort = new RpcTypeNullWrap(new ShortRpcType()); + static final RpcType sByte = new RpcTypeNullWrap(new ByteRpcType()); + static final RpcType sLong = new RpcTypeNullWrap(new LongRpcType()); + static final RpcType sDouble = new RpcTypeNullWrap(new DoubleRpcType()); + static final RpcType sString = sDirect; + static final RpcType sDecimal = new RpcTypeNullWrap(new DecimalRpcType()); + static final RpcType sDate = new RpcTypeNullWrap(new DateRpcType()); + static final RpcType sTable = new RpcTypeNullWrap(new TableRpcType()); + + static final void reset() { + sRpcTypeCache.clear(); + } + + private static final class NamedValueRpcType implements RpcType { + + private final String mIdtype; + + public NamedValueRpcType(String rpcType) { + mIdtype = getNamedValueTidType(rpcType); + } + + public Object fromJson(Object jsonValue) { + Short val = (Short) sShort.fromJson(jsonValue); + return NamedValue.create(mIdtype, val); + } + + } + + private static final class TableRpcType implements RpcType { + + public Object fromJson(Object jsonValue) { + try { + JSONObject obj = (JSONObject) jsonValue; + Map cols = getTableColumns(obj); + RpcObjectMeta meta = new RpcObjectMeta("table", cols); + ArrayList rows = getTableRows(obj, meta); + RpcObject sumRow = getTableSumRow(obj, meta); + return new DFDataTable(cols, rows, sumRow); + } catch (JsonRpcException e) { + throw new JsonRpcRuntimeException(e); + } + } + + private static Map getTableColumns( + JSONObject obj) throws JsonRpcException { + Map cols; + JSONArray meta = obj.optJSONArray("_meta"); + if (meta != null) { + cols = parseTableCols(meta); + } else { + cols = new HashMap(); + } + return cols; + } + + private static ArrayList getTableRows(JSONObject obj, + RpcObjectMeta rpcObjectMeta) throws JsonRpcException { + ArrayList rows; + JSONArray rowsJson = obj.optJSONArray("rows"); + if (rowsJson == null) { + rows = new ArrayList(); + } else { + rows = doGetTableRows(rowsJson, rpcObjectMeta); + } + return rows; + } + + private static RpcObject getTableSumRow(JSONObject obj, + RpcObjectMeta meta) throws JsonRpcException { + RpcObject sumRow = null; + JSONArray sumRowJson = obj.optJSONArray("sumrow"); + if (sumRowJson != null) { + sumRow = RpcObject.create(meta, sumRowJson); + } + return sumRow; + } + + private static ArrayList doGetTableRows(JSONArray rows, + RpcObjectMeta meta) throws JsonRpcException { + ArrayList result = new ArrayList( + rows.length()); + for (int i = 0; i < rows.length(); i++) { + result.add(RpcObject.create(meta, Helper.getJsonArray(rows, i))); + } + return result; + } + + private static Map parseTableCols( + JSONArray _meta) throws JsonRpcException { + // use LinkedHashMap to maintain column order + Map result = new LinkedHashMap( + _meta.length()); + return RpcPropertyMeta.parse(result, _meta); + } + + } + + private static final class MapRpcType implements RpcType { + + private final RpcType mValueType; + + public MapRpcType(String rpcType) throws JsonRpcException { + checkMapKeyType(rpcType); + String valueType = getMapValueType(rpcType); + mValueType = parse(valueType); + } + + public Object fromJson(Object jsonValue) { + JSONObject obj = (JSONObject) jsonValue; + Map result = new HashMap( + obj.length()); + Iterator iter = obj.keys(); + while (iter.hasNext()) { + String key = iter.next(); + Object value; + try { + value = Helper.get(obj, key); + } catch (JsonRpcException e) { + throw new JsonRpcRuntimeException(e); + } + if (RpcTypeParser.isNull(value)) { + result.put(key, null); + } else { + result.put(key, mValueType.fromJson(value)); + } + } + return result; + } + + private static void checkMapKeyType(String rpcType) { + String keyType = getMapKeyType(rpcType); + if (!keyType.equals(STRING)) { + String message = "jsonrpc android client only support `str' map key. " + + rpcType; + throw new JsonRpcRuntimeException(message); + } + } + + private static String getMapKeyType(String rpcType) { + int end = rpcType.indexOf(':'); + return rpcType.substring(1, end); + } + } + + private static final class RpcTypeNullWrap implements RpcType { + private final RpcType mInner; + + public RpcTypeNullWrap(RpcType inner) { + mInner = inner; + } + + public Object fromJson(Object jsonValue) { + if (jsonValue == JSONObject.NULL) { + return null; + } + return mInner.fromJson(jsonValue); + } + + } + + private static final class ManyListRpcType implements RpcType { + + private final RpcObjectMeta mItemMeta; + private final RpcType mItemType; + + public ManyListRpcType(String rpcType) throws JsonRpcException { + String itemRpcType = getManyListItemType(rpcType); + mItemType = parse(itemRpcType); + mItemMeta = RpcObjectMeta.get(itemRpcType); + } + + public Object fromJson(Object jsonValue) { + try { + ManyList result = new ManyList(mItemMeta); + restoreFromJson((JSONObject) jsonValue, result); + return result; + } catch (JsonRpcException e) { + throw new JsonRpcRuntimeException(e); + } + } + + private void restoreFromJson(JSONObject json, ManyList result) + throws JsonRpcException { + JSONArray _data = json.optJSONArray("_data"); + if (_data != null && _data.length() != 0) { + fromJson(result, _data); + } + } + + private void fromJson(ManyList result, JSONArray _data) + throws JsonRpcException { + for (int i = 0; i < _data.length(); i++) { + JSONObject itemJson = getJsonObject(_data, i); + RpcObject item = (RpcObject) mItemType.fromJson(itemJson); + result.add(item); + } + result.acceptChanges(); + } + } + + private static final class DirectRpcType implements RpcType { + + public Object fromJson(Object jsonValue) { + return jsonValue; + } + } + + private static final class LongRpcType implements RpcType { + + public Object fromJson(Object jsonValue) { + if (jsonValue instanceof Long) { + return jsonValue; + } + return ((Integer) jsonValue).longValue(); + } + } + + private static final class ShortRpcType implements RpcType { + + public Object fromJson(Object jsonValue) { + return ((Integer) jsonValue).shortValue(); + } + + } + + private static final class ByteRpcType implements RpcType { + + public Object fromJson(Object jsonValue) { + short result = ((Integer) jsonValue).shortValue(); + + if (result > 255 || result < 0) { + throw new JsonRpcRuntimeException("can not cast value " + + result + " to dotnet byte type"); + } + return result; + } + + } + + private static final class DoubleRpcType implements RpcType { + + public Object fromJson(Object jsonValue) { + if (jsonValue instanceof Double) { + return jsonValue; + } + return ((Number) jsonValue).doubleValue(); + } + + } + + private static final class DecimalRpcType implements RpcType { + + public Object fromJson(Object jsonValue) { + return new BigDecimal(jsonValue.toString()); + } + + } + + private static final class ListRpcType implements RpcType { + + private final RpcType mItemType; + + public ListRpcType(String rpcType) throws JsonRpcException { + String itemRpcType = getListItemType(rpcType); + mItemType = parse(itemRpcType); + } + + public Object fromJson(Object jsonValue) { + JSONArray json = (JSONArray) jsonValue; + List result = new ArrayList(json.length()); + for (int i = 0; i < json.length(); i++) { + Object itemJson; + try { + itemJson = Helper.get(json, i); + } catch (JsonRpcException e) { + throw new JsonRpcRuntimeException(e); + } + result.add(mItemType.fromJson(itemJson)); + } + return result; + } + + } + + private static final class RpcObjectRpcType implements RpcType { + + private final RpcObjectMeta mMeta; + + public RpcObjectRpcType(RpcObjectMeta meta) { + mMeta = meta; + } + + public Object fromJson(Object jsonValue) { + try { + JSONObject json = (JSONObject) jsonValue; + RpcObject result = new RpcObject(mMeta); + for (RpcPropertyMeta prop : mMeta.getProps().values()) { + String name = prop.getName(); + Object value = json.opt(name); + if (value != null) { + result.put(name, + RpcTypeParser.fromJson(value, prop.getType())); + } else if (json.has(name)) { + result.put(name, null); + } + } + result.acceptChanges(); + return result; + } catch (JsonRpcException e) { + throw new JsonRpcRuntimeException(e); + } + } + + } + + private static final class DateRpcType implements RpcType { + + public Object fromJson(Object jsonValue) { + String s = (String) jsonValue; + if (!RpcFacade.sDebug || isDateString(s)) { + return new Date(parseMillsSinceEpoch(s)); + } + + String message = "can not convert '" + s + "' to Date"; + throw new JsonRpcRuntimeException(message); + } + + private static boolean isDateString(String s) { + return s.startsWith("/Date(") && s.endsWith("+0800)/"); + } + + private static final long parseMillsSinceEpoch(String s) { + int endIdx = s.indexOf('+'); + String numStr = s.substring(6, endIdx); + return Long.parseLong(numStr); + } + } + +} diff --git a/jsonrpc/src/main/res/values/strings.xml b/jsonrpc/src/main/res/values/strings.xml new file mode 100644 index 0000000..fbe7d1b --- /dev/null +++ b/jsonrpc/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + jsonrpc + diff --git a/jsonrpc/src/test/java/org/forks/jsonrpc/ExampleUnitTest.java b/jsonrpc/src/test/java/org/forks/jsonrpc/ExampleUnitTest.java new file mode 100644 index 0000000..6dbb1a1 --- /dev/null +++ b/jsonrpc/src/test/java/org/forks/jsonrpc/ExampleUnitTest.java @@ -0,0 +1,15 @@ +package org.forks.jsonrpc; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * To work on unit tests, switch the Test Artifact in the Build Variants view. + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() throws Exception { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..0e91993 --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +include ':app', ':jsonrpc'